Discussion:
[Patch v2 1/6] cifs: smbd: Check for iov length on sending the last iov
Steve French via samba-technical
2018-04-17 20:04:47 UTC
Permalink
merged into cifs-2.6.git for-next
When sending the last iov that breaks into smaller buffers to fit the
transfer size, it's necessary to check if this is the last iov.
If this is the latest iov, stop and proceed to send pages.
---
fs/cifs/smbdirect.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 90e673c..b5c6c0d 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2197,6 +2197,8 @@ int smbd_send(struct smbd_connection *info, struct
smb_rqst *rqst)
goto done;
}
i++;
+ if (i == rqst->rq_nvec)
+ break;
}
start = i;
buflen = 0;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Thanks,

Steve
Long Li via samba-technical
2018-04-17 20:11:14 UTC
Permalink
Subject: RE: [Patch v2 2/6] cifs: Allocate validate negotiation request through
kmalloc
-----Original Message-----
Sent: Tuesday, April 17, 2018 2:17 PM
Subject: [Patch v2 2/6] cifs: Allocate validate negotiation request
through kmalloc
The data buffer allocated on the stack can't be DMA'ed, and hence
can't send through RDMA via SMB Direct.
Fix this by allocating the request on the heap in smb3_validate_negotiate.
Fixes: ff1c038addc4f205d5f1ede449426c7d316c0eed "Check SMB3 dialects
against downgrade attacks"
Fixes: ff1c038addc4 ("Check SMB3 dialects against downgrade attacks") It
should be right above Signed-off signature.
I will fix up and resend this patch.

