aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-28 12:51:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-28 12:51:56 -0400
commitcac264288abe0f54b91e51d97c949b706c9435c7 (patch)
treebec86258708d5f7a9bce34de14fcaed58bc46e34
parent0d95cfa922c24bcc20b5ccf7496b6ac7c8e29efb (diff)
parent8bcda1d2a79da4ab84162574eee2c9f6e1a12a03 (diff)
Merge tag '4.17-rc2-smb3' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "A few security related fixes for SMB3, most importantly for SMB3.11 encryption" * tag '4.17-rc2-smb3' of git://git.samba.org/sfrench/cifs-2.6: cifs: smbd: Avoid allocating iov on the stack cifs: smbd: Don't use RDMA read/write when signing is used SMB311: Fix reconnect SMB3: Fix 3.11 encryption to Windows and handle encrypted smb3 tcon CIFS: set *resp_buf_type to NO_BUFFER on error
-rw-r--r--fs/cifs/cifssmb.c3
-rw-r--r--fs/cifs/connect.c32
-rw-r--r--fs/cifs/smb2ops.c18
-rw-r--r--fs/cifs/smb2pdu.c13
-rw-r--r--fs/cifs/smb2pdu.h2
-rw-r--r--fs/cifs/smbdirect.c36
-rw-r--r--fs/cifs/transport.c9
7 files changed, 59 insertions, 54 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6d3e40d7029c..1529a088383d 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)
455 server->sign = true; 455 server->sign = true;
456 } 456 }
457 457
458 if (cifs_rdma_enabled(server) && server->sign)
459 cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled");
460
458 return 0; 461 return 0;
459} 462}
460 463
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e8830f076a7f..a5aa158d535a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2959,6 +2959,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
2959 } 2959 }
2960 } 2960 }
2961 2961
2962 if (volume_info->seal) {
2963 if (ses->server->vals->protocol_id == 0) {
2964 cifs_dbg(VFS,
2965 "SMB3 or later required for encryption\n");
2966 rc = -EOPNOTSUPP;
2967 goto out_fail;
2968 } else if (tcon->ses->server->capabilities &
2969 SMB2_GLOBAL_CAP_ENCRYPTION)
2970 tcon->seal = true;
2971 else {
2972 cifs_dbg(VFS, "Encryption is not supported on share\n");
2973 rc = -EOPNOTSUPP;
2974 goto out_fail;
2975 }
2976 }
2977
2962 /* 2978 /*
2963 * BB Do we need to wrap session_mutex around this TCon call and Unix 2979 * BB Do we need to wrap session_mutex around this TCon call and Unix
2964 * SetFS as we do on SessSetup and reconnect? 2980 * SetFS as we do on SessSetup and reconnect?
@@ -3007,22 +3023,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3007 tcon->use_resilient = true; 3023 tcon->use_resilient = true;
3008 } 3024 }
3009 3025
3010 if (volume_info->seal) {
3011 if (ses->server->vals->protocol_id == 0) {
3012 cifs_dbg(VFS,
3013 "SMB3 or later required for encryption\n");
3014 rc = -EOPNOTSUPP;
3015 goto out_fail;
3016 } else if (tcon->ses->server->capabilities &
3017 SMB2_GLOBAL_CAP_ENCRYPTION)
3018 tcon->seal = true;
3019 else {
3020 cifs_dbg(VFS, "Encryption is not supported on share\n");
3021 rc = -EOPNOTSUPP;
3022 goto out_fail;
3023 }
3024 }
3025
3026 /* 3026 /*
3027 * We can have only one retry value for a connection to a share so for 3027 * We can have only one retry value for a connection to a share so for
3028 * resources mounted more than once to the same server share the last 3028 * resources mounted more than once to the same server share the last
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 38ebf3f357d2..b76b85881dcc 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)
252 wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; 252 wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
253 wsize = min_t(unsigned int, wsize, server->max_write); 253 wsize = min_t(unsigned int, wsize, server->max_write);
254#ifdef CONFIG_CIFS_SMB_DIRECT 254#ifdef CONFIG_CIFS_SMB_DIRECT
255 if (server->rdma) 255 if (server->rdma) {
256 wsize = min_t(unsigned int, 256 if (server->sign)
257 wsize = min_t(unsigned int,
258 wsize, server->smbd_conn->max_fragmented_send_size);
259 else
260 wsize = min_t(unsigned int,
257 wsize, server->smbd_conn->max_readwrite_size); 261 wsize, server->smbd_conn->max_readwrite_size);
262 }
258#endif 263#endif
259 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) 264 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
260 wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); 265 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)
272 rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; 277 rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
273 rsize = min_t(unsigned int, rsize, server->max_read); 278 rsize = min_t(unsigned int, rsize, server->max_read);
274#ifdef CONFIG_CIFS_SMB_DIRECT 279#ifdef CONFIG_CIFS_SMB_DIRECT
275 if (server->rdma) 280 if (server->rdma) {
276 rsize = min_t(unsigned int, 281 if (server->sign)
282 rsize = min_t(unsigned int,
283 rsize, server->smbd_conn->max_fragmented_recv_size);
284 else
285 rsize = min_t(unsigned int,
277 rsize, server->smbd_conn->max_readwrite_size); 286 rsize, server->smbd_conn->max_readwrite_size);
287 }
278#endif 288#endif
279 289
280 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) 290 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 0f044c4a2dc9..60db51bae0e3 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -383,10 +383,10 @@ static void
383build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) 383build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
384{ 384{
385 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES; 385 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
386 pneg_ctxt->DataLength = cpu_to_le16(6); 386 pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + le16 cipher */
387 pneg_ctxt->CipherCount = cpu_to_le16(2); 387 pneg_ctxt->CipherCount = cpu_to_le16(1);
388 pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM; 388/* pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;*/ /* not supported yet */
389 pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM; 389 pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM;
390} 390}
391 391
392static void 392static void
@@ -444,6 +444,7 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server,
444 return -EINVAL; 444 return -EINVAL;
445 } 445 }
446 server->cipher_type = ctxt->Ciphers[0]; 446 server->cipher_type = ctxt->Ciphers[0];
447 server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
447 return 0; 448 return 0;
448} 449}
449 450
@@ -2590,7 +2591,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
2590 * If we want to do a RDMA write, fill in and append 2591 * If we want to do a RDMA write, fill in and append
2591 * smbd_buffer_descriptor_v1 to the end of read request 2592 * smbd_buffer_descriptor_v1 to the end of read request
2592 */ 2593 */
2593 if (server->rdma && rdata && 2594 if (server->rdma && rdata && !server->sign &&
2594 rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) { 2595 rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) {
2595 2596
2596 struct smbd_buffer_descriptor_v1 *v1; 2597 struct smbd_buffer_descriptor_v1 *v1;
@@ -2968,7 +2969,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
2968 * If we want to do a server RDMA read, fill in and append 2969 * If we want to do a server RDMA read, fill in and append
2969 * smbd_buffer_descriptor_v1 to the end of write request 2970 * smbd_buffer_descriptor_v1 to the end of write request
2970 */ 2971 */
2971 if (server->rdma && wdata->bytes >= 2972 if (server->rdma && !server->sign && wdata->bytes >=
2972 server->smbd_conn->rdma_readwrite_threshold) { 2973 server->smbd_conn->rdma_readwrite_threshold) {
2973 2974
2974 struct smbd_buffer_descriptor_v1 *v1; 2975 struct smbd_buffer_descriptor_v1 *v1;
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 6093e5142b2b..d28f358022c5 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -297,7 +297,7 @@ struct smb2_encryption_neg_context {
297 __le16 DataLength; 297 __le16 DataLength;
298 __le32 Reserved; 298 __le32 Reserved;
299 __le16 CipherCount; /* AES-128-GCM and AES-128-CCM */ 299 __le16 CipherCount; /* AES-128-GCM and AES-128-CCM */
300 __le16 Ciphers[2]; /* Ciphers[0] since only one used now */ 300 __le16 Ciphers[1]; /* Ciphers[0] since only one used now */
301} __packed; 301} __packed;
302 302
303struct smb2_negotiate_rsp { 303struct smb2_negotiate_rsp {
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 87817ddcc096..c62f7c95683c 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2086,7 +2086,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2086 int start, i, j; 2086 int start, i, j;
2087 int max_iov_size = 2087 int max_iov_size =
2088 info->max_send_size - sizeof(struct smbd_data_transfer); 2088 info->max_send_size - sizeof(struct smbd_data_transfer);
2089 struct kvec iov[SMBDIRECT_MAX_SGE]; 2089 struct kvec *iov;
2090 int rc; 2090 int rc;
2091 2091
2092 info->smbd_send_pending++; 2092 info->smbd_send_pending++;
@@ -2096,32 +2096,20 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2096 } 2096 }
2097 2097
2098 /* 2098 /*
2099 * This usually means a configuration error 2099 * Skip the RFC1002 length defined in MS-SMB2 section 2.1
2100 * We use RDMA read/write for packet size > rdma_readwrite_threshold 2100 * It is used only for TCP transport in the iov[0]
2101 * as long as it's properly configured we should never get into this
2102 * situation
2103 */
2104 if (rqst->rq_nvec + rqst->rq_npages > SMBDIRECT_MAX_SGE) {
2105 log_write(ERR, "maximum send segment %x exceeding %x\n",
2106 rqst->rq_nvec + rqst->rq_npages, SMBDIRECT_MAX_SGE);
2107 rc = -EINVAL;
2108 goto done;
2109 }
2110
2111 /*
2112 * Remove the RFC1002 length defined in MS-SMB2 section 2.1
2113 * It is used only for TCP transport
2114 * In future we may want to add a transport layer under protocol 2101 * In future we may want to add a transport layer under protocol
2115 * layer so this will only be issued to TCP transport 2102 * layer so this will only be issued to TCP transport
2116 */ 2103 */
2117 iov[0].iov_base = (char *)rqst->rq_iov[0].iov_base + 4; 2104
2118 iov[0].iov_len = rqst->rq_iov[0].iov_len - 4; 2105 if (rqst->rq_iov[0].iov_len != 4) {
2119 buflen += iov[0].iov_len; 2106 log_write(ERR, "expected the pdu length in 1st iov, but got %zu\n", rqst->rq_iov[0].iov_len);
2107 return -EINVAL;
2108 }
2109 iov = &rqst->rq_iov[1];
2120 2110
2121 /* total up iov array first */ 2111 /* total up iov array first */
2122 for (i = 1; i < rqst->rq_nvec; i++) { 2112 for (i = 0; i < rqst->rq_nvec-1; i++) {
2123 iov[i].iov_base = rqst->rq_iov[i].iov_base;
2124 iov[i].iov_len = rqst->rq_iov[i].iov_len;
2125 buflen += iov[i].iov_len; 2113 buflen += iov[i].iov_len;
2126 } 2114 }
2127 2115
@@ -2198,14 +2186,14 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2198 goto done; 2186 goto done;
2199 } 2187 }
2200 i++; 2188 i++;
2201 if (i == rqst->rq_nvec) 2189 if (i == rqst->rq_nvec-1)
2202 break; 2190 break;
2203 } 2191 }
2204 start = i; 2192 start = i;
2205 buflen = 0; 2193 buflen = 0;
2206 } else { 2194 } else {
2207 i++; 2195 i++;
2208 if (i == rqst->rq_nvec) { 2196 if (i == rqst->rq_nvec-1) {
2209 /* send out all remaining vecs */ 2197 /* send out all remaining vecs */
2210 remaining_data_length -= buflen; 2198 remaining_data_length -= buflen;
2211 log_write(INFO, 2199 log_write(INFO,
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 8f6f25918229..927226a2122f 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -753,7 +753,7 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
753 goto out; 753 goto out;
754 754
755#ifdef CONFIG_CIFS_SMB311 755#ifdef CONFIG_CIFS_SMB311
756 if (ses->status == CifsNew) 756 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
757 smb311_update_preauth_hash(ses, rqst->rq_iov+1, 757 smb311_update_preauth_hash(ses, rqst->rq_iov+1,
758 rqst->rq_nvec-1); 758 rqst->rq_nvec-1);
759#endif 759#endif
@@ -798,7 +798,7 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
798 *resp_buf_type = CIFS_SMALL_BUFFER; 798 *resp_buf_type = CIFS_SMALL_BUFFER;
799 799
800#ifdef CONFIG_CIFS_SMB311 800#ifdef CONFIG_CIFS_SMB311
801 if (ses->status == CifsNew) { 801 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
802 struct kvec iov = { 802 struct kvec iov = {
803 .iov_base = buf + 4, 803 .iov_base = buf + 4,
804 .iov_len = get_rfc1002_length(buf) 804 .iov_len = get_rfc1002_length(buf)
@@ -834,8 +834,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
834 if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { 834 if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
835 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), 835 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
836 GFP_KERNEL); 836 GFP_KERNEL);
837 if (!new_iov) 837 if (!new_iov) {
838 /* otherwise cifs_send_recv below sets resp_buf_type */
839 *resp_buf_type = CIFS_NO_BUFFER;
838 return -ENOMEM; 840 return -ENOMEM;
841 }
839 } else 842 } else
840 new_iov = s_iov; 843 new_iov = s_iov;
841 844