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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v6.17rc7-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Fix unlink bug

- Fix potential out of bounds access in processing compound requests

* tag 'v6.17rc7-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb: client: fix wrong index reference in smb2_compound_op()
smb: client: handle unlink(2) of files open by different clients

+90 -13
+90 -13
fs/smb/client/smb2inode.c
··· 687 687 } 688 688 689 689 for (i = 0; i < num_cmds; i++) { 690 - char *buf = rsp_iov[i + i].iov_base; 690 + char *buf = rsp_iov[i + 1].iov_base; 691 691 692 692 if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER) 693 693 rc = server->ops->map_error(buf, false); ··· 1175 1175 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, 1176 1176 struct cifs_sb_info *cifs_sb, struct dentry *dentry) 1177 1177 { 1178 + struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; 1179 + __le16 *utf16_path __free(kfree) = NULL; 1180 + int retries = 0, cur_sleep = 1; 1181 + struct TCP_Server_Info *server; 1178 1182 struct cifs_open_parms oparms; 1183 + struct smb2_create_req *creq; 1179 1184 struct inode *inode = NULL; 1185 + struct smb_rqst rqst[2]; 1186 + struct kvec rsp_iov[2]; 1187 + struct kvec close_iov; 1188 + int resp_buftype[2]; 1189 + struct cifs_fid fid; 1190 + int flags = 0; 1191 + __u8 oplock; 1180 1192 int rc; 1181 1193 1182 - if (dentry) 1183 - inode = d_inode(dentry); 1194 + utf16_path = cifs_convert_path_to_utf16(name, cifs_sb); 1195 + if (!utf16_path) 1196 + return -ENOMEM; 1184 1197 1185 - oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, 1186 - FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); 1187 - rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, 1188 - NULL, &(int){SMB2_OP_UNLINK}, 1189 - 1, NULL, NULL, NULL, dentry); 1190 - if (rc == -EINVAL) { 1191 - cifs_dbg(FYI, "invalid lease key, resending request without lease"); 1192 - rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, 1193 - NULL, &(int){SMB2_OP_UNLINK}, 1194 - 1, NULL, NULL, NULL, NULL); 1198 + if (smb3_encryption_required(tcon)) 1199 + flags |= CIFS_TRANSFORM_REQ; 1200 + again: 1201 + oplock = SMB2_OPLOCK_LEVEL_NONE; 1202 + server = cifs_pick_channel(tcon->ses); 1203 + 1204 + memset(rqst, 0, sizeof(rqst)); 1205 + memset(resp_buftype, 0, sizeof(resp_buftype)); 1206 + memset(rsp_iov, 0, sizeof(rsp_iov)); 1207 + 1208 + rqst[0].rq_iov = open_iov; 1209 + rqst[0].rq_nvec = ARRAY_SIZE(open_iov); 1210 + 1211 + oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE | FILE_READ_ATTRIBUTES, 1212 + FILE_OPEN, CREATE_DELETE_ON_CLOSE | 1213 + OPEN_REPARSE_POINT, ACL_NO_MODE); 1214 + oparms.fid = &fid; 1215 + 1216 + if (dentry) { 1217 + inode = d_inode(dentry); 1218 + if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) { 1219 + oplock = SMB2_OPLOCK_LEVEL_LEASE; 1220 + server->ops->get_lease_key(inode, &fid); 1221 + } 1222 + } 1223 + 1224 + rc = SMB2_open_init(tcon, server, 1225 + &rqst[0], &oplock, &oparms, utf16_path); 1226 + if (rc) 1227 + goto err_free; 1228 + smb2_set_next_command(tcon, &rqst[0]); 1229 + creq = rqst[0].rq_iov[0].iov_base; 1230 + creq->ShareAccess = FILE_SHARE_DELETE_LE; 1231 + 1232 + rqst[1].rq_iov = &close_iov; 1233 + rqst[1].rq_nvec = 1; 1234 + 1235 + rc = SMB2_close_init(tcon, server, &rqst[1], 1236 + COMPOUND_FID, COMPOUND_FID, false); 1237 + smb2_set_related(&rqst[1]); 1238 + if (rc) 1239 + goto err_free; 1240 + 1241 + if (retries) { 1242 + for (int i = 0; i < ARRAY_SIZE(rqst); i++) 1243 + smb2_set_replay(server, &rqst[i]); 1244 + } 1245 + 1246 + rc = compound_send_recv(xid, tcon->ses, server, flags, 1247 + ARRAY_SIZE(rqst), rqst, 1248 + resp_buftype, rsp_iov); 1249 + SMB2_open_free(&rqst[0]); 1250 + SMB2_close_free(&rqst[1]); 1251 + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 1252 + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 1253 + 1254 + if (is_replayable_error(rc) && 1255 + smb2_should_replay(tcon, &retries, &cur_sleep)) 1256 + goto again; 1257 + 1258 + /* Retry compound request without lease */ 1259 + if (rc == -EINVAL && dentry) { 1260 + dentry = NULL; 1261 + retries = 0; 1262 + cur_sleep = 1; 1263 + goto again; 1195 1264 } 1196 1265 /* 1197 1266 * If dentry (hence, inode) is NULL, lease break is going to ··· 1268 1199 */ 1269 1200 if (!rc && inode) 1270 1201 cifs_mark_open_handles_for_deleted_file(inode, name); 1202 + 1203 + return rc; 1204 + 1205 + err_free: 1206 + SMB2_open_free(&rqst[0]); 1207 + SMB2_close_free(&rqst[1]); 1208 + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 1209 + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 1271 1210 return rc; 1272 1211 } 1273 1212