Skip to content

Commit f26a246

Browse files
committed
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
2 parents d874367 + fbe2dc6 commit f26a246

File tree

1 file changed

+89
-12
lines changed

1 file changed

+89
-12
lines changed

fs/smb/client/smb2inode.c

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
687687
}
688688

689689
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;
691691

692692
if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER)
693693
rc = server->ops->map_error(buf, false);
@@ -1175,30 +1175,107 @@ int
11751175
smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
11761176
struct cifs_sb_info *cifs_sb, struct dentry *dentry)
11771177
{
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;
11781182
struct cifs_open_parms oparms;
1183+
struct smb2_create_req *creq;
11791184
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;
11801192
int rc;
11811193

1182-
if (dentry)
1194+
utf16_path = cifs_convert_path_to_utf16(name, cifs_sb);
1195+
if (!utf16_path)
1196+
return -ENOMEM;
1197+
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) {
11831217
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+
}
11841223

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);
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;
11951264
}
11961265
/*
11971266
* If dentry (hence, inode) is NULL, lease break is going to
11981267
* take care of degrading leases on handles for deleted files.
11991268
*/
12001269
if (!rc && inode)
12011270
cifs_mark_open_handles_for_deleted_file(inode, name);
1271+
1272+
return rc;
1273+
1274+
err_free:
1275+
SMB2_open_free(&rqst[0]);
1276+
SMB2_close_free(&rqst[1]);
1277+
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1278+
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
12021279
return rc;
12031280
}
12041281

0 commit comments

Comments
 (0)