Skip to content

Commit e77fe73

Browse files
Ronnie SahlbergSteve French
authored andcommitted
cifs: we can not use small padding iovs together with encryption
We can not append small padding buffers as separate iovs when encryption is used. For this case we must flatten the request into a single buffer containing both the data from all the iovs as well as the padding bytes. This is at least needed for 4.20 as well due to compounding changes. CC: Stable <[email protected]> Signed-off-by: Ronnie Sahlberg <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 14e92c5 commit e77fe73

File tree

3 files changed

+55
-33
lines changed

3 files changed

+55
-33
lines changed

fs/cifs/smb2inode.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
4949
struct cifs_open_parms oparms;
5050
struct cifs_fid fid;
5151
struct cifs_ses *ses = tcon->ses;
52-
struct TCP_Server_Info *server = ses->server;
5352
int num_rqst = 0;
5453
struct smb_rqst rqst[3];
5554
int resp_buftype[3];
@@ -97,7 +96,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
9796
if (rc)
9897
goto finished;
9998

100-
smb2_set_next_command(server, &rqst[num_rqst++], 0);
99+
smb2_set_next_command(tcon, &rqst[num_rqst++]);
101100

102101
/* Operation */
103102
switch (command) {
@@ -111,7 +110,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
111110
SMB2_O_INFO_FILE, 0,
112111
sizeof(struct smb2_file_all_info) +
113112
PATH_MAX * 2, 0, NULL);
114-
smb2_set_next_command(server, &rqst[num_rqst], 0);
113+
smb2_set_next_command(tcon, &rqst[num_rqst]);
115114
smb2_set_related(&rqst[num_rqst++]);
116115
break;
117116
case SMB2_OP_DELETE:
@@ -134,7 +133,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
134133
COMPOUND_FID, current->tgid,
135134
FILE_DISPOSITION_INFORMATION,
136135
SMB2_O_INFO_FILE, 0, data, size);
137-
smb2_set_next_command(server, &rqst[num_rqst], 1);
136+
smb2_set_next_command(tcon, &rqst[num_rqst]);
138137
smb2_set_related(&rqst[num_rqst++]);
139138
break;
140139
case SMB2_OP_SET_EOF:
@@ -149,7 +148,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
149148
COMPOUND_FID, current->tgid,
150149
FILE_END_OF_FILE_INFORMATION,
151150
SMB2_O_INFO_FILE, 0, data, size);
152-
smb2_set_next_command(server, &rqst[num_rqst], 0);
151+
smb2_set_next_command(tcon, &rqst[num_rqst]);
153152
smb2_set_related(&rqst[num_rqst++]);
154153
break;
155154
case SMB2_OP_SET_INFO:
@@ -165,7 +164,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
165164
COMPOUND_FID, current->tgid,
166165
FILE_BASIC_INFORMATION,
167166
SMB2_O_INFO_FILE, 0, data, size);
168-
smb2_set_next_command(server, &rqst[num_rqst], 0);
167+
smb2_set_next_command(tcon, &rqst[num_rqst]);
169168
smb2_set_related(&rqst[num_rqst++]);
170169
break;
171170
case SMB2_OP_RENAME:
@@ -189,7 +188,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
189188
COMPOUND_FID, current->tgid,
190189
FILE_RENAME_INFORMATION,
191190
SMB2_O_INFO_FILE, 0, data, size);
192-
smb2_set_next_command(server, &rqst[num_rqst], 0);
191+
smb2_set_next_command(tcon, &rqst[num_rqst]);
193192
smb2_set_related(&rqst[num_rqst++]);
194193
break;
195194
case SMB2_OP_HARDLINK:
@@ -213,7 +212,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
213212
COMPOUND_FID, current->tgid,
214213
FILE_LINK_INFORMATION,
215214
SMB2_O_INFO_FILE, 0, data, size);
216-
smb2_set_next_command(server, &rqst[num_rqst], 0);
215+
smb2_set_next_command(tcon, &rqst[num_rqst]);
217216
smb2_set_related(&rqst[num_rqst++]);
218217
break;
219218
default:
@@ -388,7 +387,6 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
388387
rc = -ENOMEM;
389388
goto smb2_rename_path;
390389
}
391-
392390
rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
393391
FILE_OPEN, 0, smb2_to_name, command);
394392
smb2_rename_path:

fs/cifs/smb2ops.c

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,6 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
884884
struct cifs_sb_info *cifs_sb)
885885
{
886886
struct cifs_ses *ses = tcon->ses;
887-
struct TCP_Server_Info *server = ses->server;
888887
__le16 *utf16_path = NULL;
889888
int ea_name_len = strlen(ea_name);
890889
int flags = 0;
@@ -936,7 +935,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
936935
rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path);
937936
if (rc)
938937
goto sea_exit;
939-
smb2_set_next_command(ses->server, &rqst[0], 0);
938+
smb2_set_next_command(tcon, &rqst[0]);
940939

941940

942941
/* Set Info */
@@ -963,7 +962,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
963962
COMPOUND_FID, current->tgid,
964963
FILE_FULL_EA_INFORMATION,
965964
SMB2_O_INFO_FILE, 0, data, size);
966-
smb2_set_next_command(server, &rqst[1], 0);
965+
smb2_set_next_command(tcon, &rqst[1]);
967966
smb2_set_related(&rqst[1]);
968967

969968

@@ -1222,7 +1221,7 @@ smb2_ioctl_query_info(const unsigned int xid,
12221221
rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path);
12231222
if (rc)
12241223
goto iqinf_exit;
1225-
smb2_set_next_command(ses->server, &rqst[0], 0);
1224+
smb2_set_next_command(tcon, &rqst[0]);
12261225

