Skip to content

Commit 3a5af36

Browse files
committed
Merge tag '4.19-rc3-smb3-cifs' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Fixes for four CIFS/SMB3 potential pointer overflow issues, one minor build fix, and a build warning cleanup" * tag '4.19-rc3-smb3-cifs' of git://git.samba.org/sfrench/cifs-2.6: cifs: read overflow in is_valid_oplock_break() cifs: integer overflow in in SMB2_ioctl() CIFS: fix wrapping bugs in num_entries() cifs: prevent integer overflow in nxt_dir_entry() fs/cifs: require sha512 fs/cifs: suppress a string overflow warning
2 parents 589109d + 097f586 commit 3a5af36

File tree

5 files changed

+43
-17
lines changed

5 files changed

+43
-17
lines changed

fs/cifs/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config CIFS
66
select CRYPTO_MD4
77
select CRYPTO_MD5
88
select CRYPTO_SHA256
9+
select CRYPTO_SHA512
910
select CRYPTO_CMAC
1011
select CRYPTO_HMAC
1112
select CRYPTO_ARC4

fs/cifs/cifssmb.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,15 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
601601
}
602602

603603
count = 0;
604+
/*
605+
* We know that all the name entries in the protocols array
606+
* are short (< 16 bytes anyway) and are NUL terminated.
607+
*/
604608
for (i = 0; i < CIFS_NUM_PROT; i++) {
605-
strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
606-
count += strlen(protocols[i].name) + 1;
607-
/* null at end of source and target buffers anyway */
609+
size_t len = strlen(protocols[i].name) + 1;
610+
611+
memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
612+
count += len;
608613
}
609614
inc_rfc1001_len(pSMB, count);
610615
pSMB->ByteCount = cpu_to_le16(count);

fs/cifs/misc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,17 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
402402
(struct smb_com_transaction_change_notify_rsp *)buf;
403403
struct file_notify_information *pnotify;
404404
__u32 data_offset = 0;
405+
size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
406+
405407
if (get_bcc(buf) > sizeof(struct file_notify_information)) {
406408
data_offset = le32_to_cpu(pSMBr->DataOffset);
407409

410+
if (data_offset >
411+
len - sizeof(struct file_notify_information)) {
412+
cifs_dbg(FYI, "invalid data_offset %u\n",
413+
data_offset);
414+
return true;
415+
}
408416
pnotify = (struct file_notify_information *)
409417
((char *)&pSMBr->hdr.Protocol + data_offset);
410418
cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",

fs/cifs/readdir.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
376376

377377
new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
378378
pfData->FileNameLength;
379-
} else
380-
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
379+
} else {
380+
u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
381+
382+
if (old_entry + next_offset < old_entry) {
383+
cifs_dbg(VFS, "invalid offset %u\n", next_offset);
384+
return NULL;
385+
}
386+
new_entry = old_entry + next_offset;
387+
}
381388
cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
382389
/* validate that new_entry is not past end of SMB */
383390
if (new_entry >= end_of_smb) {

fs/cifs/smb2pdu.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,14 +2459,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
24592459
/* We check for obvious errors in the output buffer length and offset */
24602460
if (*plen == 0)
24612461
goto ioctl_exit; /* server returned no data */
2462-
else if (*plen > 0xFF00) {
2462+
else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
24632463
cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
24642464
*plen = 0;
24652465
rc = -EIO;
24662466
goto ioctl_exit;
24672467
}
24682468

2469-
if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
2469+
if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
24702470
cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
24712471
le32_to_cpu(rsp->OutputOffset));
24722472
*plen = 0;
@@ -3577,33 +3577,38 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
35773577
int len;
35783578
unsigned int entrycount = 0;
35793579
unsigned int next_offset = 0;
3580-
FILE_DIRECTORY_INFO *entryptr;
3580+
char *entryptr;
3581+
FILE_DIRECTORY_INFO *dir_info;
35813582

35823583
if (bufstart == NULL)
35833584
return 0;
35843585

3585-
entryptr = (FILE_DIRECTORY_INFO *)bufstart;
3586+
entryptr = bufstart;
35863587

35873588
while (1) {
3588-
entryptr = (FILE_DIRECTORY_INFO *)
3589-
((char *)entryptr + next_offset);
3590-
3591-
if ((char *)entryptr + size > end_of_buf) {
3589+
if (entryptr + next_offset < entryptr ||
3590+
entryptr + next_offset > end_of_buf ||
3591+
entryptr + next_offset + size > end_of_buf) {
35923592
cifs_dbg(VFS, "malformed search entry would overflow\n");
35933593
break;
35943594
}
35953595

3596-
len = le32_to_cpu(entryptr->FileNameLength);
3597-
if ((char *)entryptr + len + size > end_of_buf) {
3596+
entryptr = entryptr + next_offset;
3597+
dir_info = (FILE_DIRECTORY_INFO *)entryptr;
3598+
3599+
len = le32_to_cpu(dir_info->FileNameLength);
3600+
if (entryptr + len < entryptr ||
3601+
entryptr + len > end_of_buf ||
3602+
entryptr + len + size > end_of_buf) {
35983603
cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
35993604
end_of_buf);
36003605
break;
36013606
}
36023607

3603-
*lastentry = (char *)entryptr;
3608+
*lastentry = entryptr;
36043609
entrycount++;
36053610

3606-
next_offset = le32_to_cpu(entryptr->NextEntryOffset);
3611+
next_offset = le32_to_cpu(dir_info->NextEntryOffset);
36073612
if (!next_offset)
36083613
break;
36093614
}

0 commit comments

Comments
 (0)