2023-02-07 17:07 GMT+09:00, Hangyu Hua <hbh25y@xxxxxxxxx>: > 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") > Signed-off-by: Hangyu Hua <hbh25y@xxxxxxxxx> > --- > > v2: avoid NULL pointer dereference in set_close_state_blocked_works() > v3: avoid race condition between smb2_lock() and smb2_cancel() > > fs/ksmbd/smb2pdu.c | 23 ++++++++++++++--------- > fs/ksmbd/vfs_cache.c | 2 ++ > 2 files changed, 16 insertions(+), 9 deletions(-) > > diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c > index d681f91947d9..f4079518eaf6 100644 > --- a/fs/ksmbd/smb2pdu.c > +++ b/fs/ksmbd/smb2pdu.c > @@ -6644,7 +6644,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", > @@ -6666,7 +6666,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); > @@ -6685,18 +6687,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; > @@ -7050,6 +7046,7 @@ int smb2_lock(struct ksmbd_work *work) > smb2_remove_blocked_lock, > argv); > if (rc) { > + kfree(argv); > err = -ENOMEM; > goto out; > } > @@ -7061,6 +7058,10 @@ int smb2_lock(struct ksmbd_work *work) > > ksmbd_vfs_posix_lock_wait(flock); > > + spin_lock(&work->conn->request_lock); > + list_del_init(&work->async_request_entry); It is called again in ksmbd_conn_try_dequeue_request(). > + spin_unlock(&work->conn->request_lock); > +