mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ksmbd: fix wrong interim response on compound
If smb2_lock or smb2_open request is compound, ksmbd could send wrong interim response to client. ksmbd allocate new interim buffer instead of using resonse buffer to support compound request. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
e2b76ab8b5
commit
041bba4414
4 changed files with 26 additions and 26 deletions
|
@ -160,9 +160,11 @@ int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
|
||||||
return __ksmbd_iov_pin_rsp(work, ib, len, aux_buf, aux_size);
|
return __ksmbd_iov_pin_rsp(work, ib, len, aux_buf, aux_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksmbd_iov_reset(struct ksmbd_work *work)
|
int allocate_interim_rsp_buf(struct ksmbd_work *work)
|
||||||
{
|
{
|
||||||
work->iov_idx = 0;
|
work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
|
||||||
work->iov_cnt = 0;
|
if (!work->response_buf)
|
||||||
*(__be32 *)work->iov[0].iov_base = 0;
|
return -ENOMEM;
|
||||||
|
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,5 +131,5 @@ bool ksmbd_queue_work(struct ksmbd_work *work);
|
||||||
int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
|
int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
|
||||||
void *aux_buf, unsigned int aux_size);
|
void *aux_buf, unsigned int aux_size);
|
||||||
int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len);
|
int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len);
|
||||||
void ksmbd_iov_reset(struct ksmbd_work *work);
|
int allocate_interim_rsp_buf(struct ksmbd_work *work);
|
||||||
#endif /* __KSMBD_WORK_H__ */
|
#endif /* __KSMBD_WORK_H__ */
|
||||||
|
|
|
@ -616,15 +616,6 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int allocate_oplock_break_buf(struct ksmbd_work *work)
|
|
||||||
{
|
|
||||||
work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
|
|
||||||
if (!work->response_buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
|
* __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
|
||||||
* to client
|
* to client
|
||||||
|
@ -647,7 +638,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
|
||||||
if (!fp)
|
if (!fp)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (allocate_oplock_break_buf(work)) {
|
if (allocate_interim_rsp_buf(work)) {
|
||||||
pr_err("smb2_allocate_rsp_buf failed! ");
|
pr_err("smb2_allocate_rsp_buf failed! ");
|
||||||
ksmbd_fd_put(work, fp);
|
ksmbd_fd_put(work, fp);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -752,7 +743,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
|
||||||
struct lease_break_info *br_info = work->request_buf;
|
struct lease_break_info *br_info = work->request_buf;
|
||||||
struct smb2_hdr *rsp_hdr;
|
struct smb2_hdr *rsp_hdr;
|
||||||
|
|
||||||
if (allocate_oplock_break_buf(work)) {
|
if (allocate_interim_rsp_buf(work)) {
|
||||||
ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
|
ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -843,7 +834,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
|
||||||
setup_async_work(in_work, NULL, NULL);
|
setup_async_work(in_work, NULL, NULL);
|
||||||
smb2_send_interim_resp(in_work, STATUS_PENDING);
|
smb2_send_interim_resp(in_work, STATUS_PENDING);
|
||||||
list_del(&in_work->interim_entry);
|
list_del(&in_work->interim_entry);
|
||||||
ksmbd_iov_reset(in_work);
|
|
||||||
}
|
}
|
||||||
INIT_WORK(&work->work, __smb2_lease_break_noti);
|
INIT_WORK(&work->work, __smb2_lease_break_noti);
|
||||||
ksmbd_queue_work(work);
|
ksmbd_queue_work(work);
|
||||||
|
|
|
@ -153,8 +153,8 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
|
||||||
err_rsp->ByteCount = 0;
|
err_rsp->ByteCount = 0;
|
||||||
err_rsp->ErrorData[0] = 0;
|
err_rsp->ErrorData[0] = 0;
|
||||||
err = ksmbd_iov_pin_rsp(work, (void *)err_rsp,
|
err = ksmbd_iov_pin_rsp(work, (void *)err_rsp,
|
||||||
work->conn->vals->header_size +
|
__SMB2_HEADER_STRUCTURE_SIZE +
|
||||||
SMB2_ERROR_STRUCTURE_SIZE2);
|
SMB2_ERROR_STRUCTURE_SIZE2);
|
||||||
if (err)
|
if (err)
|
||||||
work->send_no_response = 1;
|
work->send_no_response = 1;
|
||||||
}
|
}
|
||||||
|
@ -709,13 +709,24 @@ 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 smb2_hdr *rsp_hdr;
|
struct smb2_hdr *rsp_hdr;
|
||||||
|
struct ksmbd_work *in_work = ksmbd_alloc_work_struct();
|
||||||
|
|
||||||
rsp_hdr = ksmbd_resp_buf_next(work);
|
if (allocate_interim_rsp_buf(in_work)) {
|
||||||
smb2_set_err_rsp(work);
|
pr_err("smb_allocate_rsp_buf failed!\n");
|
||||||
|
ksmbd_free_work_struct(in_work);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_work->conn = work->conn;
|
||||||
|
memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
|
||||||
|
__SMB2_HEADER_STRUCTURE_SIZE);
|
||||||
|
|
||||||
|
rsp_hdr = smb2_get_msg(in_work->response_buf);
|
||||||
|
smb2_set_err_rsp(in_work);
|
||||||
rsp_hdr->Status = status;
|
rsp_hdr->Status = status;
|
||||||
|
|
||||||
ksmbd_conn_write(work);
|
ksmbd_conn_write(in_work);
|
||||||
rsp_hdr->Status = 0;
|
ksmbd_free_work_struct(in_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
|
static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
|
||||||
|
@ -7049,8 +7060,6 @@ skip:
|
||||||
list_del(&work->fp_entry);
|
list_del(&work->fp_entry);
|
||||||
spin_unlock(&fp->f_lock);
|
spin_unlock(&fp->f_lock);
|
||||||
|
|
||||||
ksmbd_iov_reset(work);
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -7068,7 +7077,6 @@ skip:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_smb2_rsp_hdr(work);
|
|
||||||
rsp->hdr.Status =
|
rsp->hdr.Status =
|
||||||
STATUS_RANGE_NOT_LOCKED;
|
STATUS_RANGE_NOT_LOCKED;
|
||||||
kfree(smb_lock);
|
kfree(smb_lock);
|
||||||
|
|
Loading…
Add table
Reference in a new issue