Skip to content

Commit 127c501

Browse files
committed
Merge tag '5.10-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Four smb3 fixes for stable: one fixes a memleak, the other three address a problem found with decryption offload that can cause a use after free" * tag '5.10-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb3: Handle error case during offload read path smb3: Avoid Mid pending list corruption smb3: Call cifs reconnect from demultiplex thread cifs: fix a memleak with modefromsid
2 parents 073861e + 1254100 commit 127c501

File tree

2 files changed

+74
-15
lines changed

2 files changed

+74
-15
lines changed

fs/cifs/cifsacl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
12661266
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
12671267
} else if (mode_from_special_sid) {
12681268
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
1269+
kfree(pntsd);
12691270
} else {
12701271
/* get approximated mode from ACL */
12711272
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);

fs/cifs/smb2ops.c

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
264264
}
265265

266266
static struct mid_q_entry *
267-
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
267+
__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
268268
{
269269
struct mid_q_entry *mid;
270270
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
@@ -281,6 +281,10 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
281281
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
282282
(mid->command == shdr->Command)) {
283283
kref_get(&mid->refcount);
284+
if (dequeue) {
285+
list_del_init(&mid->qhead);
286+
mid->mid_flags |= MID_DELETED;
287+
}
284288
spin_unlock(&GlobalMid_Lock);
285289
return mid;
286290
}
@@ -289,6 +293,18 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
289293
return NULL;
290294
}
291295

296+
static struct mid_q_entry *
297+
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
298+
{
299+
return __smb2_find_mid(server, buf, false);
300+
}
301+
302+
static struct mid_q_entry *
303+
smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
304+
{
305+
return __smb2_find_mid(server, buf, true);
306+
}
307+
292308
static void
293309
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
294310
{
@@ -4356,7 +4372,8 @@ init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
43564372
static int
43574373
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
43584374
char *buf, unsigned int buf_len, struct page **pages,
4359-
unsigned int npages, unsigned int page_data_size)
4375+
unsigned int npages, unsigned int page_data_size,
4376+
bool is_offloaded)
43604377
{
43614378
unsigned int data_offset;
43624379
unsigned int data_len;
@@ -4378,7 +4395,8 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
43784395

43794396
if (server->ops->is_session_expired &&
43804397
server->ops->is_session_expired(buf)) {
4381-
cifs_reconnect(server);
4398+
if (!is_offloaded)
4399+
cifs_reconnect(server);
43824400
return -1;
43834401
}
43844402

@@ -4402,7 +4420,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
44024420
cifs_dbg(FYI, "%s: server returned error %d\n",
44034421
__func__, rdata->result);
44044422
/* normal error on read response */
4405-
dequeue_mid(mid, false);
4423+
if (is_offloaded)
4424+
mid->mid_state = MID_RESPONSE_RECEIVED;
4425+
else
4426+
dequeue_mid(mid, false);
44064427
return 0;
44074428
}
44084429

@@ -4426,7 +4447,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
44264447
cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
44274448
__func__, data_offset);
44284449
rdata->result = -EIO;
4429-
dequeue_mid(mid, rdata->result);
4450+
if (is_offloaded)
4451+
mid->mid_state = MID_RESPONSE_MALFORMED;
4452+
else
4453+
dequeue_mid(mid, rdata->result);
44304454
return 0;
44314455
}
44324456

@@ -4442,21 +4466,30 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
44424466
cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
44434467
__func__, data_offset);
44444468
rdata->result = -EIO;
4445-
dequeue_mid(mid, rdata->result);
4469+
if (is_offloaded)
4470+
mid->mid_state = MID_RESPONSE_MALFORMED;
4471+
else
4472+
dequeue_mid(mid, rdata->result);
44464473
return 0;
44474474
}
44484475

