summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-07-07 21:31:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-07-07 21:31:34 -0400
commitb2d44d145d2a72386b1b17da59a5e04989594897 (patch)
treee6e8742ca479c8ab8eba123f7990dbb8d2166012
parent4f572efde4600a577d1fc0bcee191bc9cec842f8 (diff)
parent729c0c9dd55204f0c9a823ac8a7bfa83d36c7e78 (diff)
Merge tag '4.18-rc3-smb3fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Five smb3/cifs fixes for stable (including for some leaks and memory overwrites) and also a few fixes for recent regressions in packet signing. Additional testing at the recent SMB3 test event, and some good work by Paulo and others spotted the issues fixed here. In addition to my xfstest runs on these, Aurelien and Stefano did additional test runs to verify this set" * tag '4.18-rc3-smb3fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: Fix stack out-of-bounds in smb{2,3}_create_lease_buf() cifs: Fix infinite loop when using hard mount option cifs: Fix slab-out-of-bounds in send_set_info() on SMB2 ACE setting cifs: Fix memory leak in smb2_set_ea() cifs: fix SMB1 breakage cifs: Fix validation of signed data in smb2 cifs: Fix validation of signed data in smb3+ cifs: Fix use after free of a mid_q_entry
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c10
-rw-r--r--fs/cifs/connect.c8
-rw-r--r--fs/cifs/smb1ops.c1
-rw-r--r--fs/cifs/smb2file.c11
-rw-r--r--fs/cifs/smb2ops.c14
-rw-r--r--fs/cifs/smb2pdu.c32
-rw-r--r--fs/cifs/smb2pdu.h6
-rw-r--r--fs/cifs/smb2proto.h4
-rw-r--r--fs/cifs/smb2transport.c60
-rw-r--r--fs/cifs/smbdirect.c5
-rw-r--r--fs/cifs/smbdirect.h4
-rw-r--r--fs/cifs/transport.c27
14 files changed, 132 insertions, 54 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index bd78da59a4fd..c923c7854027 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -423,7 +423,7 @@ struct smb_version_operations {
423 void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int, 423 void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int,
424 bool *); 424 bool *);
425 /* create lease context buffer for CREATE request */ 425 /* create lease context buffer for CREATE request */
426 char * (*create_lease_buf)(u8 *, u8); 426 char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
427 /* parse lease context buffer and return oplock/epoch info */ 427 /* parse lease context buffer and return oplock/epoch info */
428 __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey); 428 __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey);
429 ssize_t (*copychunk_range)(const unsigned int, 429 ssize_t (*copychunk_range)(const unsigned int,
@@ -1416,6 +1416,7 @@ typedef int (mid_handle_t)(struct TCP_Server_Info *server,
1416/* one of these for every pending CIFS request to the server */ 1416/* one of these for every pending CIFS request to the server */
1417struct mid_q_entry { 1417struct mid_q_entry {
1418 struct list_head qhead; /* mids waiting on reply from this server */ 1418 struct list_head qhead; /* mids waiting on reply from this server */
1419 struct kref refcount;
1419 struct TCP_Server_Info *server; /* server corresponding to this mid */ 1420 struct TCP_Server_Info *server; /* server corresponding to this mid */
1420 __u64 mid; /* multiplex id */ 1421 __u64 mid; /* multiplex id */
1421 __u32 pid; /* process id */ 1422 __u32 pid; /* process id */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 03018be17283..1890f534c88b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -82,6 +82,7 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
82 struct TCP_Server_Info *server); 82 struct TCP_Server_Info *server);
83extern void DeleteMidQEntry(struct mid_q_entry *midEntry); 83extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
84extern void cifs_delete_mid(struct mid_q_entry *mid); 84extern void cifs_delete_mid(struct mid_q_entry *mid);
85extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry);
85extern void cifs_wake_up_task(struct mid_q_entry *mid); 86extern void cifs_wake_up_task(struct mid_q_entry *mid);
86extern int cifs_handle_standard(struct TCP_Server_Info *server, 87extern int cifs_handle_standard(struct TCP_Server_Info *server,
87 struct mid_q_entry *mid); 88 struct mid_q_entry *mid);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d352da325de3..93408eab92e7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -157,8 +157,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
157 * greater than cifs socket timeout which is 7 seconds 157 * greater than cifs socket timeout which is 7 seconds
158 */ 158 */
159 while (server->tcpStatus == CifsNeedReconnect) { 159 while (server->tcpStatus == CifsNeedReconnect) {
160 wait_event_interruptible_timeout(server->response_q, 160 rc = wait_event_interruptible_timeout(server->response_q,
161 (server->tcpStatus != CifsNeedReconnect), 10 * HZ); 161 (server->tcpStatus != CifsNeedReconnect),
162 10 * HZ);
163 if (rc < 0) {
164 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
165 " signal by the process\n", __func__);
166 return -ERESTARTSYS;
167 }
162 168
163 /* are we still trying to reconnect? */ 169 /* are we still trying to reconnect? */
164 if (server->tcpStatus != CifsNeedReconnect) 170 if (server->tcpStatus != CifsNeedReconnect)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a57da1b88bdf..5df2c0698cda 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -924,6 +924,7 @@ next_pdu:
924 server->pdu_size = next_offset; 924 server->pdu_size = next_offset;
925 } 925 }
926 926
927 mid_entry = NULL;
927 if (server->ops->is_transform_hdr && 928 if (server->ops->is_transform_hdr &&
928 server->ops->receive_transform && 929 server->ops->receive_transform &&
929 server->ops->is_transform_hdr(buf)) { 930 server->ops->is_transform_hdr(buf)) {
@@ -938,8 +939,11 @@ next_pdu:
938 length = mid_entry->receive(server, mid_entry); 939 length = mid_entry->receive(server, mid_entry);
939 } 940 }
940 941
941 if (length < 0) 942 if (length < 0) {
943 if (mid_entry)
944 cifs_mid_q_entry_release(mid_entry);
942 continue; 945 continue;
946 }
943 947
944 if (server->large_buf) 948 if (server->large_buf)
945 buf = server->bigbuf; 949 buf = server->bigbuf;
@@ -956,6 +960,8 @@ next_pdu:
956 960
957 if (!mid_entry->multiRsp || mid_entry->multiEnd) 961 if (!mid_entry->multiRsp || mid_entry->multiEnd)
958 mid_entry->callback(mid_entry); 962 mid_entry->callback(mid_entry);
963
964 cifs_mid_q_entry_release(mid_entry);
959 } else if (server->ops->is_oplock_break && 965 } else if (server->ops->is_oplock_break &&
960 server->ops->is_oplock_break(buf, server)) { 966 server->ops->is_oplock_break(buf, server)) {
961 cifs_dbg(FYI, "Received oplock break\n"); 967 cifs_dbg(FYI, "Received oplock break\n");
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index aff8ce8ba34d..646dcd149de1 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -107,6 +107,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
107 if (compare_mid(mid->mid, buf) && 107 if (compare_mid(mid->mid, buf) &&
108 mid->mid_state == MID_REQUEST_SUBMITTED && 108 mid->mid_state == MID_REQUEST_SUBMITTED &&
109 le16_to_cpu(mid->command) == buf->Command) { 109 le16_to_cpu(mid->command) == buf->Command) {
110 kref_get(&mid->refcount);
110 spin_unlock(&GlobalMid_Lock); 111 spin_unlock(&GlobalMid_Lock);
111 return mid; 112 return mid;
112 } 113 }
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 788412675723..4ed10dd086e6 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -41,7 +41,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
41 int rc; 41 int rc;
42 __le16 *smb2_path; 42 __le16 *smb2_path;
43 struct smb2_file_all_info *smb2_data = NULL; 43 struct smb2_file_all_info *smb2_data = NULL;
44 __u8 smb2_oplock[17]; 44 __u8 smb2_oplock;
45 struct cifs_fid *fid = oparms->fid; 45 struct cifs_fid *fid = oparms->fid;
46 struct network_resiliency_req nr_ioctl_req; 46 struct network_resiliency_req nr_ioctl_req;
47 47
@@ -59,12 +59,9 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
59 } 59 }
60 60
61 oparms->desired_access |= FILE_READ_ATTRIBUTES; 61 oparms->desired_access |= FILE_READ_ATTRIBUTES;
62 *smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; 62 smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
63 63
64 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) 64 rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL,
65 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
66
67 rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
68 NULL); 65 NULL);
69 if (rc) 66 if (rc)
70 goto out; 67 goto out;
@@ -101,7 +98,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
101 move_smb2_info_to_cifs(buf, smb2_data); 98 move_smb2_info_to_cifs(buf, smb2_data);
102 } 99 }
103 100
104 *oplock = *smb2_oplock; 101 *oplock = smb2_oplock;
105out: 102out:
106 kfree(smb2_data); 103 kfree(smb2_data);
107 kfree(smb2_path); 104 kfree(smb2_path);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 0356b5559c71..ea92a38b2f08 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -203,6 +203,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
203 if ((mid->mid == wire_mid) && 203 if ((mid->mid == wire_mid) &&
204 (mid->mid_state == MID_REQUEST_SUBMITTED) && 204 (mid->mid_state == MID_REQUEST_SUBMITTED) &&
205 (mid->command == shdr->Command)) { 205 (mid->command == shdr->Command)) {
206 kref_get(&mid->refcount);
206 spin_unlock(&GlobalMid_Lock); 207 spin_unlock(&GlobalMid_Lock);
207 return mid; 208 return mid;
208 } 209 }
@@ -855,6 +856,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
855 856
856 rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea, 857 rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
857 len); 858 len);
859 kfree(ea);
860
858 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 861 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
859 862
860 return rc; 863 return rc;
@@ -2219,8 +2222,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
2219 if (!buf) 2222 if (!buf)
2220 return NULL; 2223 return NULL;
2221 2224
2222 buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key)); 2225 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
2223 buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
2224 buf->lcontext.LeaseState = map_oplock_to_lease(oplock); 2226 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
2225 2227
2226 buf->ccontext.DataOffset = cpu_to_le16(offsetof 2228 buf->ccontext.DataOffset = cpu_to_le16(offsetof
@@ -2246,8 +2248,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock)
2246 if (!buf) 2248 if (!buf)
2247 return NULL; 2249 return NULL;
2248 2250
2249 buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key)); 2251 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
2250 buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
2251 buf->lcontext.LeaseState = map_oplock_to_lease(oplock); 2252 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
2252 2253
2253 buf->ccontext.DataOffset = cpu_to_le16(offsetof 2254 buf->ccontext.DataOffset = cpu_to_le16(offsetof
@@ -2284,8 +2285,7 @@ smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
2284 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) 2285 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
2285 return SMB2_OPLOCK_LEVEL_NOCHANGE; 2286 return SMB2_OPLOCK_LEVEL_NOCHANGE;
2286 if (lease_key) 2287 if (lease_key)
2287 memcpy(lease_key, &lc->lcontext.LeaseKeyLow, 2288 memcpy(lease_key, &lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
2288 SMB2_LEASE_KEY_SIZE);
2289 return le32_to_cpu(lc->lcontext.LeaseState); 2289 return le32_to_cpu(lc->lcontext.LeaseState);
2290} 2290}
2291 2291
@@ -2521,7 +2521,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2521 if (!tr_hdr) 2521 if (!tr_hdr)
2522 goto err_free_iov; 2522 goto err_free_iov;
2523 2523
2524 orig_len = smb2_rqst_len(old_rq, false); 2524 orig_len = smb_rqst_len(server, old_rq);
2525 2525
2526 /* fill the 2nd iov with a transform header */ 2526 /* fill the 2nd iov with a transform header */
2527 fill_transform_hdr(tr_hdr, orig_len, old_rq); 2527 fill_transform_hdr(tr_hdr, orig_len, old_rq);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 810b85787c91..3c92678cb45b 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -155,7 +155,7 @@ out:
155static int 155static int
156smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) 156smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
157{ 157{
158 int rc = 0; 158 int rc;
159 struct nls_table *nls_codepage; 159 struct nls_table *nls_codepage;
160 struct cifs_ses *ses; 160 struct cifs_ses *ses;
161 struct TCP_Server_Info *server; 161 struct TCP_Server_Info *server;
@@ -166,10 +166,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
166 * for those three - in the calling routine. 166 * for those three - in the calling routine.
167 */ 167 */
168 if (tcon == NULL) 168 if (tcon == NULL)
169 return rc; 169 return 0;
170 170
171 if (smb2_command == SMB2_TREE_CONNECT) 171 if (smb2_command == SMB2_TREE_CONNECT)
172 return rc; 172 return 0;
173 173
174 if (tcon->tidStatus == CifsExiting) { 174 if (tcon->tidStatus == CifsExiting) {
175 /* 175 /*
@@ -212,8 +212,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
212 return -EAGAIN; 212 return -EAGAIN;
213 } 213 }
214 214
215 wait_event_interruptible_timeout(server->response_q, 215 rc = wait_event_interruptible_timeout(server->response_q,
216 (server->tcpStatus != CifsNeedReconnect), 10 * HZ); 216 (server->tcpStatus != CifsNeedReconnect),
217 10 * HZ);
218 if (rc < 0) {
219 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
220 " signal by the process\n", __func__);
221 return -ERESTARTSYS;
222 }
217 223
218 /* are we still trying to reconnect? */ 224 /* are we still trying to reconnect? */
219 if (server->tcpStatus != CifsNeedReconnect) 225 if (server->tcpStatus != CifsNeedReconnect)
@@ -231,7 +237,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
231 } 237 }
232 238
233 if (!tcon->ses->need_reconnect && !tcon->need_reconnect) 239 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
234 return rc; 240 return 0;
235 241
236 nls_codepage = load_nls_default(); 242 nls_codepage = load_nls_default();
237 243
@@ -340,7 +346,10 @@ smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
340 return rc; 346 return rc;
341 347
342 /* BB eventually switch this to SMB2 specific small buf size */ 348 /* BB eventually switch this to SMB2 specific small buf size */
343 *request_buf = cifs_small_buf_get(); 349 if (smb2_command == SMB2_SET_INFO)
350 *request_buf = cifs_buf_get();
351 else
352 *request_buf = cifs_small_buf_get();
344 if (*request_buf == NULL) { 353 if (*request_buf == NULL) {
345 /* BB should we add a retry in here if not a writepage? */ 354 /* BB should we add a retry in here if not a writepage? */
346 return -ENOMEM; 355 return -ENOMEM;
@@ -1707,12 +1716,12 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
1707 1716
1708static int 1717static int
1709add_lease_context(struct TCP_Server_Info *server, struct kvec *iov, 1718add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
1710 unsigned int *num_iovec, __u8 *oplock) 1719 unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
1711{ 1720{
1712 struct smb2_create_req *req = iov[0].iov_base; 1721 struct smb2_create_req *req = iov[0].iov_base;
1713 unsigned int num = *num_iovec; 1722 unsigned int num = *num_iovec;
1714 1723
1715 iov[num].iov_base = server->ops->create_lease_buf(oplock+1, *oplock); 1724 iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
1716 if (iov[num].iov_base == NULL) 1725 if (iov[num].iov_base == NULL)
1717 return -ENOMEM; 1726 return -ENOMEM;
1718 iov[num].iov_len = server->vals->create_lease_size; 1727 iov[num].iov_len = server->vals->create_lease_size;
@@ -2172,7 +2181,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
2172 *oplock == SMB2_OPLOCK_LEVEL_NONE) 2181 *oplock == SMB2_OPLOCK_LEVEL_NONE)
2173 req->RequestedOplockLevel = *oplock; 2182 req->RequestedOplockLevel = *oplock;
2174 else { 2183 else {
2175 rc = add_lease_context(server, iov, &n_iov, oplock); 2184 rc = add_lease_context(server, iov, &n_iov,
2185 oparms->fid->lease_key, oplock);
2176 if (rc) { 2186 if (rc) {
2177 cifs_small_buf_release(req); 2187 cifs_small_buf_release(req);
2178 kfree(copy_path); 2188 kfree(copy_path);
@@ -3720,7 +3730,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
3720 3730
3721 rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, 3731 rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
3722 &rsp_iov); 3732 &rsp_iov);
3723 cifs_small_buf_release(req); 3733 cifs_buf_release(req);
3724 rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; 3734 rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
3725 3735
3726 if (rc != 0) { 3736 if (rc != 0) {
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 824dddeee3f2..a671adcc44a6 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -678,16 +678,14 @@ struct create_context {
678#define SMB2_LEASE_KEY_SIZE 16 678#define SMB2_LEASE_KEY_SIZE 16
679 679
680struct lease_context { 680struct lease_context {
681 __le64 LeaseKeyLow; 681 u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
682 __le64 LeaseKeyHigh;
683 __le32 LeaseState; 682 __le32 LeaseState;
684 __le32 LeaseFlags; 683 __le32 LeaseFlags;
685 __le64 LeaseDuration; 684 __le64 LeaseDuration;
686} __packed; 685} __packed;
687 686
688struct lease_context_v2 { 687struct lease_context_v2 {
689 __le64 LeaseKeyLow; 688 u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
690 __le64 LeaseKeyHigh;
691 __le32 LeaseState; 689 __le32 LeaseState;
692 __le32 LeaseFlags; 690 __le32 LeaseFlags;
693 __le64 LeaseDuration; 691 __le64 LeaseDuration;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 3ae208ac2a77..6e6a4f2ec890 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -113,8 +113,8 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile,
113extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); 113extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
114extern void smb2_reconnect_server(struct work_struct *work); 114extern void smb2_reconnect_server(struct work_struct *work);
115extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); 115extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
116extern unsigned long 116extern unsigned long smb_rqst_len(struct TCP_Server_Info *server,
117smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker); 117 struct smb_rqst *rqst);
118 118
119/* 119/*
120 * SMB2 Worker functions - most of protocol specific implementation details 120 * SMB2 Worker functions - most of protocol specific implementation details
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 51b9437c3c7b..719d55e63d88 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -173,6 +173,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
173 struct kvec *iov = rqst->rq_iov; 173 struct kvec *iov = rqst->rq_iov;
174 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; 174 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
175 struct cifs_ses *ses; 175 struct cifs_ses *ses;
176 struct shash_desc *shash = &server->secmech.sdeschmacsha256->shash;
177 struct smb_rqst drqst;
176 178
177 ses = smb2_find_smb_ses(server, shdr->SessionId); 179 ses = smb2_find_smb_ses(server, shdr->SessionId);
178 if (!ses) { 180 if (!ses) {
@@ -190,21 +192,39 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
190 } 192 }
191 193
192 rc = crypto_shash_setkey(server->secmech.hmacsha256, 194 rc = crypto_shash_setkey(server->secmech.hmacsha256,
193 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); 195 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
194 if (rc) { 196 if (rc) {
195 cifs_dbg(VFS, "%s: Could not update with response\n", __func__); 197 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
196 return rc; 198 return rc;
197 } 199 }
198 200
199 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); 201 rc = crypto_shash_init(shash);
200 if (rc) { 202 if (rc) {
201 cifs_dbg(VFS, "%s: Could not init sha256", __func__); 203 cifs_dbg(VFS, "%s: Could not init sha256", __func__);
202 return rc; 204 return rc;
203 } 205 }
204 206
205 rc = __cifs_calc_signature(rqst, server, sigptr, 207 /*
206 &server->secmech.sdeschmacsha256->shash); 208 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
209 * data, that is, iov[0] should not contain a rfc1002 length.
210 *
211 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
212 * __cifs_calc_signature().
213 */
214 drqst = *rqst;
215 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
216 rc = crypto_shash_update(shash, iov[0].iov_base,
217 iov[0].iov_len);
218 if (rc) {
219 cifs_dbg(VFS, "%s: Could not update with payload\n",
220 __func__);
221 return rc;
222 }
223 drqst.rq_iov++;
224 drqst.rq_nvec--;
225 }
207 226
227 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
208 if (!rc) 228 if (!rc)
209 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); 229 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
210 230
@@ -408,12 +428,14 @@ generate_smb311signingkey(struct cifs_ses *ses)
408int 428int
409smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) 429smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
410{ 430{
411 int rc = 0; 431 int rc;
412 unsigned char smb3_signature[SMB2_CMACAES_SIZE]; 432 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
413 unsigned char *sigptr = smb3_signature; 433 unsigned char *sigptr = smb3_signature;
414 struct kvec *iov = rqst->rq_iov; 434 struct kvec *iov = rqst->rq_iov;
415 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; 435 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
416 struct cifs_ses *ses; 436 struct cifs_ses *ses;
437 struct shash_desc *shash = &server->secmech.sdesccmacaes->shash;
438 struct smb_rqst drqst;
417 439
418 ses = smb2_find_smb_ses(server, shdr->SessionId); 440 ses = smb2_find_smb_ses(server, shdr->SessionId);
419 if (!ses) { 441 if (!ses) {
@@ -425,8 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
425 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); 447 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
426 448
427 rc = crypto_shash_setkey(server->secmech.cmacaes, 449 rc = crypto_shash_setkey(server->secmech.cmacaes,
428 ses->smb3signingkey, SMB2_CMACAES_SIZE); 450 ses->smb3signingkey, SMB2_CMACAES_SIZE);
429
430 if (rc) { 451 if (rc) {
431 cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); 452 cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
432 return rc; 453 return rc;
@@ -437,15 +458,33 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
437 * so unlike smb2 case we do not have to check here if secmech are 458 * so unlike smb2 case we do not have to check here if secmech are
438 * initialized 459 * initialized
439 */ 460 */
440 rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash); 461 rc = crypto_shash_init(shash);
441 if (rc) { 462 if (rc) {
442 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); 463 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
443 return rc; 464 return rc;
444 } 465 }
445 466
446 rc = __cifs_calc_signature(rqst, server, sigptr, 467 /*
447 &server->secmech.sdesccmacaes->shash); 468 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
469 * data, that is, iov[0] should not contain a rfc1002 length.
470 *
471 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
472 * __cifs_calc_signature().
473 */
474 drqst = *rqst;
475 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
476 rc = crypto_shash_update(shash, iov[0].iov_base,
477 iov[0].iov_len);
478 if (rc) {
479 cifs_dbg(VFS, "%s: Could not update with payload\n",
480 __func__);
481 return rc;
482 }
483 drqst.rq_iov++;
484 drqst.rq_nvec--;
485 }
448 486
487 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
449 if (!rc) 488 if (!rc)
450 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); 489 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
451 490
@@ -548,6 +587,7 @@ smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
548 587
549 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS); 588 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
550 memset(temp, 0, sizeof(struct mid_q_entry)); 589 memset(temp, 0, sizeof(struct mid_q_entry));
590 kref_init(&temp->refcount);
551 temp->mid = le64_to_cpu(shdr->MessageId); 591 temp->mid = le64_to_cpu(shdr->MessageId);
552 temp->pid = current->pid; 592 temp->pid = current->pid;
553 temp->command = shdr->Command; /* Always LE */ 593 temp->command = shdr->Command; /* Always LE */
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 6fd94d9ffac2..c55ea4e6201b 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2083,8 +2083,9 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
2083 * rqst: the data to write 2083 * rqst: the data to write
2084 * return value: 0 if successfully write, otherwise error code 2084 * return value: 0 if successfully write, otherwise error code
2085 */ 2085 */
2086int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) 2086int smbd_send(struct TCP_Server_Info *server, struct smb_rqst *rqst)
2087{ 2087{
2088 struct smbd_connection *info = server->smbd_conn;
2088 struct kvec vec; 2089 struct kvec vec;
2089 int nvecs; 2090 int nvecs;
2090 int size; 2091 int size;
@@ -2118,7 +2119,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2118 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and 2119 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
2119 * ends at page boundary 2120 * ends at page boundary
2120 */ 2121 */
2121 buflen = smb2_rqst_len(rqst, true); 2122 buflen = smb_rqst_len(server, rqst);
2122 2123
2123 if (buflen + sizeof(struct smbd_data_transfer) > 2124 if (buflen + sizeof(struct smbd_data_transfer) >
2124 info->max_fragmented_send_size) { 2125 info->max_fragmented_send_size) {
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
index 1e419c21dc60..a11096254f29 100644
--- a/fs/cifs/smbdirect.h
+++ b/fs/cifs/smbdirect.h
@@ -292,7 +292,7 @@ void smbd_destroy(struct smbd_connection *info);
292 292
293/* Interface for carrying upper layer I/O through send/recv */ 293/* Interface for carrying upper layer I/O through send/recv */
294int smbd_recv(struct smbd_connection *info, struct msghdr *msg); 294int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
295int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst); 295int smbd_send(struct TCP_Server_Info *server, struct smb_rqst *rqst);
296 296
297enum mr_state { 297enum mr_state {
298 MR_READY, 298 MR_READY,
@@ -332,7 +332,7 @@ static inline void *smbd_get_connection(
332static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; } 332static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
333static inline void smbd_destroy(struct smbd_connection *info) {} 333static inline void smbd_destroy(struct smbd_connection *info) {}
334static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; } 334static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
335static inline int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) {return -1; } 335static inline int smbd_send(struct TCP_Server_Info *server, struct smb_rqst *rqst) {return -1; }
336#endif 336#endif
337 337
338#endif 338#endif
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index fb57dfbfb749..a341ec839c83 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -61,6 +61,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
61 61
62 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS); 62 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
63 memset(temp, 0, sizeof(struct mid_q_entry)); 63 memset(temp, 0, sizeof(struct mid_q_entry));
64 kref_init(&temp->refcount);
64 temp->mid = get_mid(smb_buffer); 65 temp->mid = get_mid(smb_buffer);
65 temp->pid = current->pid; 66 temp->pid = current->pid;
66 temp->command = cpu_to_le16(smb_buffer->Command); 67 temp->command = cpu_to_le16(smb_buffer->Command);
@@ -82,6 +83,21 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
82 return temp; 83 return temp;
83} 84}
84 85
86static void _cifs_mid_q_entry_release(struct kref *refcount)
87{
88 struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
89 refcount);
90
91 mempool_free(mid, cifs_mid_poolp);
92}
93
94void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
95{
96 spin_lock(&GlobalMid_Lock);
97 kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
98 spin_unlock(&GlobalMid_Lock);
99}
100
85void 101void
86DeleteMidQEntry(struct mid_q_entry *midEntry) 102DeleteMidQEntry(struct mid_q_entry *midEntry)
87{ 103{
@@ -110,7 +126,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
110 } 126 }
111 } 127 }
112#endif 128#endif
113 mempool_free(midEntry, cifs_mid_poolp); 129 cifs_mid_q_entry_release(midEntry);
114} 130}
115 131
116void 132void
@@ -202,14 +218,15 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
202} 218}
203 219
204unsigned long 220unsigned long
205smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker) 221smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
206{ 222{
207 unsigned int i; 223 unsigned int i;
208 struct kvec *iov; 224 struct kvec *iov;
209 int nvec; 225 int nvec;
210 unsigned long buflen = 0; 226 unsigned long buflen = 0;
211 227
212 if (skip_rfc1002_marker && rqst->rq_iov[0].iov_len == 4) { 228 if (server->vals->header_preamble_size == 0 &&
229 rqst->rq_nvec >= 2 && rqst->rq_iov[0].iov_len == 4) {
213 iov = &rqst->rq_iov[1]; 230 iov = &rqst->rq_iov[1];
214 nvec = rqst->rq_nvec - 1; 231 nvec = rqst->rq_nvec - 1;
215 } else { 232 } else {
@@ -260,7 +277,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
260 __be32 rfc1002_marker; 277 __be32 rfc1002_marker;
261 278
262 if (cifs_rdma_enabled(server) && server->smbd_conn) { 279 if (cifs_rdma_enabled(server) && server->smbd_conn) {
263 rc = smbd_send(server->smbd_conn, rqst); 280 rc = smbd_send(server, rqst);
264 goto smbd_done; 281 goto smbd_done;
265 } 282 }
266 if (ssocket == NULL) 283 if (ssocket == NULL)
@@ -271,7 +288,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
271 (char *)&val, sizeof(val)); 288 (char *)&val, sizeof(val));
272 289
273 for (j = 0; j < num_rqst; j++) 290 for (j = 0; j < num_rqst; j++)
274 send_length += smb2_rqst_len(&rqst[j], true); 291 send_length += smb_rqst_len(server, &rqst[j]);
275 rfc1002_marker = cpu_to_be32(send_length); 292 rfc1002_marker = cpu_to_be32(send_length);
276 293
277 /* Generate a rfc1002 marker for SMB2+ */ 294 /* Generate a rfc1002 marker for SMB2+ */