mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
ksmbd: fix possible memory leak in smb2_lock()
[ Upstream commitd3ca9f7aeb] argv needs to be free when setup_async_work fails or when the current process is woken up. Fixes:e2f34481b2("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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d625db885a
commit
bfe8372ef2
@@ -6676,7 +6676,7 @@ int smb2_cancel(struct ksmbd_work *work)
|
|||||||
struct ksmbd_conn *conn = work->conn;
|
struct ksmbd_conn *conn = work->conn;
|
||||||
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
|
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
|
||||||
struct smb2_hdr *chdr;
|
struct smb2_hdr *chdr;
|
||||||
struct ksmbd_work *cancel_work = NULL, *iter;
|
struct ksmbd_work *iter;
|
||||||
struct list_head *command_list;
|
struct list_head *command_list;
|
||||||
|
|
||||||
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
|
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
|
||||||
@@ -6698,7 +6698,9 @@ int smb2_cancel(struct ksmbd_work *work)
|
|||||||
"smb2 with AsyncId %llu cancelled command = 0x%x\n",
|
"smb2 with AsyncId %llu cancelled command = 0x%x\n",
|
||||||
le64_to_cpu(hdr->Id.AsyncId),
|
le64_to_cpu(hdr->Id.AsyncId),
|
||||||
le16_to_cpu(chdr->Command));
|
le16_to_cpu(chdr->Command));
|
||||||
cancel_work = iter;
|
iter->state = KSMBD_WORK_CANCELLED;
|
||||||
|
if (iter->cancel_fn)
|
||||||
|
iter->cancel_fn(iter->cancel_argv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
spin_unlock(&conn->request_lock);
|
spin_unlock(&conn->request_lock);
|
||||||
@@ -6717,18 +6719,12 @@ int smb2_cancel(struct ksmbd_work *work)
|
|||||||
"smb2 with mid %llu cancelled command = 0x%x\n",
|
"smb2 with mid %llu cancelled command = 0x%x\n",
|
||||||
le64_to_cpu(hdr->MessageId),
|
le64_to_cpu(hdr->MessageId),
|
||||||
le16_to_cpu(chdr->Command));
|
le16_to_cpu(chdr->Command));
|
||||||
cancel_work = iter;
|
iter->state = KSMBD_WORK_CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
spin_unlock(&conn->request_lock);
|
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*/
|
/* For SMB2_CANCEL command itself send no response*/
|
||||||
work->send_no_response = 1;
|
work->send_no_response = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -7094,6 +7090,14 @@ skip:
|
|||||||
|
|
||||||
ksmbd_vfs_posix_lock_wait(flock);
|
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) {
|
if (work->state != KSMBD_WORK_ACTIVE) {
|
||||||
list_del(&smb_lock->llist);
|
list_del(&smb_lock->llist);
|
||||||
spin_lock(&work->conn->llist_lock);
|
spin_lock(&work->conn->llist_lock);
|
||||||
@@ -7102,9 +7106,6 @@ skip:
|
|||||||
locks_free_lock(flock);
|
locks_free_lock(flock);
|
||||||
|
|
||||||
if (work->state == KSMBD_WORK_CANCELLED) {
|
if (work->state == KSMBD_WORK_CANCELLED) {
|
||||||
spin_lock(&fp->f_lock);
|
|
||||||
list_del(&work->fp_entry);
|
|
||||||
spin_unlock(&fp->f_lock);
|
|
||||||
rsp->hdr.Status =
|
rsp->hdr.Status =
|
||||||
STATUS_CANCELLED;
|
STATUS_CANCELLED;
|
||||||
kfree(smb_lock);
|
kfree(smb_lock);
|
||||||
@@ -7126,9 +7127,6 @@ skip:
|
|||||||
list_del(&smb_lock->clist);
|
list_del(&smb_lock->clist);
|
||||||
spin_unlock(&work->conn->llist_lock);
|
spin_unlock(&work->conn->llist_lock);
|
||||||
|
|
||||||
spin_lock(&fp->f_lock);
|
|
||||||
list_del(&work->fp_entry);
|
|
||||||
spin_unlock(&fp->f_lock);
|
|
||||||
goto retry;
|
goto retry;
|
||||||
} else if (!rc) {
|
} else if (!rc) {
|
||||||
spin_lock(&work->conn->llist_lock);
|
spin_lock(&work->conn->llist_lock);
|
||||||
|
|||||||
@@ -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)
|
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);
|
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) {
|
fp_entry) {
|
||||||
list_del(&cancel_work->fp_entry);
|
|
||||||
cancel_work->state = KSMBD_WORK_CLOSED;
|
cancel_work->state = KSMBD_WORK_CLOSED;
|
||||||
cancel_work->cancel_fn(cancel_work->cancel_argv);
|
cancel_work->cancel_fn(cancel_work->cancel_argv);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user