How about the rest patches (1, 3-6) in the series? If they don't need any changes, is it okay that I resend this one only?
Removed duplicated code on freeing buffers on function exit.
Fixed typo in the patch title.
---
fs/cifs/smb2pdu.c | 57
++++++++++++++++++++++++++++++------------------------
-
1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index
0f044c4..41625e4
100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -729,8 +729,8 @@ SMB2_negotiate(const unsigned int xid, struct
cifs_ses
*ses)
int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
{
- int rc = 0;
- struct validate_negotiate_info_req vneg_inbuf;
+ int ret, rc = -EIO;
+ struct validate_negotiate_info_req *pneg_inbuf;
struct validate_negotiate_info_rsp *pneg_rsp = NULL;
u32 rsplen;
smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon
*tcon)
if (tcon->ses->server->rdma)
return 0;
#endif
+ pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_KERNEL);
+ if (!pneg_inbuf)
+ return -ENOMEM;
/* In SMB3.11 preauth integrity supersedes validate negotiate */
cifs_tcon *tcon)
if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag
sent by
server\n");
- vneg_inbuf.Capabilities =
+ pneg_inbuf->Capabilities =
cpu_to_le32(tcon->ses->server->vals-
req_capabilities);
- memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
+ memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid,
SMB2_CLIENT_GUID_SIZE);
if (tcon->ses->sign)
- vneg_inbuf.SecurityMode =
+ pneg_inbuf->SecurityMode =
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
else if (global_secflags & CIFSSEC_MAY_SIGN)
- vneg_inbuf.SecurityMode =
+ pneg_inbuf->SecurityMode =
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
else
- vneg_inbuf.SecurityMode = 0;
+ pneg_inbuf->SecurityMode = 0;
if (strcmp(tcon->ses->server->vals->version_string,
Please check if strncmp() should be used or not.
SMB3ANY_VERSION_STRING) == 0) {
- vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
- vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
- vneg_inbuf.DialectCount = cpu_to_le16(2);
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(2);
/* structure is big enough for 3 dialects, sending only 2 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 2;
} else if (strcmp(tcon->ses->server->vals->version_string,
SMBDEFAULT_VERSION_STRING) == 0) {
- vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
- vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
- vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
- vneg_inbuf.DialectCount = cpu_to_le16(3);
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(3);
/* structure is big enough for 3 dialects */
inbuflen = sizeof(struct validate_negotiate_info_req);
} else {
/* otherwise specific dialect was requested */
- vneg_inbuf.Dialects[0] =
+ pneg_inbuf->Dialects[0] =
cpu_to_le16(tcon->ses->server->vals->protocol_id);
- vneg_inbuf.DialectCount = cpu_to_le16(1);
+ pneg_inbuf->DialectCount = cpu_to_le16(1);
/* structure is big enough for 3 dialects, sending only 1 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 4;
}
- rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ ret = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
- (char *)&vneg_inbuf, sizeof(struct
validate_negotiate_info_req),
+ (char *)pneg_inbuf, sizeof(struct
validate_negotiate_info_req),
Use sizeof(*pneg_inbuf)
(char **)&pneg_rsp, &rsplen);
- if (rc != 0) {
- cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
- return -EIO;
+ if (ret != 0) {
if (ret) is fine.
+ cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", ret);
+ goto out_free_inbuf;
}
-820,7
if (rsplen != sizeof(*pneg_rsp))
Steve French via samba-technical
2018-04-17 20:37:10 UTC
Permalink
On Tue, Apr 17, 2018 at 3:11 PM, Long Li via samba-technical
Post by Long Li via samba-technical
Subject: RE: [Patch v2 2/6] cifs: Allocate validate negotiation request through
kmalloc
-----Original Message-----
Sent: Tuesday, April 17, 2018 2:17 PM
Subject: [Patch v2 2/6] cifs: Allocate validate negotiation request
through kmalloc
The data buffer allocated on the stack can't be DMA'ed, and hence
can't send through RDMA via SMB Direct.
Fix this by allocating the request on the heap in smb3_validate_negotiate.
Fixes: ff1c038addc4f205d5f1ede449426c7d316c0eed "Check SMB3 dialects
against downgrade attacks"
Fixes: ff1c038addc4 ("Check SMB3 dialects against downgrade attacks") It
should be right above Signed-off signature.
I will fix up and resend this patch.
How about the rest patches (1, 3-6) in the series? If they don't need any changes, is it okay that I resend this one only?
Doesn't matter to me either way - I already merged patch 1 in any case.
Post by Long Li via samba-technical
Removed duplicated code on freeing buffers on function exit.
--
Thanks,

Steve
Long Li via samba-technical
2018-04-19 00:48:57 UTC
Permalink
Subject: RE: [Patch v2 2/6] cifs: Allocate validate negotiation request through
kmalloc
-----Original Message-----
Sent: Tuesday, April 17, 2018 12:17 PM
Subject: [Patch v2 2/6] cifs: Allocate validate negotiation request
through kmalloc
The data buffer allocated on the stack can't be DMA'ed, and hence
can't send through RDMA via SMB Direct.
Fix this by allocating the request on the heap in smb3_validate_negotiate.
Fixes: ff1c038addc4f205d5f1ede449426c7d316c0eed "Check SMB3 dialects
against downgrade attacks"
Removed duplicated code on freeing buffers on function exit.
Fixed typo in the patch title.
---
fs/cifs/smb2pdu.c | 57
++++++++++++++++++++++++++++++-------------------------
1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index
0f044c4..41625e4 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -729,8 +729,8 @@ SMB2_negotiate(const unsigned int xid, struct
cifs_ses *ses)
int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon
*tcon) {
- int rc = 0;
- struct validate_negotiate_info_req vneg_inbuf;
+ int ret, rc = -EIO;
+ struct validate_negotiate_info_req *pneg_inbuf;
struct validate_negotiate_info_rsp *pneg_rsp = NULL;
u32 rsplen;
smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon
*tcon)
if (tcon->ses->server->rdma)
return 0;
#endif
+ pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_KERNEL);
+ if (!pneg_inbuf)
+ return -ENOMEM;
Immediately after the above new code, there are three if statements that
can 'return 0' and never free the pneg_inbuf memory. They should instead
set 'rc'
appropriately and 'goto' the out_free_inbuf label.
Thanks!

I will move the kmalloc after those statements.
Michael
/* In SMB3.11 preauth integrity supersedes validate negotiate */
+767,53
@@ int smb3_validate_negotiate(const unsigned int xid, struct
cifs_tcon
*tcon)
if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag
sent by
server\n");
- vneg_inbuf.Capabilities =
+ pneg_inbuf->Capabilities =
cpu_to_le32(tcon->ses->server->vals-
req_capabilities);
- memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
+ memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid,
SMB2_CLIENT_GUID_SIZE);
if (tcon->ses->sign)
- vneg_inbuf.SecurityMode =
+ pneg_inbuf->SecurityMode =
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
else if (global_secflags & CIFSSEC_MAY_SIGN)
- vneg_inbuf.SecurityMode =
+ pneg_inbuf->SecurityMode =
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
else
- vneg_inbuf.SecurityMode = 0;
+ pneg_inbuf->SecurityMode = 0;
if (strcmp(tcon->ses->server->vals->version_string,
SMB3ANY_VERSION_STRING) == 0) {
- vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
- vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
- vneg_inbuf.DialectCount = cpu_to_le16(2);
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(2);
/* structure is big enough for 3 dialects, sending only 2 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 2;
} else if (strcmp(tcon->ses->server->vals->version_string,
SMBDEFAULT_VERSION_STRING) == 0) {
- vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
- vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
- vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
- vneg_inbuf.DialectCount = cpu_to_le16(3);
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(3);
/* structure is big enough for 3 dialects */
inbuflen = sizeof(struct validate_negotiate_info_req);
} else {
/* otherwise specific dialect was requested */
- vneg_inbuf.Dialects[0] =
+ pneg_inbuf->Dialects[0] =
cpu_to_le16(tcon->ses->server->vals->protocol_id);
- vneg_inbuf.DialectCount = cpu_to_le16(1);
+ pneg_inbuf->DialectCount = cpu_to_le16(1);
/* structure is big enough for 3 dialects, sending only 1 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 4;
}
- rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ ret = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
- (char *)&vneg_inbuf, sizeof(struct
validate_negotiate_info_req),
+ (char *)pneg_inbuf, sizeof(struct
validate_negotiate_info_req),
(char **)&pneg_rsp, &rsplen);
- if (rc != 0) {
- cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
- return -EIO;
+ if (ret != 0) {
+ cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", ret);
+ goto out_free_inbuf;
}
struct cifs_tcon
*tcon)
/* relax check since Mac returns max bufsize allowed on ioctl
*/
if ((rsplen > CIFSMaxBufSize)
|| (rsplen < sizeof(struct validate_negotiate_info_rsp)))
- goto err_rsp_free;
+ goto out_free_rsp;
}
/* check validate negotiate info response matches what we got
unsigned int xid, struct cifs_tcon
*tcon)
/* validate negotiate successful */
cifs_dbg(FYI, "validate negotiate info successful\n");
- kfree(pneg_rsp);
- return 0;
+ rc = 0;
+ goto out_free_rsp;
cifs_dbg(VFS, "protocol revalidation - security settings
mismatch\n");
kfree(pneg_rsp);
- return -EIO;
+ kfree(pneg_inbuf);
+ return rc;
}
enum securityEnum
--
2.7.4
Steve French via samba-technical
2018-04-23 15:31:51 UTC
Permalink
Didn't see any obvious problems, but can you fix the checkpatch
warnings and resend to the list (I am more concerned about the last
two warnings rather than the first one).

