Skip to content

Commit

Permalink
ksmbd: fix wrong smbd max read/write size check
Browse files Browse the repository at this point in the history
smb-direct max read/write size can be different with smb2 max read/write
size. So smb2_read() can return error by wrong max read/write size check.
This patch use smb_direct_max_read_write_size for this check in
smb-direct read/write().

Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
namjaejeon committed May 16, 2022
1 parent 9c1234b commit cdd2c68
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 14 deletions.
39 changes: 25 additions & 14 deletions smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -6269,6 +6269,8 @@ int smb2_read(struct ksmbd_work *work)
size_t length, mincount;
ssize_t nbytes = 0, remain_bytes = 0;
int err = 0;
bool is_rdma_channel = false;
unsigned int max_read_size = conn->vals->max_read_size;

WORK_BUFFERS(work, req, rsp);

Expand All @@ -6280,6 +6282,11 @@ int smb2_read(struct ksmbd_work *work)

if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
is_rdma_channel = true;
max_read_size = get_smbd_max_read_write_size();
}

if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);

if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
Expand Down Expand Up @@ -6311,9 +6318,9 @@ int smb2_read(struct ksmbd_work *work)
length = le32_to_cpu(req->Length);
mincount = le32_to_cpu(req->MinimumCount);

if (length > conn->vals->max_read_size) {
if (length > max_read_size) {
ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
conn->vals->max_read_size);
max_read_size);
err = -EINVAL;
goto out;
}
Expand Down Expand Up @@ -6345,8 +6352,7 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
nbytes, offset, mincount);

if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
if (is_rdma_channel == true) {
/* write data to the client using rdma channel */
remain_bytes = smb2_read_rdma_channel(work, req,
work->aux_payload_buf,
Expand Down Expand Up @@ -6507,8 +6513,9 @@ int smb2_write(struct ksmbd_work *work)
size_t length;
ssize_t nbytes;
char *data_buf;
bool writethrough = false;
bool writethrough = false, is_rdma_channel = false;
int err = 0;
unsigned int max_write_size = work->conn->vals->max_write_size;

WORK_BUFFERS(work, req, rsp);

Expand All @@ -6517,8 +6524,17 @@ int smb2_write(struct ksmbd_work *work)
return smb2_write_pipe(work);
}

offset = le64_to_cpu(req->Offset);
length = le32_to_cpu(req->Length);

if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
is_rdma_channel = true;
max_write_size = get_smbd_max_read_write_size();
length = le32_to_cpu(req->RemainingBytes);
}

if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);

if (req->Length != 0 || req->DataOffset != 0 ||
Expand Down Expand Up @@ -6553,21 +6569,17 @@ int smb2_write(struct ksmbd_work *work)
goto out;
}

offset = le64_to_cpu(req->Offset);
length = le32_to_cpu(req->Length);

if (length > work->conn->vals->max_write_size) {
if (length > max_write_size) {
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
work->conn->vals->max_write_size);
max_write_size);
err = -EINVAL;
goto out;
}

if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;

if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
if (is_rdma_channel == false) {
if ((u64)le16_to_cpu(req->DataOffset) + length >
get_rfc1002_len(work->request_buf)) {
pr_err("invalid write data offset %u, smb_len %u\n",
Expand All @@ -6593,8 +6605,7 @@ int smb2_write(struct ksmbd_work *work)
/* read data from the client using rdma channel, and
* write the data.
*/
nbytes = smb2_write_rdma_channel(work, req, fp, offset,
le32_to_cpu(req->RemainingBytes),
nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
writethrough);
if (nbytes < 0) {
err = (int)nbytes;
Expand Down
5 changes: 5 additions & 0 deletions transport_rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
smb_direct_max_read_write_size = sz;
}

unsigned int get_smbd_max_read_write_size(void)
{
return smb_direct_max_read_write_size;
}

static inline int get_buf_page_count(void *buf, int size)
{
return (int)(DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
Expand Down
2 changes: 2 additions & 0 deletions transport_rdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
void ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
void init_smbd_max_io_size(unsigned int sz);
unsigned int get_smbd_max_read_write_size(void);
#else
static inline int ksmbd_rdma_init(void) { return 0; }
static inline int ksmbd_rdma_destroy(void) { return 0; }
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
static inline void init_smbd_max_io_size(unsigned int sz) { }
static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
#endif

#endif /* __KSMBD_TRANSPORT_RDMA_H__ */

0 comments on commit cdd2c68

Please sign in to comment.