aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilov@microsoft.com>2016-11-23 18:14:57 -0500
committerSteve French <smfrench@gmail.com>2017-02-01 17:46:35 -0500
commit738f9de5cdb9175c19d24cfdf90b4543fc3b47bf (patch)
tree121fd4b54bec97e745cf6e6beb093b34408afd17
parentfb2036d817584df42504910fe104f68517e8990e (diff)
CIFS: Send RFC1001 length in a separate iov
In order to simplify further encryption support we need to separate RFC1001 length and SMB2 header when sending a request. Put the length field in iov[0] and the rest of the packet into following iovs. Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
-rw-r--r--fs/cifs/cifsencrypt.c38
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifssmb.c51
-rw-r--r--fs/cifs/smb2pdu.c64
-rw-r--r--fs/cifs/smb2transport.c28
-rw-r--r--fs/cifs/transport.c86
6 files changed, 174 insertions, 95 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 66bd7fa9b7a6..d8af15f19dd8 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -75,24 +75,20 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
75 struct kvec *iov = rqst->rq_iov; 75 struct kvec *iov = rqst->rq_iov;
76 int n_vec = rqst->rq_nvec; 76 int n_vec = rqst->rq_nvec;
77 77
78 for (i = 0; i < n_vec; i++) { 78 if (n_vec < 2 || iov[0].iov_len != 4)
79 return -EIO;
80
81 for (i = 1; i < n_vec; i++) {
79 if (iov[i].iov_len == 0) 82 if (iov[i].iov_len == 0)
80 continue; 83 continue;
81 if (iov[i].iov_base == NULL) { 84 if (iov[i].iov_base == NULL) {
82 cifs_dbg(VFS, "null iovec entry\n"); 85 cifs_dbg(VFS, "null iovec entry\n");
83 return -EIO; 86 return -EIO;
84 } 87 }
85 /* The first entry includes a length field (which does not get 88 if (i == 1 && iov[1].iov_len <= 4)
86 signed that occupies the first 4 bytes before the header */ 89 break; /* nothing to sign or corrupt header */
87 if (i == 0) { 90 rc = crypto_shash_update(shash,
88 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 91 iov[i].iov_base, iov[i].iov_len);
89 break; /* nothing to sign or corrupt header */
90 rc = crypto_shash_update(shash,
91 iov[i].iov_base + 4, iov[i].iov_len - 4);
92 } else {
93 rc = crypto_shash_update(shash,
94 iov[i].iov_base, iov[i].iov_len);
95 }
96 if (rc) { 92 if (rc) {
97 cifs_dbg(VFS, "%s: Could not update with payload\n", 93 cifs_dbg(VFS, "%s: Could not update with payload\n",
98 __func__); 94 __func__);
@@ -168,6 +164,10 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
168 char smb_signature[20]; 164 char smb_signature[20];
169 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 165 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
170 166
167 if (rqst->rq_iov[0].iov_len != 4 ||
168 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
169 return -EIO;
170
171 if ((cifs_pdu == NULL) || (server == NULL)) 171 if ((cifs_pdu == NULL) || (server == NULL))
172 return -EINVAL; 172 return -EINVAL;
173 173
@@ -209,12 +209,14 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
209int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 209int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
210 __u32 *pexpected_response_sequence_number) 210 __u32 *pexpected_response_sequence_number)
211{ 211{
212 struct kvec iov; 212 struct kvec iov[2];
213 213
214 iov.iov_base = cifs_pdu; 214 iov[0].iov_base = cifs_pdu;
215 iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; 215 iov[0].iov_len = 4;
216 iov[1].iov_base = (char *)cifs_pdu + 4;
217 iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
216 218
217 return cifs_sign_smbv(&iov, 1, server, 219 return cifs_sign_smbv(iov, 2, server,
218 pexpected_response_sequence_number); 220 pexpected_response_sequence_number);
219} 221}
220 222
@@ -227,6 +229,10 @@ int cifs_verify_signature(struct smb_rqst *rqst,
227 char what_we_think_sig_should_be[20]; 229 char what_we_think_sig_should_be[20];
228 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 230 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
229 231
232 if (rqst->rq_iov[0].iov_len != 4 ||
233 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
234 return -EIO;
235
230 if (cifs_pdu == NULL || server == NULL) 236 if (cifs_pdu == NULL || server == NULL)
231 return -EINVAL; 237 return -EINVAL;
232 238
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6d5fc87ba335..eb0ffac73f90 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1119,7 +1119,7 @@ struct cifs_readdata {
1119 int (*read_into_pages)(struct TCP_Server_Info *server, 1119 int (*read_into_pages)(struct TCP_Server_Info *server,
1120 struct cifs_readdata *rdata, 1120 struct cifs_readdata *rdata,
1121 unsigned int len); 1121 unsigned int len);
1122 struct kvec iov; 1122 struct kvec iov[2];
1123 unsigned int pagesz; 1123 unsigned int pagesz;
1124 unsigned int tailsz; 1124 unsigned int tailsz;
1125 unsigned int credits; 1125 unsigned int credits;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 609ce335e6ac..be9fa7ffe799 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -708,9 +708,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
708{ 708{
709 ECHO_REQ *smb; 709 ECHO_REQ *smb;
710 int rc = 0; 710 int rc = 0;
711 struct kvec iov; 711 struct kvec iov[2];
712 struct smb_rqst rqst = { .rq_iov = &iov, 712 struct smb_rqst rqst = { .rq_iov = iov,
713 .rq_nvec = 1 }; 713 .rq_nvec = 2 };
714 714
715 cifs_dbg(FYI, "In echo request\n"); 715 cifs_dbg(FYI, "In echo request\n");
716 716
@@ -725,8 +725,11 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
725 put_bcc(1, &smb->hdr); 725 put_bcc(1, &smb->hdr);
726 smb->Data[0] = 'a'; 726 smb->Data[0] = 'a';
727 inc_rfc1001_len(smb, 3); 727 inc_rfc1001_len(smb, 3);
728 iov.iov_base = smb; 728
729 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; 729 iov[0].iov_len = 4;
730 iov[0].iov_base = smb;
731 iov[1].iov_len = get_rfc1002_length(smb);
732 iov[1].iov_base = (char *)smb + 4;
730 733
731 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, 734 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
732 server, CIFS_ASYNC_OP | CIFS_ECHO_OP); 735 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
@@ -1509,10 +1512,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1509 } 1512 }
1510 1513
1511 /* set up first iov for signature check */ 1514 /* set up first iov for signature check */
1512 rdata->iov.iov_base = buf; 1515 rdata->iov[0].iov_base = buf;
1513 rdata->iov.iov_len = server->total_read; 1516 rdata->iov[0].iov_len = 4;
1514 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", 1517 rdata->iov[1].iov_base = buf + 4;
1515 rdata->iov.iov_base, rdata->iov.iov_len); 1518 rdata->iov[1].iov_len = server->total_read - 4;
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1520 rdata->iov[0].iov_base, server->total_read);
1516 1521
1517 /* how much data is in the response? */ 1522 /* how much data is in the response? */
1518 data_len = server->ops->read_data_length(buf); 1523 data_len = server->ops->read_data_length(buf);
@@ -1545,8 +1550,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
1545 struct cifs_readdata *rdata = mid->callback_data; 1550 struct cifs_readdata *rdata = mid->callback_data;
1546 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1551 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1547 struct TCP_Server_Info *server = tcon->ses->server; 1552 struct TCP_Server_Info *server = tcon->ses->server;
1548 struct smb_rqst rqst = { .rq_iov = &rdata->iov, 1553 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1549 .rq_nvec = 1, 1554 .rq_nvec = 2,
1550 .rq_pages = rdata->pages, 1555 .rq_pages = rdata->pages,
1551 .rq_npages = rdata->nr_pages, 1556 .rq_npages = rdata->nr_pages,
1552 .rq_pagesz = rdata->pagesz, 1557 .rq_pagesz = rdata->pagesz,
@@ -1601,8 +1606,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
1601 READ_REQ *smb = NULL; 1606 READ_REQ *smb = NULL;
1602 int wct; 1607 int wct;
1603 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1608 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1604 struct smb_rqst rqst = { .rq_iov = &rdata->iov, 1609 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1605 .rq_nvec = 1 }; 1610 .rq_nvec = 2 };
1606 1611
1607 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", 1612 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1608 __func__, rdata->offset, rdata->bytes); 1613 __func__, rdata->offset, rdata->bytes);
@@ -1642,8 +1647,10 @@ cifs_async_readv(struct cifs_readdata *rdata)
1642 } 1647 }
1643 1648
1644 /* 4 for RFC1001 length + 1 for BCC */ 1649 /* 4 for RFC1001 length + 1 for BCC */
1645 rdata->iov.iov_base = smb; 1650 rdata->iov[0].iov_base = smb;
1646 rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; 1651 rdata->iov[0].iov_len = 4;
1652 rdata->iov[1].iov_base = (char *)smb + 4;
1653 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1647 1654
1648 kref_get(&rdata->refcount); 1655 kref_get(&rdata->refcount);
1649 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, 1656 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
@@ -2096,7 +2103,7 @@ cifs_async_writev(struct cifs_writedata *wdata,
2096 WRITE_REQ *smb = NULL; 2103 WRITE_REQ *smb = NULL;
2097 int wct; 2104 int wct;
2098 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 2105 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2099 struct kvec iov; 2106 struct kvec iov[2];
2100 struct smb_rqst rqst = { }; 2107 struct smb_rqst rqst = { };
2101 2108
2102 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 2109 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -2129,11 +2136,13 @@ cifs_async_writev(struct cifs_writedata *wdata,
2129 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); 2136 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2130 2137
2131 /* 4 for RFC1001 length + 1 for BCC */ 2138 /* 4 for RFC1001 length + 1 for BCC */
2132 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; 2139 iov[0].iov_len = 4;
2133 iov.iov_base = smb; 2140 iov[0].iov_base = smb;
2141 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2142 iov[1].iov_base = (char *)smb + 4;
2134 2143
2135 rqst.rq_iov = &iov; 2144 rqst.rq_iov = iov;
2136 rqst.rq_nvec = 1; 2145 rqst.rq_nvec = 2;
2137 rqst.rq_pages = wdata->pages; 2146 rqst.rq_pages = wdata->pages;
2138 rqst.rq_npages = wdata->nr_pages; 2147 rqst.rq_npages = wdata->nr_pages;
2139 rqst.rq_pagesz = wdata->pagesz; 2148 rqst.rq_pagesz = wdata->pagesz;
@@ -2154,7 +2163,7 @@ cifs_async_writev(struct cifs_writedata *wdata,
2154 (struct smb_com_writex_req *)smb; 2163 (struct smb_com_writex_req *)smb;
2155 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); 2164 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2156 put_bcc(wdata->bytes + 5, &smbw->hdr); 2165 put_bcc(wdata->bytes + 5, &smbw->hdr);
2157 iov.iov_len += 4; /* pad bigger by four bytes */ 2166 iov[1].iov_len += 4; /* pad bigger by four bytes */
2158 } 2167 }
2159 2168
2160 kref_get(&wdata->refcount); 2169 kref_get(&wdata->refcount);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index fb6cf1b68dc5..438c4b108c07 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2047,9 +2047,9 @@ SMB2_echo(struct TCP_Server_Info *server)
2047{ 2047{
2048 struct smb2_echo_req *req; 2048 struct smb2_echo_req *req;
2049 int rc = 0; 2049 int rc = 0;
2050 struct kvec iov; 2050 struct kvec iov[2];
2051 struct smb_rqst rqst = { .rq_iov = &iov, 2051 struct smb_rqst rqst = { .rq_iov = iov,
2052 .rq_nvec = 1 }; 2052 .rq_nvec = 2 };
2053 2053
2054 cifs_dbg(FYI, "In echo request\n"); 2054 cifs_dbg(FYI, "In echo request\n");
2055 2055
@@ -2065,9 +2065,11 @@ SMB2_echo(struct TCP_Server_Info *server)
2065 2065
2066 req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1); 2066 req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
2067 2067
2068 iov.iov_base = (char *)req;
2069 /* 4 for rfc1002 length field */ 2068 /* 4 for rfc1002 length field */
2070 iov.iov_len = get_rfc1002_length(req) + 4; 2069 iov[0].iov_len = 4;
2070 iov[0].iov_base = (char *)req;
2071 iov[1].iov_len = get_rfc1002_length(req);
2072 iov[1].iov_base = (char *)req + 4;
2071 2073
2072 rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server, 2074 rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server,
2073 CIFS_ECHO_OP); 2075 CIFS_ECHO_OP);
@@ -2123,8 +2125,9 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
2123 * have the end_of_chain boolean set to true. 2125 * have the end_of_chain boolean set to true.
2124 */ 2126 */
2125static int 2127static int
2126smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, 2128smb2_new_read_req(void **buf, unsigned int *total_len,
2127 unsigned int remaining_bytes, int request_type) 2129 struct cifs_io_parms *io_parms, unsigned int remaining_bytes,
2130 int request_type)
2128{ 2131{
2129 int rc = -EACCES; 2132 int rc = -EACCES;
2130 struct smb2_read_req *req = NULL; 2133 struct smb2_read_req *req = NULL;
@@ -2172,9 +2175,9 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
2172 else 2175 else
2173 req->RemainingBytes = 0; 2176 req->RemainingBytes = 0;
2174 2177
2175 iov[0].iov_base = (char *)req; 2178 *buf = req;
2176 /* 4 for rfc1002 length field */ 2179 /* 4 for rfc1002 length field */
2177 iov[0].iov_len = get_rfc1002_length(req) + 4; 2180 *total_len = get_rfc1002_length(req) + 4;
2178 return rc; 2181 return rc;
2179} 2182}
2180 2183
@@ -2184,10 +2187,11 @@ smb2_readv_callback(struct mid_q_entry *mid)
2184 struct cifs_readdata *rdata = mid->callback_data; 2187 struct cifs_readdata *rdata = mid->callback_data;
2185 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 2188 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
2186 struct TCP_Server_Info *server = tcon->ses->server; 2189 struct TCP_Server_Info *server = tcon->ses->server;
2187 struct smb2_sync_hdr *shdr = get_sync_hdr(rdata->iov.iov_base); 2190 struct smb2_sync_hdr *shdr =
2191 (struct smb2_sync_hdr *)rdata->iov[1].iov_base;
2188 unsigned int credits_received = 1; 2192 unsigned int credits_received = 1;
2189 struct smb_rqst rqst = { .rq_iov = &rdata->iov, 2193 struct smb_rqst rqst = { .rq_iov = rdata->iov,
2190 .rq_nvec = 1, 2194 .rq_nvec = 2,
2191 .rq_pages = rdata->pages, 2195 .rq_pages = rdata->pages,
2192 .rq_npages = rdata->nr_pages, 2196 .rq_npages = rdata->nr_pages,
2193 .rq_pagesz = rdata->pagesz, 2197 .rq_pagesz = rdata->pagesz,
@@ -2238,7 +2242,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
2238 add_credits(server, credits_received, 0); 2242 add_credits(server, credits_received, 0);
2239} 2243}
2240 2244
2241/* smb2_async_readv - send an async write, and set up mid to handle result */ 2245/* smb2_async_readv - send an async read, and set up mid to handle result */
2242int 2246int
2243smb2_async_readv(struct cifs_readdata *rdata) 2247smb2_async_readv(struct cifs_readdata *rdata)
2244{ 2248{
@@ -2246,9 +2250,10 @@ smb2_async_readv(struct cifs_readdata *rdata)
2246 char *buf; 2250 char *buf;
2247 struct smb2_sync_hdr *shdr; 2251 struct smb2_sync_hdr *shdr;
2248 struct cifs_io_parms io_parms; 2252 struct cifs_io_parms io_parms;
2249 struct smb_rqst rqst = { .rq_iov = &rdata->iov, 2253 struct smb_rqst rqst = { .rq_iov = rdata->iov,
2250 .rq_nvec = 1 }; 2254 .rq_nvec = 2 };
2251 struct TCP_Server_Info *server; 2255 struct TCP_Server_Info *server;
2256 unsigned int total_len;
2252 2257
2253 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", 2258 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
2254 __func__, rdata->offset, rdata->bytes); 2259 __func__, rdata->offset, rdata->bytes);
@@ -2262,7 +2267,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
2262 2267
2263 server = io_parms.tcon->ses->server; 2268 server = io_parms.tcon->ses->server;
2264 2269
2265 rc = smb2_new_read_req(&rdata->iov, &io_parms, 0, 0); 2270 rc = smb2_new_read_req((void **) &buf, &total_len, &io_parms, 0, 0);
2266 if (rc) { 2271 if (rc) {
2267 if (rc == -EAGAIN && rdata->credits) { 2272 if (rc == -EAGAIN && rdata->credits) {
2268 /* credits was reset by reconnect */ 2273 /* credits was reset by reconnect */
@@ -2275,10 +2280,12 @@ smb2_async_readv(struct cifs_readdata *rdata)
2275 return rc; 2280 return rc;
2276 } 2281 }
2277 2282
2278 buf = rdata->iov.iov_base;
2279 shdr = get_sync_hdr(buf); 2283 shdr = get_sync_hdr(buf);
2280 /* 4 for rfc1002 length field */ 2284 /* 4 for rfc1002 length field */
2281 rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4; 2285 rdata->iov[0].iov_len = 4;
2286 rdata->iov[0].iov_base = buf;
2287 rdata->iov[1].iov_len = total_len - 4;
2288 rdata->iov[1].iov_base = buf + 4;
2282 2289
2283 if (rdata->credits) { 2290 if (rdata->credits) {
2284 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, 2291 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
@@ -2314,12 +2321,17 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
2314 struct smb2_sync_hdr *shdr; 2321 struct smb2_sync_hdr *shdr;
2315 struct kvec iov[1]; 2322 struct kvec iov[1];
2316 struct kvec rsp_iov; 2323 struct kvec rsp_iov;
2324 unsigned int total_len;
2325 char *req;
2317 2326
2318 *nbytes = 0; 2327 *nbytes = 0;
2319 rc = smb2_new_read_req(iov, io_parms, 0, 0); 2328 rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0);
2320 if (rc) 2329 if (rc)
2321 return rc; 2330 return rc;
2322 2331
2332 iov[0].iov_base = buf;
2333 iov[0].iov_len = total_len;
2334
2323 rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1, 2335 rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1,
2324 &resp_buftype, CIFS_LOG_ERROR, &rsp_iov); 2336 &resp_buftype, CIFS_LOG_ERROR, &rsp_iov);
2325 cifs_small_buf_release(iov[0].iov_base); 2337 cifs_small_buf_release(iov[0].iov_base);
@@ -2424,8 +2436,8 @@ smb2_async_writev(struct cifs_writedata *wdata,
2424 struct smb2_sync_hdr *shdr; 2436 struct smb2_sync_hdr *shdr;
2425 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 2437 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2426 struct TCP_Server_Info *server = tcon->ses->server; 2438 struct TCP_Server_Info *server = tcon->ses->server;
2427 struct kvec iov; 2439 struct kvec iov[2];
2428 struct smb_rqst rqst; 2440 struct smb_rqst rqst = { };
2429 2441
2430 rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); 2442 rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req);
2431 if (rc) { 2443 if (rc) {
@@ -2455,11 +2467,13 @@ smb2_async_writev(struct cifs_writedata *wdata,
2455 req->RemainingBytes = 0; 2467 req->RemainingBytes = 0;
2456 2468
2457 /* 4 for rfc1002 length field and 1 for Buffer */ 2469 /* 4 for rfc1002 length field and 1 for Buffer */
2458 iov.iov_len = get_rfc1002_length(req) + 4 - 1; 2470 iov[0].iov_len = 4;
2459 iov.iov_base = req; 2471 iov[0].iov_base = req;
2472 iov[1].iov_len = get_rfc1002_length(req) - 1;
2473 iov[1].iov_base = (char *)req + 4;
2460 2474
2461 rqst.rq_iov = &iov; 2475 rqst.rq_iov = iov;
2462 rqst.rq_nvec = 1; 2476 rqst.rq_nvec = 2;
2463 rqst.rq_pages = wdata->pages; 2477 rqst.rq_pages = wdata->pages;
2464 rqst.rq_npages = wdata->nr_pages; 2478 rqst.rq_npages = wdata->nr_pages;
2465 rqst.rq_pagesz = wdata->pagesz; 2479 rqst.rq_pagesz = wdata->pagesz;
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 52ff937fd1ed..93b27752b634 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -138,7 +138,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
138 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; 138 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
139 unsigned char *sigptr = smb2_signature; 139 unsigned char *sigptr = smb2_signature;
140 struct kvec *iov = rqst->rq_iov; 140 struct kvec *iov = rqst->rq_iov;
141 struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base); 141 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
142 struct cifs_ses *ses; 142 struct cifs_ses *ses;
143 143
144 ses = smb2_find_smb_ses(shdr, server); 144 ses = smb2_find_smb_ses(shdr, server);
@@ -355,7 +355,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
355 unsigned char smb3_signature[SMB2_CMACAES_SIZE]; 355 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
356 unsigned char *sigptr = smb3_signature; 356 unsigned char *sigptr = smb3_signature;
357 struct kvec *iov = rqst->rq_iov; 357 struct kvec *iov = rqst->rq_iov;
358 struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base); 358 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
359 struct cifs_ses *ses; 359 struct cifs_ses *ses;
360 360
361 ses = smb2_find_smb_ses(shdr, server); 361 ses = smb2_find_smb_ses(shdr, server);
@@ -400,7 +400,8 @@ static int
400smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) 400smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
401{ 401{
402 int rc = 0; 402 int rc = 0;
403 struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); 403 struct smb2_sync_hdr *shdr =
404 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
404 405
405 if (!(shdr->Flags & SMB2_FLAGS_SIGNED) || 406 if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
406 server->tcpStatus == CifsNeedNegotiate) 407 server->tcpStatus == CifsNeedNegotiate)
@@ -421,7 +422,8 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
421{ 422{
422 unsigned int rc; 423 unsigned int rc;
423 char server_response_sig[16]; 424 char server_response_sig[16];
424 struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); 425 struct smb2_sync_hdr *shdr =
426 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
425 427
426 if ((shdr->Command == SMB2_NEGOTIATE) || 428 if ((shdr->Command == SMB2_NEGOTIATE) ||
427 (shdr->Command == SMB2_SESSION_SETUP) || 429 (shdr->Command == SMB2_SESSION_SETUP) ||
@@ -550,12 +552,14 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
550 bool log_error) 552 bool log_error)
551{ 553{
552 unsigned int len = get_rfc1002_length(mid->resp_buf); 554 unsigned int len = get_rfc1002_length(mid->resp_buf);
553 struct kvec iov; 555 struct kvec iov[2];
554 struct smb_rqst rqst = { .rq_iov = &iov, 556 struct smb_rqst rqst = { .rq_iov = iov,
555 .rq_nvec = 1 }; 557 .rq_nvec = 2 };
556 558
557 iov.iov_base = (char *)mid->resp_buf; 559 iov[0].iov_base = (char *)mid->resp_buf;
558 iov.iov_len = get_rfc1002_length(mid->resp_buf) + 4; 560 iov[0].iov_len = 4;
561 iov[1].iov_base = (char *)mid->resp_buf + 4;
562 iov[1].iov_len = len;
559 563
560 dump_smb(mid->resp_buf, min_t(u32, 80, len)); 564 dump_smb(mid->resp_buf, min_t(u32, 80, len));
561 /* convert the length into a more usable form */ 565 /* convert the length into a more usable form */
@@ -575,7 +579,8 @@ struct mid_q_entry *
575smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) 579smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
576{ 580{
577 int rc; 581 int rc;
578 struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); 582 struct smb2_sync_hdr *shdr =
583 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
579 struct mid_q_entry *mid; 584 struct mid_q_entry *mid;
580 585
581 smb2_seq_num_into_buf(ses->server, shdr); 586 smb2_seq_num_into_buf(ses->server, shdr);
@@ -595,7 +600,8 @@ struct mid_q_entry *
595smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) 600smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
596{ 601{
597 int rc; 602 int rc;
598 struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); 603 struct smb2_sync_hdr *shdr =
604 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
599 struct mid_q_entry *mid; 605 struct mid_q_entry *mid;
600 606
601 smb2_seq_num_into_buf(server, shdr); 607 smb2_seq_num_into_buf(server, shdr);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 878f0dceeb13..dacfdf080330 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -245,8 +245,12 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
245 return -EIO; 245 return -EIO;
246 } 246 }
247 247
248 if (n_vec < 2)
249 return -EIO;
250
248 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); 251 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
249 dump_smb(iov[0].iov_base, iov[0].iov_len); 252 dump_smb(iov[0].iov_base, iov[0].iov_len);
253 dump_smb(iov[1].iov_base, iov[1].iov_len);
250 254
251 /* cork the socket */ 255 /* cork the socket */
252 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, 256 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
@@ -321,12 +325,14 @@ int
321smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, 325smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
322 unsigned int smb_buf_length) 326 unsigned int smb_buf_length)
323{ 327{
324 struct kvec iov; 328 struct kvec iov[2];
325 329
326 iov.iov_base = smb_buffer; 330 iov[0].iov_base = smb_buffer;
327 iov.iov_len = smb_buf_length + 4; 331 iov[0].iov_len = 4;
332 iov[1].iov_base = (char *)smb_buffer + 4;
333 iov[1].iov_len = smb_buf_length;
328 334
329 return smb_sendv(server, &iov, 1); 335 return smb_sendv(server, iov, 2);
330} 336}
331 337
332static int 338static int
@@ -454,6 +460,10 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
454 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 460 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
455 struct mid_q_entry *mid; 461 struct mid_q_entry *mid;
456 462
463 if (rqst->rq_iov[0].iov_len != 4 ||
464 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
465 return ERR_PTR(-EIO);
466
457 /* enable signing if server requires it */ 467 /* enable signing if server requires it */
458 if (server->sign) 468 if (server->sign)
459 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 469 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -477,8 +487,8 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
477 */ 487 */
478int 488int
479cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, 489cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
480 mid_receive_t *receive, mid_callback_t *callback, 490 mid_receive_t *receive, mid_callback_t *callback, void *cbdata,
481 void *cbdata, const int flags) 491 const int flags)
482{ 492{
483 int rc, timeout, optype; 493 int rc, timeout, optype;
484 struct mid_q_entry *mid; 494 struct mid_q_entry *mid;
@@ -613,13 +623,15 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
613 623
614 /* convert the length into a more usable form */ 624 /* convert the length into a more usable form */
615 if (server->sign) { 625 if (server->sign) {
616 struct kvec iov; 626 struct kvec iov[2];
617 int rc = 0; 627 int rc = 0;
618 struct smb_rqst rqst = { .rq_iov = &iov, 628 struct smb_rqst rqst = { .rq_iov = iov,
619 .rq_nvec = 1 }; 629 .rq_nvec = 2 };
620 630
621 iov.iov_base = mid->resp_buf; 631 iov[0].iov_base = mid->resp_buf;
622 iov.iov_len = len; 632 iov[0].iov_len = 4;
633 iov[1].iov_base = (char *)mid->resp_buf + 4;
634 iov[1].iov_len = len - 4;
623 /* FIXME: add code to kill session */ 635 /* FIXME: add code to kill session */
624 rc = cifs_verify_signature(&rqst, server, 636 rc = cifs_verify_signature(&rqst, server,
625 mid->sequence_number); 637 mid->sequence_number);
@@ -639,6 +651,10 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
639 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 651 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
640 struct mid_q_entry *mid; 652 struct mid_q_entry *mid;
641 653
654 if (rqst->rq_iov[0].iov_len != 4 ||
655 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
656 return ERR_PTR(-EIO);
657
642 rc = allocate_mid(ses, hdr, &mid); 658 rc = allocate_mid(ses, hdr, &mid);
643 if (rc) 659 if (rc)
644 return ERR_PTR(rc); 660 return ERR_PTR(rc);
@@ -650,18 +666,16 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
650 return mid; 666 return mid;
651} 667}
652 668
653int 669static int
654SendReceive2(const unsigned int xid, struct cifs_ses *ses, 670cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
655 struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, 671 struct smb_rqst *rqst, int *resp_buf_type, const int flags,
656 const int flags, struct kvec *resp_iov) 672 struct kvec *resp_iov)
657{ 673{
658 int rc = 0; 674 int rc = 0;
659 int timeout, optype; 675 int timeout, optype;
660 struct mid_q_entry *midQ; 676 struct mid_q_entry *midQ;
661 char *buf = iov[0].iov_base;
662 unsigned int credits = 1; 677 unsigned int credits = 1;
663 struct smb_rqst rqst = { .rq_iov = iov, 678 char *buf;
664 .rq_nvec = n_vec };
665 679
666 timeout = flags & CIFS_TIMEOUT_MASK; 680 timeout = flags & CIFS_TIMEOUT_MASK;
667 optype = flags & CIFS_OP_MASK; 681 optype = flags & CIFS_OP_MASK;
@@ -694,7 +708,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
694 708
695 mutex_lock(&ses->server->srv_mutex); 709 mutex_lock(&ses->server->srv_mutex);
696 710
697 midQ = ses->server->ops->setup_request(ses, &rqst); 711 midQ = ses->server->ops->setup_request(ses, rqst);
698 if (IS_ERR(midQ)) { 712 if (IS_ERR(midQ)) {
699 mutex_unlock(&ses->server->srv_mutex); 713 mutex_unlock(&ses->server->srv_mutex);
700 /* Update # of requests on wire to server */ 714 /* Update # of requests on wire to server */
@@ -704,7 +718,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
704 718
705 midQ->mid_state = MID_REQUEST_SUBMITTED; 719 midQ->mid_state = MID_REQUEST_SUBMITTED;
706 cifs_in_send_inc(ses->server); 720 cifs_in_send_inc(ses->server);
707 rc = smb_sendv(ses->server, iov, n_vec); 721 rc = smb_send_rqst(ses->server, rqst);
708 cifs_in_send_dec(ses->server); 722 cifs_in_send_dec(ses->server);
709 cifs_save_when_sent(midQ); 723 cifs_save_when_sent(midQ);
710 724
@@ -720,7 +734,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
720 734
721 rc = wait_for_response(ses->server, midQ); 735 rc = wait_for_response(ses->server, midQ);
722 if (rc != 0) { 736 if (rc != 0) {
723 send_cancel(ses->server, &rqst, midQ); 737 send_cancel(ses->server, rqst, midQ);
724 spin_lock(&GlobalMid_Lock); 738 spin_lock(&GlobalMid_Lock);
725 if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 739 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
726 midQ->callback = DeleteMidQEntry; 740 midQ->callback = DeleteMidQEntry;
@@ -767,6 +781,36 @@ out:
767} 781}
768 782
769int 783int
784SendReceive2(const unsigned int xid, struct cifs_ses *ses,
785 struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
786 const int flags, struct kvec *resp_iov)
787{
788 struct smb_rqst rqst;
789 struct kvec *new_iov;
790 int rc;
791
792 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL);
793 if (!new_iov)
794 return -ENOMEM;
795
796 /* 1st iov is a RFC1001 length followed by the rest of the packet */
797 memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
798
799 new_iov[0].iov_base = new_iov[1].iov_base;
800 new_iov[0].iov_len = 4;
801 new_iov[1].iov_base += 4;
802 new_iov[1].iov_len -= 4;
803
804 memset(&rqst, 0, sizeof(struct smb_rqst));
805 rqst.rq_iov = new_iov;
806 rqst.rq_nvec = n_vec + 1;
807
808 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
809 kfree(new_iov);
810 return rc;
811}
812
813int
770SendReceive(const unsigned int xid, struct cifs_ses *ses, 814SendReceive(const unsigned int xid, struct cifs_ses *ses,
771 struct smb_hdr *in_buf, struct smb_hdr *out_buf, 815 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
772 int *pbytes_returned, const int timeout) 816 int *pbytes_returned, const int timeout)