aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorHangyu Hua2023-02-17 22:29:34 +0900
committerGreg Kroah-Hartman2023-03-10 09:34:07 +0100
commit6bf555ed8938444466c3d7f3252eb874a518f293 (patch)
tree86997493a87b125cbe2a12f411078efb526798b1 /fs
parentdf6c263a31a4dcdf2c48e0e8d3158fd406151e48 (diff)
ksmbd: fix possible memory leak in smb2_lock()
commit d3ca9f7aeba793d74361d88a8800b2f205c9236b upstream. argv needs to be free when setup_async_work fails or when the current process is woken up. Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") Cc: stable@vger.kernel.org Signed-off-by: Hangyu Hua <hbh25y@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ksmbd/smb2pdu.c28
-rw-r--r--fs/ksmbd/vfs_cache.c5
2 files changed, 15 insertions, 18 deletions
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 9b16ee657b51..0f0f1243a9cb 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6642,7 +6642,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",
@@ -6664,7 +6664,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);
@@ -6683,18 +6685,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;
@@ -7055,6 +7051,14 @@ skip:
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);
@@ -7063,9 +7067,6 @@ skip:
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);
@@ -7087,9 +7088,6 @@ skip:
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);
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index da9163b00350..0ae5dd0829e9 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -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);
}