Commit f2689647 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 0e4f8f1a b425e4d0
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -102,9 +102,11 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)

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,
					struct ksmbd_tree_connect *tree_conn)
@@ -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;
}

+12 −5
Original line number Diff line number Diff line
@@ -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 @@ int smb2_sess_setup(struct ksmbd_work *work)
			}
		}
		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);