From patchwork Wed Dec 19 03:57:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronnie Sahlberg X-Patchwork-Id: 1015823 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=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43KLgc1Dk6z9s2P for ; Wed, 19 Dec 2018 14:57:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726716AbeLSD5P (ORCPT ); Tue, 18 Dec 2018 22:57:15 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35148 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726652AbeLSD5P (ORCPT ); Tue, 18 Dec 2018 22:57:15 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0BF3EC0587F9; Wed, 19 Dec 2018 03:57:15 +0000 (UTC) Received: from test1135.test.redhat.com (vpn2-54-53.bne.redhat.com [10.64.54.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5E28E60C44; Wed, 19 Dec 2018 03:57:14 +0000 (UTC) From: Ronnie Sahlberg To: Linux CIFS mailing list Cc: Steve French Subject: [PATCH] cifs: fix rmdir + azure + compounding regression Date: Wed, 19 Dec 2018 13:57:08 +1000 Message-Id: <20181219035708.26546-1-lsahlber@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 19 Dec 2018 03:57:15 +0000 (UTC) Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org When we send a SET_INFO command for file disposition, this ends up as an iov of a single byte. This causes problems with SMB3 and encryption. To avoid this, instead of creating a one byte iov for the disposition value and then appending an additional iov with a 7 byte padding we now handle this as a single 8 byte iov containing both the disposition byte as well as the padding in one single buffer. Signed-off-by: Ronnie Sahlberg --- fs/cifs/smb2inode.c | 14 +++++++------- fs/cifs/smb2ops.c | 23 +++++++++++++++-------- fs/cifs/smb2proto.h | 3 ++- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 633d20b7ca03..a8999f930b22 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -97,7 +97,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, if (rc) goto finished; - smb2_set_next_command(server, &rqst[num_rqst++]); + smb2_set_next_command(server, &rqst[num_rqst++], 0); /* Operation */ switch (command) { @@ -111,7 +111,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 0, NULL); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 0); smb2_set_related(&rqst[num_rqst++]); break; case SMB2_OP_DELETE: @@ -134,7 +134,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, COMPOUND_FID, current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 1); smb2_set_related(&rqst[num_rqst++]); break; case SMB2_OP_SET_EOF: @@ -149,7 +149,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, COMPOUND_FID, current->tgid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 0); smb2_set_related(&rqst[num_rqst++]); break; case SMB2_OP_SET_INFO: @@ -165,7 +165,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, COMPOUND_FID, current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 0); smb2_set_related(&rqst[num_rqst++]); break; case SMB2_OP_RENAME: @@ -189,7 +189,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, COMPOUND_FID, current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 0); smb2_set_related(&rqst[num_rqst++]); break; case SMB2_OP_HARDLINK: @@ -213,7 +213,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, COMPOUND_FID, current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); - smb2_set_next_command(server, &rqst[num_rqst]); + smb2_set_next_command(server, &rqst[num_rqst], 0); smb2_set_related(&rqst[num_rqst++]); break; default: diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 225fec1cfa67..e25c7aade98a 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1194,7 +1194,7 @@ smb2_ioctl_query_info(const unsigned int xid, rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); if (rc) goto iqinf_exit; - smb2_set_next_command(ses->server, &rqst[0]); + smb2_set_next_command(ses->server, &rqst[0], 0); /* Query */ memset(&qi_iov, 0, sizeof(qi_iov)); @@ -1208,7 +1208,7 @@ smb2_ioctl_query_info(const unsigned int xid, qi.output_buffer_length, buffer); if (rc) goto iqinf_exit; - smb2_set_next_command(ses->server, &rqst[1]); + smb2_set_next_command(ses->server, &rqst[1], 0); smb2_set_related(&rqst[1]); /* Close */ @@ -1761,16 +1761,23 @@ smb2_set_related(struct smb_rqst *rqst) char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0}; void -smb2_set_next_command(struct TCP_Server_Info *server, struct smb_rqst *rqst) +smb2_set_next_command(struct TCP_Server_Info *server, struct smb_rqst *rqst, + bool has_space_for_padding) { struct smb2_sync_hdr *shdr; unsigned long len = smb_rqst_len(server, rqst); /* SMB headers in a compound are 8 byte aligned. */ if (len & 7) { - rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; - rqst->rq_iov[rqst->rq_nvec].iov_len = 8 - (len & 7); - rqst->rq_nvec++; + if (has_space_for_padding) { + len = rqst->rq_iov[rqst->rq_nvec - 1].iov_len; + rqst->rq_iov[rqst->rq_nvec - 1].iov_len = + (len + 7) & ~7; + } else { + rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; + rqst->rq_iov[rqst->rq_nvec].iov_len = 8 - (len & 7); + rqst->rq_nvec++; + } len = smb_rqst_len(server, rqst); } @@ -1820,7 +1827,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &srch_path); if (rc) goto qfs_exit; - smb2_set_next_command(server, &rqst[0]); + smb2_set_next_command(server, &rqst[0], 0); memset(&qi_iov, 0, sizeof(qi_iov)); rqst[1].rq_iov = qi_iov; @@ -1833,7 +1840,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, NULL); if (rc) goto qfs_exit; - smb2_set_next_command(server, &rqst[1]); + smb2_set_next_command(server, &rqst[1], 0); smb2_set_related(&rqst[1]); memset(&close_iov, 0, sizeof(close_iov)); diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 9f4e9ed9ce53..2fe78acd7d0c 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -117,7 +117,8 @@ extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); extern unsigned long smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst); extern void smb2_set_next_command(struct TCP_Server_Info *server, - struct smb_rqst *rqst); + struct smb_rqst *rqst, + bool has_space_for_padding); extern void smb2_set_related(struct smb_rqst *rqst); /*