From patchwork Mon Jan 30 21:39:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9546115 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 3568860415 for ; Mon, 30 Jan 2017 21:42:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3DA38283B3 for ; Mon, 30 Jan 2017 21:42:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 31B27283F4; Mon, 30 Jan 2017 21:42:14 +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 B6918283B3 for ; Mon, 30 Jan 2017 21:42:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754543AbdA3VmL (ORCPT ); Mon, 30 Jan 2017 16:42:11 -0500 Received: from mail-by2nam03on0117.outbound.protection.outlook.com ([104.47.42.117]:46301 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754380AbdA3VmF (ORCPT ); Mon, 30 Jan 2017 16:42:05 -0500 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=NVFskJAD1L3odCKODM9C+crwIWBY2TzTeYkU1ttOn4VdixcnnP03GbDEX9Jv+YCY/dGtDwXdc2rjYSJW8YU7WsBk8oOO+eJiwQzAvnobE4hiLWy+091G4Ihjg80UgMcwoMgFiAHCr62l09gftiI99uWMW7dhQGtcsQYGNX2Yx6o= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=pshilov@microsoft.com; Received: from ubuntu-vm.corp.microsoft.com (2001:4898:80e8:b::63b) by BN6PR03MB2545.namprd03.prod.outlook.com (10.173.142.148) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.874.12; Mon, 30 Jan 2017 21:39:55 +0000 From: Pavel Shilovsky To: Subject: [PATCH v2 04/15] CIFS: Send RFC1001 length in a separate iov Date: Mon, 30 Jan 2017 13:39:33 -0800 Message-ID: <1485812384-28870-5-git-send-email-pshilov@microsoft.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485812384-28870-1-git-send-email-pshilov@microsoft.com> References: <1485812384-28870-1-git-send-email-pshilov@microsoft.com> MIME-Version: 1.0 X-Originating-IP: [2001:4898:80e8:b::63b] X-ClientProxiedBy: BN6PR1401CA0011.namprd14.prod.outlook.com (10.174.237.149) To BN6PR03MB2545.namprd03.prod.outlook.com (10.173.142.148) X-MS-Office365-Filtering-Correlation-Id: 511e8cd1-5745-4d57-67ce-08d44958887b X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:BN6PR03MB2545; X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 3:+7IZjk3fY8Mn/9Ybl7uJo0GVKEdQALC8A+eWB+hN8pQBJAc2nRtLO0aiueJn6DDBNFXEVYkg11a+4qnETn0vvZj8or2BgI016J+eWFUbqWoA5uECDowOQTTRUdfvfl1J1670rB0vGhrjOdEIowl5w7zIli+eJcxZZAzq4WAZsEp/etyujfRzU5eZGQ0lgPVn/Ge196NlA3t/P4PCL1KUKJLlKcovytQt0Z/QEFpl4cCU/ffY1gM11LENnPs9t3HZJfrxz3zpyNcOpW0NkhcJ2A== X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 25:HMeJz+2/UpiVh9cAFxyPg46mq47/YVGA0DlOYThK/V98+uNMozxmcBu1x4/jrjS54CfbHjlo33uXjO9n+UufQenuGVDB4VKDxSCLW727zWPmnuYHCmk6bvYzEckWlnI/uUjBzRZMj/6brvC4iVstsAk5aljOY6qO2B0L88Almq7rlwatiUuQF2m46AI5t6KybkxowqY4QUa1d83Wh5dy473M4Q88q46EqF8N1XJ7vGYsMej1tOb2fyDry/SFvhAux4tBUeevQMftdRD4WPZqRZtb803wSJggaL1QNkrUm+yykq+G5mzKGfGHkcKwI2dJtN4scWHgzQuqek0cvFy17s5X/ZK++INZ9HSl+DRfrABDEPqSolQVCirWx8o0B6XnS56Lp7NZ9cQE1iL6wkH+GRnNa31KP4wbC8t9HGUUebM/j92BxEo5yUT3pUSZSCNMALlIdNUkwUmaCPu5dgifPIUdP6uGrNspSnvxwhbUcSsw9561TWvyTKAy1SkWFvDAIwTiFeZTqA7orZl3qi6HUQXbUZmaZ8bA1y1z4SHvydIk8/oKWsLbwjplN8BCxrw3YJczcdwR3xW5daFUB7yFqUdFFaDr7SIWjcofC1ccxNe+5E6c2M557UyfU2IGEUo03o1xzNp0cixWJnz+Qrq747liFJgWF68UMvUHNK5+xqUiJrWzEr3bvI3si0YJfNRHufLlk7xLvrHQZvcc4yV1yg== X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 31:abt2rXbqiaTOqW1AUeMsEqPeii47nwaUC2disNlU389/42gi8h9y77p+ncKxKXFgN08OXKY0aJ6JNOAgA1yNByPAyrPzSxMHZtWZKc9dnecPoJnjJR/GXAbVneBX58/tuhLDM99oPsm5gJhKgD1pZGhmnwwvcWkahUcSkgkHN0zYitAI4kNZSiyh84pSxygjznlq+oMod+ouVLD4JvGw5wAOJ5BbrOv4i67GNHVASW6C5awJmEjt/0YKKvxZNcQP9Bro3OinQasFTehesTqVww==; 20:tTvnJC1P/1LVIk0OrXRwIrGaKEsOlpEDMMAXdk4DTL0+COOW5qByu7jluMJFBBWeDnKv3facrbY2QhmvFWcrYS3NAfsHII+oAF1/Nx7U4iyHHAzexMTW/nfcg/CIz0hSlDtxW7NA9R1+iBRrV436TS8qoomp/2I89PQiPnn7z4iVJe46tU30nvgZx5FHKLBkUcT8ZOU7W42gkOAExasnJVDjy4v66KpBD86B+yxn8DJeixMebwQT7JXb5CjiCUDkMPQJje9DgBjKWCCVz0BaIjMJOMvrwL0V7CUTkXvzanrLHr3z+n6qYW1WeqAy+sjilpwMj7T54hgc4K4NMvW3Rp1zLt+IDnn6U25NTU0ujsC/iQygkLwRfJj5JrT97LU306g7REQI15Zk4ct8+OATJb3bO4sDEJGMGjc0QYOBN7ZOROJ9ZYMG5JukcyJjU3ENGvAfy81qSmmDMbVJtfiRUe1FcoAwNJqxjtUKmjI2whB2YzShOWgDSElJCjaqOUNu 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)(20161123555025)(20161123564025)(20161123562025)(20161123560025)(6072148)(6047074); SRVR:BN6PR03MB2545; BCL:0; PCL:0; RULEID:; SRVR:BN6PR03MB2545; X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 4:SRCaKiH5i7MhS1ly84BhnRFdkJhscKpiEkhgko6kX+9EV4Xck7OkNJLFhFsahwpYb/SbFhq+FdyrzOF+/7Lpo6Cl5aSf64LLGwLPuE+Nii0FjiVrQhmJRhTa9bojHJUKGGOZgQMYFl0Ue+6r5o9UFcVDAvc4Zx1Fd4mSvOCQwLFjeFfNs58gRcp1kaqsJaHHa9DY3USv4iUBw7pygDxBcajkl+gnAtSOz81hqijdj4m5WtHEjQPXDlEa1ef0qnE9OkwUKYkrpv40fd7fQkzNxo6HOzWwLBDI/wHkS+BQ54kfAGVb1JN2t5fKiotF/Pcun3iTMFBODrfvgup506ezapfyMYY0ilO6ihuMapEbYmM4vaUcMquOVui57y6kVVFRIXH5/8NxzX2TUmNKpxzHBpJM/qGmc8cNYuEa3rOyRMC3NcVZ62/hETF14T1cJXz5vJCYWi+4YsCqsw8xBooup0GPn27eMszvszBMwwhqmepS4R4M3Oe1fq5CRksHwp9UAY3xlmjNEAUCIOgaeGEih0HS/lxSEHt7ssflEUWfWEHWP8F8s7SzlH5CcYEveaaBryDDxEf2KLUVPKvV1DCgH9sS1Rgdu9CDGw5m1rFUZ6pUl4474Dm2G/zz/fYQb29EzYeeGzzgucL1ilbB6RDlQQ== X-Forefront-PRVS: 0203C93D51 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(7916002)(39450400003)(39410400002)(39840400002)(39860400002)(39850400002)(189002)(199003)(69234005)(86612001)(38730400001)(25786008)(6916009)(6666003)(106356001)(2950100002)(575784001)(189998001)(50986999)(76176999)(86362001)(50226002)(105586002)(68736007)(107886002)(97736004)(2906002)(450100001)(6486002)(53936002)(101416001)(42186005)(8676002)(5660300001)(81166006)(305945005)(50466002)(81156014)(48376002)(5003940100001)(6116002)(36756003)(2351001)(92566002)(10290500002)(110136003)(7736002)(10090500001)(33646002)(47776003)(5005710100001); DIR:OUT; SFP:1102; SCL:1; SRVR:BN6PR03MB2545; H:ubuntu-vm.corp.microsoft.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A: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; BN6PR03MB2545; 23:rxedR5KYx7Y4SjyjtasP9ez+wFY+gXuiz1hdiAtCS?= =?us-ascii?Q?Y4pyle4vTiWCYxYqbmCVn/ZVNDDrHTLGyc0pUJgzLJmi6xzFESmBj2aBkErN?= =?us-ascii?Q?D6pQh3Izlvw1+An4OUNBESHrJmLtU4lTDWzpH423XsL0IYWCyaNcd1O62Hlk?= =?us-ascii?Q?/cqxapdNUGUT4RWEa1xWV9pW5PoN9RI3uLfF3ubNQ0bTJ1+JZP5/gbrPIo7U?= =?us-ascii?Q?rQpvgaU7xpg66vn1yI6oXU67hD+zPKYSsO2RspFxJyGMOOZQpPVbQHQcKbrR?= =?us-ascii?Q?ySsVNGnJkr921bCRcpGd7Nfzt0L5fMjREQb6uKfFc4J5OuC5OSjzjGPAM9Gb?= =?us-ascii?Q?Vb+JSRqJGpTyuGa48Nzwaaz2K5YtZ0W3OD5OwsWCflc1Fh8a0aGzw7a9olV1?= =?us-ascii?Q?GPiPIK7b7nNhD0hnVXYrRYocASy8oe0dmjPaJ8Xc+NiZ1xdGTXH7ClbmelC6?= =?us-ascii?Q?UTRh4qgV52JYPoHzJ20b4/PanW6FMCNlVoI7D5LHIGak1mrmC1K8/JZis4vk?= =?us-ascii?Q?wypgHcsHQFTY5P8tYDWLCDpGFhFxaFbAfdxZ2FcKMzJU2Y8z5mycX9XXCoTk?= =?us-ascii?Q?aqVCaXnzHELHL+L449banjDpSR/FayJF+h2vvh+IChkNkYBgAoEEyYStKhKc?= =?us-ascii?Q?tMgyF0OmcVUIAn/tLBZ4MtX5ALQD8bdvz6bN7gTSLyq47L0xyAjnd3DrpQE/?= =?us-ascii?Q?ue4ned28uTJDnocz6te8ujNA1bhZcK00Umz6rGOEX0+QLm8H9cjWYis7CIll?= =?us-ascii?Q?uCqJ9twLLHCT0V3drPsKS/WOf/emOKyMyr9PQbGaphLnApbwhCABYrnl1ilW?= =?us-ascii?Q?ao7XiYn8D4NvOhYhuX6Yd2YvzU52C9B7cqNSb2Ux3pOYAURiRA/rxyGHjrmT?= =?us-ascii?Q?yHCkH9DH7h7pHzQdyqv5uW0CRb/L5Bup2/7Viws0jle+LhG7EGlDpRF4LuK1?= =?us-ascii?Q?VzUJIzZeh2+w09RnKD1Mt/PkK3k8a5ppckkyMcZLUElWFuDainmTXmmPwfgW?= =?us-ascii?Q?oKyozQSJ1FbMxeNXmWEmAJ8hM7iQSuws1uvVZkatjgH18I32KmQ/vJ1Pckm4?= =?us-ascii?Q?/cyaaTmIPvizbRPF8Xho73ghhw64khXSmb+gQMRHbRkET3Axg5zD4AFjAtVA?= =?us-ascii?Q?TKhgpEI+YAjCjHpxKR4FxrUIoUsl9r6S5BJ7qGOAU6rKnj4XlmCasv2T5L6V?= =?us-ascii?Q?MZq8pDLhgPuCaBnns0i+xapphQKWk19DIiaIPfcxKhZVVQpxf44aFuufhoYa?= =?us-ascii?Q?0yN6MqG5/Z2VNlyl3X64jIHZsqZYdX1pGttxYyB+HjaZx7ryi8m7/urTiN6D?= =?us-ascii?Q?iYyE2dRPCdVSSGtpk7mQK28P2/NrIxHbPQh5pKy1aDV?= X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 6:9JnsIAhUU8/nAl6pBYQi3CiEg9XAk38Li74RybQ7/mZDBnSY+PrxBaWy1OXx10ntpaj6k+7iDs0FeEi1f6yWNbLOaPJmj12ahJJmlOhtvZpyGs8D9YVNRhqDEB/hD9un38jKT1JLLAydUfyzwQdhace5hMVaMdDPWtvne1hg5W+wBYaEivm5KzVyYZ7mRrBCk/qYu1/yugIgbaF3RcGTwHZg9JOTBVgQ2eSbIHWJithnkLmVHxIl4uc+orWmSKVxJwZpFzPOmYZDwyeddYRY8YYFGGR2cRBSEVucKJQzZIAzzgVliy6x3p81+3j9zDW8jUr3vlCaaI1bySMfntOLFjg8exqi2zTnZQTFbpAtFc+RwMhdPwEYP+yijW+tMAmLpor1bvIOMCj+OoGw1toXJCGV8zd3mztQbRmsyLgksXZd1Il+NOkQbxyimhBP5Yfg; 5:BNpRNgCkAj3PmjpkZkKlRwUMMXhpMumnzTb3dq9Q4N+KYyQhbhEJMJ34Ez7E3SgYsuLpCMe4+BbkbL3OLLdIrvGAHdj4wO3g2i2FPB10yiHBdR696j5O6ljEaSvU3BIt3PCZIZi+f+QNScFhYIyggh73N6Z7YwxaqvAOu6TGNDk=; 24:ogfATEDisMjdzPg1yTmYKWUitlI43/pkxfTJ67ampLuvUClqH4BxvEBlED1lGBcYrNntWPiuUI2tnuSvWBXT/sU+utjERqnFEZVRVe3d6+c= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 7:Q3KQo8Ks50yRKhZXOYxDg/SZ93QHLjKLQrx4h5hjS7L7CHkoo3YLuoUh7Ncc0Uk5lEbDaHvhmJU+ysNPGTpE4rkKUKgmI8IWTKzVEMLLDp9bTVPi8/pMpBLIw0GN8WhwTpYQmb+NNA8e5Mw+FfhHg7NfTpduaI5afAohzrAYsXxS1SVfwJ5Ai3tdI0QGBOTXtjmKs+lx4YShPJWK3fr0xNpok2M904u5CsKx6ZVEDpflCRbAZE9UbnXmLOQrwsAlkpvtQVO3a4UbJpEdJWlYEShux2SoULmlF78px/dnj12m3N6KRXucS1LuL146wlsQIiy77J0Oulv/D1RUttHEs+tSRF8joBh+0PZqneG8+Zfrs60UQqkA9vGi6uPSgB3Tr/qYvHWKqAVOzhpaFBiQgNNr/hTiKAidjClkASVP/UGFxVcSpcm1ZkRXh2aIQLBHQjYU4rqIeB0VrPgXF/TEOw== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Jan 2017 21:39:55.9549 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR03MB2545 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)