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 <linkinjeon@kernel.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
65bb45b97b
commit
7a84399e1c
@ -6183,6 +6183,8 @@ int smb2_read(struct ksmbd_work *work)
|
|||||||
size_t length, mincount;
|
size_t length, mincount;
|
||||||
ssize_t nbytes = 0, remain_bytes = 0;
|
ssize_t nbytes = 0, remain_bytes = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
bool is_rdma_channel = false;
|
||||||
|
unsigned int max_read_size = conn->vals->max_read_size;
|
||||||
|
|
||||||
WORK_BUFFERS(work, req, rsp);
|
WORK_BUFFERS(work, req, rsp);
|
||||||
|
|
||||||
@ -6194,6 +6196,11 @@ int smb2_read(struct ksmbd_work *work)
|
|||||||
|
|
||||||
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
|
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
|
||||||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
|
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);
|
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
|
||||||
|
|
||||||
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
|
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
|
||||||
@ -6225,9 +6232,9 @@ int smb2_read(struct ksmbd_work *work)
|
|||||||
length = le32_to_cpu(req->Length);
|
length = le32_to_cpu(req->Length);
|
||||||
mincount = le32_to_cpu(req->MinimumCount);
|
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",
|
ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
|
||||||
conn->vals->max_read_size);
|
max_read_size);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -6259,8 +6266,7 @@ int smb2_read(struct ksmbd_work *work)
|
|||||||
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
|
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
|
||||||
nbytes, offset, mincount);
|
nbytes, offset, mincount);
|
||||||
|
|
||||||
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
|
if (is_rdma_channel == true) {
|
||||||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
|
|
||||||
/* write data to the client using rdma channel */
|
/* write data to the client using rdma channel */
|
||||||
remain_bytes = smb2_read_rdma_channel(work, req,
|
remain_bytes = smb2_read_rdma_channel(work, req,
|
||||||
work->aux_payload_buf,
|
work->aux_payload_buf,
|
||||||
@ -6421,8 +6427,9 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
size_t length;
|
size_t length;
|
||||||
ssize_t nbytes;
|
ssize_t nbytes;
|
||||||
char *data_buf;
|
char *data_buf;
|
||||||
bool writethrough = false;
|
bool writethrough = false, is_rdma_channel = false;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
unsigned int max_write_size = work->conn->vals->max_write_size;
|
||||||
|
|
||||||
WORK_BUFFERS(work, req, rsp);
|
WORK_BUFFERS(work, req, rsp);
|
||||||
|
|
||||||
@ -6431,8 +6438,17 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
return smb2_write_pipe(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 ||
|
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
|
||||||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
|
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);
|
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
|
||||||
|
|
||||||
if (req->Length != 0 || req->DataOffset != 0 ||
|
if (req->Length != 0 || req->DataOffset != 0 ||
|
||||||
@ -6467,12 +6483,9 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = le64_to_cpu(req->Offset);
|
if (length > max_write_size) {
|
||||||
length = le32_to_cpu(req->Length);
|
|
||||||
|
|
||||||
if (length > work->conn->vals->max_write_size) {
|
|
||||||
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
|
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
|
||||||
work->conn->vals->max_write_size);
|
max_write_size);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -6480,8 +6493,7 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
|
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
|
||||||
writethrough = true;
|
writethrough = true;
|
||||||
|
|
||||||
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
|
if (is_rdma_channel == false) {
|
||||||
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
|
|
||||||
if ((u64)le16_to_cpu(req->DataOffset) + length >
|
if ((u64)le16_to_cpu(req->DataOffset) + length >
|
||||||
get_rfc1002_len(work->request_buf)) {
|
get_rfc1002_len(work->request_buf)) {
|
||||||
pr_err("invalid write data offset %u, smb_len %u\n",
|
pr_err("invalid write data offset %u, smb_len %u\n",
|
||||||
@ -6507,8 +6519,7 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
/* read data from the client using rdma channel, and
|
/* read data from the client using rdma channel, and
|
||||||
* write the data.
|
* write the data.
|
||||||
*/
|
*/
|
||||||
nbytes = smb2_write_rdma_channel(work, req, fp, offset,
|
nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
|
||||||
le32_to_cpu(req->RemainingBytes),
|
|
||||||
writethrough);
|
writethrough);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
err = (int)nbytes;
|
err = (int)nbytes;
|
||||||
|
@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
|
|||||||
smb_direct_max_read_write_size = 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)
|
static inline int get_buf_page_count(void *buf, int size)
|
||||||
{
|
{
|
||||||
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
|
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
|
||||||
|
@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
|
|||||||
void ksmbd_rdma_destroy(void);
|
void ksmbd_rdma_destroy(void);
|
||||||
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
|
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
|
||||||
void init_smbd_max_io_size(unsigned int sz);
|
void init_smbd_max_io_size(unsigned int sz);
|
||||||
|
unsigned int get_smbd_max_read_write_size(void);
|
||||||
#else
|
#else
|
||||||
static inline int ksmbd_rdma_init(void) { return 0; }
|
static inline int ksmbd_rdma_init(void) { return 0; }
|
||||||
static inline int ksmbd_rdma_destroy(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 bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
|
||||||
static inline void init_smbd_max_io_size(unsigned int sz) { }
|
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
|
||||||
|
|
||||||
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
|
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user