From patchwork Tue Dec 6 22:02:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9463315 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C4D1860231 for ; Tue, 6 Dec 2016 22:17:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B4F8B284F0 for ; Tue, 6 Dec 2016 22:17:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A9DA2284F9; Tue, 6 Dec 2016 22:17:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4E83B284F5 for ; Tue, 6 Dec 2016 22:17:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751590AbcLFWRr (ORCPT ); Tue, 6 Dec 2016 17:17:47 -0500 Received: from mail-bn3nam01on0100.outbound.protection.outlook.com ([104.47.33.100]:51568 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751618AbcLFWRn (ORCPT ); Tue, 6 Dec 2016 17:17:43 -0500 X-Greylist: delayed 892 seconds by postgrey-1.27 at vger.kernel.org; Tue, 06 Dec 2016 17:17:41 EST DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=xyV+lQbRwTBLhmHttu4UE98ytBBcYKBjSUVU8LH/ggs=; b=bAJE/qgJv+h3IiRKo4Fiwsnowj4qVDfktRypLYYeymIGD0gJY47hh868XEFHZantz8rF641ec9zNLEJgLV42D8mqM0PYuxPk2LGpwcX5rCsQEmReUmtVh3tOPn7H4JFdp/9CXFe33p78HzJ33fX5MdEHvaCXxql98lRNkw+1d2c= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=pshilov@microsoft.com; Received: from ubuntu-vm.corp.microsoft.com (2001:4898:80e8:2::63b) by CY4PR03MB2549.namprd03.prod.outlook.com (10.173.41.148) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.761.9; Tue, 6 Dec 2016 22:02:47 +0000 From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH 04/15] CIFS: Send RFC1001 length in a separate iov Date: Tue, 6 Dec 2016 14:02:27 -0800 Message-Id: <1481061758-52020-5-git-send-email-pshilov@microsoft.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1481061758-52020-1-git-send-email-pshilov@microsoft.com> References: <1481061758-52020-1-git-send-email-pshilov@microsoft.com> MIME-Version: 1.0 X-Originating-IP: [2001:4898:80e8:2::63b] X-ClientProxiedBy: CY1PR17CA0004.namprd17.prod.outlook.com (10.163.68.14) To CY4PR03MB2549.namprd03.prod.outlook.com (10.173.41.148) X-MS-Office365-Filtering-Correlation-Id: b35d6e0c-b346-43db-c19c-08d41e239d03 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:CY4PR03MB2549; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 3:WGEFwbG6lXvjUOX0TwlndE3QdmIB/1SRzix2IPF7Yjl0qzw7kAOfgawzBwSjYZqgTQcOU/5U9/ohfKsYTM01yE247aqkCbq73eUE3DWMZnmaySdAWjTNLq1LyBYMbQMczvg7SkK4rG21eDPOKGHUXyERR8d1TUsbdgE8CK9GYWRLV3iK/Cy9gNd0WZd9/aXsjNKB0Fhb3imyrOfRoAovpkoDRKbKV376y4KCQ32nnI9l60X0DPkFmgfkwfA/YvEdI/7EQgXTk4jNflgrfBx7pQ== X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 25:9a7ETLwTgIMSNXQqgzr0wGt/I0GCkdRzgtn1sBnU/2lAbVeN69KdVCmCFGVXTwM5O5A1yvUeTpsbjHB6I394tYWzUkhKdu5oLj+N3/KG9Q/+sUCCUQQ2OeuVDKthprOd7CMRXRG5mXtlOOffpVuDmId7zTCTTz8pNIcuTgcx/+lY7a+zsY7sS6RH+izvEojekFHNvatjHbvoE7z4IIGZtLwwAN0gsaATl1WWwwfhrV6IMd8l9hI20zreFQLOhs33iEzEbLHgjmJrhjU/16hzt/7h14V28hS1mJj1v5TbtmjJP+cKNxsx5y2saeT7HxnUwcASgbpGjpbfYF41E+Z6Qezuk7A/oQGTitWqSbtpn8pikVble4UWtv1vxeoJ+P7d23sEMYJjt+A6EsTcTzRpAZw69avos/53ol3Sucrq7CyfHqFAxe+9hOQf3YPmzA2zaBG3uncS+pmOxbdrQ1rrsyQTadlwRTcseEdnW9DCGmTG2hcp4dW+9U3UeZ0d8L3NX/yucgAyChyk+bCmbgM2StATGaMRxBE0hUMKgMDbaDSZavKgqORcKbe0+6QIP0OchHyG6nxwp8ZBxGK9/Cj+ZqQtJ3Bd3N6KUFahJN2Y9nkeXMbGl2MhYTjf57Hvtn9SfcJl1mzRI2ydUcnydFNIPERXhPO7P9+yMScBdo7rSnZ8CIOPTFANMMrTe7QHFnb7W6N7dPKqwAJG0Qz1v6K7408QLR2NE4sYACwjX7h6INOIwVY7Oqpw01oF8BEl06osH/GviECETlv1th3MeXQiXpxfVnt+/lAfxMpBXAWDpLg= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 31:uahDWTG9OXEGTVXGcYAG3PmtmUQEwveTP6nff0rxAEd9A1lfOl6nQz2wQ0PPsSNt1sCR14HlxRSh+OXCZKvnQWk9ZCTf26HgcZiT8NxwhG8r3nKZC+BrvvuDfi4dz8m2QPM7wsoXkDzGjf1niBfzQgE3itgBh0Xem05hsVlZKyUr1OqqMlcDuEw1V0rFpWmr5uvV1+CKIBd7MGFV5pW9H9sGVr1FhDACW4KF65kvDn6Ho51r+m3+4eD+kZQEyrNrngsuXO32f1FezgJnHbBuWA==; 20:kj6A4WamAre5k0k/r6lXa7CKNTHhDpD9bIURMYGwoh6DxLIKy2MCcJG8eoxeZZxLBJsSCBYOIY3MPjjEZ7nHhrdaDHGNDcX2Xd3xbuRdp0P6xQGuOFvBezAefi1eXkXz+flfe0mE50fXRF7taGakzoTXzaxAmUjVJpJaq5RGkuX0JkTkHsp8n+nm1+o6XOEJfuG7OmQ3bfBKCnWmjpBlmvfQhYlDeeUlOAyQK/MSXHrvsa7k0xLKDNBvSQRdeMuB+8CtNDAihGoNG+BPGoDAX6FuEdfn1lIjFxgE+eqk7sa2ygJBqudRPCLG5q+LfNttCOo+qJskPPLpAsIPTC8mIaPK+H3C6cbM3Pbs0PrUgq+KmaUbKi4XLAj7feix1829/Kdcq0+ZhZD/V7iPxgjHRlNx5DEjadgf77Wk1g1cKdoGg1Q3liGkMUQ439L8vPEM/djcipoNdkFPio8THFjRtIq7Go88I6h4oYDtMIYwimhVS7cElR+uT+5jsV+bci2B X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(158342451672863); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6055026)(6041248)(20161123560025)(20161123562025)(20161123564025)(20161123555025)(6047074)(6072148); SRVR:CY4PR03MB2549; BCL:0; PCL:0; RULEID:; SRVR:CY4PR03MB2549; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 4:SdxGfptw/SNHtiiLIanKaCJJ7plDn0CqONL0xp6vquZ5w2D4DSUPkeqhIwn0QSy+0WdL4H7jI0DsBNZal735CsOdfZaRteAc//9V2tnejW5yMlf/fQljUvJGwFzMcBzRrXc4DOpmt9QpyNNpfjobW1NDC3NPkM+9+BzmWGObfKE57sv5xXW0iWXW2vS8iGRQonvPJMPT0GaNCrRtYiUH6eQRIAssh6nP10kjtKimnwhhM9ScjXnhYSdyQ/02/yARcehFFBwse2fgUZD+n+bLLp+SmYcXymBqjHv/qnW3tDWSKdhuF31sFg6Fa8fYbhq2pmhD/3D53KM13ubQrduaz+jiOk1sfTV/yLH3ef6NRQJwBCiLVD5SkIY+facm3jY0ng3cqfnvPBczPwz83C/ecF1yXHhw2u2k/NgEcudJnWNcYjD1ZTA+GPK3IJkHhNd+zFDWtw49cKTIT1QAD6V8JXc5q1gV4f0jmWlfWHktIl3jSizbVTjMmN5qoLNfUHkzrWi5mIed3r/EaorPFCCO9m/fQJgK9jJgqS5R69W3Q2zmgmU3gqHPQ7p5p9ZOyOro/sGQljWob1A7YpRQ8ByQoZmp+EPCzxJDGY4KMdBN4q/FHqem/CbSVf/PNDARjGtlythlz5oj05l2A6vtzc9GLA== X-Forefront-PRVS: 01480965DA X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(7916002)(69234005)(199003)(189002)(50466002)(92566002)(101416001)(86362001)(33646002)(47776003)(48376002)(2950100002)(6916009)(106356001)(575784001)(105586002)(6666003)(50986999)(42186005)(39860400001)(39850400001)(39840400001)(86612001)(76176999)(2361001)(110136003)(2351001)(450100001)(189998001)(5660300001)(10090500001)(5003940100001)(10290500002)(38730400001)(5005710100001)(8676002)(6116002)(36756003)(107886002)(39410400001)(733004)(7846002)(2906002)(39450400002)(6486002)(7736002)(50226002)(68736007)(305945005)(81156014)(97736004)(81166006); DIR:OUT; SFP:1102; SCL:1; SRVR:CY4PR03MB2549; H:ubuntu-vm.corp.microsoft.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: microsoft.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY4PR03MB2549; 23:tXBlK5TSrrrFuVNTPaL911PY39sZ7yiqR/EX7J3jd?= =?us-ascii?Q?CVLF7wGCyh6AEYR0YOIK/CeLGERJ6/fatS5Qg3K7QINSzTjyGr/mQuyXiN8n?= =?us-ascii?Q?vlKqe3g/DK7v92lHPKy05117eTOXIVqRQiDBtFRu1uNN65YCj9AzouraV2P0?= =?us-ascii?Q?yMU7gAInb4Ggn/whM/s8KNv/QDf5cI73tcjmtZHB3bDQzZCWeohxIZ86dKtC?= =?us-ascii?Q?xLsvfBhB05DKbfX8ExA6aK8B+OZ782Ys4bi+Eis83RL17L/jnVb95kHsU+BY?= =?us-ascii?Q?0co7oqA4agWk4jmRsZD+3J321CR/R+Ua2JXV2PVqkC7pq1LGTAFRv31yCTTW?= =?us-ascii?Q?JXpqxsXCwMQEX6euGBi7MGYkTiQ9/i2SDJQvFm9+dKjrcZeFwm5FPvy8Kb48?= =?us-ascii?Q?4yFMLvb1t3jeDTsfNG2NLphvGli3mi0fvvq5GLqLRAh5c1zQyaEN/M4KTo9i?= =?us-ascii?Q?i+SpqrlPtXu6WdgR1Ry7hApZZoNYHHmZTnTjxbMZzbdxfEGwfcvU8TQFM1vi?= =?us-ascii?Q?pjnlTCAo7e41dRpZN24e6heZnsN49GTmT41EAvUDagXl12QUyc7TELqNFoXU?= =?us-ascii?Q?k/p9qy197OIXYP2FWQANWQEK6ORkVX5JWfyvOI5vaxS2Cj1+j9QM8FENcAO3?= =?us-ascii?Q?UM5qiea7dQ9bNy+DzgXdRMuvUNX4Eq5HyX+psEcxsuDAoJxOAifRhcpMdhru?= =?us-ascii?Q?+NtgJQ6SXy6c3MDkyIyydstIDMCngITHT1DUhb/jmFqM5KKQsSTxSDEi7J96?= =?us-ascii?Q?7+STJlomeg8OVnOtt2upjskhgxYi3KDU4fxalvJcbbpQnrMIqmdT4M7oyuNV?= =?us-ascii?Q?lunNKvUFfeQNDDy9WNQYiCHabTmZzHM9Vg6gcXt/8zytI8MJUN9jUnoaTMOE?= =?us-ascii?Q?9qeBXHU5KT4UB8FMoTduu9lLa02VwmxRppySe4jzpT0GOumXCEgjGW3yJoDa?= =?us-ascii?Q?dlG/oybhTpIowLAHGphIono+X4OYUO3lQvLxnyGVDijYBwusrOIUwObOJ/WZ?= =?us-ascii?Q?+kevGcJMOo2NCu3ypUYNZilxEX1VoDI7tl91nRo49RD+9LOFMQau8KAPxciQ?= =?us-ascii?Q?+Js0tybTsTyR9HIU//Y5pYC53YsFVXobzRlxrzlIzSJ1hImksWjIzsBaDH6i?= =?us-ascii?Q?/l87L2l2sLli0J5QGJrcNPUx6TTtlcwaNTe37qEoai3O1vuZX7wImCOSVWNW?= =?us-ascii?Q?VNzz351/AmYdjBrkUoTCME3k+2ANqxix/ay02bu0520S/Kv39LyNF2NVfmiu?= =?us-ascii?Q?J0+vq3dlVCY5fPMt7gGn3OCC7BX+ncZ/TPtvKUwffOrtM1SIB7FopUJYC07Q?= =?us-ascii?Q?MzDjVBqw8wzEpq39Rxtzp5fqdY8BCFVefl9+2Lf098/?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 6:+hZ/Q1ctuVFUw2wSPuXS2e76zqUKjsnW+cEZnbjt+Th9zbok+MQt+X2aovW7WjPOMblvMMIzf3sYNeAjhGCoMDsjcHwqTTu8Mg1WZ+ROuJT/14W47JOtBw872/CKkRVP1hIPrcVENbK5Yn3qT7evz6rvxggqfRhsrL0CcDCqGhf71csT7+U0opWC2cHLWBnCg1n+wvUVjtfRKNQxXwQaWTqmj39+cB1IPd/1lqL/R06sR6pfBz7cbZzmoo1YRY8huetfamzaD/CkiAyIQ+vBQDM5FrnW7jCymWQ0+U071N/nSpAHGvYfwZHA2N0CClEKTqDPwlDX3MuPEeGeVy+u+Rz3Kef/F29GFa0bG2QN5iFa2Hto9fJwdobWnW2KzJr5lmVPGcVQgNGOmDwHyShKA6eFh4IV3q94Fos6weTNoE96K5X2EDpzVsDVhy3vs0OcZB3cYH9zS5e87rDLSE5rYA==; 5:wwHk1vpRLRzNcnFntMxEDZ5oGmrBqQKkiJpimZrIwm9fwRYffunhF5PJ5lteJpdw+u268e0hiIcUhI/tanrY+bLIhcUedYQWCan8XaBz9nZZ+ooSxbG+xm2Elz4qunwt6Iw4j6PdnqxCHbawsCHm8ZS7pr45q4Zlpt8xiZcJLNg=; 24:rY67YZkaNnBCA96uvzfxzxx387I469VgjaKAD8R+XYoyTcrdDNYu0U/cXmF8QtiQc0pCO7njx9w+MvgDKT216oJUFYq9l5o4FdSK1Sc/QP8= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 7:1xa5S7dOyLvZDb/5UVZ8+6bEm45JWX0ShMsFOcimQDOBQiI9luGzZZNuohWe47n0mahpTx7ckvKMCmGOYdZEyGXBbTXJ3Qj8I9U4jp1mM1MlNvW+dUiE0V/YAmiC1bMCKyZg8OwOPA0duCOWoBVMIih07DR+u2isimV+3P6IwQIbNV74CsaR/kKLtBorMlKHzSUnAfk+WNZE2TxFNQaLAAPk19Jx6ktKHoRq2wN54LDop0NzCYkhR2X9ecJZlwpx04iwyjPaZx/GxPA74qamA9ws/BY9RGUkS8RcRKaBWkxrdl8ON5QeW/+/qIZRMwb47VnZF7W1VT1Ur1Edvrmze8HBQJhIuFAZ92rhEHE533G661LvrGFJGzCZedwHP7YYkNco6a4fg09235UvQCVerwcM9pSw04qhmapbsNKYshHHjVsqrum4ArZRQt5gAfnOdQfN3lhHAI8u75N5+1QPhQ== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Dec 2016 22:02:47.2139 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR03MB2549 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- fs/cifs/cifsencrypt.c | 38 +++++++++++++--------- fs/cifs/cifsglob.h | 2 +- fs/cifs/cifssmb.c | 51 +++++++++++++++++------------ fs/cifs/smb2pdu.c | 64 ++++++++++++++++++++++-------------- fs/cifs/smb2transport.c | 28 +++++++++------- fs/cifs/transport.c | 86 +++++++++++++++++++++++++++++++++++++------------ 6 files changed, 174 insertions(+), 95 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 5eb0412..3a0aaf0 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -75,24 +75,20 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; - for (i = 0; i < n_vec; i++) { + if (n_vec < 2 || iov[0].iov_len != 4) + return -EIO; + + for (i = 1; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { cifs_dbg(VFS, "null iovec entry\n"); return -EIO; } - /* The first entry includes a length field (which does not get - signed that occupies the first 4 bytes before the header */ - if (i == 0) { - if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ - break; /* nothing to sign or corrupt header */ - rc = crypto_shash_update(shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); - } else { - rc = crypto_shash_update(shash, - iov[i].iov_base, iov[i].iov_len); - } + if (i == 1 && iov[1].iov_len <= 4) + break; /* nothing to sign or corrupt header */ + rc = crypto_shash_update(shash, + iov[i].iov_base, iov[i].iov_len); if (rc) { cifs_dbg(VFS, "%s: Could not update with payload\n", __func__); @@ -168,6 +164,10 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, char smb_signature[20]; struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; + if (rqst->rq_iov[0].iov_len != 4 || + rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) + return -EIO; + if ((cifs_pdu == NULL) || (server == NULL)) return -EINVAL; @@ -209,12 +209,14 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { - struct kvec iov; + struct kvec iov[2]; - iov.iov_base = cifs_pdu; - iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; + iov[0].iov_base = cifs_pdu; + iov[0].iov_len = 4; + iov[1].iov_base = (char *)cifs_pdu + 4; + iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length); - return cifs_sign_smbv(&iov, 1, server, + return cifs_sign_smbv(iov, 2, server, pexpected_response_sequence_number); } @@ -227,6 +229,10 @@ int cifs_verify_signature(struct smb_rqst *rqst, char what_we_think_sig_should_be[20]; struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; + if (rqst->rq_iov[0].iov_len != 4 || + rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) + return -EIO; + if (cifs_pdu == NULL || server == NULL) return -EINVAL; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4f4fffd..5a89875 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1117,7 +1117,7 @@ struct cifs_readdata { int (*read_into_pages)(struct TCP_Server_Info *server, struct cifs_readdata *rdata, unsigned int len); - struct kvec iov; + struct kvec iov[2]; unsigned int pagesz; unsigned int tailsz; unsigned int credits; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index e2a790a..be261a3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -708,9 +708,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) { ECHO_REQ *smb; int rc = 0; - struct kvec iov; - struct smb_rqst rqst = { .rq_iov = &iov, - .rq_nvec = 1 }; + struct kvec iov[2]; + struct smb_rqst rqst = { .rq_iov = iov, + .rq_nvec = 2 }; cifs_dbg(FYI, "In echo request\n"); @@ -725,8 +725,11 @@ CIFSSMBEcho(struct TCP_Server_Info *server) put_bcc(1, &smb->hdr); smb->Data[0] = 'a'; inc_rfc1001_len(smb, 3); - iov.iov_base = smb; - iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; + + iov[0].iov_len = 4; + iov[0].iov_base = smb; + iov[1].iov_len = get_rfc1002_length(smb); + iov[1].iov_base = (char *)smb + 4; rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, server, CIFS_ASYNC_OP | CIFS_ECHO_OP); @@ -1509,10 +1512,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) } /* set up first iov for signature check */ - rdata->iov.iov_base = buf; - rdata->iov.iov_len = server->total_read; - cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", - rdata->iov.iov_base, rdata->iov.iov_len); + rdata->iov[0].iov_base = buf; + rdata->iov[0].iov_len = 4; + rdata->iov[1].iov_base = buf + 4; + rdata->iov[1].iov_len = server->total_read - 4; + cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", + rdata->iov[0].iov_base, server->total_read); /* how much data is in the response? */ data_len = server->ops->read_data_length(buf); @@ -1545,8 +1550,8 @@ cifs_readv_callback(struct mid_q_entry *mid) struct cifs_readdata *rdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; - struct smb_rqst rqst = { .rq_iov = &rdata->iov, - .rq_nvec = 1, + struct smb_rqst rqst = { .rq_iov = rdata->iov, + .rq_nvec = 2, .rq_pages = rdata->pages, .rq_npages = rdata->nr_pages, .rq_pagesz = rdata->pagesz, @@ -1601,8 +1606,8 @@ cifs_async_readv(struct cifs_readdata *rdata) READ_REQ *smb = NULL; int wct; struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - struct smb_rqst rqst = { .rq_iov = &rdata->iov, - .rq_nvec = 1 }; + struct smb_rqst rqst = { .rq_iov = rdata->iov, + .rq_nvec = 2 }; cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", __func__, rdata->offset, rdata->bytes); @@ -1642,8 +1647,10 @@ cifs_async_readv(struct cifs_readdata *rdata) } /* 4 for RFC1001 length + 1 for BCC */ - rdata->iov.iov_base = smb; - rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; + rdata->iov[0].iov_base = smb; + rdata->iov[0].iov_len = 4; + rdata->iov[1].iov_base = (char *)smb + 4; + rdata->iov[1].iov_len = get_rfc1002_length(smb); kref_get(&rdata->refcount); rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, @@ -2096,7 +2103,7 @@ cifs_async_writev(struct cifs_writedata *wdata, WRITE_REQ *smb = NULL; int wct; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct kvec iov; + struct kvec iov[2]; struct smb_rqst rqst = { }; if (tcon->ses->capabilities & CAP_LARGE_FILES) { @@ -2129,11 +2136,13 @@ cifs_async_writev(struct cifs_writedata *wdata, cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); /* 4 for RFC1001 length + 1 for BCC */ - iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; - iov.iov_base = smb; + iov[0].iov_len = 4; + iov[0].iov_base = smb; + iov[1].iov_len = get_rfc1002_length(smb) + 1; + iov[1].iov_base = (char *)smb + 4; - rqst.rq_iov = &iov; - rqst.rq_nvec = 1; + rqst.rq_iov = iov; + rqst.rq_nvec = 2; rqst.rq_pages = wdata->pages; rqst.rq_npages = wdata->nr_pages; rqst.rq_pagesz = wdata->pagesz; @@ -2154,7 +2163,7 @@ cifs_async_writev(struct cifs_writedata *wdata, (struct smb_com_writex_req *)smb; inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); put_bcc(wdata->bytes + 5, &smbw->hdr); - iov.iov_len += 4; /* pad bigger by four bytes */ + iov[1].iov_len += 4; /* pad bigger by four bytes */ } kref_get(&wdata->refcount); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index fb6cf1b..438c4b1 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2047,9 +2047,9 @@ SMB2_echo(struct TCP_Server_Info *server) { struct smb2_echo_req *req; int rc = 0; - struct kvec iov; - struct smb_rqst rqst = { .rq_iov = &iov, - .rq_nvec = 1 }; + struct kvec iov[2]; + struct smb_rqst rqst = { .rq_iov = iov, + .rq_nvec = 2 }; cifs_dbg(FYI, "In echo request\n"); @@ -2065,9 +2065,11 @@ SMB2_echo(struct TCP_Server_Info *server) req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1); - iov.iov_base = (char *)req; /* 4 for rfc1002 length field */ - iov.iov_len = get_rfc1002_length(req) + 4; + iov[0].iov_len = 4; + iov[0].iov_base = (char *)req; + iov[1].iov_len = get_rfc1002_length(req); + iov[1].iov_base = (char *)req + 4; rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server, CIFS_ECHO_OP); @@ -2123,8 +2125,9 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, * have the end_of_chain boolean set to true. */ static int -smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, - unsigned int remaining_bytes, int request_type) +smb2_new_read_req(void **buf, unsigned int *total_len, + struct cifs_io_parms *io_parms, unsigned int remaining_bytes, + int request_type) { int rc = -EACCES; struct smb2_read_req *req = NULL; @@ -2172,9 +2175,9 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, else req->RemainingBytes = 0; - iov[0].iov_base = (char *)req; + *buf = req; /* 4 for rfc1002 length field */ - iov[0].iov_len = get_rfc1002_length(req) + 4; + *total_len = get_rfc1002_length(req) + 4; return rc; } @@ -2184,10 +2187,11 @@ smb2_readv_callback(struct mid_q_entry *mid) struct cifs_readdata *rdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; - struct smb2_sync_hdr *shdr = get_sync_hdr(rdata->iov.iov_base); + struct smb2_sync_hdr *shdr = + (struct smb2_sync_hdr *)rdata->iov[1].iov_base; unsigned int credits_received = 1; - struct smb_rqst rqst = { .rq_iov = &rdata->iov, - .rq_nvec = 1, + struct smb_rqst rqst = { .rq_iov = rdata->iov, + .rq_nvec = 2, .rq_pages = rdata->pages, .rq_npages = rdata->nr_pages, .rq_pagesz = rdata->pagesz, @@ -2238,7 +2242,7 @@ smb2_readv_callback(struct mid_q_entry *mid) add_credits(server, credits_received, 0); } -/* smb2_async_readv - send an async write, and set up mid to handle result */ +/* smb2_async_readv - send an async read, and set up mid to handle result */ int smb2_async_readv(struct cifs_readdata *rdata) { @@ -2246,9 +2250,10 @@ smb2_async_readv(struct cifs_readdata *rdata) char *buf; struct smb2_sync_hdr *shdr; struct cifs_io_parms io_parms; - struct smb_rqst rqst = { .rq_iov = &rdata->iov, - .rq_nvec = 1 }; + struct smb_rqst rqst = { .rq_iov = rdata->iov, + .rq_nvec = 2 }; struct TCP_Server_Info *server; + unsigned int total_len; cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", __func__, rdata->offset, rdata->bytes); @@ -2262,7 +2267,7 @@ smb2_async_readv(struct cifs_readdata *rdata) server = io_parms.tcon->ses->server; - rc = smb2_new_read_req(&rdata->iov, &io_parms, 0, 0); + rc = smb2_new_read_req((void **) &buf, &total_len, &io_parms, 0, 0); if (rc) { if (rc == -EAGAIN && rdata->credits) { /* credits was reset by reconnect */ @@ -2275,10 +2280,12 @@ smb2_async_readv(struct cifs_readdata *rdata) return rc; } - buf = rdata->iov.iov_base; shdr = get_sync_hdr(buf); /* 4 for rfc1002 length field */ - rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4; + rdata->iov[0].iov_len = 4; + rdata->iov[0].iov_base = buf; + rdata->iov[1].iov_len = total_len - 4; + rdata->iov[1].iov_base = buf + 4; if (rdata->credits) { 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, struct smb2_sync_hdr *shdr; struct kvec iov[1]; struct kvec rsp_iov; + unsigned int total_len; + char *req; *nbytes = 0; - rc = smb2_new_read_req(iov, io_parms, 0, 0); + rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0); if (rc) return rc; + iov[0].iov_base = buf; + iov[0].iov_len = total_len; + rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1, &resp_buftype, CIFS_LOG_ERROR, &rsp_iov); cifs_small_buf_release(iov[0].iov_base); @@ -2424,8 +2436,8 @@ smb2_async_writev(struct cifs_writedata *wdata, struct smb2_sync_hdr *shdr; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; - struct kvec iov; - struct smb_rqst rqst; + struct kvec iov[2]; + struct smb_rqst rqst = { }; rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); if (rc) { @@ -2455,11 +2467,13 @@ smb2_async_writev(struct cifs_writedata *wdata, req->RemainingBytes = 0; /* 4 for rfc1002 length field and 1 for Buffer */ - iov.iov_len = get_rfc1002_length(req) + 4 - 1; - iov.iov_base = req; + iov[0].iov_len = 4; + iov[0].iov_base = req; + iov[1].iov_len = get_rfc1002_length(req) - 1; + iov[1].iov_base = (char *)req + 4; - rqst.rq_iov = &iov; - rqst.rq_nvec = 1; + rqst.rq_iov = iov; + rqst.rq_nvec = 2; rqst.rq_pages = wdata->pages; rqst.rq_npages = wdata->nr_pages; rqst.rq_pagesz = wdata->pagesz; diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 52ff937..93b2775 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) unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char *sigptr = smb2_signature; struct kvec *iov = rqst->rq_iov; - struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base); + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; struct cifs_ses *ses; ses = smb2_find_smb_ses(shdr, server); @@ -355,7 +355,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char *sigptr = smb3_signature; struct kvec *iov = rqst->rq_iov; - struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base); + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; struct cifs_ses *ses; ses = smb2_find_smb_ses(shdr, server); @@ -400,7 +400,8 @@ static int smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) { int rc = 0; - struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); + struct smb2_sync_hdr *shdr = + (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; if (!(shdr->Flags & SMB2_FLAGS_SIGNED) || server->tcpStatus == CifsNeedNegotiate) @@ -421,7 +422,8 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { unsigned int rc; char server_response_sig[16]; - struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); + struct smb2_sync_hdr *shdr = + (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; if ((shdr->Command == SMB2_NEGOTIATE) || (shdr->Command == SMB2_SESSION_SETUP) || @@ -550,12 +552,14 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error) { unsigned int len = get_rfc1002_length(mid->resp_buf); - struct kvec iov; - struct smb_rqst rqst = { .rq_iov = &iov, - .rq_nvec = 1 }; + struct kvec iov[2]; + struct smb_rqst rqst = { .rq_iov = iov, + .rq_nvec = 2 }; - iov.iov_base = (char *)mid->resp_buf; - iov.iov_len = get_rfc1002_length(mid->resp_buf) + 4; + iov[0].iov_base = (char *)mid->resp_buf; + iov[0].iov_len = 4; + iov[1].iov_base = (char *)mid->resp_buf + 4; + iov[1].iov_len = len; dump_smb(mid->resp_buf, min_t(u32, 80, len)); /* convert the length into a more usable form */ @@ -575,7 +579,8 @@ struct mid_q_entry * smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) { int rc; - struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); + struct smb2_sync_hdr *shdr = + (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; struct mid_q_entry *mid; smb2_seq_num_into_buf(ses->server, shdr); @@ -595,7 +600,8 @@ struct mid_q_entry * smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) { int rc; - struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base); + struct smb2_sync_hdr *shdr = + (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; struct mid_q_entry *mid; smb2_seq_num_into_buf(server, shdr); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index d59ebd0..988f124 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -244,8 +244,12 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) return -EIO; } + if (n_vec < 2) + return -EIO; + cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); dump_smb(iov[0].iov_base, iov[0].iov_len); + dump_smb(iov[1].iov_base, iov[1].iov_len); /* cork the socket */ kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, @@ -320,12 +324,14 @@ int smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, unsigned int smb_buf_length) { - struct kvec iov; + struct kvec iov[2]; - iov.iov_base = smb_buffer; - iov.iov_len = smb_buf_length + 4; + iov[0].iov_base = smb_buffer; + iov[0].iov_len = 4; + iov[1].iov_base = (char *)smb_buffer + 4; + iov[1].iov_len = smb_buf_length; - return smb_sendv(server, &iov, 1); + return smb_sendv(server, iov, 2); } static int @@ -453,6 +459,10 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct mid_q_entry *mid; + if (rqst->rq_iov[0].iov_len != 4 || + rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) + return ERR_PTR(-EIO); + /* enable signing if server requires it */ if (server->sign) hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; @@ -476,8 +486,8 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) */ int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, - mid_receive_t *receive, mid_callback_t *callback, - void *cbdata, const int flags) + mid_receive_t *receive, mid_callback_t *callback, void *cbdata, + const int flags) { int rc, timeout, optype; struct mid_q_entry *mid; @@ -612,13 +622,15 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, /* convert the length into a more usable form */ if (server->sign) { - struct kvec iov; + struct kvec iov[2]; int rc = 0; - struct smb_rqst rqst = { .rq_iov = &iov, - .rq_nvec = 1 }; + struct smb_rqst rqst = { .rq_iov = iov, + .rq_nvec = 2 }; - iov.iov_base = mid->resp_buf; - iov.iov_len = len; + iov[0].iov_base = mid->resp_buf; + iov[0].iov_len = 4; + iov[1].iov_base = (char *)mid->resp_buf + 4; + iov[1].iov_len = len - 4; /* FIXME: add code to kill session */ rc = cifs_verify_signature(&rqst, server, mid->sequence_number); @@ -638,6 +650,10 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct mid_q_entry *mid; + if (rqst->rq_iov[0].iov_len != 4 || + rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) + return ERR_PTR(-EIO); + rc = allocate_mid(ses, hdr, &mid); if (rc) return ERR_PTR(rc); @@ -649,18 +665,16 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) return mid; } -int -SendReceive2(const unsigned int xid, struct cifs_ses *ses, - struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, - const int flags, struct kvec *resp_iov) +static int +cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct smb_rqst *rqst, int *resp_buf_type, const int flags, + struct kvec *resp_iov) { int rc = 0; int timeout, optype; struct mid_q_entry *midQ; - char *buf = iov[0].iov_base; unsigned int credits = 1; - struct smb_rqst rqst = { .rq_iov = iov, - .rq_nvec = n_vec }; + char *buf; timeout = flags & CIFS_TIMEOUT_MASK; optype = flags & CIFS_OP_MASK; @@ -693,7 +707,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, mutex_lock(&ses->server->srv_mutex); - midQ = ses->server->ops->setup_request(ses, &rqst); + midQ = ses->server->ops->setup_request(ses, rqst); if (IS_ERR(midQ)) { mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ @@ -703,7 +717,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, midQ->mid_state = MID_REQUEST_SUBMITTED; cifs_in_send_inc(ses->server); - rc = smb_sendv(ses->server, iov, n_vec); + rc = smb_send_rqst(ses->server, rqst); cifs_in_send_dec(ses->server); cifs_save_when_sent(midQ); @@ -719,7 +733,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, rc = wait_for_response(ses->server, midQ); if (rc != 0) { - send_cancel(ses->server, &rqst, midQ); + send_cancel(ses->server, rqst, midQ); spin_lock(&GlobalMid_Lock); if (midQ->mid_state == MID_REQUEST_SUBMITTED) { midQ->callback = DeleteMidQEntry; @@ -766,6 +780,36 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, } int +SendReceive2(const unsigned int xid, struct cifs_ses *ses, + struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, + const int flags, struct kvec *resp_iov) +{ + struct smb_rqst rqst; + struct kvec *new_iov; + int rc; + + new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL); + if (!new_iov) + return -ENOMEM; + + /* 1st iov is a RFC1001 length followed by the rest of the packet */ + memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); + + new_iov[0].iov_base = new_iov[1].iov_base; + new_iov[0].iov_len = 4; + new_iov[1].iov_base += 4; + new_iov[1].iov_len -= 4; + + memset(&rqst, 0, sizeof(struct smb_rqst)); + rqst.rq_iov = new_iov; + rqst.rq_nvec = n_vec + 1; + + rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); + kfree(new_iov); + return rc; +} + +int SendReceive(const unsigned int xid, struct cifs_ses *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned, const int timeout)