From patchwork Thu Mar 28 08:45:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 1067907 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="d+7i86pw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44VJPH2Fynz9sPj for ; Thu, 28 Mar 2019 19:46:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726082AbfC1IqK (ORCPT ); Thu, 28 Mar 2019 04:46:10 -0400 Received: from mail-pf1-f175.google.com ([209.85.210.175]:46543 "EHLO mail-pf1-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725948AbfC1IqK (ORCPT ); Thu, 28 Mar 2019 04:46:10 -0400 Received: by mail-pf1-f175.google.com with SMTP id 9so11009368pfj.13 for ; Thu, 28 Mar 2019 01:46:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=r/rtoXXCt7BBi9T1Ga/l6JRWUviwPHVCabQ1TObOJy4=; b=d+7i86pwGJMr7Salys+1QXjo5W6A9aCvaXetCwrLnGZhBcOB2+oX8ZbgvznIHfJ/mc RyI7XbGOnzQDX1f/vAgAqzraHOggwRrz9JqXr7xd2S+6liy1VO7igDQjVaVpCWlA57lf 0LyYS58udezuD03y6mp2izApXtgO6XK50lLvJoCB1rBXkynskQw/hTI2eg8+anCs1Y7o MvnMZ89cDl8bZh00dqDH+Qu+4dEfxnVGmGKPPc2uZVD5hiwwVMvyRP1CZfOthHdnDXLi khWg3f7Hyo25gtL3yLWQBIums2FgWR585stKY1cSMZEmgR1p7E5/cateCo1HrNFvDKip 7I5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=r/rtoXXCt7BBi9T1Ga/l6JRWUviwPHVCabQ1TObOJy4=; b=W7gF5NLAfBEmSTrcTRT2jC3GsvHRMjHv1VoGGXrfxx0yCLY5UGW+api2lFR2ggk2JS QAujcwfsULA+jrqpYOR3Eho7MTGlSkGE3fiQuoyOO5ZrKy7MPRU7lbCTnb5qn0c4u1P2 Pc1d/1pZxofXOWSD4H4vODcHpktu4Sz9rGoaz/kjhOYdZKjY7yLqdAZ28yr3P1tzURCC TWTWO09ZbErM/n2h/zvguSeesZj6XTguJgO7BacsdhCAzkTL8b/f7uLqrko8Oo/g2r0N wbzvWkpO+XnJPotgd819ky+ZZSpVjVOgXtbpnGget5J//e0BN9CTBrytcjCz5rQYRr72 RLHg== X-Gm-Message-State: APjAAAXQDdrYvscpjhoFvOihHu59MkUTOXWWAwvqTkBsf85gHPS4TKvK Em72gfny0Ua1mKo/nEqLaKyLQHcXUDdwdKnpmBxXGfq1 X-Google-Smtp-Source: APXvYqyCrQHITpf7b7ZThh1sbY+a0ium8h0EM3738hciNJLMxLVhiwGQ6Yibx6EBrwRix7My1tvs/+7v3EMDwa1Q8eI= X-Received: by 2002:a62:1cc7:: with SMTP id c190mr18603688pfc.246.1553762769054; Thu, 28 Mar 2019 01:46:09 -0700 (PDT) MIME-Version: 1.0 From: Steve French Date: Thu, 28 Mar 2019 03:45:56 -0500 Message-ID: Subject: [PATCH][SMB3] Fix snapshot enumeration to Azure To: CIFS Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Some servers (see MS-SMB2 protocol specification note 310 and section 3.3.5.15.1) expect that the FSCTL enumerate snapshots is done twice, with the first query having EXACTLY the minimum size response buffer requested (16 bytes) which refreshes the snapshot list (otherwise that and subsequent queries get an empty list returned). So had to add code to set the maximum response size differently for the first snapshot query (which gets the size needed for the second query which contains the actual list of snapshots). This better matches what Windows client does as well. From f11f658baccb6c59786ae5a3cb65145ed655cf2f Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Mar 2019 03:37:52 -0500 Subject: [PATCH] smb3: Fix enumerating snapshots to Azure Some servers (see MS-SMB2 protocol specification note 310 and section 3.3.5.15.1) expect that the FSCTL enumerate snapshots is done twice, with the first query having EXACTLY the minimum size response buffer requested (16 bytes) which refreshes the snapshot list (otherwise that and subsequent queries get an empty list returned). So had to add code to set the maximum response size differently for the first snapshot query (which gets the size needed for the second query which contains the actual list of snapshots). Signed-off-by: Steve French --- fs/cifs/smb2ops.c | 7 +++++-- fs/cifs/smb2pdu.c | 31 +++++++++++++++++++++++++++---- fs/cifs/smb2proto.h | 3 ++- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 7cfafac255aa..e755236af8ff 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1402,7 +1402,7 @@ smb2_ioctl_query_info(const unsigned int xid, rc = SMB2_ioctl_init(tcon, &rqst[1], COMPOUND_FID, COMPOUND_FID, qi.info_type, true, NULL, - 0); + 0, false); } } else if (qi.flags == PASSTHRU_QUERY_INFO) { memset(&qi_iov, 0, sizeof(qi_iov)); @@ -1820,6 +1820,9 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, int rc; struct smb_snapshot_array snapshot_in; + if (get_user(ret_data_len, (unsigned int __user *)ioc_buf)) + return -EFAULT; + rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SRV_ENUMERATE_SNAPSHOTS, @@ -2656,7 +2659,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, rc = SMB2_ioctl_init(tcon, &rqst[num++], cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, true /* is_fctl */, (char *)&fsctl_buf, - sizeof(struct file_zero_data_information)); + sizeof(struct file_zero_data_information), false); if (rc) goto zero_range_exit; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 21ac19ff19cb..bc830519d7eb 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2478,7 +2478,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, - bool is_fsctl, char *in_data, u32 indatalen) + bool is_fsctl, char *in_data, u32 indatalen, + bool rsp_buf_not_allowed) { struct smb2_ioctl_req *req; struct kvec *iov = rqst->rq_iov; @@ -2529,7 +2530,18 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, * in responses (except for read responses which can be bigger. * We may want to bump this limit up */ - req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize); + + /* + * Servers like Azure expect first query to be minimal (to get number of + * previous versions) so the response size must be specified as EXACTLY + * sizeof(struct snapshot_array) which is 16 when rounded up to multiple + * of eight bytes. + */ + + if (rsp_buf_not_allowed) + req->MaxOutputResponse = cpu_to_le32(16); + else + req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize); if (is_fsctl) req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); @@ -2567,12 +2579,23 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, int resp_buftype = CIFS_NO_BUFFER; int rc = 0; int flags = 0; + bool rsp_buf_not_allowed = false; cifs_dbg(FYI, "SMB2 IOCTL\n"); if (out_data != NULL) *out_data = NULL; + + /* + * Servers like Azure expect first query to be minimal (to get number of + * previous versions) so the response size must be specified as EXACTLY + * sizeof(struct snapshot_array) which is 16 when rounded up to multiple + * of eight bytes. + */ + if ((opcode == FSCTL_SRV_ENUMERATE_SNAPSHOTS) && plen && (*plen == 0)) + rsp_buf_not_allowed = true; + /* zero out returned data len, in case of error */ if (plen) *plen = 0; @@ -2593,8 +2616,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, rqst.rq_iov = iov; rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, - opcode, is_fsctl, in_data, indatalen); + rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, opcode, + is_fsctl, in_data, indatalen, rsp_buf_not_allowed); if (rc) goto ioctl_exit; diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 3c32d0cfea69..6f2fc1685199 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -146,7 +146,8 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, char **out_data, u32 *plen /* returned data len */); extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, - bool is_fsctl, char *in_data, u32 indatalen); + bool is_fsctl, char *in_data, u32 indatalen, + bool rsp_buf_not_allowed); extern void SMB2_ioctl_free(struct smb_rqst *rqst); extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); -- 2.17.1