Commit e5b02087 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.19-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server updates from Steve French:

 - rdma (smbdirect) fixes, cleanup and optimizations

 - crediting (flow control) fix for mounts from Windows client

 - ACL fix

 - Windows client query dir fix

 - write validation fix

 - cleanups

* tag '5.19-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: smbd: relax the count of sges required
  ksmbd: fix outstanding credits related bugs
  ksmbd: smbd: fix connection dropped issue
  ksmbd: Fix some kernel-doc comments
  ksmbd: fix wrong smbd max read/write size check
  ksmbd: add smbd max io size parameter
  ksmbd: handle smb2 query dir request for OutputBufferLength that is too small
  ksmbd: smbd: handle multiple Buffer descriptors
  ksmbd: smbd: change the return value of get_sg_list
  ksmbd: smbd: simplify tracking pending packets
  ksmbd: smbd: introduce read/write credits for RDMA read/write
  ksmbd: smbd: change prototypes of RDMA read/write related functions
  ksmbd: validate length in smb2_write()
  ksmbd: fix reference count leak in smb_check_perm_dacl()
parents 17eabd42 621433b7
...@@ -62,7 +62,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) ...@@ -62,7 +62,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
atomic_set(&conn->req_running, 0); atomic_set(&conn->req_running, 0);
atomic_set(&conn->r_count, 0); atomic_set(&conn->r_count, 0);
conn->total_credits = 1; conn->total_credits = 1;
conn->outstanding_credits = 1; conn->outstanding_credits = 0;
init_waitqueue_head(&conn->req_running_q); init_waitqueue_head(&conn->req_running_q);
INIT_LIST_HEAD(&conn->conns_list); INIT_LIST_HEAD(&conn->conns_list);
...@@ -205,31 +205,31 @@ int ksmbd_conn_write(struct ksmbd_work *work) ...@@ -205,31 +205,31 @@ int ksmbd_conn_write(struct ksmbd_work *work)
return 0; return 0;
} }
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf, int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
unsigned int buflen, u32 remote_key, u64 remote_offset, void *buf, unsigned int buflen,
u32 remote_len) struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len)
{ {
int ret = -EINVAL; int ret = -EINVAL;
if (conn->transport->ops->rdma_read) if (conn->transport->ops->rdma_read)
ret = conn->transport->ops->rdma_read(conn->transport, ret = conn->transport->ops->rdma_read(conn->transport,
buf, buflen, buf, buflen,
remote_key, remote_offset, desc, desc_len);
remote_len);
return ret; return ret;
} }
int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf, int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
unsigned int buflen, u32 remote_key, void *buf, unsigned int buflen,
u64 remote_offset, u32 remote_len) struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len)
{ {
int ret = -EINVAL; int ret = -EINVAL;
if (conn->transport->ops->rdma_write) if (conn->transport->ops->rdma_write)
ret = conn->transport->ops->rdma_write(conn->transport, ret = conn->transport->ops->rdma_write(conn->transport,
buf, buflen, buf, buflen,
remote_key, remote_offset, desc, desc_len);
remote_len);
return ret; return ret;
} }
......
...@@ -122,11 +122,14 @@ struct ksmbd_transport_ops { ...@@ -122,11 +122,14 @@ struct ksmbd_transport_ops {
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov, int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
int size, bool need_invalidate_rkey, int size, bool need_invalidate_rkey,
unsigned int remote_key); unsigned int remote_key);
int (*rdma_read)(struct ksmbd_transport *t, void *buf, unsigned int len, int (*rdma_read)(struct ksmbd_transport *t,
u32 remote_key, u64 remote_offset, u32 remote_len); void *buf, unsigned int len,
int (*rdma_write)(struct ksmbd_transport *t, void *buf, struct smb2_buffer_desc_v1 *desc,
unsigned int len, u32 remote_key, u64 remote_offset, unsigned int desc_len);
u32 remote_len); int (*rdma_write)(struct ksmbd_transport *t,
void *buf, unsigned int len,
struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len);
}; };
struct ksmbd_transport { struct ksmbd_transport {
...@@ -148,12 +151,14 @@ struct ksmbd_conn *ksmbd_conn_alloc(void); ...@@ -148,12 +151,14 @@ struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn); void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c); bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
int ksmbd_conn_write(struct ksmbd_work *work); int ksmbd_conn_write(struct ksmbd_work *work);
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf, int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
unsigned int buflen, u32 remote_key, u64 remote_offset, void *buf, unsigned int buflen,
u32 remote_len); struct smb2_buffer_desc_v1 *desc,
int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf, unsigned int desc_len);
unsigned int buflen, u32 remote_key, u64 remote_offset, int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
u32 remote_len); void *buf, unsigned int buflen,
struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len);
void ksmbd_conn_enqueue_request(struct ksmbd_work *work); void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work); int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops); void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
......
...@@ -104,7 +104,8 @@ struct ksmbd_startup_request { ...@@ -104,7 +104,8 @@ struct ksmbd_startup_request {
*/ */
__u32 sub_auth[3]; /* Subauth value for Security ID */ __u32 sub_auth[3]; /* Subauth value for Security ID */
__u32 smb2_max_credits; /* MAX credits */ __u32 smb2_max_credits; /* MAX credits */
__u32 reserved[128]; /* Reserved room */ __u32 smbd_max_io_size; /* smbd read write size */
__u32 reserved[127]; /* Reserved room */
__u32 ifc_list_sz; /* interfaces list size */ __u32 ifc_list_sz; /* interfaces list size */
__s8 ____payload[]; __s8 ____payload[];
}; };
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* wildcard '*' and '?' * wildcard '*' and '?'
* TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR * TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR
* *
* @string: string to compare with a pattern * @str: string to compare with a pattern
* @len: string length * @len: string length
* @pattern: pattern string which might include wildcard '*' and '?' * @pattern: pattern string which might include wildcard '*' and '?'
* *
...@@ -152,8 +152,8 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type) ...@@ -152,8 +152,8 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
/** /**
* convert_to_nt_pathname() - extract and return windows path string * convert_to_nt_pathname() - extract and return windows path string
* whose share directory prefix was removed from file path * whose share directory prefix was removed from file path
* @filename : unix filename * @share: ksmbd_share_config pointer
* @sharepath: share path string * @path: path to report
* *
* Return : windows path string or error * Return : windows path string or error
*/ */
...@@ -250,8 +250,8 @@ char *ksmbd_extract_sharename(char *treename) ...@@ -250,8 +250,8 @@ char *ksmbd_extract_sharename(char *treename)
/** /**
* convert_to_unix_name() - convert windows name to unix format * convert_to_unix_name() - convert windows name to unix format
* @path: name to be converted * @share: ksmbd_share_config pointer
* @tid: tree id of mathing share * @name: file name that is relative to share
* *
* Return: converted name on success, otherwise NULL * Return: converted name on success, otherwise NULL
*/ */
......
...@@ -338,7 +338,7 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn, ...@@ -338,7 +338,7 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
ret = 1; ret = 1;
} }
if ((u64)conn->outstanding_credits + credit_charge > conn->vals->max_credits) { if ((u64)conn->outstanding_credits + credit_charge > conn->total_credits) {
ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n", ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n",
credit_charge, conn->outstanding_credits); credit_charge, conn->outstanding_credits);
ret = 1; ret = 1;
......
...@@ -3938,6 +3938,12 @@ int smb2_query_dir(struct ksmbd_work *work) ...@@ -3938,6 +3938,12 @@ int smb2_query_dir(struct ksmbd_work *work)
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir); set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx); rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
/*
* req->OutputBufferLength is too small to contain even one entry.
* In this case, it immediately returns OutputBufferLength 0 to client.
*/
if (!d_info.out_buf_len && !d_info.num_entry)
goto no_buf_len;
if (rc == 0) if (rc == 0)
restart_ctx(&dir_fp->readdir_data.ctx); restart_ctx(&dir_fp->readdir_data.ctx);
if (rc == -ENOSPC) if (rc == -ENOSPC)
...@@ -3964,10 +3970,12 @@ int smb2_query_dir(struct ksmbd_work *work) ...@@ -3964,10 +3970,12 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->Buffer[0] = 0; rsp->Buffer[0] = 0;
inc_rfc1001_len(work->response_buf, 9); inc_rfc1001_len(work->response_buf, 9);
} else { } else {
no_buf_len:
((struct file_directory_info *) ((struct file_directory_info *)
((char *)rsp->Buffer + d_info.last_entry_offset)) ((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0; ->NextEntryOffset = 0;
d_info.data_count -= d_info.last_entry_off_align; if (d_info.data_count >= d_info.last_entry_off_align)
d_info.data_count -= d_info.last_entry_off_align;
rsp->StructureSize = cpu_to_le16(9); rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72); rsp->OutputBufferOffset = cpu_to_le16(72);
...@@ -6116,7 +6124,6 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work) ...@@ -6116,7 +6124,6 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work, static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
struct smb2_buffer_desc_v1 *desc, struct smb2_buffer_desc_v1 *desc,
__le32 Channel, __le32 Channel,
__le16 ChannelInfoOffset,
__le16 ChannelInfoLength) __le16 ChannelInfoLength)
{ {
unsigned int i, ch_count; unsigned int i, ch_count;
...@@ -6134,15 +6141,13 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work, ...@@ -6134,15 +6141,13 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
le32_to_cpu(desc[i].length)); le32_to_cpu(desc[i].length));
} }
} }
if (ch_count != 1) { if (!ch_count)
ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
ch_count);
return -EINVAL; return -EINVAL;
}
work->need_invalidate_rkey = work->need_invalidate_rkey =
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
work->remote_key = le32_to_cpu(desc->token); if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE)
work->remote_key = le32_to_cpu(desc->token);
return 0; return 0;
} }
...@@ -6150,14 +6155,12 @@ static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work, ...@@ -6150,14 +6155,12 @@ static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
struct smb2_read_req *req, void *data_buf, struct smb2_read_req *req, void *data_buf,
size_t length) size_t length)
{ {
struct smb2_buffer_desc_v1 *desc =
(struct smb2_buffer_desc_v1 *)&req->Buffer[0];
int err; int err;
err = ksmbd_conn_rdma_write(work->conn, data_buf, length, err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
le32_to_cpu(desc->token), (struct smb2_buffer_desc_v1 *)
le64_to_cpu(desc->offset), ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)),
le32_to_cpu(desc->length)); le16_to_cpu(req->ReadChannelInfoLength));
if (err) if (err)
return err; return err;
...@@ -6180,6 +6183,8 @@ int smb2_read(struct ksmbd_work *work) ...@@ -6180,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);
...@@ -6191,6 +6196,11 @@ int smb2_read(struct ksmbd_work *work) ...@@ -6191,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)) {
...@@ -6201,7 +6211,6 @@ int smb2_read(struct ksmbd_work *work) ...@@ -6201,7 +6211,6 @@ int smb2_read(struct ksmbd_work *work)
(struct smb2_buffer_desc_v1 *) (struct smb2_buffer_desc_v1 *)
((char *)req + ch_offset), ((char *)req + ch_offset),
req->Channel, req->Channel,
req->ReadChannelInfoOffset,
req->ReadChannelInfoLength); req->ReadChannelInfoLength);
if (err) if (err)
goto out; goto out;
...@@ -6223,9 +6232,9 @@ int smb2_read(struct ksmbd_work *work) ...@@ -6223,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;
} }
...@@ -6257,8 +6266,7 @@ int smb2_read(struct ksmbd_work *work) ...@@ -6257,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,
...@@ -6328,23 +6336,18 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work) ...@@ -6328,23 +6336,18 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
length = le32_to_cpu(req->Length); length = le32_to_cpu(req->Length);
id = req->VolatileFileId; id = req->VolatileFileId;
if (le16_to_cpu(req->DataOffset) == if ((u64)le16_to_cpu(req->DataOffset) + length >
offsetof(struct smb2_write_req, Buffer)) { get_rfc1002_len(work->request_buf)) {
data_buf = (char *)&req->Buffer[0]; pr_err("invalid write data offset %u, smb_len %u\n",
} else { le16_to_cpu(req->DataOffset),
if ((u64)le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(work->request_buf));
get_rfc1002_len(work->request_buf)) { err = -EINVAL;
pr_err("invalid write data offset %u, smb_len %u\n", goto out;
le16_to_cpu(req->DataOffset),
get_rfc1002_len(work->request_buf));
err = -EINVAL;
goto out;
}
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
} }
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length); rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
if (rpc_resp) { if (rpc_resp) {
if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) { if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
...@@ -6384,21 +6387,18 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work, ...@@ -6384,21 +6387,18 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
struct ksmbd_file *fp, struct ksmbd_file *fp,
loff_t offset, size_t length, bool sync) loff_t offset, size_t length, bool sync)
{ {
struct smb2_buffer_desc_v1 *desc;
char *data_buf; char *data_buf;
int ret; int ret;
ssize_t nbytes; ssize_t nbytes;
desc = (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO); data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!data_buf) if (!data_buf)
return -ENOMEM; return -ENOMEM;
ret = ksmbd_conn_rdma_read(work->conn, data_buf, length, ret = ksmbd_conn_rdma_read(work->conn, data_buf, length,
le32_to_cpu(desc->token), (struct smb2_buffer_desc_v1 *)
le64_to_cpu(desc->offset), ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)),
le32_to_cpu(desc->length)); le16_to_cpu(req->WriteChannelInfoLength));
if (ret < 0) { if (ret < 0) {
kvfree(data_buf); kvfree(data_buf);
return ret; return ret;
...@@ -6427,8 +6427,9 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6427,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);
...@@ -6437,8 +6438,17 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6437,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 ||
...@@ -6450,7 +6460,6 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6450,7 +6460,6 @@ int smb2_write(struct ksmbd_work *work)
(struct smb2_buffer_desc_v1 *) (struct smb2_buffer_desc_v1 *)
((char *)req + ch_offset), ((char *)req + ch_offset),
req->Channel, req->Channel,
req->WriteChannelInfoOffset,
req->WriteChannelInfoLength); req->WriteChannelInfoLength);
if (err) if (err)
goto out; goto out;
...@@ -6474,12 +6483,9 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6474,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;
} }
...@@ -6487,24 +6493,17 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6487,24 +6493,17 @@ 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 (le16_to_cpu(req->DataOffset) == get_rfc1002_len(work->request_buf)) {
offsetof(struct smb2_write_req, Buffer)) { pr_err("invalid write data offset %u, smb_len %u\n",
data_buf = (char *)&req->Buffer[0]; le16_to_cpu(req->DataOffset),
} else { get_rfc1002_len(work->request_buf));
if ((u64)le16_to_cpu(req->DataOffset) + length > err = -EINVAL;
get_rfc1002_len(work->request_buf)) { goto out;
pr_err("invalid write data offset %u, smb_len %u\n",
le16_to_cpu(req->DataOffset),
get_rfc1002_len(work->request_buf));
err = -EINVAL;
goto out;
}
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
} }
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags)); ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH) if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
...@@ -6520,8 +6519,7 @@ int smb2_write(struct ksmbd_work *work) ...@@ -6520,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;
......
...@@ -140,8 +140,10 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work) ...@@ -140,8 +140,10 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
hdr = work->request_buf; hdr = work->request_buf;
if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER && if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
hdr->Command == SMB_COM_NEGOTIATE) hdr->Command == SMB_COM_NEGOTIATE) {
work->conn->outstanding_credits++;
return 0; return 0;
}
return -EINVAL; return -EINVAL;
} }
......
...@@ -1261,6 +1261,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, ...@@ -1261,6 +1261,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
if (!access_bits) if (!access_bits)
access_bits = access_bits =
SET_MINIMUM_RIGHTS; SET_MINIMUM_RIGHTS;
posix_acl_release(posix_acls);
goto check_access_bits; goto check_access_bits;
} }
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "mgmt/ksmbd_ida.h" #include "mgmt/ksmbd_ida.h"
#include "connection.h" #include "connection.h"
#include "transport_tcp.h" #include "transport_tcp.h"
#include "transport_rdma.h"
#define IPC_WAIT_TIMEOUT (2 * HZ) #define IPC_WAIT_TIMEOUT (2 * HZ)
...@@ -303,6 +304,8 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req) ...@@ -303,6 +304,8 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
init_smb2_max_trans_size(req->smb2_max_trans); init_smb2_max_trans_size(req->smb2_max_trans);
if (req->smb2_max_credits) if (req->smb2_max_credits)
init_smb2_max_credits(req->smb2_max_credits); init_smb2_max_credits(req->smb2_max_credits);
if (req->smbd_max_io_size)
init_smbd_max_io_size(req->smbd_max_io_size);
ret = ksmbd_set_netbios_name(req->netbios_name); ret = ksmbd_set_netbios_name(req->netbios_name);
ret |= ksmbd_set_server_string(req->server_string); ret |= ksmbd_set_server_string(req->server_string);
......
This diff is collapsed.
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#ifndef __KSMBD_TRANSPORT_RDMA_H__ #ifndef __KSMBD_TRANSPORT_RDMA_H__
#define __KSMBD_TRANSPORT_RDMA_H__ #define __KSMBD_TRANSPORT_RDMA_H__
#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
#define SMBD_MIN_IOSIZE (512 * 1024)
#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
/* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */ /* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
struct smb_direct_negotiate_req { struct smb_direct_negotiate_req {
__le16 min_version; __le16 min_version;
...@@ -52,10 +56,14 @@ struct smb_direct_data_transfer { ...@@ -52,10 +56,14 @@ struct smb_direct_data_transfer {
int ksmbd_rdma_init(void); 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);
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 unsigned int get_smbd_max_read_write_size(void) { return 0; }
#endif #endif
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */ #endif /* __KSMBD_TRANSPORT_RDMA_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment