Commit a1aee52b authored by Hangyu Hua's avatar Hangyu Hua Committed by Zizhi Wo
Browse files

ksmbd: fix possible memory leak in smb2_lock()

mainline inclusion
from mainline-v6.3-rc1
commit d3ca9f7a
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6KEWO?from=project-issue
CVE: CVE-2023-1193

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d3ca9f7aeba793d74361d88a8800b2f205c9236b



--------------------------------

argv needs to be free when setup_async_work fails or when the current
process is woken up.

Fixes: e2f34481 ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarHangyu Hua <hbh25y@gmail.com>
Acked-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
parent 1c7cb4fc
Loading
Loading
Loading
Loading
+13 −15
Original line number Diff line number Diff line
@@ -6655,7 +6655,7 @@ int smb2_cancel(struct ksmbd_work *work)
	struct ksmbd_conn *conn = work->conn;
	struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *chdr;
	struct ksmbd_work *cancel_work = NULL, *iter;
	struct ksmbd_work *iter;
	struct list_head *command_list;

	ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
@@ -6677,7 +6677,9 @@ int smb2_cancel(struct ksmbd_work *work)
				    "smb2 with AsyncId %llu cancelled command = 0x%x\n",
				    le64_to_cpu(hdr->Id.AsyncId),
				    le16_to_cpu(chdr->Command));
			cancel_work = iter;
			iter->state = KSMBD_WORK_CANCELLED;
			if (iter->cancel_fn)
				iter->cancel_fn(iter->cancel_argv);
			break;
		}
		spin_unlock(&conn->request_lock);
@@ -6696,18 +6698,12 @@ int smb2_cancel(struct ksmbd_work *work)
				    "smb2 with mid %llu cancelled command = 0x%x\n",
				    le64_to_cpu(hdr->MessageId),
				    le16_to_cpu(chdr->Command));
			cancel_work = iter;
			iter->state = KSMBD_WORK_CANCELLED;
			break;
		}
		spin_unlock(&conn->request_lock);
	}

	if (cancel_work) {
		cancel_work->state = KSMBD_WORK_CANCELLED;
		if (cancel_work->cancel_fn)
			cancel_work->cancel_fn(cancel_work->cancel_argv);
	}

	/* For SMB2_CANCEL command itself send no response*/
	work->send_no_response = 1;
	return 0;
@@ -7071,6 +7067,14 @@ int smb2_lock(struct ksmbd_work *work)

				ksmbd_vfs_posix_lock_wait(flock);

				spin_lock(&work->conn->request_lock);
				spin_lock(&fp->f_lock);
				list_del(&work->fp_entry);
				work->cancel_fn = NULL;
				kfree(argv);
				spin_unlock(&fp->f_lock);
				spin_unlock(&work->conn->request_lock);

				if (work->state != KSMBD_WORK_ACTIVE) {
					list_del(&smb_lock->llist);
					spin_lock(&work->conn->llist_lock);
@@ -7079,9 +7083,6 @@ int smb2_lock(struct ksmbd_work *work)
					locks_free_lock(flock);

					if (work->state == KSMBD_WORK_CANCELLED) {
						spin_lock(&fp->f_lock);
						list_del(&work->fp_entry);
						spin_unlock(&fp->f_lock);
						rsp->hdr.Status =
							STATUS_CANCELLED;
						kfree(smb_lock);
@@ -7103,9 +7104,6 @@ int smb2_lock(struct ksmbd_work *work)
				list_del(&smb_lock->clist);
				spin_unlock(&work->conn->llist_lock);

				spin_lock(&fp->f_lock);
				list_del(&work->fp_entry);
				spin_unlock(&fp->f_lock);
				goto retry;
			} else if (!rc) {
				spin_lock(&work->conn->llist_lock);
+2 −3
Original line number Diff line number Diff line
@@ -364,12 +364,11 @@ static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp)

static void set_close_state_blocked_works(struct ksmbd_file *fp)
{
	struct ksmbd_work *cancel_work, *ctmp;
	struct ksmbd_work *cancel_work;

	spin_lock(&fp->f_lock);
	list_for_each_entry_safe(cancel_work, ctmp, &fp->blocked_works,
	list_for_each_entry(cancel_work, &fp->blocked_works,
				 fp_entry) {
		list_del(&cancel_work->fp_entry);
		cancel_work->state = KSMBD_WORK_CLOSED;
		cancel_work->cancel_fn(cancel_work->cancel_argv);
	}