six server fixes

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmmwX+wACgkQiiy9cAdy
 T1FWkQv9GHg6IWRG8PlbhGZG7NbQnHNndv2+hjR2v41+ZtB9zZADpC0bdoHFNGZV
 KeYrLQa9sypss2w6hCynkRAtPobf7aROe7lscVQk+uCC2XVTI5eSyalpf8jiQHVi
 0XXgvs3FuBcvLHNtzrCJeTUxAko0EGRkjLkSYDr7mijr31FKkV6Vwvy+JuT6JArR
 M706MwIyWgWYWc7N6mrt3WrA5dT4KJc5KH2/4hCQMoJTgjKn1ExVwp/b/rogQEdC
 yV+MkMinQJ3s+WvSYQR+WvG1HQeCs6UJiI5heDHCgu6husdvzeAD4LagVsAIYbFB
 jXCjiIJunL5H1ISWsQVhPykfg3CUY6CT34trNPAwxEStziW0kAcJ6bou5v2IUwnK
 hkztVeeEwSX3e4VFAPhYmqo5x5EDoSEG444rTSxiGdA4Ut3KNrpyxu9SJM4L4Fhi
 7OCdR70p+DagzNz28dE1e6pM4S/47vNrVRcLPBy9WPpviO1G1C5elUXBNduwucUd
 ca1sEA/u
 =BNF+
 -----END PGP SIGNATURE-----

Merge tag 'v7.0-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

 - Fix potential use after free errors

 - Fix refcount leak in smb2 open error path

 - Prevent allowing logging signing or encryption keys

* tag 'v7.0-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: Don't log keys in SMB3 signing and encryption key generation
  smb: server: fix use-after-free in smb2_open()
  ksmbd: fix use-after-free in smb_lazy_parent_lease_break_close()
  ksmbd: fix use-after-free by using call_rcu() for oplock_info
  ksmbd: fix use-after-free in proc_show_files due to early rcu_read_unlock
  smb/server: Fix another refcount leak in smb2_open()
This commit is contained in:
Linus Torvalds 2026-03-10 20:30:52 -07:00
commit b29fb8829b
5 changed files with 39 additions and 41 deletions

View File

@ -589,12 +589,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
ksmbd_debug(AUTH, "generated SMB3 signing key\n");
ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
ksmbd_debug(AUTH, "Session Key %*ph\n",
SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
ksmbd_debug(AUTH, "Signing Key %*ph\n",
SMB3_SIGN_KEY_SIZE, key);
return 0;
}
@ -652,23 +648,9 @@ static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
ptwin->decryption.context,
sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
ksmbd_debug(AUTH, "generated SMB3 encryption/decryption keys\n");
ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
ksmbd_debug(AUTH, "Session Key %*ph\n",
SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
} else {
ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
}
}
void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,

View File

@ -120,7 +120,7 @@ static void free_lease(struct oplock_info *opinfo)
kfree(lease);
}
static void free_opinfo(struct oplock_info *opinfo)
static void __free_opinfo(struct oplock_info *opinfo)
{
if (opinfo->is_lease)
free_lease(opinfo);
@ -129,6 +129,18 @@ static void free_opinfo(struct oplock_info *opinfo)
kfree(opinfo);
}
static void free_opinfo_rcu(struct rcu_head *rcu)
{
struct oplock_info *opinfo = container_of(rcu, struct oplock_info, rcu);
__free_opinfo(opinfo);
}
static void free_opinfo(struct oplock_info *opinfo)
{
call_rcu(&opinfo->rcu, free_opinfo_rcu);
}
struct oplock_info *opinfo_get(struct ksmbd_file *fp)
{
struct oplock_info *opinfo;
@ -176,9 +188,9 @@ void opinfo_put(struct oplock_info *opinfo)
free_opinfo(opinfo);
}
static void opinfo_add(struct oplock_info *opinfo)
static void opinfo_add(struct oplock_info *opinfo, struct ksmbd_file *fp)
{
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
struct ksmbd_inode *ci = fp->f_ci;
down_write(&ci->m_lock);
list_add(&opinfo->op_entry, &ci->m_op_list);
@ -1123,10 +1135,12 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
rcu_read_lock();
opinfo = rcu_dereference(fp->f_opinfo);
rcu_read_unlock();
if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2)
if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2) {
rcu_read_unlock();
return;
}
rcu_read_unlock();
p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
if (!p_ci)
@ -1277,20 +1291,21 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
set_oplock_level(opinfo, req_op_level, lctx);
out:
rcu_assign_pointer(fp->f_opinfo, opinfo);
opinfo->o_fp = fp;
opinfo_count_inc(fp);
opinfo_add(opinfo);
opinfo_add(opinfo, fp);
if (opinfo->is_lease) {
err = add_lease_global_list(opinfo);
if (err)
goto err_out;
}
rcu_assign_pointer(fp->f_opinfo, opinfo);
opinfo->o_fp = fp;
return 0;
err_out:
free_opinfo(opinfo);
__free_opinfo(opinfo);
return err;
}

View File

@ -69,8 +69,9 @@ struct oplock_info {
struct lease *o_lease;
struct list_head op_entry;
struct list_head lease_entry;
wait_queue_head_t oplock_q; /* Other server threads */
wait_queue_head_t oplock_brk; /* oplock breaking wait */
wait_queue_head_t oplock_q; /* Other server threads */
wait_queue_head_t oplock_brk; /* oplock breaking wait */
struct rcu_head rcu;
};
struct lease_break_info {

View File

@ -3012,13 +3012,14 @@ int smb2_open(struct ksmbd_work *work)
goto err_out2;
}
fp = dh_info.fp;
if (ksmbd_override_fsids(work)) {
rc = -ENOMEM;
ksmbd_put_durable_fd(dh_info.fp);
goto err_out2;
}
fp = dh_info.fp;
file_info = FILE_OPENED;
rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat);
@ -3616,10 +3617,8 @@ int smb2_open(struct ksmbd_work *work)
reconnected_fp:
rsp->StructureSize = cpu_to_le16(89);
rcu_read_lock();
opinfo = rcu_dereference(fp->f_opinfo);
opinfo = opinfo_get(fp);
rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
rcu_read_unlock();
rsp->Flags = 0;
rsp->CreateAction = cpu_to_le32(file_info);
rsp->CreationTime = cpu_to_le64(fp->create_time);
@ -3660,6 +3659,7 @@ int smb2_open(struct ksmbd_work *work)
next_ptr = &lease_ccontext->Next;
next_off = conn->vals->create_lease_size;
}
opinfo_put(opinfo);
if (maximal_access_ctxt) {
struct create_context *mxac_ccontext;

View File

@ -87,11 +87,7 @@ static int proc_show_files(struct seq_file *m, void *v)
rcu_read_lock();
opinfo = rcu_dereference(fp->f_opinfo);
rcu_read_unlock();
if (!opinfo) {
seq_printf(m, " %-15s", " ");
} else {
if (opinfo) {
const struct ksmbd_const_name *const_names;
int count;
unsigned int level;
@ -105,8 +101,12 @@ static int proc_show_files(struct seq_file *m, void *v)
count = ARRAY_SIZE(ksmbd_oplock_const_names);
level = opinfo->level;
}
rcu_read_unlock();
ksmbd_proc_show_const_name(m, " %-15s",
const_names, count, level);
} else {
rcu_read_unlock();
seq_printf(m, " %-15s", " ");
}
seq_printf(m, " %#010x %#010x %s\n",