From patchwork Mon Jan 30 21:39:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9546135 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 8C48160415 for ; Mon, 30 Jan 2017 21:44:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 96D52283B4 for ; Mon, 30 Jan 2017 21:44:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8BBCE283E7; Mon, 30 Jan 2017 21:44:09 +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 98B6F283B4 for ; Mon, 30 Jan 2017 21:44:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754576AbdA3VoH (ORCPT ); Mon, 30 Jan 2017 16:44:07 -0500 Received: from mail-by2nam03on0111.outbound.protection.outlook.com ([104.47.42.111]:42816 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932067AbdA3Vnq (ORCPT ); Mon, 30 Jan 2017 16:43:46 -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=Thp4QKk6C6/yrzQ+WsEXAk96IqNhvaXeox2/NDoFT/k=; b=JK5ruf8hEPYqShLIjuGvJ4U7P7Vkh/GacHwSOa4+/I9l5BbmDAb2kC0hTPegmlRTjJzRkdvMXOqVxY3ay5ZeSQ4rjCTQlVHd44JM5Lb5/NcbIIEzenBUYA8VO2cnCqzdnZTaM1wTmTyUIAX9GOD8CVpJCb8VNvrZfjGOOPUyuns= 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:41:09 +0000 From: Pavel Shilovsky To: Subject: [PATCH v2 13/15] CIFS: Decrypt and process small encrypted packets Date: Mon, 30 Jan 2017 13:39:42 -0800 Message-ID: <1485812384-28870-14-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: 4f14d0fd-06b2-462e-48df-08d44958b49d X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:BN6PR03MB2545; X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 3:Sqs2YIyvQRnNOB5dOPyDt17Bue0dS8oEnjLG9P2zSJrMYHh+vUx5msLdoxCTBYSTRPWUhRpifyhNJ2Oyn7QlD7VOgrbSg8VlOjQq8EBKXf6mQtUlCLV93n1GV9aaQTyQbBV2gyRelyTGQ/1A+IR9iR4yMhpU/WcId/a4gZ04x6f7Y3F75zYp7z6IwfyNlmXAZIcsu6/+iy/T3P1ygIXa4or7mIBEeng0/yPecovCdWadgRRgRsbcWiDOS5e/BypbgZT43Z4imLitmLEwERT0ag== X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 25:0mdAYvAxMp6SLz+j33Z9Eyl/dLpHWYfp3bz1gFLrxzg88de7DGQe1dfwb2Ndkr2xO/Tpqb7zLeoqAStHzOOo6LVGBZAKsdDECrdXe3yEHJw5yia6usyK1Q/RkwBjb/FAgacpDap9mztppiAXUYjqCpbGc8C/IvrT8HfCDMCpM9tYlsU/rOeJFpWPDh1tV2o1Af70WyM1GMbelC4Ciwk7KCPzlICZ+i/5aFzueqoUDjs8sWg7YKUxd0A7UxFmDkqVtvYWLsyu0PtrURpXmndtrxtqF+L/bYdG+Niu4wpuNlx/uA89uOXqE5C4GQ1JUarYkbGQ99v+gbV4rzbp6hRT3n6B7lqZ7oti2uGq/P6AxmjODOOk1/4+J93NtD87Onh2hoA5IIipdiWY2fc/tz7vceqVVW3w/ufYFQLJoeBJYVQkUR5UPQsJU4qccDoyuc4jfpY3iouF0mSFGXYG2EVAXkCIKLzhSiK937kMBMLaNBk4aWfKyBKvKEvEWC/NtdtPMgEUuEQO9ZVl475V+9AkbOyMi76nxoz1dp+CwoOz55U/79KRdvGdKyr7nBDnNhRFs/BnLjplbfYt8efObGsCkSgAwGTRC7Vy1QyN6nfDeezQ39yi4oTdcIF1kugVtkN0iV91AsezEu9INQOi9JREowdavFeFbRaoriKoNdkRLNfNXlLwSXoQg1m83KMNmXLizWmrMnz8s7lX4L8mnY6dzxsi8PMh24IWffMy4S+KR2M= X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 31:ltfwh+n0+h6LBxk5/HCtNa/vbmEIZtI+iiyDw7u5OprWTacmZHewctkTEkxhAD32ySQ3Silid/U1AgGjxukafGvDICzrk0knO03/HIpuSPiF1sJsuHsDpmTJiXmiNJOnYuFjCUgHRDX08irvZ0gQIXAi5BJMHZYo0maeqq3y8mxZrSY5rIAW6CTL3JHROUrjWolrWbe1fzeFPe25ubhZU5FKNABpgwYkNiIqUFO+uy/u5HorvVzwsHeszcoq50hGtc5CXtLLQv6pFysSiPciWQ==; 20:aMcuTtaRPuUSQKmvcZVIuqB1RejE5Dys3oXriVVcBXkAla+CDATYAjL5tPchVZ+0T8g/siOvW85FSF16XYinY1jmEij1GmLqZDdUN7gGcc3avNEbQJXIcmN0guLoWSTubp4PtyUXl3R0+2JWhwPATXWbkC4J9l25a8JCdUTC1h6K97qvGn0lksTlz3mHbP+3B2kEFMzJ3Fm9AR+CoGNEKgf/KJ9Gb5jErpCymL1H0ITmt4kkTOFDmAWSAK1pGnv/4c1nw0eGzC9wsR0GQVBIDsMbkrDwPaZgRhRsBSfYnO5UcDCU3rzodMbU+2RbOf1r4YySg8WhlZWez4TMTHPzastYCMfuLgReOCp/jJ0lYp82YrayXHFo5AOa0K3U9oA09JWWLr6SA7/BCrK799dnqpHCGV0SslqQHo7fgtT4qbR7n7i2F6VPk1npSUwkRxmWGTYazKDr7+KMad3k8j2emGAQtez1vDgzY5NSaX5BR6rENVVBSvnhxbzdZZHdORy5 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)(20161123555025)(20161123564025)(20161123562025)(20161123560025)(6072148)(6047074); SRVR:BN6PR03MB2545; BCL:0; PCL:0; RULEID:; SRVR:BN6PR03MB2545; X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 4:7wEaZAmXF5bTLRwL0nmH78/jnDhDbVeLvE64Oe7XScwlzIgUxYGBrovdW/+H+xUilA9XxLU57Le6lbzHQdNWPKhvpuSBoJJSt0/atcXFpId0ojc7do5luH194gwlvAebyDSi3iswhkvZFr0ERYLXclM1VtvpOfJwSSGEupCQqi6rT76VhAHKXR7O92EzwpaUGkZ7+E6COvibUOmEhRar2i3i2Te3v92/KiF7nEdOfYOuIcN8V0WEmu/at7sKgUwd3E08fmddtB4s9SDIFBD+5M+EpB286fLFD8gZTK/Dq/XDTTCn4DiutVFPJlqmPt2ZCq/MyqRgFpmLYXfd97HfxJC6UwhxsMMlHQSyHAcC3oyS7MQ2S9uF05NA3Iol48vA6yPH5PHiq6W+yFEX+mUHe5Qrirh0LgwV0bOLsHqpk56jJFgJl57aWCp+PRMeq0rvYJp2Lkw34CHgIaZ8pW9mU1x381aiaDIwOJiZdJWDO6hWUO9tqjNus13fDO/nj2IojgHGyeSn/VpDcuibM8k8Gq5gLUM64RzPhOz7M/4naxNd1euLieT7seqO2Qi3ToTVPGxfNyl5PJFIfZXK4xbwcvZJhBHnUqUEUgPI6XfdpfXB7nHkkNcTs2HH/H95KCtL+rbZxjYUYaaV0U+5bjAeKR7lrZR1AHAhje1Akt1ZZZldF5Kw9aIFR1mBKzXDcV7L X-Forefront-PRVS: 0203C93D51 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(7916002)(39850400002)(39860400002)(39840400002)(39450400003)(39410400002)(69234005)(189002)(199003)(305945005)(5660300001)(8676002)(81166006)(5003940100001)(6116002)(50466002)(48376002)(81156014)(53936002)(101416001)(42186005)(110136003)(7736002)(10290500002)(47776003)(5005710100001)(10090500001)(33646002)(36756003)(92566002)(2351001)(6486002)(2950100002)(50226002)(105586002)(76176999)(189998001)(50986999)(106356001)(86362001)(38730400001)(86612001)(25786008)(6916009)(6666003)(2906002)(450100001)(107886002)(68736007)(97736004); 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:21GFhAV9GinoWwcqEh+8m0dawhEHu/IdAN0600QZ/?= =?us-ascii?Q?3OYhJBX4Bd7jZdlcH7QUpv7XKBhNwKXw1QdnIeTRsTkRj6gu9LbgWauIXYhc?= =?us-ascii?Q?9c7WbqiWBB18ZwuVGVUuGzilrrbJSkyoTprExwmEVXH1oBEA/yAFgPXhb3cA?= =?us-ascii?Q?n+1eIv3Lj3gvup84rmIA+5QvTzMCZraHsz+NmIq4KVxbRrb/ziHqXEI9YX4R?= =?us-ascii?Q?/JZrsdoPvTOx89EyiWpKoNpiquKyN38oNASBAazPliu0xcQKsudMXAv+SUl/?= =?us-ascii?Q?bEXpsc0XSBUs87v1n0Hwu0IcUHxEyrdj2bVt0Apb7jsrJVrwabwh34w8St6m?= =?us-ascii?Q?SVeLWgllGY2wNta3B49Fkf3ijk3W5gGmUTSyL+UjlTEOfRfiz49g/I7cQxXA?= =?us-ascii?Q?t+9EyrAyRtmOVN1cRXEV057insNrG9I4siPixERKhYLrP2myuMmgtUINRa2u?= =?us-ascii?Q?Y3142ccZ/IH4JQW9lK1Lt7e+m+tCn5Nv+Y2TqypoQ6Os6qWIiuyzerumSZrp?= =?us-ascii?Q?wlWZU48scd69xUOAlIaB44IggU8XF8evj08FcWNhw5ntWpc3/9LNO7hfgSzb?= =?us-ascii?Q?CwZ/2nUh5ID+YK1AvS3Vf0mHvAbpLg1XiNv6d6JX4wO0AdyGbr76YjUbR7yF?= =?us-ascii?Q?7KHmbsH0W8x8DEOBJt2RDp2AuXTHuQG4Gqk7he4o7PVLznqO+wfczESVBGd3?= =?us-ascii?Q?mkw7+vGzkJ72hWrcjRKWSUNVpfmwbUE/rg33KOI8PjylfydxHjOH3uebhBwO?= =?us-ascii?Q?J2MgxHAN3J49Bo9RYBFrMhB3WXNzpra43LzI5bmWENmsGiGNUJ3K/1RBAJ60?= =?us-ascii?Q?3GfowAWuOD5pgFv4hO274Um3v37MmiaUS1+3hY9sdMmYtDX1LdcN/FOZOAWg?= =?us-ascii?Q?VMysK0p94GOalZMav1I1W1BxtnoOmUQioWcJ8aPZVRXnXtiT0U+nPYr8Y6LP?= =?us-ascii?Q?IZsqmtJUNakf+ApE0MsHn6yrYLlcrlbQYizQKNAiRoF/wguWhTDVtZYby2m6?= =?us-ascii?Q?mdE2p90sdCFP2Gd+q7bMiId5An8xSYsZg+TBw9rMcGV6FKdiIcDWYeUq+3JX?= =?us-ascii?Q?OUBuR6zsZthFZmMLvDihM9ADyl4Kcn7NMsSsg2DJxWdN9N1kdXDIkOwbrRi6?= =?us-ascii?Q?6rnlDUWl3xT7uymgQ+y12kuHXaxLhfP9Lz4ign0NzorQC3DIjkzvLShFFBpR?= =?us-ascii?Q?asoexQHPkXm1xT9Bo55RkYAJXCyD5s3eFI3FfxH8NA05iujVcWhxu6/F5M6v?= =?us-ascii?Q?V4c6WFtZvHIwfavd4Z1Vh9AjtwqLjTSKW+lT4z+uAqe96M+7xoNsb6POOLm6?= =?us-ascii?Q?zacPrcwWzp5tDasdCf+mC0=3D?= X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 6:ZwDCpfTmUO9ak7ip10Dzr7U8WwP2OhTKw4eFTjkoPzYQU9RAIpEPhLwExuKCoV4ooLYhvvLuxsw+U/vJTzGetE0kygTjpOa8r8qeCBh67+oKg4rCNUpbXIgLHyTLUkuCOkZ2PDq5DKa+XhgB/ue5Usvc8+4EGLZgD6VTp7zYpCMIs1Gg9/IECIJ4tTp9+q4Ubm6CwwrmYE1WCVuQOJVA2AXviYinzIADHdJaPWPFbBYmR8y7niZ/GLphPE0HtCB4grvnFg8xMarHGsPZpGZfY8rkHq+gUnwep/RJi3peJLBGnR3O3qIE39cdCmxQfG4sHcJksEA9lZFZk0QF3e4eId+aOMhTEriSFl3UMKacxQtfjTztL53rsb4nH0QuW5EEL+egXZCPILwE2SNWbK4it2NiDbRVH6qHzjTqySr8i7M4A92vDVQVR8OzLsZCgqdD; 5:X1VkOP+wrONzM6h/QqQREdqGqj78vWrhY3n3QQq773+wJNlnQ3zH4LvyP/M2gYswfIs2gfNRO+cT4+gMLZy78/EU0CgkLNZNPo5gY71XN83VK6oIiUgD30PqDUJacx4WCg3+nXodnjzAqmiow9M68EyKyRzmHik8tMOSYtofVfg=; 24:U8ID5YLr9ogtrb1RpMIpti6EhQsxhUOWRV2BwI3eBsypfwS0Wsu/OIbrCBd9fqQIsksHvLJNd9KTC9pE74LM9juOwuhHzMSGKSfQHxiJdWc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2545; 7:n7iLA3BmWyX1c+lW3drwHnuXbVdgGmMWHmz4rii7TPaahNc5GQYxjqFK5hkqoj6jhK31+NtF2rJQ6Y6A9Q9BkJerf6te6uPZAkcA5yHd6d/2IpkafSlpw9BBshax6dXDe0vXR5aaNAYHoKL+PQGazFcwlIA8c+SAvzR+9ry3XK47hIm5/m+rL2ius/QB1pxLrW8jY9xNRNOxqSGf6RCj2EcGrOsk/36nqArKe8+4YRFOhHmXUB935nSEYc5PYUuNaXeYRcBs1CN7aXr0SQfC1PIhDIp/8M5b+CUXAixJnuFDlareNDws7k6l3SegCt3X44FWlN/NdIwEu2ZrZKP3rtVHmLwwmu0iTdIVWC/m9jvnoh0NxeDrqSvpHIJuZo1SbXVgqTE1u3Ws04UpFEJdvglyQbPovIBMowqkGyNm+GynVziwXSdcKk5MMj6PB6FlXnGjOz07LqJZ/5cJo7oh/Q== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Jan 2017 21:41:09.9967 (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 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 | 227 +++++++++++++++++++++++++++++++++++++++++++++++- fs/cifs/smb2pdu.c | 4 +- fs/cifs/smb2proto.h | 2 + fs/cifs/smb2transport.c | 2 +- 7 files changed, 243 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..86b8ab2 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1799,6 +1799,228 @@ 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); + dequeue_mid(mid, 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; + dequeue_mid(mid, rdata->result); + 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 either in buf or in pages"); + 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; + dequeue_mid(mid, rdata->result); + 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 +2269,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 +2361,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);