Commit 6a31658a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '6.8-rc-smb-server-fixes' of git://git.samba.org/ksmbd

Pull smb server updates from Steve French:

 - memory allocation fix

 - three lease fixes, including important rename fix

 - read only share fix

 - thread freeze fix

 - three cleanup fixes (two kernel doc related)

 - locking fix in setting EAs

 - packet header validation fix

* tag '6.8-rc-smb-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: Add missing set_freezable() for freezable kthread
  ksmbd: free ppace array on error in parse_dacl
  ksmbd: send lease break notification on FILE_RENAME_INFORMATION
  ksmbd: don't allow O_TRUNC open on read-only share
  ksmbd: vfs: fix all kernel-doc warnings
  ksmbd: auth: fix most kernel-doc warnings
  ksmbd: Remove usage of the deprecated ida_simple_xx() API
  ksmbd: don't increment epoch if current state and request state are same
  ksmbd: fix potential circular locking issue in smb2_set_ea()
  ksmbd: set v2 lease version on lease upgrade
  ksmbd: validate the zero field of packet header
parents 48892692 8fb7b723
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -208,10 +208,12 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,

/**
 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
 * @conn:		connection
 * @sess:		session of connection
 * @ntlmv2:		NTLMv2 challenge response
 * @blen:		NTLMv2 blob length
 * @domain_name:	domain name
 * @cryptkey:		session crypto key
 *
 * Return:	0 on success, error number on error
 */
@@ -294,7 +296,8 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
 * authenticate blob
 * @authblob:	authenticate blob source pointer
 * @usr:	user details
 * @blob_len:	length of the @authblob message
 * @conn:	connection
 * @sess:	session of connection
 *
 * Return:	0 on success, error number on error
@@ -376,8 +379,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
 * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
 * negotiate blob
 * @negblob: negotiate blob source pointer
 * @rsp:     response header pointer to be updated
 * @sess:    session of connection
 * @blob_len:	length of the @authblob message
 * @conn:	connection
 *
 */
int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
@@ -403,8 +406,7 @@ int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
 * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
 * challenge blob
 * @chgblob: challenge blob source pointer to initialize
 * @rsp:     response header pointer to be updated
 * @sess:    session of connection
 * @conn:	connection
 *
 */
unsigned int
+1 −0
Original line number Diff line number Diff line
@@ -284,6 +284,7 @@ int ksmbd_conn_handler_loop(void *p)
		goto out;

	conn->last_active = jiffies;
	set_freezable();
	while (ksmbd_conn_alive(conn)) {
		if (try_to_freeze())
			continue;
+6 −15
Original line number Diff line number Diff line
@@ -5,42 +5,33 @@

#include "ksmbd_ida.h"

static inline int __acquire_id(struct ida *ida, int from, int to)
{
	return ida_simple_get(ida, from, to, GFP_KERNEL);
}

int ksmbd_acquire_smb2_tid(struct ida *ida)
{
	int id;

	id = __acquire_id(ida, 1, 0xFFFFFFFF);

	return id;
	return ida_alloc_range(ida, 1, 0xFFFFFFFE, GFP_KERNEL);
}

int ksmbd_acquire_smb2_uid(struct ida *ida)
{
	int id;

	id = __acquire_id(ida, 1, 0);
	id = ida_alloc_min(ida, 1, GFP_KERNEL);
	if (id == 0xFFFE)
		id = __acquire_id(ida, 1, 0);
		id = ida_alloc_min(ida, 1, GFP_KERNEL);

	return id;
}

int ksmbd_acquire_async_msg_id(struct ida *ida)
{
	return __acquire_id(ida, 1, 0);
	return ida_alloc_min(ida, 1, GFP_KERNEL);
}

int ksmbd_acquire_id(struct ida *ida)
{
	return __acquire_id(ida, 0, 0);
	return ida_alloc(ida, GFP_KERNEL);
}

void ksmbd_release_id(struct ida *ida, int id)
{
	ida_simple_remove(ida, id);
	ida_free(ida, id);
}
+11 −5
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
	lease->is_dir = lctx->is_dir;
	memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
	lease->version = lctx->version;
	lease->epoch = le16_to_cpu(lctx->epoch);
	lease->epoch = le16_to_cpu(lctx->epoch) + 1;
	INIT_LIST_HEAD(&opinfo->lease_entry);
	opinfo->o_lease = lease;

@@ -546,6 +546,7 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
			     atomic_read(&ci->sop_count)) == 1) {
				if (lease->state != SMB2_LEASE_NONE_LE &&
				    lease->state == (lctx->req_state & lease->state)) {
					lease->epoch++;
					lease->state |= lctx->req_state;
					if (lctx->req_state &
						SMB2_LEASE_WRITE_CACHING_LE)
@@ -556,14 +557,18 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
				    atomic_read(&ci->sop_count)) > 1) {
				if (lctx->req_state ==
				    (SMB2_LEASE_READ_CACHING_LE |
				     SMB2_LEASE_HANDLE_CACHING_LE))
				     SMB2_LEASE_HANDLE_CACHING_LE)) {
					lease->epoch++;
					lease->state = lctx->req_state;
				}
			}

			if (lctx->req_state && lease->state ==
			    SMB2_LEASE_NONE_LE)
			    SMB2_LEASE_NONE_LE) {
				lease->epoch++;
				lease_none_upgrade(opinfo, lctx->req_state);
			}
		}
		read_lock(&ci->m_lock);
	}
	read_unlock(&ci->m_lock);
