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

Pull smb server fixes from Steve French:

 - Three use after free fixes (in close, in compounded ops, and in tree
   disconnect)

 - Multichannel fix

 - return proper volume identifier (superblock uuid if available) in
   FS_OBJECT_ID queries

* tag 'v7.0-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix use-after-free in durable v2 replay of active file handles
  ksmbd: fix use-after-free of share_conf in compound request
  ksmbd: use volume UUID in FS_OBJECT_ID_INFORMATION
  ksmbd: unset conn->binding on failed binding request
  ksmbd: fix share_conf UAF in tree_conn disconnect
This commit is contained in:
Linus Torvalds
2026-03-20 09:03:37 -07:00
2 changed files with 18 additions and 8 deletions

View File

@@ -102,8 +102,10 @@ out_error:
void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
{
if (atomic_dec_and_test(&tcon->refcount))
if (atomic_dec_and_test(&tcon->refcount)) {
ksmbd_share_config_put(tcon->share_conf);
kfree(tcon);
}
}
static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
@@ -113,10 +115,11 @@ static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
ksmbd_release_tree_conn_id(sess, tree_conn->id);
ksmbd_share_config_put(tree_conn->share_conf);
ksmbd_counter_dec(KSMBD_COUNTER_TREE_CONNS);
if (atomic_dec_and_test(&tree_conn->refcount))
if (atomic_dec_and_test(&tree_conn->refcount)) {
ksmbd_share_config_put(tree_conn->share_conf);
kfree(tree_conn);
}
return ret;
}

View File

@@ -126,6 +126,8 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
pr_err("The first operation in the compound does not have tcon\n");
return -EINVAL;
}
if (work->tcon->t_state != TREE_CONNECTED)
return -ENOENT;
if (tree_id != UINT_MAX && work->tcon->id != tree_id) {
pr_err("tree id(%u) is different with id(%u) in first operation\n",
tree_id, work->tcon->id);
@@ -1948,6 +1950,7 @@ out_err:
}
}
smb2_set_err_rsp(work);
conn->binding = false;
} else {
unsigned int iov_len;
@@ -2828,7 +2831,11 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
goto out;
}
dh_info->fp->conn = conn;
if (dh_info->fp->conn) {
ksmbd_put_durable_fd(dh_info->fp);
err = -EBADF;
goto out;
}
dh_info->reconnected = true;
goto out;
}
@@ -5452,7 +5459,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp)
{
struct ksmbd_session *sess = work->sess;
struct ksmbd_conn *conn = work->conn;
struct ksmbd_share_config *share = work->tcon->share_conf;
int fsinfoclass = 0;
@@ -5589,10 +5595,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info = (struct object_id_info *)(rsp->Buffer);
if (!user_guest(sess->user))
memcpy(info->objid, user_passkey(sess->user), 16);
if (path.mnt->mnt_sb->s_uuid_len == 16)
memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b,
path.mnt->mnt_sb->s_uuid_len);
else
memset(info->objid, 0, 16);
memcpy(info->objid, &stfs.f_fsid, sizeof(stfs.f_fsid));
info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC);
info->extended_info.version = cpu_to_le32(1);