From patchwork Tue Dec 6 22:02:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9463333 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 B7C2160231 for ; Tue, 6 Dec 2016 22:18:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A93CD284F0 for ; Tue, 6 Dec 2016 22:18:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E077284F4; Tue, 6 Dec 2016 22:18:04 +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 E86A0284F0 for ; Tue, 6 Dec 2016 22:18:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752250AbcLFWSD (ORCPT ); Tue, 6 Dec 2016 17:18:03 -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 S1752102AbcLFWSC (ORCPT ); Tue, 6 Dec 2016 17:18:02 -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=wgIdjycNCt0pH1CZmTghKpA5w/A/hvApJyC3tmBib60=; b=lxnlO1ZINvyyzckhykji0xKMudw7XvNhi/SMq7RYbBiEzHTpEReHzj8CoFgaQqnsm3aab82WZMzU0llfrcg+6UeDFZ82RPZlUENGc2hPK+gSVRbyXKxweaTUV6u6Yq0ZFE8ogDXtulsdunKNizy7mXwCYSgjfV5le+L6XXTeM7g= 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 14/15] CIFS: Add capability to decrypt big read responses Date: Tue, 6 Dec 2016 14:02:37 -0800 Message-Id: <1481061758-52020-15-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: 0fd7143b-9426-4ec7-c2b0-08d41e239f3e X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:CY4PR03MB2549; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 3:CVEBo2TyP8FuZJOFhA/x1t09UINPza2GkzS6ZY7mumPg+tZ5MZCVHgxellGCUMuiuvnyCTwVbA97lkZPCWyhcB4cQPpbJdJiYv5YV7WuAYJ6peSVtzTKXbRuVWx6lENyQMeamFa1G+lOohaMpO2L/Hsek0ZtNfr6A3RNONIvl8WDkmsvOMfUmRgHX7UVOo222iU8GqxJ6QNweA4yUeK4BJfiQdanj2cAjmxe65LL9B2thPJo1kvu8Kkug4VV8mjNf/DmBQWLJwiiO+hs0q04BQ==; 25:aDFHrbXsF9qJB97AKRRTPXQcSe4UobUB1UKw2FQo+Zg2e78X3D1nPL33btC/f6Zzshx8o3BWd0DsPt65Imu0UzvDVJNYYk8wHl8DRuUmpZx/YmEOef+Nr7sqqAE1oYna7YSKSChb1awv7ElC+cB9QQoZ+BRvAFc7ft4gYhjjiMC2n5yIRHOZ11mTLhpQaIPhXzGzp0FhCkkYvczIlvD+lOhpR/2fV6AtTBeTBcYvzenkTWWHxuuDI8DZ2goxV1npAFj1XJ5Q+VvGziQrEFAqM3DyQ9ZguljzoDO2FFLUbmmyNtBcvSiQnJo80kYd39vQtatPgZXDj/+9YRhJl9MwcpVrwhgnGhg1WG5T5MLorLXSiUDZ5Dq+qXXzsTmBILhyj/mZU1uEZFl0i86wkzuD8Ndmu3f8iLeG6mmKdkyZuKEvXSSa1FhSdp1wVTQ71jBWLkxXDvGdUG1Gui3Pgc/r+w== X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 31:DsHkwh4C9i2uhUKnyx0avZUaeGuya6GQd6rcR/7AGcRc68bzEPfAypxkxT4NulmjWjRGgqu7n65n0XeBbOD/zValeNOH28Q08xFBPXRIlNxmhl0b2yabHS+qsvHPGvh5UVSfBW4St0TP+0LoO0e4+71JcSsF2sjx09pd76zuXXd8N6HvACStGkHUIkBRpQ3QGZTkgkqiGKXAd5Z4pFcciF6M1SZr6WUBw7ZBZfDA9XeVVpECpmorg8eV85kjdDZMn9UsD2SNNgCqHl28kOWzxg==; 20:o5PnVsRT8sNzrXs8JGnf1RincnesBm7vCLY1tVczRR1RRwz9CqulLXD4SiImcGHnqOT4770/726DiAR3fbamT5pns0lVZ6Q90PEzoynm89EvF+tqrlfxEvy9v/6M2YpaRXhAA+10GLgyZLs32dmfHqQfePi8zUhSOBUqwkFiuS44c/mccyf8EK27S1SlPPvlAb3pWZ/4gXEK+6HXor4wr664oJ9+pcYGzr2ME+oqimXlwslCA+paRLFOtNQXlnHENGvL3TUxPrg2MAb5E15flsPodHdHZZNE3M5hyiHO+GOY3H1DTSJo3plYWp66DtfdQ3RpifcYXuRzuJt0qKkw7KFlnMQFyB3wLgtRRD2rAsx2XiZWwBRvaXg/fhn+ooxlJgvxBogpqwiGiFgoRpq050MIrSiIeTNd+FR2OuGkdhCvHa83HiMLsjl1lvNv4YrFC9M/ePUUHB8Il0bHOiGwF4o1cp0JzviXxne55JnFIV+NbVVp1HaHbXSXRheiCucF 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:O/4dQRhy+XwrhEgnASVz9in6CIKqMcXXyqO7JGOFhQuzuQpQ8fDBUsggGBo0e71d60PJQwZpTEXEfRbZB8EsJKlwf3uLse8q3uVS+HXcpBR1G2ZPofjOfYlu6JBjoD6oz7Ri0Nyp72IpBC/DePkU5mg768Wys48nTSmIRKpapaMLDDSGTDxGxDVES5fMaf4q1DI3inS1YLBuQAx7rvezHKPQoq3rYt+yQW+KfbzK/PqgfGfiphJhAvcy25l0iBnTSfCU8rgdEREiGmmvmPwWPBBSKtAmFkZE9YBH3dCz8qIUxvNvW/oDffiK+p67YlgUYteCySBnpo4sZKFNyjkszS00b0LEQmyeWFOTO/QpnDT6IYznzrmHOQ+RjLDbii/34yBVr3Sb3WZ9vamnWrrIiFiMK2ZmDLpf9p9E/c4oneUCCuUKeQtrT6E701igCQ8CK5QrqHSOE4JC1tGmoxxqKcK9DBsUZ7pXmIgdn4oB1TspXgwxagbLhOSO0JNpX0kDyeyfaAwZV/U11ygOTk0FE8UcUM4/edIQLDQ8R1ojWe+IRu70WguD+OAQJTzzJMyrNQQ1YhgV77nM6fbnZaREaMYvlc2eqx1oHOALkSpOb5mDmWMEqfTDwpyeJGWIb9F+yg+w3PCXQc0kferExTqinQsY57tJxS+8D82/yt8RE48= 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:oV2uSaVvhULqZgaOQa82ThGxnHWVZwmmHJOH5U2H8?= =?us-ascii?Q?7z+uYxhFxdW1Fuegx0ygpBqG/vcP7ovjt0GhVd9slH5XI0tbmOqAks9qdWyC?= =?us-ascii?Q?ZhBmDhzBzolYFc4NEKzvg+klbLep8OXZ/cbZBJ5dSIqO3Xnp77dzTuZA+UJh?= =?us-ascii?Q?1WMzYjLGgx/+QfUmd53f5D/FQGSSSAYpWEL1q/aNbM4n92m42s13DN0Jw4Et?= =?us-ascii?Q?w/VHWAUAjImRpSX1825qCLXW3+IjZm8vP8tPrDJhXcwe/qvDi57bxPC3KSGt?= =?us-ascii?Q?sGPK+oTeCSQfGHYbFw2yt9ijx1B48tyGixy2T+4jahxTCnD3Bq1o22tVZpoe?= =?us-ascii?Q?yNgeE1ofAQ1OFKdblcDXunMI1uG0RFYAMMM1+wcgbWuRrvOhS74RiGISKpt5?= =?us-ascii?Q?SQdiU3OhdBvfk0yXdEk81rzvPg0mbcicpt7g2AyypkBOyRzP8uwebDNO17e7?= =?us-ascii?Q?mb5HBqN6c+vUNJJ2NwMQ94i+HukmvapysHSzpv+Q4Gqd/IlLVeb8rv90Jbmf?= =?us-ascii?Q?6eckuA0WDtCGFm0JUNXJU+UocuAdN0XsTyPLxgORSHpqwu5pIxUpb1F01H6L?= =?us-ascii?Q?0DVkL+kxEedBtGtweHba6cdciZq/qn6obzUCGOsDoK4cmK8hsAC5BjqKZxtu?= =?us-ascii?Q?Hoj2gmMac2SPj+6knHPamteg4AIDVRxxjAjAydSc/5L9CfEREX7GcrUDT/Q6?= =?us-ascii?Q?bGBep9qGiqZ4W0vOahohL26duzgxzBUhCyrej76+8GF2MVqXMlgZusTamZ+6?= =?us-ascii?Q?+GDJ335Wk8zEDysC6Nx+hJS7Rbjj9ikDFyORP5eOpc0QN4LLRtzla0AZizWO?= =?us-ascii?Q?xdmHuBMFqGPo3nsXQlZcUr0IJcIUxuehVKxAnqVX6/YvNjU/oUN5cMXxnT2n?= =?us-ascii?Q?suUvF2NZlD4qKcuNarQzV0uiFALz3vOtCm0UcqeHPaFUK1EdtpFHO+x6gh9I?= =?us-ascii?Q?zRrk3D9YmvEmJJauvt4nvAd/m4wznd9BILWfUpIchC/vu0ECKNjCD9qW/0hb?= =?us-ascii?Q?/K8Ma2rDC/H1HWg1S6uxLf+v25WbJdlus/9PDUWWRcAVdPN/Rfw9FYeHVwkl?= =?us-ascii?Q?TTC+JhVDRq3vFDT7IsxcTe3vJj1nI9VLdvrxHRXE5UE84TFYAChmmywHC7dT?= =?us-ascii?Q?mnjvPjipE7qnREVpwkKR0No9uGWcDE8uhsyZPQRlnLiI6gomeswNjLwQMack?= =?us-ascii?Q?dLg9IKwGOtr218B8C1+ijjuYphDW6CldPNKMDap/Xf+2DqOQr1pVsv34Z6OX?= =?us-ascii?Q?be0xaj/j9XfYeDR1E28XwCgcm2LtwZv4cXz5i3muTga5SJR8yzDJIRoztm3t?= =?us-ascii?Q?3gs9OmSd/FI589HMcH+xUc=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 6:PnPb5+0+XpJZnOStHKb13hIwYb9sTslPziyN7ZM7YxzFFl0I4QbWeSgOg4/FtJHScRm/XaR7JL6Azig/cvkXUagxAYNbzWrmz8pwhela64gl3sfFQREvI8hVutk8SN5SPTAHO7jR4WV/chBXsRMNfmdXHMK0mpuuBtAyFm0pmY80nVAQ3pV8bWiwMGdHigD/fhPGJWI/+CMurq5DxkukGZcPNufDxr1SIXgwdhPT4bdxrjbyqkN44yeTI4DGclS9iKujY5SXZKEgjEaxHXntKYv8zLhsQeggHtTDOLwDgMWM7BKLFttenbiDMxsW5O+a5TL3rj3ICkuplP0fUKrE2eYdYYYv8OkeEqeCZNHiP1jyRlIQJ00oX+gCNQHq+j4GGxg6kLN67J/MOnVFnSPEc5y2qFRw3YKqB5ywHWGw0uJnEldl8arlpo6jcSBNxXteEcdv/bkUHYUVFyojvTvrlg==; 5:/xiLBeWC8rS7QZdFV/Hpk08wXA1ZGPSu9KxruCPBZqNCliEupcIW33v+MbLpyvJGldRSC42XUqk6FffZtaz8vIb3X0j9++3uso6D+63dFLjtQlgJDX1zfa1vEQRIZLMTm5Lg/X6bBjPw5W62gMHF3kF8JYyjvpMUi/e1Y7kLsV4=; 24:qD89uqECse8mU7Nfy6wgD0TOBiNXcN/U1o7fMtHMfUy8Lcu8pyL9N0aRlKgTyQY1gAoottgWQv/TtNUfIdI+hAWJ5VUOEOLAg4aE5fq83OM= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2549; 7:qJKCRDh+3o5Kk7gArtTztSijBhW/G9ib6WuLzg2ASfJnnJZaeYS6HigYCSTftb1p31IL7vBCp+a8GT+rJ5PIPb1XbjrA9N84lI7F87XWS7lLBVZaQPSXlrgQMbTD4Dzxt4jPuTly9HLCeXOVs8hm2uIVqVpG4eVxO/fcsKbLmI+duU0aSLXyu3zM7tRewCSz5Q8vomPTa56ak9mQH3vgDDR7MkOSUvHD7WcVzOp+FvmiD0GmDN9AwfzTZTPis2tipsd8hXfBXBrky5zHgYyX56WGKOstE+bDkGatSqN9fnddCI7DlyJptE7au61hfz/0idxQLgTJVBTyS+GfKBVBT9AU5IgUIWiT/jJFo74BgiKqCXzW3nRv5wJI662pe+5+zgb3ZSSMiC4cM6wEuX9jcR5S6dgmgevFeK7LkWDEZf9SKB2sE3KEYdPJvK3I8veI5KElOfRw2PH2mcctABsa8g== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Dec 2016 22:02:50.9600 (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 that are bigger than the big buffer size. In particular it is used for read responses that can only exceed the big buffer size. Signed-off-by: Pavel Shilovsky --- fs/cifs/cifsproto.h | 1 + fs/cifs/cifssmb.c | 8 +-- fs/cifs/smb2ops.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 160 insertions(+), 13 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0eb35d2..0dbafc8 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -76,6 +76,7 @@ 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_discard_remaining_data(struct TCP_Server_Info *server); 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/cifssmb.c b/fs/cifs/cifssmb.c index 8326212..5d9ad38 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1399,8 +1399,8 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, * Discard any remaining data in the current SMB. To do this, we borrow the * current bigbuf. */ -static int -discard_remaining_data(struct TCP_Server_Info *server) +int +cifs_discard_remaining_data(struct TCP_Server_Info *server) { unsigned int rfclen = get_rfc1002_length(server->smallbuf); int remaining = rfclen + 4 - server->total_read; @@ -1426,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) int length; struct cifs_readdata *rdata = mid->callback_data; - length = discard_remaining_data(server); + length = cifs_discard_remaining_data(server); dequeue_mid(mid, rdata->result); return length; } @@ -1459,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) if (server->ops->is_status_pending && server->ops->is_status_pending(buf, server, 0)) { - discard_remaining_data(server); + cifs_discard_remaining_data(server); return -1; } diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 627096c..a27a234 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1844,12 +1844,72 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, } static int +read_data_into_pages(struct TCP_Server_Info *server, struct page **pages, + unsigned int npages, unsigned int len) +{ + int i; + int length; + + for (i = 0; i < npages; i++) { + struct page *page = pages[i]; + size_t n; + + n = len; + if (len >= PAGE_SIZE) { + /* enough data to fill the page */ + n = PAGE_SIZE; + len -= n; + } else { + zero_user(page, len, PAGE_SIZE - len); + len = 0; + } + length = cifs_read_page_from_socket(server, page, n); + if (length < 0) + return length; + server->total_read += length; + } + + return 0; +} + +static int +init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size, + unsigned int cur_off, struct bio_vec **page_vec) +{ + struct bio_vec *bvec; + int i; + + bvec = kcalloc(npages, sizeof(struct bio_vec), GFP_KERNEL); + if (!bvec) + return -EIO; + + for (i = 0; i < npages; i++) { + bvec[i].bv_page = pages[i]; + bvec[i].bv_offset = (i == 0) ? cur_off : 0; + bvec[i].bv_len = min_t(unsigned int, PAGE_SIZE, data_size); + data_size -= bvec[i].bv_len; + } + + if (data_size != 0) { + cifs_dbg(VFS, "%s: something went wrong\n", __func__); + kfree(bvec); + return -EIO; + } + + *page_vec = bvec; + return 0; +} + +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; + unsigned int cur_off; + unsigned int cur_page_idx; + unsigned int pad_len; struct cifs_readdata *rdata = mid->callback_data; struct smb2_sync_hdr *shdr = get_sync_hdr(buf); struct bio_vec *bvec = NULL; @@ -1893,9 +1953,33 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, return 0; } + pad_len = data_offset - server->vals->read_rsp_size; + if (buf_len <= data_offset) { /* read response payload is in pages */ - /* BB add code to init iter with pages */ + cur_page_idx = pad_len / PAGE_SIZE; + cur_off = pad_len % PAGE_SIZE; + + if (cur_page_idx != 0) { + /* data offset is beyond the 1st page of response */ + cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n", + __func__, data_offset); + rdata->result = -EIO; + return 0; + } + + if (data_len > page_data_size - pad_len) { + /* data_len is corrupt -- discard frame */ + rdata->result = -EIO; + return 0; + } + + rdata->result = init_read_bvec(pages, npages, page_data_size, + cur_off, &bvec); + if (rdata->result != 0) + return 0; + + iov_iter_bvec(&iter, WRITE | ITER_BVEC, bvec, npages, data_len); } 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"); @@ -1929,6 +2013,74 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, } static int +receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) +{ + char *buf = server->smallbuf; + struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; + unsigned int npages; + struct page **pages; + unsigned int len; + unsigned int buflen = get_rfc1002_length(buf) + 4; + int rc; + int i; + + len = min_t(unsigned int, buflen, server->vals->read_rsp_size - 4 + + sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; + + rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); + if (rc < 0) + return rc; + server->total_read += rc; + + len = le32_to_cpu(tr_hdr->OriginalMessageSize) + 4 - + server->vals->read_rsp_size; + npages = DIV_ROUND_UP(len, PAGE_SIZE); + + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return -ENOMEM; + + for (i = 0; i < npages; i++) { + pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); + if (!pages[i]) { + rc = -ENOMEM; + goto free_pages; + } + } + + /* read read data into pages */ + rc = read_data_into_pages(server, pages, npages, len); + if (rc) + goto free_pages; + + rc = cifs_discard_remaining_data(server); + if (rc) + goto free_pages; + + rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - 4, + pages, npages, len); + if (rc) + goto free_pages; + + *mid = smb2_find_mid(server, buf); + if (*mid == NULL) + cifs_dbg(FYI, "mid not found\n"); + else { + cifs_dbg(FYI, "mid found\n"); + (*mid)->decrypted = true; + rc = handle_read_data(server, *mid, buf, + server->vals->read_rsp_size, + pages, npages, len); + } + +free_pages: + for (i = i - 1; i >= 0; i--) + put_page(pages[i]); + kfree(pages); + return rc; +} + +static int receive_encrypted_standard(struct TCP_Server_Info *server, struct mid_q_entry **mid) { @@ -1997,14 +2149,8 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) 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; - } + if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) + return receive_encrypted_read(server, mid); return receive_encrypted_standard(server, mid); }