@@ -1035,7 +1040,8 @@ static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
	       SMB2_LEASE_KEY_SIZE);
	lease2->duration = lease1->duration;
	lease2->flags = lease1->flags;
	lease2->epoch = lease1->epoch++;
	lease2->epoch = lease1->epoch;
	lease2->version = lease1->version;
}

static int add_lease_global_list(struct oplock_info *opinfo)
@@ -1447,7 +1453,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
		memcpy(buf->lcontext.LeaseKey, lease->lease_key,
		       SMB2_LEASE_KEY_SIZE);
		buf->lcontext.LeaseFlags = lease->flags;
		buf->lcontext.Epoch = cpu_to_le16(++lease->epoch);
		buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
		buf->lcontext.LeaseState = lease->state;
		memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
		       SMB2_LEASE_KEY_SIZE);
+14 −17
Original line number Diff line number Diff line
@@ -2311,11 +2311,12 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
 * @eabuf:	set info command buffer
 * @buf_len:	set info command buffer length
 * @path:	dentry path for get ea
 * @get_write:	get write access to a mount
 *
 * Return:	0 on success, otherwise error
 */
static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
		       const struct path *path)
		       const struct path *path, bool get_write)
{
	struct mnt_idmap *idmap = mnt_idmap(path->mnt);
	char *attr_name = NULL, *value;
@@ -2971,7 +2972,7 @@ int smb2_open(struct ksmbd_work *work)
					    &may_flags);

	if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
		if (open_flags & O_CREAT) {
		if (open_flags & (O_CREAT | O_TRUNC)) {
			ksmbd_debug(SMB,
				    "User does not have write permission\n");
			rc = -EACCES;
@@ -3003,7 +3004,7 @@ int smb2_open(struct ksmbd_work *work)

			rc = smb2_set_ea(&ea_buf->ea,
					 le32_to_cpu(ea_buf->ccontext.DataLength),
					 &path);
					 &path, false);
			if (rc == -EOPNOTSUPP)
				rc = 0;
			else if (rc)
@@ -5568,6 +5569,7 @@ static int smb2_rename(struct ksmbd_work *work,
	if (!file_info->ReplaceIfExists)
		flags = RENAME_NOREPLACE;

	smb_break_all_levII_oplock(work, fp, 0);
	rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags);
out:
	kfree(new_name);
@@ -5943,12 +5945,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
	}
	case FILE_RENAME_INFORMATION:
	{
		if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
			ksmbd_debug(SMB,
				    "User does not have write permission\n");
			return -EACCES;
		}

		if (buf_len < sizeof(struct smb2_file_rename_info))
			return -EINVAL;

@@ -5968,12 +5964,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
	}
	case FILE_DISPOSITION_INFORMATION:
	{
		if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
			ksmbd_debug(SMB,
				    "User does not have write permission\n");
			return -EACCES;
		}

		if (buf_len < sizeof(struct smb2_file_disposition_info))
			return -EINVAL;

@@ -5992,7 +5982,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
				   buf_len, &fp->filp->f_path);
				   buf_len, &fp->filp->f_path, true);
	}
	case FILE_POSITION_INFORMATION:
	{
@@ -6035,7 +6025,7 @@ int smb2_set_info(struct ksmbd_work *work)
{
	struct smb2_set_info_req *req;
	struct smb2_set_info_rsp *rsp;
	struct ksmbd_file *fp;
	struct ksmbd_file *fp = NULL;
	int rc = 0;
	unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;

@@ -6055,6 +6045,13 @@ int smb2_set_info(struct ksmbd_work *work)
		rsp = smb2_get_msg(work->response_buf);
	}

	if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
		ksmbd_debug(SMB, "User does not have write permission\n");
		pr_err("User does not have write permission\n");
		rc = -EACCES;
		goto err_out;
	}

	if (!has_file_id(id)) {
		id = req->VolatileFileId;
		pid = req->PersistentFileId;
Loading