mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
ksmbd: delete asynchronous work from list
[ Upstream commit 3a9b557f44 ]
When smb2_lock request is canceled by smb2_cancel or smb2_close(),
ksmbd is missing deleting async_request_entry async_requests list.
Because calling init_smb2_rsp_hdr() in smb2_lock() mark ->synchronous
as true and then it will not be deleted in
ksmbd_conn_try_dequeue_request(). This patch add release_async_work() to
release the ones allocated for async work.
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
4ef3fd2f85
commit
8d271ef5e5
@@ -114,10 +114,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
|
|||||||
struct ksmbd_conn *conn = work->conn;
|
struct ksmbd_conn *conn = work->conn;
|
||||||
struct list_head *requests_queue = NULL;
|
struct list_head *requests_queue = NULL;
|
||||||
|
|
||||||
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
|
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)
|
||||||
requests_queue = &conn->requests;
|
requests_queue = &conn->requests;
|
||||||
work->synchronous = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requests_queue) {
|
if (requests_queue) {
|
||||||
atomic_inc(&conn->req_running);
|
atomic_inc(&conn->req_running);
|
||||||
@@ -138,14 +136,14 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
|
|||||||
|
|
||||||
if (!work->multiRsp)
|
if (!work->multiRsp)
|
||||||
atomic_dec(&conn->req_running);
|
atomic_dec(&conn->req_running);
|
||||||
spin_lock(&conn->request_lock);
|
|
||||||
if (!work->multiRsp) {
|
if (!work->multiRsp) {
|
||||||
|
spin_lock(&conn->request_lock);
|
||||||
list_del_init(&work->request_entry);
|
list_del_init(&work->request_entry);
|
||||||
if (!work->synchronous)
|
spin_unlock(&conn->request_lock);
|
||||||
list_del_init(&work->async_request_entry);
|
if (work->asynchronous)
|
||||||
|
release_async_work(work);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
spin_unlock(&conn->request_lock);
|
|
||||||
|
|
||||||
wake_up_all(&conn->req_running_q);
|
wake_up_all(&conn->req_running_q);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ struct ksmbd_work {
|
|||||||
/* Request is encrypted */
|
/* Request is encrypted */
|
||||||
bool encrypted:1;
|
bool encrypted:1;
|
||||||
/* Is this SYNC or ASYNC ksmbd_work */
|
/* Is this SYNC or ASYNC ksmbd_work */
|
||||||
bool synchronous:1;
|
bool asynchronous:1;
|
||||||
bool need_invalidate_rkey:1;
|
bool need_invalidate_rkey:1;
|
||||||
|
|
||||||
unsigned int remote_key;
|
unsigned int remote_key;
|
||||||
|
|||||||
@@ -508,12 +508,6 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
|
|||||||
rsp_hdr->SessionId = rcv_hdr->SessionId;
|
rsp_hdr->SessionId = rcv_hdr->SessionId;
|
||||||
memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
|
memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
|
||||||
|
|
||||||
work->synchronous = true;
|
|
||||||
if (work->async_id) {
|
|
||||||
ksmbd_release_id(&conn->async_ida, work->async_id);
|
|
||||||
work->async_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +665,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
|
|||||||
pr_err("Failed to alloc async message id\n");
|
pr_err("Failed to alloc async message id\n");
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
work->synchronous = false;
|
work->asynchronous = true;
|
||||||
work->async_id = id;
|
work->async_id = id;
|
||||||
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
|
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
|
||||||
|
|
||||||
@@ -691,6 +685,24 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void release_async_work(struct ksmbd_work *work)
|
||||||
|
{
|
||||||
|
struct ksmbd_conn *conn = work->conn;
|
||||||
|
|
||||||
|
spin_lock(&conn->request_lock);
|
||||||
|
list_del_init(&work->async_request_entry);
|
||||||
|
spin_unlock(&conn->request_lock);
|
||||||
|
|
||||||
|
work->asynchronous = 0;
|
||||||
|
work->cancel_fn = NULL;
|
||||||
|
kfree(work->cancel_argv);
|
||||||
|
work->cancel_argv = NULL;
|
||||||
|
if (work->async_id) {
|
||||||
|
ksmbd_release_id(&conn->async_ida, work->async_id);
|
||||||
|
work->async_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
|
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
|
||||||
{
|
{
|
||||||
struct smb2_hdr *rsp_hdr;
|
struct smb2_hdr *rsp_hdr;
|
||||||
@@ -7153,13 +7165,9 @@ skip:
|
|||||||
|
|
||||||
ksmbd_vfs_posix_lock_wait(flock);
|
ksmbd_vfs_posix_lock_wait(flock);
|
||||||
|
|
||||||
spin_lock(&work->conn->request_lock);
|
|
||||||
spin_lock(&fp->f_lock);
|
spin_lock(&fp->f_lock);
|
||||||
list_del(&work->fp_entry);
|
list_del(&work->fp_entry);
|
||||||
work->cancel_fn = NULL;
|
|
||||||
kfree(argv);
|
|
||||||
spin_unlock(&fp->f_lock);
|
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);
|
||||||
@@ -7177,6 +7185,7 @@ skip:
|
|||||||
work->send_no_response = 1;
|
work->send_no_response = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_smb2_rsp_hdr(work);
|
init_smb2_rsp_hdr(work);
|
||||||
smb2_set_err_rsp(work);
|
smb2_set_err_rsp(work);
|
||||||
rsp->hdr.Status =
|
rsp->hdr.Status =
|
||||||
@@ -7189,7 +7198,7 @@ skip:
|
|||||||
spin_lock(&work->conn->llist_lock);
|
spin_lock(&work->conn->llist_lock);
|
||||||
list_del(&smb_lock->clist);
|
list_del(&smb_lock->clist);
|
||||||
spin_unlock(&work->conn->llist_lock);
|
spin_unlock(&work->conn->llist_lock);
|
||||||
|
release_async_work(work);
|
||||||
goto retry;
|
goto retry;
|
||||||
} else if (!rc) {
|
} else if (!rc) {
|
||||||
spin_lock(&work->conn->llist_lock);
|
spin_lock(&work->conn->llist_lock);
|
||||||
|
|||||||
@@ -488,6 +488,7 @@ int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
|
|||||||
struct file_lock *smb_flock_init(struct file *f);
|
struct file_lock *smb_flock_init(struct file *f);
|
||||||
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
|
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
|
||||||
void **arg);
|
void **arg);
|
||||||
|
void release_async_work(struct ksmbd_work *work);
|
||||||
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
|
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
|
||||||
struct channel *lookup_chann_list(struct ksmbd_session *sess,
|
struct channel *lookup_chann_list(struct ksmbd_session *sess,
|
||||||
struct ksmbd_conn *conn);
|
struct ksmbd_conn *conn);
|
||||||
|
|||||||
Reference in New Issue
Block a user