Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 102466f303ff ("smb: client: allow creating special files via reparse points")
Signed-off-by: Pali Rohár <pali@kernel.org>
Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Pali Rohár and committed by
Steve French
c9432ad5 1eecd880

+22 -2
+22 -2
fs/smb/client/smb2inode.c
··· 1205 1205 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 1206 1206 struct cifsFileInfo *cfile; 1207 1207 struct inode *new = NULL; 1208 + int out_buftype[4] = {}; 1209 + struct kvec out_iov[4] = {}; 1208 1210 struct kvec in_iov[2]; 1209 1211 int cmds[2]; 1210 1212 int rc; 1213 + int i; 1211 1214 1212 1215 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, 1213 1216 SYNCHRONIZE | DELETE | ··· 1231 1228 cmds[1] = SMB2_OP_POSIX_QUERY_INFO; 1232 1229 cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 1233 1230 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, 1234 - in_iov, cmds, 2, cfile, NULL, NULL, NULL); 1231 + in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); 1235 1232 if (!rc) { 1236 1233 rc = smb311_posix_get_inode_info(&new, full_path, 1237 1234 data, sb, xid); ··· 1240 1237 cmds[1] = SMB2_OP_QUERY_INFO; 1241 1238 cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 1242 1239 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, 1243 - in_iov, cmds, 2, cfile, NULL, NULL, NULL); 1240 + in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); 1244 1241 if (!rc) { 1245 1242 rc = cifs_get_inode_info(&new, full_path, 1246 1243 data, sb, xid, NULL); 1247 1244 } 1248 1245 } 1246 + 1247 + 1248 + /* 1249 + * If CREATE was successful but SMB2_OP_SET_REPARSE failed then 1250 + * remove the intermediate object created by CREATE. Otherwise 1251 + * empty object stay on the server when reparse call failed. 1252 + */ 1253 + if (rc && 1254 + out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER && 1255 + ((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS && 1256 + (out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER || 1257 + ((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS)) 1258 + smb2_unlink(xid, tcon, full_path, cifs_sb, NULL); 1259 + 1260 + for (i = 0; i < ARRAY_SIZE(out_buftype); i++) 1261 + free_rsp_buf(out_buftype[i], out_iov[i].iov_base); 1262 + 1249 1263 return rc ? ERR_PTR(rc) : new; 1250 1264 } 1251 1265