44494476
if (data_len > page_data_size - pad_len) {
44504477
/* data_len is corrupt -- discard frame */
44514478
rdata->result = -EIO;
4452-
dequeue_mid(mid, rdata->result);
4479+
if (is_offloaded)
4480+
mid->mid_state = MID_RESPONSE_MALFORMED;
4481+
else
4482+
dequeue_mid(mid, rdata->result);
44534483
return 0;
44544484
}
44554485

44564486
rdata->result = init_read_bvec(pages, npages, page_data_size,
44574487
cur_off, &bvec);
44584488
if (rdata->result != 0) {
4459-
dequeue_mid(mid, rdata->result);
4489+
if (is_offloaded)
4490+
mid->mid_state = MID_RESPONSE_MALFORMED;
4491+
else
4492+
dequeue_mid(mid, rdata->result);
44604493
return 0;
44614494
}
44624495

@@ -4471,7 +4504,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
44714504
/* read response payload cannot be in both buf and pages */
44724505
WARN_ONCE(1, "buf can not contain only a part of read data");
44734506
rdata->result = -EIO;
4474-
dequeue_mid(mid, rdata->result);
4507+
if (is_offloaded)
4508+
mid->mid_state = MID_RESPONSE_MALFORMED;
4509+
else
4510+
dequeue_mid(mid, rdata->result);
44754511
return 0;
44764512
}
44774513

@@ -4482,7 +4518,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
44824518
if (length < 0)
44834519
return length;
44844520

4485-
dequeue_mid(mid, false);
4521+
if (is_offloaded)
4522+
mid->mid_state = MID_RESPONSE_RECEIVED;
4523+
else
4524+
dequeue_mid(mid, false);
44864525
return length;
44874526
}
44884527

@@ -4511,15 +4550,34 @@ static void smb2_decrypt_offload(struct work_struct *work)
45114550
}
45124551

45134552
dw->server->lstrp = jiffies;
4514-
mid = smb2_find_mid(dw->server, dw->buf);
4553+
mid = smb2_find_dequeue_mid(dw->server, dw->buf);
45154554
if (mid == NULL)
45164555
cifs_dbg(FYI, "mid not found\n");
45174556
else {
45184557
mid->decrypted = true;
45194558
rc = handle_read_data(dw->server, mid, dw->buf,
45204559
dw->server->vals->read_rsp_size,
4521-
dw->ppages, dw->npages, dw->len);
4522-
mid->callback(mid);
4560+
dw->ppages, dw->npages, dw->len,
4561+
true);
4562+
if (rc >= 0) {
4563+
#ifdef CONFIG_CIFS_STATS2
4564+
mid->when_received = jiffies;
4565+
#endif
4566+
mid->callback(mid);
4567+
} else {
4568+
spin_lock(&GlobalMid_Lock);
4569+
if (dw->server->tcpStatus == CifsNeedReconnect) {
4570+
mid->mid_state = MID_RETRY_NEEDED;
4571+
spin_unlock(&GlobalMid_Lock);
4572+
mid->callback(mid);
4573+
} else {
4574+
mid->mid_state = MID_REQUEST_SUBMITTED;
4575+
mid->mid_flags &= ~(MID_DELETED);
4576+
list_add_tail(&mid->qhead,
4577+
&dw->server->pending_mid_q);
4578+
spin_unlock(&GlobalMid_Lock);
4579+
}
4580+
}
45234581
cifs_mid_q_entry_release(mid);
45244582
}
45254583

@@ -4622,7 +4680,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
46224680
(*mid)->decrypted = true;
46234681
rc = handle_read_data(server, *mid, buf,
46244682
server->vals->read_rsp_size,
4625-
pages, npages, len);
4683+
pages, npages, len, false);
46264684
}
46274685

46284686
free_pages:
@@ -4765,7 +4823,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
47654823
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
47664824

47674825
return handle_read_data(server, mid, buf, server->pdu_size,
4768-
NULL, 0, 0);
4826+
NULL, 0, 0, false);
47694827
}
47704828

47714829
static int

0 commit comments

Comments
 (0)