Skip to content

Commit c9432ad

Browse files
palismfrench
authored andcommitted
cifs: Remove intermediate object of failed create reparse call
If CREATE was successful but SMB2_OP_SET_REPARSE failed then remove the intermediate object created by CREATE. Otherwise empty object stay on the server when reparse call failed. This ensures that if the creating of special files is unsupported by the server then no empty file stay on the server as a result of unsupported operation. Fixes: 102466f ("smb: client: allow creating special files via reparse points") Signed-off-by: Pali Rohár <[email protected]> Acked-by: Paulo Alcantara (Red Hat) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 1eecd88 commit c9432ad

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

fs/smb/client/smb2inode.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,9 +1205,12 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
12051205
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
12061206
struct cifsFileInfo *cfile;
12071207
struct inode *new = NULL;
1208+
int out_buftype[4] = {};
1209+
struct kvec out_iov[4] = {};
12081210
struct kvec in_iov[2];
12091211
int cmds[2];
12101212
int rc;
1213+
int i;
12111214

12121215
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
12131216
SYNCHRONIZE | DELETE |
@@ -1228,7 +1231,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
12281231
cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
12291232
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
12301233
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1231-
in_iov, cmds, 2, cfile, NULL, NULL, NULL);
1234+
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
12321235
if (!rc) {
12331236
rc = smb311_posix_get_inode_info(&new, full_path,
12341237
data, sb, xid);
@@ -1237,12 +1240,29 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
12371240
cmds[1] = SMB2_OP_QUERY_INFO;
12381241
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
12391242
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1240-
in_iov, cmds, 2, cfile, NULL, NULL, NULL);
1243+
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
12411244
if (!rc) {
12421245
rc = cifs_get_inode_info(&new, full_path,
12431246
data, sb, xid, NULL);
12441247
}
12451248
}
1249+
1250+
1251+
/*
1252+
* If CREATE was successful but SMB2_OP_SET_REPARSE failed then
1253+
* remove the intermediate object created by CREATE. Otherwise
1254+
* empty object stay on the server when reparse call failed.
1255+
*/
1256+
if (rc &&
1257+
out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER &&
1258+
((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS &&
1259+
(out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER ||
1260+
((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS))
1261+
smb2_unlink(xid, tcon, full_path, cifs_sb, NULL);
1262+
1263+
for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
1264+
free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
1265+
12461266
return rc ? ERR_PTR(rc) : new;
12471267
}
12481268

0 commit comments

Comments
 (0)