From patchwork Tue Dec 6 22:02:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9463331 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 9E50360231 for ; Tue, 6 Dec 2016 22:18:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8F608284F0 for ; Tue, 6 Dec 2016 22:18:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 82CFE284F4; Tue, 6 Dec 2016 22:18:03 +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 A2910284F0 for ; Tue, 6 Dec 2016 22:18:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752237AbcLFWSC (ORCPT ); Tue, 6 Dec 2016 17:18:02 -0500 Received: from mail-bn3nam01on0129.outbound.protection.outlook.com ([104.47.33.129]:2800 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752190AbcLFWSB (ORCPT ); Tue, 6 Dec 2016 17:18:01 -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=I8o7JCU7NePVLmrndOODRD5WUwiCJgX+iSgVmedjc7o=; b=h46sukunYLoSBD2//Kfimy3ufhB7PDQ2jFFcdLYbvJZuReeAO8CrivjOqBU0zaa1SFosAh25MqfAJlyO4dBWp81JDxIASonM6GAeuFpRR5yq7YVpgL5PhuOSXE2phdXw4f6rpT/YE/zO63Xrff6xBdaUwfIT/UQZVixDPhrjLxs= 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:50 +0000 From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH 13/15] CIFS: Decrypt and process small encrypted packets Date: Tue, 6 Dec 2016 14:02:36 -0800 Message-Id: <1481061758-52020-14-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: 70832957-e5c9-4ab2-193a-08d41e239f11 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:CY4PR03MB2549; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 3:2csXhApLm4HP46aPpQAHpAHVbTO1QmmkW7YaJbeg8NN6EQ+OPKy249KncyAfwrQHUNap2vSxNbW31b2m7VU2sLkcJkvhkfCGN89o1h97UGYqYOUs663nrOfVQbY8gb4NjK6zIH2LFA+zD/mkoH9u05RcX0tthyQTi03e6P1ADeqcOekvRKeAvyGbEPKUWKMrC++T3AUJyGlNobF48xIgMFo9TVaMG7DvgSjK+qxF97c8FizanEBNCZYmSeovklTXz4wvzaPOl2RoytmqoAAW+g== X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 25:XeqGa2j3DiJ5j/gWgMMZ5AF7rLilXEYUCMOZ13vZmagBzzlnGvFuZrECqY9u0CB3qHi8K0l6xgan8JD4Rhkv6S/JgCwo3ccyREN1pIiALw30aDCe6K+LGiA/gLzdqYT+R1QK+nkTNeEO9cLeSzA+y1jLlqm8biinxQMFO0q8r7GXcQ1FdSCf8IOXrmnnBj094RpkjZ+65Crrgv0utIjzTpgAQEjrzWLzzI6QGA2/p7eXqPxb79mNCSw+y0Ef0+CBJRpRE3ndltzhhw9E2sYUZD/Ao85H9f7TLdi2eoZFaWR9AS+Lj84SYai2a7lLnSiI8YI80XnXhdxZuDWkv+dtFjcNpTlQgOD6NEa/v71yOkMrT2zJn4SNBKVtoCPdozJbxwF4fQdDGZh6j6LeGwlwXYn/y2yl5QATQVn2d91+JFC2cXbLaDCtIGoErt+ulO1ojQoR2BMFBYOqwEGu5z3yiAr3GhQgjrzBzYnjq37xol4b1JC3bw9QEwdvTwhoV/Io/4H9sdghYpjGG9NzvVx2M5LY8XBXxk7vKUkBkbipWVLvFMyn8NwccVFkDea6Z/w7/LAMzPs3BAvUObhfQGANe9T/uBZCbXAr5PO0a9gx5e3sfc/Pd+9kXI8PiCc6m58xvm/lm5XSFC+ZHqeeo/652ZwFIZ7RSoGrDoBkk0/yj/HHOBE6r3UZ6TlzPpqWFmv3BO3OniwEfrIyaf4gwihm8/+vO0WR+fYKwBa5X/GesQWTeUNeiLNgfitM4ZKzlfQ2HnVoGpylrKm34UkE5Z2/kgp95B9h+4nAr8q6hElFiG0= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 31:eKRgyj9j+aq5A3dx1HBME5JskqJxAbe5YGWAcsJJck43lZIbZmoqxsvvDLFvMr9D+NIk5IRBlgMsXkXzLyBhFWpv4fCcHRiPehJxVY/0WUcvpB9khFsPBqy9laeleUCKtf5QFCVoaLtbvVmdgbgcBYU3wFF/512I0hMe3+8LB5IdqZxdo94n4VyfnY63suOu5BliJjWr5gqD9hXMZpvVMo9RUq0r/PApLtCrkES1zztqPDY0QwBB8r5xml4DP5XSZoWUJdR+cLyH9PszPRiTjQ==; 20:5jTp9+qOxLfNVjTbxaDmM2Sv6N4MmbUSxFmqk0QkFZC2RxQXbz0Pag9cA5dOsMXCdZ/gEyMX/gS3K+lo3L04glHjuwKUQk1RyJSoxoVYzg1Qent/v4tddgtyRLlSocPb6kzX/spsUZ7drMPL9J44o5MklmUkw55Wc/QSBGrZ1XCuWwl2wcR5jb6YsIx2yjAbSPPkPhOHKa3XuKj6B8uQhWGxseHphCvr3RS/Op88aYsbkH+YgEoML4V+I+P7poAUh5xxx/M3tmIq08QIP31rWgrycCZTcMjj6aivJxFYtHXQEsfrpmnOhmZEnQChyMYdvo6LMcxziEkoOhznR8hpvHyevmnAC2+z7yo41dWCcuWaAnGrZYk+1kafCDw+RpFm3QzG696t/G1p/IufYQ2vJNRpDZEV3pwjIsBL68aw3UEf0SRw5NZxxQV2o4gAObpRvXxOF7iXxA/IPRoUkDblwXy4fen+yaFu3RZ+mPJ0AcRoIfr8RLKnTGMghr1z/A1Y X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(158342451672863)(17755550239193); 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:HvFydDZCtehoPxj23q1wJfulZh4UuQNVCrQ03Xj7TWZVeDF4hX258k+xTVJKO+OcmZe3TEnZeI3jVevQ3FtIeOVYuT/z3WUnRSZPt3/V8k4EbkhHE0bIamTSA0Je0VQbbtJa/sqjq229o/4KgEx7AUOnJVBUoHP3GYQZ53/z6q+3lW+Tl2dZUjgYsttbbc+yIZliP8xaonohUvdxDWqNtW7w3kVksU70YwCBBUrTra2GE3jGjC2Ds1y6kZ5jBkPkn14WDnw6b5OVPBj8NYPhcgmJx/OSYHf5vonBvz55hwRjkcb4hIxkd+B1MzEH+8P5fTl5IHjModqi6EvoIMvMXTNsz6yqxobxvzL1yV5D3UlAbrD7D4PXBcCv0D4HtUTZuH9xdVrc1/vHIUgmjOEsIELSbQa6goUUFVQkDUi024MMgY6I7mBLQGEL730l84HtbgG26lz6ffUhcm3Y/5NqcNFlSZjfekYWXQiWWwRpqnoAS/lk5KxJX6orobCyKOzT/Rp0p/lVzlHRGBXWGej3B2m6D5CPt3Fv//y4cJUzHPsDxDHPnn6XzRmgh34ZK1ArpGB9zasJxJHpulgo21t61HXerAIXbEl9vJlX+8/nJloLDwUd+hAeAc44Ys+unuIHMTMyCJa7lrLHJOpDuxgqXgXba7aZX3yT0aDWbmstjQ8ZrbaNgp5HD8HhOgnElsO0 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)(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:qV2p59aM6adyTYr4wMDELqny3vG6G1VbeZ2Se8E81?= =?us-ascii?Q?zjJLoQmNlmBuuxpN+MCxlBwp67sSsPkT9IXgGb0rKqdb1+eX7KzvejUVdfxS?= =?us-ascii?Q?ss1hY6HC0x9+LHwimXtZmSjvpOrNiXtTTJjL/h/mhtnmsqzvDvFRPFnAWGcj?= =?us-ascii?Q?aYlFzzU3S23uHx30lntvDkYAvZCI5EkjaWjnFETzwNwlE025iNC/XuE6sJ2A?= =?us-ascii?Q?zkwaVHvwfBafngxx+vaBONdmPkTHYmiBMo/Z1Ntgh5cgJxFey9sKSUy3XqSB?= =?us-ascii?Q?Q2xWiQWxgfVuP5e0fhvT4JAWTnZwQCLQBVcnjf+21S2PmCUoc6mOBC4rHMWe?= =?us-ascii?Q?VxawwfZNhCjMX0mG/I+vVLda2oEUezp4x+2zBptP2Zm4dj7YZF4Ng3+5R/jQ?= =?us-ascii?Q?2DNOfmjEsBbH8weSHajP+XzFXHfLBiSRkNCkZ+y9R0wt+poEOaX1WZX4fKf0?= =?us-ascii?Q?32ygKqsofJCt5U1p9p4z1a498erkcyHj4RKhp7/56pTpYanpinUF6uSQZjin?= =?us-ascii?Q?xVCD0nJzCOeKEMN6NV/2dm+qnMpFN858+KVUFzDU6B5d2u5dKMzbeEwRrrUV?= =?us-ascii?Q?3hz49vjPyhkVAQJq6kyeYixf2Hve5f/or0WD3Re1kHNC+3TuZg1dxiACAqJP?= =?us-ascii?Q?KsWTuTu8YwSAKob0mPxsDDZdKLxMwdJhoYhmJbXbw7Qv29DR20AU2/OY6lmj?= =?us-ascii?Q?a0FsRl7XOLGzpELRhy+rH4ruD0xMGg4bgAjIT6Ae+yGXi3tALP/YQPllfyx0?= =?us-ascii?Q?WOdwjZ3cDSMchmLlTI5KACHxp6b+Eop5+iZBiiCIhpvxv6a4D5pLjwB/FehR?= =?us-ascii?Q?kNhc73C73/MKTQr6O/WBfghHP7HXcd0c0xE00Eqc49WzcTO/M3gnN/8cTz6T?= =?us-ascii?Q?8Wfd4dzHT8lsvMvpl4oSnFCciCyQntpqFJFz8USvmi5LJTO6ySKz8qpUfnRE?= =?us-ascii?Q?qEnc242+HzmEFRUfvX462FlbKJKeC4EnqG4YSooyVczoeLsIZsv/hc7dUQke?= =?us-ascii?Q?banWwnemLcmPFR3l8Vq9BtOQNOwI6Srr59IgTVtZI5TDRuUQ8vjRrwNWKDy+?= =?us-ascii?Q?tbColvczHCiChI60Z+8i159ViNOmG1Hd8tCm3RAgF3JCiz7vWXodgUddHCKu?= =?us-ascii?Q?rNYNx82HhB7rrjclW4b0eRAvK7EwGPTN9auJczO/e8I59Q21K+g2MwkIaTX8?= =?us-ascii?Q?o+zoDfUcCGHtgbHXDgX8+mgRDAjrKJSRSeX0U23hwi6Q3xHF8xIdG6yUSgZZ?= =?us-ascii?Q?zUSTvXIXo5iAVLJ8SdXm5uMqcYcAMPrTinnaK8iPK0udV6Irs6RdS6lW58NU?= =?us-ascii?Q?lgj6LdlyuhwUOdBw9ol/DY=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 6:Ms1SvMaY25Wi3pqvJ52Wz028JOd+szzGXYcF1b6P3ZT8rKDVCwcWPS8CwsauM6O/wccnY4vz3IGgjPoC+j3ZBaV1mTRcrtAJDGbFafdi7+0mirGA0Sg7PIQmP5DhMGxJtYZKO2jFovfxNONYr6HFlcfLHAdlYq/P1Q8sn9pKaxPpKLmZaF9Tj8Hs8EW+p6MlnVvgT2SOnb+AiDtICIc3W0FtvBnEZh3mjJNB7O6Dhwu38mof1CQrZ9byOJCKy19UTxY7TVjjtttTi2ffqIJjPakg/qr92VfjT9+TI9e6wavx9cxNtujEu/nSFe/2db4857DIgRHfptUIwDQB58QuzNAGDzQqFLUlpDiTP/lFW9QpDaU6lWuNGFeBZqXLmqVhR3dn3wHiA3WioYkFGnpMo4GAgFXCqurkyMMlbXU18Y71QDHvGs6Pz+Sah+znclP/aeL64GBZ0TmoObdVrBWrtQ==; 5:EUh6NC0Ik3bI13fnT1qIY301CQJ9KiH/tVJlRXTKIEHucU3KyrTj8pwFqMCQliz/GZjhfIm158+ZKMQIv0JStpSs6owpZczTessDfO/1rUn692YvJ2I7CA9itxWlMfN11cB1fu7X86f7BFZUGcEAaS1igffVh6EfEeaDvjKJsZY=; 24:hUAd0BVfnuB+bODmMcjC47CnAbkm0A3L2mUhvPcjZuXw6Onmfk/HouCH/i5GrtChdC7gO0ho3ZHQ1gjmIyn2BzVWyj8SPJF2wkMoiotRdmI= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 7:7ZCGa/VYsTkDvlWjwMfrsg0S2rJZrobZSyOrKmoU5T+xv8x1IxAht9del8YfheAik2JYYMGx7WxkRsoEzIjJv2r1nDWD2118j+Xi0P+y87UHL+QeTTf/zjPMPJ/DvmeRYXBMTWY1BeGBsDM6hOihIhH4962ZIQE0zNgQckR3K4g9pD4ZaXl54/+fIb5mdKJE35QgxQPMFsS7lkIr+xcQ8UCTMjqztViDIxDSMslzxkgAXwoFD+AafKEEe2MXWtyUnEQQfM6jXz3/lDlbL6sEu+2SOtRKAOUsS6bdj9JDrsvs8d0UD5TWRFlbADVBtZlqhelcDuoROJ9Qcsw7d2U5Iwt8opko7B/MLTZCrZjOYLANTgJyVtNxwvYPOmOEs4jR57D3s+V05o8/HcRyaBa9lBbmM9SI+F/Wab8eYnXB6vK+YdxHdW/HIoU7tdLUGjbQl0yMEhcO5/kkfcpfvL4GZQ== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Dec 2016 22:02:50.6618 (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 Allow to decrypt transformed packets, find a corresponding mid and process as usual further. Signed-off-by: Pavel Shilovsky --- fs/cifs/cifsglob.h | 1 + fs/cifs/cifsproto.h | 2 + fs/cifs/connect.c | 9 ++ fs/cifs/smb2ops.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++- fs/cifs/smb2pdu.c | 4 +- fs/cifs/smb2proto.h | 2 + fs/cifs/smb2transport.c | 2 +- 7 files changed, 240 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index fa56f47..f9a9a12 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1342,6 +1342,7 @@ struct mid_q_entry { bool large_buf:1; /* if valid response, is pointer to large buf */ bool multiRsp:1; /* multiple trans2 responses for one request */ bool multiEnd:1; /* both received */ + bool decrypted:1; /* decrypted entry */ }; /* Make code in transport.c a little cleaner by moving diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fe874dc..0eb35d2 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -74,6 +74,8 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, extern void DeleteMidQEntry(struct mid_q_entry *midEntry); extern void cifs_delete_mid(struct mid_q_entry *mid); extern void cifs_wake_up_task(struct mid_q_entry *mid); +extern int cifs_handle_standard(struct TCP_Server_Info *server, + struct mid_q_entry *mid); extern int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, mid_receive_t *receive, mid_callback_t *callback, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 3a2183a..c41f496 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -784,6 +784,15 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) dump_smb(buf, server->total_read); + return cifs_handle_standard(server, mid); +} + +int +cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) +{ + char *buf = server->large_buf ? server->bigbuf : server->smallbuf; + int length; + /* * We know that we received enough to get to the MID as we * checked the pdu_length earlier. Now check to see diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index eda9d4c..627096c 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1799,6 +1799,225 @@ smb3_free_transform_rq(struct smb_rqst *rqst) kfree(rqst->rq_iov); } +static int +smb3_is_transform_hdr(void *buf) +{ + struct smb2_transform_hdr *trhdr = buf; + + return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM; +} + +static int +decrypt_raw_data(struct TCP_Server_Info *server, char *buf, + unsigned int buf_data_size, struct page **pages, + unsigned int npages, unsigned int page_data_size) +{ + struct kvec iov[2]; + struct smb_rqst rqst = {0}; + struct smb2_hdr *hdr; + int rc; + + iov[0].iov_base = buf; + iov[0].iov_len = sizeof(struct smb2_transform_hdr); + iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); + iov[1].iov_len = buf_data_size; + + rqst.rq_iov = iov; + rqst.rq_nvec = 2; + rqst.rq_pages = pages; + rqst.rq_npages = npages; + rqst.rq_pagesz = PAGE_SIZE; + rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; + + rc = crypt_message(server, &rqst, 0); + cifs_dbg(FYI, "decrypt message returned %d\n", rc); + + if (rc) + return rc; + + memmove(buf + 4, iov[1].iov_base, buf_data_size); + hdr = (struct smb2_hdr *)buf; + hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size); + server->total_read = buf_data_size + page_data_size + 4; + + return rc; +} + +static int +handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, + char *buf, unsigned int buf_len, struct page **pages, + unsigned int npages, unsigned int page_data_size) +{ + unsigned int data_offset; + unsigned int data_len; + struct cifs_readdata *rdata = mid->callback_data; + struct smb2_sync_hdr *shdr = get_sync_hdr(buf); + struct bio_vec *bvec = NULL; + struct iov_iter iter; + struct kvec iov; + int length; + + if (shdr->Command != SMB2_READ) { + cifs_dbg(VFS, "only big read responses are supported\n"); + return -ENOTSUPP; + } + + if (server->ops->is_status_pending && + server->ops->is_status_pending(buf, server, 0)) + return -1; + + rdata->result = server->ops->map_error(buf, false); + if (rdata->result != 0) { + cifs_dbg(FYI, "%s: server returned error %d\n", + __func__, rdata->result); + return 0; + } + + data_offset = server->ops->read_data_offset(buf) + 4; + data_len = server->ops->read_data_length(buf); + + if (data_offset < server->vals->read_rsp_size) { + /* + * win2k8 sometimes sends an offset of 0 when the read + * is beyond the EOF. Treat it as if the data starts just after + * the header. + */ + cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n", + __func__, data_offset); + data_offset = server->vals->read_rsp_size; + } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { + /* data_offset is beyond the end of smallbuf */ + cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", + __func__, data_offset); + rdata->result = -EIO; + return 0; + } + + if (buf_len <= data_offset) { + /* read response payload is in pages */ + /* BB add code to init iter with pages */ + } else if (buf_len >= data_offset + data_len) { + /* read response payload is in buf */ + WARN_ONCE(npages > 0, "read data can be in buf of pages only"); + iov.iov_base = buf + data_offset; + iov.iov_len = data_len; + iov_iter_kvec(&iter, WRITE | ITER_KVEC, &iov, 1, data_len); + } else { + /* read response payload cannot be in both buf and pages */ + WARN_ONCE(1, "buf can not contain only a part of read data"); + rdata->result = -EIO; + return 0; + } + + /* set up first iov for signature check */ + 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->vals->read_rsp_size - 4; + cifs_dbg(FYI, "0: iov_base=%p iov_len=%lu\n", + rdata->iov[0].iov_base, server->vals->read_rsp_size); + + length = rdata->copy_into_pages(server, rdata, &iter); + + kfree(bvec); + + if (length < 0) + return length; + + dequeue_mid(mid, false); + return length; +} + +static int +receive_encrypted_standard(struct TCP_Server_Info *server, + struct mid_q_entry **mid) +{ + int length; + char *buf = server->smallbuf; + unsigned int pdu_length = get_rfc1002_length(buf); + unsigned int buf_size; + struct mid_q_entry *mid_entry; + + /* switch to large buffer if too big for a small one */ + if (pdu_length + 4 > MAX_CIFS_SMALL_BUFFER_SIZE) { + server->large_buf = true; + memcpy(server->bigbuf, buf, server->total_read); + buf = server->bigbuf; + } + + /* now read the rest */ + length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, + pdu_length - HEADER_SIZE(server) + 1 + 4); + if (length < 0) + return length; + server->total_read += length; + + buf_size = pdu_length + 4 - sizeof(struct smb2_transform_hdr); + length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0); + if (length) + return length; + + mid_entry = smb2_find_mid(server, buf); + if (mid_entry == NULL) + cifs_dbg(FYI, "mid not found\n"); + else { + cifs_dbg(FYI, "mid found\n"); + mid_entry->decrypted = true; + } + + *mid = mid_entry; + + if (mid_entry && mid_entry->handle) + return mid_entry->handle(server, mid_entry); + + return cifs_handle_standard(server, mid_entry); +} + +static int +smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) +{ + char *buf = server->smallbuf; + unsigned int pdu_length = get_rfc1002_length(buf); + struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; + unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); + + if (pdu_length + 4 < sizeof(struct smb2_transform_hdr) + + sizeof(struct smb2_sync_hdr)) { + cifs_dbg(VFS, "Transform message is too small (%u)\n", + pdu_length); + cifs_reconnect(server); + wake_up(&server->response_q); + return -ECONNABORTED; + } + + if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) { + cifs_dbg(VFS, "Transform message is broken\n"); + cifs_reconnect(server); + wake_up(&server->response_q); + return -ECONNABORTED; + } + + if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { + cifs_dbg(VFS, "Decoding responses of big size (%u) is not supported\n", + pdu_length); + /* BB add code to allocate and fill highmem pages here */ + cifs_reconnect(server); + wake_up(&server->response_q); + return -ECONNABORTED; + } + + return receive_encrypted_standard(server, mid); +} + +int +smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid) +{ + char *buf = server->large_buf ? server->bigbuf : server->smallbuf; + + return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 4, + NULL, 0, 0); +} + struct smb_version_operations smb20_operations = { .compare_fids = smb2_compare_fids, .setup_request = smb2_setup_request, @@ -2047,6 +2266,8 @@ struct smb_version_operations smb30_operations = { .enum_snapshots = smb3_enum_snapshots, .init_transform_rq = smb3_init_transform_rq, .free_transform_rq = smb3_free_transform_rq, + .is_transform_hdr = smb3_is_transform_hdr, + .receive_transform = smb3_receive_transform, }; #ifdef CONFIG_CIFS_SMB311 @@ -2137,7 +2358,8 @@ struct smb_version_operations smb311_operations = { .enum_snapshots = smb3_enum_snapshots, .init_transform_rq = smb3_init_transform_rq, .free_transform_rq = smb3_free_transform_rq, -}; + .is_transform_hdr = smb3_is_transform_hdr, + .receive_transform = smb3_receive_transform, }; #endif /* CIFS_SMB311 */ diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 12dee85..0abeb5f 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2281,7 +2281,7 @@ smb2_readv_callback(struct mid_q_entry *mid) case MID_RESPONSE_RECEIVED: credits_received = le16_to_cpu(shdr->CreditRequest); /* result already set, check signature */ - if (server->sign) { + if (server->sign && !mid->decrypted) { int rc; rc = smb2_verify_signature(&rqst, server); @@ -2384,7 +2384,7 @@ smb2_async_readv(struct cifs_readdata *rdata) kref_get(&rdata->refcount); rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, cifs_readv_receive, smb2_readv_callback, - NULL, rdata, flags); + smb3_handle_read_data, rdata, flags); if (rc) { kref_put(&rdata->refcount, cifs_readdata_release); cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 7d30b75..85fc7a7 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -58,6 +58,8 @@ extern bool smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv); extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id); +extern int smb3_handle_read_data(struct TCP_Server_Info *server, + struct mid_q_entry *mid); extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src); diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 3caa11d..7c3bb1b 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -564,7 +564,7 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, dump_smb(mid->resp_buf, min_t(u32, 80, len)); /* convert the length into a more usable form */ - if (len > 24 && server->sign) { + if (len > 24 && server->sign && !mid->decrypted) { int rc; rc = smb2_verify_signature(&rqst, server);