$ scripts/checkpatch.pl 0001-cifs-smbd-Avoid-allocating-iov-on-the-stack.patch
WARNING: line over 80 characters
#60: FILE: fs/cifs/smbdirect.c:2106:
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);

ERROR: Prefixing 0x with decimal output is defective
#60: FILE: fs/cifs/smbdirect.c:2106:
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);

WARNING: braces {} are not necessary for single statement blocks
#69: FILE: fs/cifs/smbdirect.c:2112:
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}

total: 1 errors, 2 warnings, 65 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

0001-cifs-smbd-Avoid-allocating-iov-on-the-stack.patch has style
problems, please review.
It's not necessary to allocate another iov when going through the buffers
in smbd_send() through RDMA send.
Remove it to reduce stack size.
---
fs/cifs/smbdirect.c | 36 ++++++++++++------------------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index b5c6c0d..f575e9a 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2088,7 +2088,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
int start, i, j;
int max_iov_size =
info->max_send_size - sizeof(struct smbd_data_transfer);
- struct kvec iov[SMBDIRECT_MAX_SGE];
+ struct kvec *iov;
int rc;
info->smbd_send_pending++;
@@ -2099,32 +2099,20 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
}
/*
- * This usually means a configuration error
- * We use RDMA read/write for packet size > rdma_readwrite_threshold
- * as long as it's properly configured we should never get into this
- * situation
- */
- if (rqst->rq_nvec + rqst->rq_npages > SMBDIRECT_MAX_SGE) {
- log_write(ERR, "maximum send segment %x exceeding %x\n",
- rqst->rq_nvec + rqst->rq_npages, SMBDIRECT_MAX_SGE);
- rc = -EINVAL;
- goto done;
- }
-
- /*
- * Remove the RFC1002 length defined in MS-SMB2 section 2.1
- * It is used only for TCP transport
+ * Skip the RFC1002 length defined in MS-SMB2 section 2.1
+ * It is used only for TCP transport in the iov[0]
* In future we may want to add a transport layer under protocol
* layer so this will only be issued to TCP transport
*/
- iov[0].iov_base = (char *)rqst->rq_iov[0].iov_base + 4;
- iov[0].iov_len = rqst->rq_iov[0].iov_len - 4;
- buflen += iov[0].iov_len;
+
+ if (rqst->rq_iov[0].iov_len != 4) {
+ log_write(ERR, "expected the pdu length in 1st iov, but got 0x%lu\n", rqst->rq_iov[0].iov_len);
+ return -EINVAL;
+ }
+ iov = &rqst->rq_iov[1];
/* total up iov array first */
- for (i = 1; i < rqst->rq_nvec; i++) {
- iov[i].iov_base = rqst->rq_iov[i].iov_base;
- iov[i].iov_len = rqst->rq_iov[i].iov_len;
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}
@@ -2197,14 +2185,14 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
goto done;
}
i++;
- if (i == rqst->rq_nvec)
+ if (i == rqst->rq_nvec-1)
break;
}
start = i;
buflen = 0;
} else {
i++;
- if (i == rqst->rq_nvec) {
+ if (i == rqst->rq_nvec-1) {
/* send out all remaining vecs */
remaining_data_length -= buflen;
log_write(INFO,
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Thanks,

Steve
Long Li via samba-technical
2018-04-23 17:33:23 UTC
Permalink
Subject: Re: [Patch v2 3/6] cifs: smbd: Avoid allocating iov on the stack
Didn't see any obvious problems, but can you fix the checkpatch warnings
and resend to the list (I am more concerned about the last two warnings
rather than the first one).
Yes, I will fix it and resend.
$ scripts/checkpatch.pl 0001-cifs-smbd-Avoid-allocating-iov-on-the-
stack.patch
WARNING: line over 80 characters
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
ERROR: Prefixing 0x with decimal output is defective
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
WARNING: braces {} are not necessary for single statement blocks
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}
total: 1 errors, 2 warnings, 65 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
0001-cifs-smbd-Avoid-allocating-iov-on-the-stack.patch has style problems,
please review.
It's not necessary to allocate another iov when going through the
buffers in smbd_send() through RDMA send.
Remove it to reduce stack size.
---
fs/cifs/smbdirect.c | 36 ++++++++++++------------------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index
b5c6c0d..f575e9a 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2088,7 +2088,7 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
int start, i, j;
int max_iov_size =
info->max_send_size - sizeof(struct smbd_data_transfer);
- struct kvec iov[SMBDIRECT_MAX_SGE];
+ struct kvec *iov;
int rc;
info->smbd_send_pending++;
@@ -2099,32 +2099,20 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
}
/*
- * This usually means a configuration error
- * We use RDMA read/write for packet size >
rdma_readwrite_threshold
- * as long as it's properly configured we should never get into this
- * situation
- */
- if (rqst->rq_nvec + rqst->rq_npages > SMBDIRECT_MAX_SGE) {
- log_write(ERR, "maximum send segment %x exceeding %x\n",
- rqst->rq_nvec + rqst->rq_npages, SMBDIRECT_MAX_SGE);
- rc = -EINVAL;
- goto done;
- }
-
- /*
- * Remove the RFC1002 length defined in MS-SMB2 section 2.1
- * It is used only for TCP transport
+ * Skip the RFC1002 length defined in MS-SMB2 section 2.1
+ * It is used only for TCP transport in the iov[0]
* In future we may want to add a transport layer under protocol
* layer so this will only be issued to TCP transport
*/
- iov[0].iov_base = (char *)rqst->rq_iov[0].iov_base + 4;
- iov[0].iov_len = rqst->rq_iov[0].iov_len - 4;
- buflen += iov[0].iov_len;
+
+ if (rqst->rq_iov[0].iov_len != 4) {
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
+ return -EINVAL;
+ }
+ iov = &rqst->rq_iov[1];
/* total up iov array first */
- for (i = 1; i < rqst->rq_nvec; i++) {
- iov[i].iov_base = rqst->rq_iov[i].iov_base;
- iov[i].iov_len = rqst->rq_iov[i].iov_len;
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}
@@ -2197,14 +2185,14 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
goto done;
}
i++;
- if (i == rqst->rq_nvec)
+ if (i == rqst->rq_nvec-1)
break;
}
start = i;
buflen = 0;
} else {
i++;
- if (i == rqst->rq_nvec) {
+ if (i == rqst->rq_nvec-1) {
/* send out all remaining vecs */
remaining_data_length -= buflen;
log_write(INFO,
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs"
majordomo
info at
https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fvger.k
ernel.org%2Fmajordomo-
info.html&data=02%7C01%7Clongli%40microsoft.com%
7C23fbdbb0598a497f624708d5a92f6435%7C72f988bf86f141af91ab2d7cd011d
b47%
7C1%7C0%7C636600943380887988&sdata=imh9cWDQQEXqxHdUrCuEykgiLfKs
UAl20jB
yPOS7FrI%3D&reserved=0
--
Thanks,
Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the
https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fvger.ke
rnel.org%2Fmajordomo-
info.html&data=02%7C01%7Clongli%40microsoft.com%7C23fbdbb0598a497f
624708d5a92f6435%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C63
6600943380887988&sdata=imh9cWDQQEXqxHdUrCuEykgiLfKsUAl20jByPOS7F
rI%3D&reserv
Steve French via samba-technical
2018-04-23 17:50:49 UTC
Permalink
I am ok with the other style warning - so I just fixed up the one
error (see attached) and merged into cifs-2.6.git for-next

That leaves two more from your series to review (and for others to
review). Let's just focus on those two.
Post by Long Li via samba-technical
Subject: Re: [Patch v2 3/6] cifs: smbd: Avoid allocating iov on the stack
Didn't see any obvious problems, but can you fix the checkpatch warnings
and resend to the list (I am more concerned about the last two warnings
rather than the first one).
Yes, I will fix it and resend.
$ scripts/checkpatch.pl 0001-cifs-smbd-Avoid-allocating-iov-on-the-
stack.patch
WARNING: line over 80 characters
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
ERROR: Prefixing 0x with decimal output is defective
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
WARNING: braces {} are not necessary for single statement blocks
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}
total: 1 errors, 2 warnings, 65 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
0001-cifs-smbd-Avoid-allocating-iov-on-the-stack.patch has style problems,
please review.
It's not necessary to allocate another iov when going through the
buffers in smbd_send() through RDMA send.
Remove it to reduce stack size.
---
fs/cifs/smbdirect.c | 36 ++++++++++++------------------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index
b5c6c0d..f575e9a 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2088,7 +2088,7 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
int start, i, j;
int max_iov_size =
info->max_send_size - sizeof(struct smbd_data_transfer);
- struct kvec iov[SMBDIRECT_MAX_SGE];
+ struct kvec *iov;
int rc;
info->smbd_send_pending++;
@@ -2099,32 +2099,20 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
}
/*
- * This usually means a configuration error
- * We use RDMA read/write for packet size >
rdma_readwrite_threshold
- * as long as it's properly configured we should never get into this
- * situation
- */
- if (rqst->rq_nvec + rqst->rq_npages > SMBDIRECT_MAX_SGE) {
- log_write(ERR, "maximum send segment %x exceeding %x\n",
- rqst->rq_nvec + rqst->rq_npages, SMBDIRECT_MAX_SGE);
- rc = -EINVAL;
- goto done;
- }
-
- /*
- * Remove the RFC1002 length defined in MS-SMB2 section 2.1
- * It is used only for TCP transport
+ * Skip the RFC1002 length defined in MS-SMB2 section 2.1
+ * It is used only for TCP transport in the iov[0]
* In future we may want to add a transport layer under protocol
* layer so this will only be issued to TCP transport
*/
- iov[0].iov_base = (char *)rqst->rq_iov[0].iov_base + 4;
- iov[0].iov_len = rqst->rq_iov[0].iov_len - 4;
- buflen += iov[0].iov_len;
+
+ if (rqst->rq_iov[0].iov_len != 4) {
+ log_write(ERR, "expected the pdu length in 1st iov, but got
0x%lu\n", rqst->rq_iov[0].iov_len);
+ return -EINVAL;
+ }
+ iov = &rqst->rq_iov[1];
/* total up iov array first */
- for (i = 1; i < rqst->rq_nvec; i++) {
- iov[i].iov_base = rqst->rq_iov[i].iov_base;
- iov[i].iov_len = rqst->rq_iov[i].iov_len;
+ for (i = 0; i < rqst->rq_nvec-1; i++) {
buflen += iov[i].iov_len;
}
@@ -2197,14 +2185,14 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
goto done;
}
i++;
- if (i == rqst->rq_nvec)
+ if (i == rqst->rq_nvec-1)
break;
}
start = i;
buflen = 0;
} else {
i++;
- if (i == rqst->rq_nvec) {
+ if (i == rqst->rq_nvec-1) {
/* send out all remaining vecs */
remaining_data_length -= buflen;
log_write(INFO,
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs"
majordomo
info at
https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fvger.k
ernel.org%2Fmajordomo-
info.html&data=02%7C01%7Clongli%40microsoft.com%
7C23fbdbb0598a497f624708d5a92f6435%7C72f988bf86f141af91ab2d7cd011d
b47%
7C1%7C0%7C636600943380887988&sdata=imh9cWDQQEXqxHdUrCuEykgiLfKs
UAl20jB
yPOS7FrI%3D&reserved=0
--
Thanks,
Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the
https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fvger.ke
rnel.org%2Fmajordomo-
info.html&data=02%7C01%7Clongli%40microsoft.com%7C23fbdbb0598a497f
624708d5a92f6435%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C63
6600943380887988&sdata=imh9cWDQQEXqxHdUrCuEykgiLfKsUAl20jByPOS7F
rI%3D&reserved=0
--
Thanks,

Steve
Steve French via samba-technical
2018-04-23 15:34:55 UTC
Permalink
merged into cifs-2.6.git for-next
SMB server will not sign data transferred through RDMA read/write. When
signing is used, it's a good idea to have all the data signed.
In this case, use RDMA send/recv for all data transfers. This will degrade
performance as this is not generally configured in RDMA environemnt. So
warn the user on signing and RDMA send/recv.
---
fs/cifs/cifssmb.c | 3 +++
fs/cifs/smb2ops.c | 18 ++++++++++++++----
fs/cifs/smb2pdu.c | 4 ++--
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6d3e40d..1529a08 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -455,6 +455,9 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
server->sign = true;
}
+ if (cifs_rdma_enabled(server) && server->sign)
+ cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled");
+
return 0;
}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 38ebf3f..b76b858 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -252,9 +252,14 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
wsize = min_t(unsigned int, wsize, server->max_write);
#ifdef CONFIG_CIFS_SMB_DIRECT
- if (server->rdma)
- wsize = min_t(unsigned int,
+ if (server->rdma) {
+ if (server->sign)
+ wsize = min_t(unsigned int,
+ wsize, server->smbd_conn->max_fragmented_send_size);
+ else
+ wsize = min_t(unsigned int,
wsize, server->smbd_conn->max_readwrite_size);
+ }
#endif
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
@@ -272,9 +277,14 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
rsize = min_t(unsigned int, rsize, server->max_read);
#ifdef CONFIG_CIFS_SMB_DIRECT
- if (server->rdma)
- rsize = min_t(unsigned int,
+ if (server->rdma) {
+ if (server->sign)
+ rsize = min_t(unsigned int,
+ rsize, server->smbd_conn->max_fragmented_recv_size);
+ else
+ rsize = min_t(unsigned int,
rsize, server->smbd_conn->max_readwrite_size);
+ }
#endif
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 41625e4..33f612f 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2595,7 +2595,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
* If we want to do a RDMA write, fill in and append
* smbd_buffer_descriptor_v1 to the end of read request
*/
- if (server->rdma && rdata &&
+ if (server->rdma && rdata && !server->sign &&
rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) {
struct smbd_buffer_descriptor_v1 *v1;
@@ -2973,7 +2973,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
* If we want to do a server RDMA read, fill in and append
* smbd_buffer_descriptor_v1 to the end of write request
*/
- if (server->rdma && wdata->bytes >=
+ if (server->rdma && !server->sign && wdata->bytes >=
server->smbd_conn->rdma_readwrite_threshold) {
struct smbd_buffer_descriptor_v1 *v1;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Thanks,

Steve
Long Li via samba-technical
2018-04-23 19:34:23 UTC
Permalink
Subject: RE: [Patch v2 1/6] cifs: smbd: Check for iov length on sending the last
iov
-----Original Message-----
Sent: Tuesday, April 17, 2018 12:17 PM
Subject: [Patch v2 1/6] cifs: smbd: Check for iov length on sending
the last iov
When sending the last iov that breaks into smaller buffers to fit the
transfer size, it's necessary to check if this is the last iov.
If this is the latest iov, stop and proceed to send pages.
But a question unrelated to this change arose during my review: At the
beginning and end of smbd_send(), the field smbd_send_pending is
incremented and decremented, respectively. The increment/decrement
are not done as atomic operations. Is this code guaranteed to be single
threaded? If not, the count could become corrupted, and
smbd_destroy_rdma_work(), which waits for the count to become zero,
could hang. A similar question applies to smbd_recv_pending in smbd_recv().
It is safe. The transport sending path is locked by TCP_Server_Info->srv_mutex.

The transport receiving path is single threaded.
---
fs/cifs/smbdirect.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index
90e673c..b5c6c0d 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2197,6 +2197,8 @@ int smbd_send(struct smbd_connection *info,
struct smb_rqst *rqst)
goto done;
}
i++;
+ if (i == rqst->rq_nvec)
+ break;
}
start = i;
buflen = 0;
--
2.7.4
Loading...