ksmbd: delete asynchronous work from list

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>
This commit is contained in:
Namjae Jeon 2023-03-31 08:42:12 +09:00 committed by Steve French
parent 2824861773
commit 3a9b557f44
4 changed files with 28 additions and 20 deletions

View File

@ -112,10 +112,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
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;
work->synchronous = true;
}
if (requests_queue) {
atomic_inc(&conn->req_running);
@ -136,14 +134,14 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
if (!work->multiRsp)
atomic_dec(&conn->req_running);
spin_lock(&conn->request_lock);
if (!work->multiRsp) {
spin_lock(&conn->request_lock);
list_del_init(&work->request_entry);
if (!work->synchronous)
list_del_init(&work->async_request_entry);
spin_unlock(&conn->request_lock);
if (work->asynchronous)
release_async_work(work);
ret = 0;
}
spin_unlock(&conn->request_lock);
wake_up_all(&conn->req_running_q);
return ret;

View File

@ -68,7 +68,7 @@ struct ksmbd_work {
/* Request is encrypted */
bool encrypted:1;
/* Is this SYNC or ASYNC ksmbd_work */
bool synchronous:1;
bool asynchronous:1;
bool need_invalidate_rkey:1;
unsigned int remote_key;

View File

@ -498,12 +498,6 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
rsp_hdr->SessionId = rcv_hdr->SessionId;
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;
}
@ -644,7 +638,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
pr_err("Failed to alloc async message id\n");
return id;
}
work->synchronous = false;
work->asynchronous = true;
work->async_id = id;
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
@ -664,6 +658,24 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
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)
{
struct smb2_hdr *rsp_hdr;
@ -7045,13 +7057,9 @@ 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);
@ -7069,6 +7077,7 @@ skip:
work->send_no_response = 1;
goto out;
}
init_smb2_rsp_hdr(work);
smb2_set_err_rsp(work);
rsp->hdr.Status =
@ -7081,7 +7090,7 @@ skip:
spin_lock(&work->conn->llist_lock);
list_del(&smb_lock->clist);
spin_unlock(&work->conn->llist_lock);
release_async_work(work);
goto retry;
} else if (!rc) {
spin_lock(&work->conn->llist_lock);

View File

@ -486,6 +486,7 @@ int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
struct file_lock *smb_flock_init(struct file *f);
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
void **arg);
void release_async_work(struct ksmbd_work *work);
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
struct channel *lookup_chann_list(struct ksmbd_session *sess,
struct ksmbd_conn *conn);