12271226
/* Query */
12281227
memset(&qi_iov, 0, sizeof(qi_iov));
@@ -1236,7 +1235,7 @@ smb2_ioctl_query_info(const unsigned int xid,
12361235
qi.output_buffer_length, buffer);
12371236
if (rc)
12381237
goto iqinf_exit;
1239-
smb2_set_next_command(ses->server, &rqst[1], 0);
1238+
smb2_set_next_command(tcon, &rqst[1]);
12401239
smb2_set_related(&rqst[1]);
12411240

12421241
/* Close */
@@ -1789,26 +1788,53 @@ smb2_set_related(struct smb_rqst *rqst)
17891788
char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0};
17901789

17911790
void
1792-
smb2_set_next_command(struct TCP_Server_Info *server, struct smb_rqst *rqst,
1793-
bool has_space_for_padding)
1791+
smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
17941792
{
17951793
struct smb2_sync_hdr *shdr;
1794+
struct cifs_ses *ses = tcon->ses;
1795+
struct TCP_Server_Info *server = ses->server;
17961796
unsigned long len = smb_rqst_len(server, rqst);
1797+
int i, num_padding;
17971798

17981799
/* SMB headers in a compound are 8 byte aligned. */
1799-
if (len & 7) {
1800-
if (has_space_for_padding) {
1801-
len = rqst->rq_iov[rqst->rq_nvec - 1].iov_len;
1802-
rqst->rq_iov[rqst->rq_nvec - 1].iov_len =
1803-
(len + 7) & ~7;
1804-
} else {
1805-
rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding;
1806-
rqst->rq_iov[rqst->rq_nvec].iov_len = 8 - (len & 7);
1807-
rqst->rq_nvec++;
1800+
1801+
/* No padding needed */
1802+
if (!(len & 7))
1803+
goto finished;
1804+
1805+
num_padding = 8 - (len & 7);
1806+
if (!smb3_encryption_required(tcon)) {
1807+
/*
1808+
* If we do not have encryption then we can just add an extra
1809+
* iov for the padding.
1810+
*/
1811+
rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding;
1812+
rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding;
1813+
rqst->rq_nvec++;
1814+
len += num_padding;
1815+
} else {
1816+
/*
1817+
* We can not add a small padding iov for the encryption case
1818+
* because the encryption framework can not handle the padding
1819+
* iovs.
1820+
* We have to flatten this into a single buffer and add
1821+
* the padding to it.
1822+
*/
1823+
for (i = 1; i < rqst->rq_nvec; i++) {
1824+
memcpy(rqst->rq_iov[0].iov_base +
1825+
rqst->rq_iov[0].iov_len,
1826+
rqst->rq_iov[i].iov_base,
1827+
rqst->rq_iov[i].iov_len);
1828+
rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len;
18081829
}
1809-
len = smb_rqst_len(server, rqst);
1830+
memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len,
1831+
0, num_padding);
1832+
rqst->rq_iov[0].iov_len += num_padding;
1833+
len += num_padding;
1834+
rqst->rq_nvec = 1;
18101835
}
18111836

1837+
finished:
18121838
shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
18131839
shdr->NextCommand = cpu_to_le32(len);
18141840
}
@@ -1825,7 +1851,6 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
18251851
struct cifs_sb_info *cifs_sb)
18261852
{
18271853
struct cifs_ses *ses = tcon->ses;
1828-
struct TCP_Server_Info *server = ses->server;
18291854
int flags = 0;
18301855
struct smb_rqst rqst[3];
18311856
int resp_buftype[3];
@@ -1862,7 +1887,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
18621887
rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path);
18631888
if (rc)
18641889
goto qic_exit;
1865-
smb2_set_next_command(server, &rqst[0], 0);
1890+
smb2_set_next_command(tcon, &rqst[0]);
18661891

18671892
memset(&qi_iov, 0, sizeof(qi_iov));
18681893
rqst[1].rq_iov = qi_iov;
@@ -1874,7 +1899,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
18741899
NULL);
18751900
if (rc)
18761901
goto qic_exit;
1877-
smb2_set_next_command(server, &rqst[1], 0);
1902+
smb2_set_next_command(tcon, &rqst[1]);
18781903
smb2_set_related(&rqst[1]);
18791904

18801905
memset(&close_iov, 0, sizeof(close_iov));
@@ -2806,7 +2831,7 @@ init_sg(int num_rqst, struct smb_rqst *rqst, u8 *sign)
28062831
smb2_sg_set_buf(&sg[idx++],
28072832
rqst[i].rq_iov[j].iov_base + skip,
28082833
rqst[i].rq_iov[j].iov_len - skip);
2809-
}
2834+
}
28102835

28112836
for (j = 0; j < rqst[i].rq_npages; j++) {
28122837
unsigned int len, offset;

fs/cifs/smb2proto.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,8 @@ extern void smb2_reconnect_server(struct work_struct *work);
116116
extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
117117
extern unsigned long smb_rqst_len(struct TCP_Server_Info *server,
118118
struct smb_rqst *rqst);
119-
extern void smb2_set_next_command(struct TCP_Server_Info *server,
120-
struct smb_rqst *rqst,
121-
bool has_space_for_padding);
119+
extern void smb2_set_next_command(struct cifs_tcon *tcon,
120+
struct smb_rqst *rqst);
122121
extern void smb2_set_related(struct smb_rqst *rqst);
123122

124123
/*

0 commit comments

Comments
 (0)