Skip to content

Commit 7a84399

Browse files
namjaejeonsmfrench
authored andcommitted
ksmbd: fix wrong smbd max read/write size check
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]> Reviewed-by: Hyunchul Lee <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 65bb45b commit 7a84399

File tree

3 files changed

+32
-14
lines changed

3 files changed

+32
-14
lines changed

fs/ksmbd/smb2pdu.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6183,6 +6183,8 @@ int smb2_read(struct ksmbd_work *work)
61836183
size_t length, mincount;
61846184
ssize_t nbytes = 0, remain_bytes = 0;
61856185
int err = 0;
6186+
bool is_rdma_channel = false;
6187+
unsigned int max_read_size = conn->vals->max_read_size;
61866188

61876189
WORK_BUFFERS(work, req, rsp);
61886190

@@ -6194,6 +6196,11 @@ int smb2_read(struct ksmbd_work *work)
61946196

61956197
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
61966198
req->Channel == SMB2_CHANNEL_RDMA_V1) {
6199+
is_rdma_channel = true;
6200+
max_read_size = get_smbd_max_read_write_size();
6201+
}
6202+
6203+
if (is_rdma_channel == true) {
61976204
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
61986205

61996206
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
@@ -6225,9 +6232,9 @@ int smb2_read(struct ksmbd_work *work)
62256232
length = le32_to_cpu(req->Length);
62266233
mincount = le32_to_cpu(req->MinimumCount);
62276234

6228-
if (length > conn->vals->max_read_size) {
6235+
if (length > max_read_size) {
62296236
ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
6230-
conn->vals->max_read_size);
6237+
max_read_size);
62316238
err = -EINVAL;
62326239
goto out;
62336240
}
@@ -6259,8 +6266,7 @@ int smb2_read(struct ksmbd_work *work)
62596266
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
62606267
nbytes, offset, mincount);
62616268

6262-
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
6263-
req->Channel == SMB2_CHANNEL_RDMA_V1) {
6269+
if (is_rdma_channel == true) {
62646270
/* write data to the client using rdma channel */
62656271
remain_bytes = smb2_read_rdma_channel(work, req,
62666272
work->aux_payload_buf,
@@ -6421,8 +6427,9 @@ int smb2_write(struct ksmbd_work *work)
64216427
size_t length;
64226428
ssize_t nbytes;
64236429
char *data_buf;
6424-
bool writethrough = false;
6430+
bool writethrough = false, is_rdma_channel = false;
64256431
int err = 0;
6432+
unsigned int max_write_size = work->conn->vals->max_write_size;
64266433

64276434
WORK_BUFFERS(work, req, rsp);
64286435

@@ -6431,8 +6438,17 @@ int smb2_write(struct ksmbd_work *work)
64316438
return smb2_write_pipe(work);
64326439
}
64336440

6441+
offset = le64_to_cpu(req->Offset);
6442+
length = le32_to_cpu(req->Length);
6443+
64346444
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
64356445
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
6446+
is_rdma_channel = true;
6447+
max_write_size = get_smbd_max_read_write_size();
6448+
length = le32_to_cpu(req->RemainingBytes);
6449+
}
6450+
6451+
if (is_rdma_channel == true) {
64366452
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
64376453

64386454
if (req->Length != 0 || req->DataOffset != 0 ||
@@ -6467,21 +6483,17 @@ int smb2_write(struct ksmbd_work *work)
64676483
goto out;
64686484
}
64696485

6470-
offset = le64_to_cpu(req->Offset);
6471-
length = le32_to_cpu(req->Length);
6472-
6473-
if (length > work->conn->vals->max_write_size) {
6486+
if (length > max_write_size) {
64746487
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
6475-
work->conn->vals->max_write_size);
6488+
max_write_size);
64766489
err = -EINVAL;
64776490
goto out;
64786491
}
64796492

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

6483-
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
6484-
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
6496+
if (is_rdma_channel == false) {
64856497
if ((u64)le16_to_cpu(req->DataOffset) + length >
64866498
get_rfc1002_len(work->request_buf)) {
64876499
pr_err("invalid write data offset %u, smb_len %u\n",
@@ -6507,8 +6519,7 @@ int smb2_write(struct ksmbd_work *work)
65076519
/* read data from the client using rdma channel, and
65086520
* write the data.
65096521
*/
6510-
nbytes = smb2_write_rdma_channel(work, req, fp, offset,
6511-
le32_to_cpu(req->RemainingBytes),
6522+
nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
65126523
writethrough);
65136524
if (nbytes < 0) {
65146525
err = (int)nbytes;

fs/ksmbd/transport_rdma.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
220220
smb_direct_max_read_write_size = sz;
221221
}
222222

223+
unsigned int get_smbd_max_read_write_size(void)
224+
{
225+
return smb_direct_max_read_write_size;
226+
}
227+
223228
static inline int get_buf_page_count(void *buf, int size)
224229
{
225230
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -

fs/ksmbd/transport_rdma.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
5757
void ksmbd_rdma_destroy(void);
5858
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
5959
void init_smbd_max_io_size(unsigned int sz);
60+
unsigned int get_smbd_max_read_write_size(void);
6061
#else
6162
static inline int ksmbd_rdma_init(void) { return 0; }
6263
static inline int ksmbd_rdma_destroy(void) { return 0; }
6364
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
6465
static inline void init_smbd_max_io_size(unsigned int sz) { }
66+
static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
6567
#endif
6668

6769
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */

0 commit comments

Comments
 (0)