fixes for four CIFS/SMB3 potential pointer overflow issues, one minor build fix, and a build warning cleanup
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAlucKDwACgkQiiy9cAdy T1EhEgwAqgVXTujce2UVPtaFY/MaGmaIwAimh+aYOCAADxLYJHkjtRzHd5PQgf+L n55R2hFcMeelWxOMEb/aRmxIKLk8fmJYVWClM2+S7Z79M3GHexDbMS8+oDZnzCTB EknvaTbi+vOt4HGABkbJ/jiQCgonmeobon30gLWaYa3XGeYc7ZV5gR+EXL9xSdvh +I+x3rSDpm8fQ5njkB7RKgfB+ha4NQqZ6dXlYQzcb0vMO3/lhQ56Ypgn95Jlu5UW pcLxUFE1do+JeGvIU1it2SCRJ5499g180Rxucl7X1xFBQ44Qss9QOeWkFTZ8784V PIYVZMTUqO0Km4H22qXD8lIY5GjDuAXLYM3AddFkJpbKaw6g++ZsUXSfoA5zRIDn 10edaPK/hDIQeFaV+ySTN5g/Qh3YFnmY4kDL3t3CRZDe4+DTW/+cmrF3sGkhZDQt +nDo0JxJsjNnJW6loB5Lb76lygvsng01owSsYSAChjhYwBvCDgp9/D85pDQ/oYkl HKD9tiF3 =YNSx -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
3a5af36b6d
|
@ -6,6 +6,7 @@ config CIFS
|
||||||
select CRYPTO_MD4
|
select CRYPTO_MD4
|
||||||
select CRYPTO_MD5
|
select CRYPTO_MD5
|
||||||
select CRYPTO_SHA256
|
select CRYPTO_SHA256
|
||||||
|
select CRYPTO_SHA512
|
||||||
select CRYPTO_CMAC
|
select CRYPTO_CMAC
|
||||||
select CRYPTO_HMAC
|
select CRYPTO_HMAC
|
||||||
select CRYPTO_ARC4
|
select CRYPTO_ARC4
|
||||||
|
|
|
@ -601,10 +601,15 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||||
}
|
}
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
/*
|
||||||
|
* We know that all the name entries in the protocols array
|
||||||
|
* are short (< 16 bytes anyway) and are NUL terminated.
|
||||||
|
*/
|
||||||
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
||||||
strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
|
size_t len = strlen(protocols[i].name) + 1;
|
||||||
count += strlen(protocols[i].name) + 1;
|
|
||||||
/* null at end of source and target buffers anyway */
|
memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
|
||||||
|
count += len;
|
||||||
}
|
}
|
||||||
inc_rfc1001_len(pSMB, count);
|
inc_rfc1001_len(pSMB, count);
|
||||||
pSMB->ByteCount = cpu_to_le16(count);
|
pSMB->ByteCount = cpu_to_le16(count);
|
||||||
|
|
|
@ -402,9 +402,17 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
|
||||||
(struct smb_com_transaction_change_notify_rsp *)buf;
|
(struct smb_com_transaction_change_notify_rsp *)buf;
|
||||||
struct file_notify_information *pnotify;
|
struct file_notify_information *pnotify;
|
||||||
__u32 data_offset = 0;
|
__u32 data_offset = 0;
|
||||||
|
size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
|
||||||
|
|
||||||
if (get_bcc(buf) > sizeof(struct file_notify_information)) {
|
if (get_bcc(buf) > sizeof(struct file_notify_information)) {
|
||||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||||
|
|
||||||
|
if (data_offset >
|
||||||
|
len - sizeof(struct file_notify_information)) {
|
||||||
|
cifs_dbg(FYI, "invalid data_offset %u\n",
|
||||||
|
data_offset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
pnotify = (struct file_notify_information *)
|
pnotify = (struct file_notify_information *)
|
||||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
((char *)&pSMBr->hdr.Protocol + data_offset);
|
||||||
cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
|
cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
|
||||||
|
|
|
@ -376,8 +376,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
|
|
||||||
new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
|
new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
|
||||||
pfData->FileNameLength;
|
pfData->FileNameLength;
|
||||||
} else
|
} else {
|
||||||
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
|
u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
|
||||||
|
|
||||||
|
if (old_entry + next_offset < old_entry) {
|
||||||
|
cifs_dbg(VFS, "invalid offset %u\n", next_offset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
new_entry = old_entry + next_offset;
|
||||||
|
}
|
||||||
cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
|
cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
|
||||||
/* validate that new_entry is not past end of SMB */
|
/* validate that new_entry is not past end of SMB */
|
||||||
if (new_entry >= end_of_smb) {
|
if (new_entry >= end_of_smb) {
|
||||||
|
|
|
@ -2459,14 +2459,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
||||||
/* We check for obvious errors in the output buffer length and offset */
|
/* We check for obvious errors in the output buffer length and offset */
|
||||||
if (*plen == 0)
|
if (*plen == 0)
|
||||||
goto ioctl_exit; /* server returned no data */
|
goto ioctl_exit; /* server returned no data */
|
||||||
else if (*plen > 0xFF00) {
|
else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
|
||||||
cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
|
cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
|
||||||
*plen = 0;
|
*plen = 0;
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto ioctl_exit;
|
goto ioctl_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
|
if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
|
||||||
cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
|
cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
|
||||||
le32_to_cpu(rsp->OutputOffset));
|
le32_to_cpu(rsp->OutputOffset));
|
||||||
*plen = 0;
|
*plen = 0;
|
||||||
|
@ -3577,33 +3577,38 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
|
||||||
int len;
|
int len;
|
||||||
unsigned int entrycount = 0;
|
unsigned int entrycount = 0;
|
||||||
unsigned int next_offset = 0;
|
unsigned int next_offset = 0;
|
||||||
FILE_DIRECTORY_INFO *entryptr;
|
char *entryptr;
|
||||||
|
FILE_DIRECTORY_INFO *dir_info;
|
||||||
|
|
||||||
if (bufstart == NULL)
|
if (bufstart == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
entryptr = (FILE_DIRECTORY_INFO *)bufstart;
|
entryptr = bufstart;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
entryptr = (FILE_DIRECTORY_INFO *)
|
if (entryptr + next_offset < entryptr ||
|
||||||
((char *)entryptr + next_offset);
|
entryptr + next_offset > end_of_buf ||
|
||||||
|
entryptr + next_offset + size > end_of_buf) {
|
||||||
if ((char *)entryptr + size > end_of_buf) {
|
|
||||||
cifs_dbg(VFS, "malformed search entry would overflow\n");
|
cifs_dbg(VFS, "malformed search entry would overflow\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = le32_to_cpu(entryptr->FileNameLength);
|
entryptr = entryptr + next_offset;
|
||||||
if ((char *)entryptr + len + size > end_of_buf) {
|
dir_info = (FILE_DIRECTORY_INFO *)entryptr;
|
||||||
|
|
||||||
|
len = le32_to_cpu(dir_info->FileNameLength);
|
||||||
|
if (entryptr + len < entryptr ||
|
||||||
|
entryptr + len > end_of_buf ||
|
||||||
|
entryptr + len + size > end_of_buf) {
|
||||||
cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
|
cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
|
||||||
end_of_buf);
|
end_of_buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lastentry = (char *)entryptr;
|
*lastentry = entryptr;
|
||||||
entrycount++;
|
entrycount++;
|
||||||
|
|
||||||
next_offset = le32_to_cpu(entryptr->NextEntryOffset);
|
next_offset = le32_to_cpu(dir_info->NextEntryOffset);
|
||||||
if (!next_offset)
|
if (!next_offset)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue