Commit 271b9c0c authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French

smb3: Fix rmdir compounding regression to strict servers

Some servers require that the setinfo matches the exact size,
and in this case compounding changes introduced by
commit c2e0fe3f ("cifs: make rmdir() use compounding")
caused us to send 8 bytes (padded length) instead of 1 byte
(the size of the structure).  See MS-FSCC section 2.4.11.

Fixing this when we send a SET_INFO command for delete file
disposition, then ends up as an iov of a single byte but 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: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Acked-by: default avatarPaulo Alcantara <palcantara@suse.de>
parent ddfbab46
...@@ -97,7 +97,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -97,7 +97,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
if (rc) if (rc)
goto finished; goto finished;
smb2_set_next_command(server, &rqst[num_rqst++]); smb2_set_next_command(server, &rqst[num_rqst++], 0);
/* Operation */ /* Operation */
switch (command) { switch (command) {
...@@ -111,7 +111,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -111,7 +111,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
SMB2_O_INFO_FILE, 0, SMB2_O_INFO_FILE, 0,
sizeof(struct smb2_file_all_info) + sizeof(struct smb2_file_all_info) +
PATH_MAX * 2, 0, NULL); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
case SMB2_OP_DELETE: case SMB2_OP_DELETE:
...@@ -127,14 +127,14 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -127,14 +127,14 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
rqst[num_rqst].rq_iov = si_iov; rqst[num_rqst].rq_iov = si_iov;
rqst[num_rqst].rq_nvec = 1; rqst[num_rqst].rq_nvec = 1;
size[0] = 8; size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
data[0] = &delete_pending[0]; data[0] = &delete_pending[0];
rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
COMPOUND_FID, current->tgid, COMPOUND_FID, current->tgid,
FILE_DISPOSITION_INFORMATION, FILE_DISPOSITION_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
case SMB2_OP_SET_EOF: case SMB2_OP_SET_EOF:
...@@ -149,7 +149,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -149,7 +149,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
COMPOUND_FID, current->tgid, COMPOUND_FID, current->tgid,
FILE_END_OF_FILE_INFORMATION, FILE_END_OF_FILE_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
case SMB2_OP_SET_INFO: case SMB2_OP_SET_INFO:
...@@ -165,7 +165,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -165,7 +165,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
COMPOUND_FID, current->tgid, COMPOUND_FID, current->tgid,
FILE_BASIC_INFORMATION, FILE_BASIC_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
case SMB2_OP_RENAME: case SMB2_OP_RENAME:
...@@ -189,7 +189,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -189,7 +189,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
COMPOUND_FID, current->tgid, COMPOUND_FID, current->tgid,
FILE_RENAME_INFORMATION, FILE_RENAME_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
case SMB2_OP_HARDLINK: case SMB2_OP_HARDLINK:
...@@ -213,7 +213,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -213,7 +213,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
COMPOUND_FID, current->tgid, COMPOUND_FID, current->tgid,
FILE_LINK_INFORMATION, FILE_LINK_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size); 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++]); smb2_set_related(&rqst[num_rqst++]);
break; break;
default: default:
......
...@@ -1194,7 +1194,7 @@ smb2_ioctl_query_info(const unsigned int xid, ...@@ -1194,7 +1194,7 @@ smb2_ioctl_query_info(const unsigned int xid,
rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path);
if (rc) if (rc)
goto iqinf_exit; goto iqinf_exit;
smb2_set_next_command(ses->server, &rqst[0]); smb2_set_next_command(ses->server, &rqst[0], 0);
/* Query */ /* Query */
memset(&qi_iov, 0, sizeof(qi_iov)); memset(&qi_iov, 0, sizeof(qi_iov));
...@@ -1208,7 +1208,7 @@ smb2_ioctl_query_info(const unsigned int xid, ...@@ -1208,7 +1208,7 @@ smb2_ioctl_query_info(const unsigned int xid,
qi.output_buffer_length, buffer); qi.output_buffer_length, buffer);
if (rc) if (rc)
goto iqinf_exit; 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]); smb2_set_related(&rqst[1]);
/* Close */ /* Close */
...@@ -1761,16 +1761,23 @@ smb2_set_related(struct smb_rqst *rqst) ...@@ -1761,16 +1761,23 @@ smb2_set_related(struct smb_rqst *rqst)
char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0}; char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0};
void 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; struct smb2_sync_hdr *shdr;
unsigned long len = smb_rqst_len(server, rqst); unsigned long len = smb_rqst_len(server, rqst);
/* SMB headers in a compound are 8 byte aligned. */ /* SMB headers in a compound are 8 byte aligned. */
if (len & 7) { if (len & 7) {
rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; if (has_space_for_padding) {
rqst->rq_iov[rqst->rq_nvec].iov_len = 8 - (len & 7); len = rqst->rq_iov[rqst->rq_nvec - 1].iov_len;
rqst->rq_nvec++; 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); len = smb_rqst_len(server, rqst);
} }
...@@ -1820,7 +1827,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -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); rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &srch_path);
if (rc) if (rc)
goto qfs_exit; 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)); memset(&qi_iov, 0, sizeof(qi_iov));
rqst[1].rq_iov = qi_iov; rqst[1].rq_iov = qi_iov;
...@@ -1833,7 +1840,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1833,7 +1840,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
NULL); NULL);
if (rc) if (rc)
goto qfs_exit; goto qfs_exit;
smb2_set_next_command(server, &rqst[1]); smb2_set_next_command(server, &rqst[1], 0);
smb2_set_related(&rqst[1]); smb2_set_related(&rqst[1]);
memset(&close_iov, 0, sizeof(close_iov)); memset(&close_iov, 0, sizeof(close_iov));
......
...@@ -117,7 +117,8 @@ extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); ...@@ -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, extern unsigned long smb_rqst_len(struct TCP_Server_Info *server,
struct smb_rqst *rqst); struct smb_rqst *rqst);
extern void smb2_set_next_command(struct TCP_Server_Info *server, 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); extern void smb2_set_related(struct smb_rqst *rqst);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment