[PATCH 4.14 102/173] CIFS: fix wrapping bugs in num_entries()

2018-09-24 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Dan Carpenter 

commit 56446f218af1133c802dad8e9e116f07f381846c upstream.

The problem is that "entryptr + next_offset" and "entryptr + len + size"
can wrap.  I ended up changing the type of "entryptr" because it makes
the math easier when we don't have to do so much casting.

Signed-off-by: Dan Carpenter 
Signed-off-by: Steve French 
Reviewed-by: Aurelien Aptel 
Reviewed-by: Pavel Shilovsky 
CC: Stable 
Signed-off-by: Greg Kroah-Hartman 

---
 fs/cifs/smb2pdu.c |   25 +++--
 1 file changed, 15 insertions(+), 10 deletions(-)

--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2939,33 +2939,38 @@ num_entries(char *bufstart, char *end_of
int len;
unsigned int entrycount = 0;
unsigned int next_offset = 0;
-   FILE_DIRECTORY_INFO *entryptr;
+   char *entryptr;
+   FILE_DIRECTORY_INFO *dir_info;
 
if (bufstart == NULL)
return 0;
 
-   entryptr = (FILE_DIRECTORY_INFO *)bufstart;
+   entryptr = bufstart;
 
while (1) {
-   entryptr = (FILE_DIRECTORY_INFO *)
-   ((char *)entryptr + next_offset);
-
-   if ((char *)entryptr + size > end_of_buf) {
+   if (entryptr + next_offset < entryptr ||
+   entryptr + next_offset > end_of_buf ||
+   entryptr + next_offset + size > end_of_buf) {
cifs_dbg(VFS, "malformed search entry would 
overflow\n");
break;
}
 
-   len = le32_to_cpu(entryptr->FileNameLength);
-   if ((char *)entryptr + len + size > end_of_buf) {
+   entryptr = entryptr + next_offset;
+   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",
 end_of_buf);
break;
}
 
-   *lastentry = (char *)entryptr;
+   *lastentry = entryptr;
entrycount++;
 
-   next_offset = le32_to_cpu(entryptr->NextEntryOffset);
+   next_offset = le32_to_cpu(dir_info->NextEntryOffset);
if (!next_offset)
break;
}




[PATCH 4.14 102/173] CIFS: fix wrapping bugs in num_entries()

2018-09-24 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Dan Carpenter 

commit 56446f218af1133c802dad8e9e116f07f381846c upstream.

The problem is that "entryptr + next_offset" and "entryptr + len + size"
can wrap.  I ended up changing the type of "entryptr" because it makes
the math easier when we don't have to do so much casting.

Signed-off-by: Dan Carpenter 
Signed-off-by: Steve French 
Reviewed-by: Aurelien Aptel 
Reviewed-by: Pavel Shilovsky 
CC: Stable 
Signed-off-by: Greg Kroah-Hartman 

---
 fs/cifs/smb2pdu.c |   25 +++--
 1 file changed, 15 insertions(+), 10 deletions(-)

--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2939,33 +2939,38 @@ num_entries(char *bufstart, char *end_of
int len;
unsigned int entrycount = 0;
unsigned int next_offset = 0;
-   FILE_DIRECTORY_INFO *entryptr;
+   char *entryptr;
+   FILE_DIRECTORY_INFO *dir_info;
 
if (bufstart == NULL)
return 0;
 
-   entryptr = (FILE_DIRECTORY_INFO *)bufstart;
+   entryptr = bufstart;
 
while (1) {
-   entryptr = (FILE_DIRECTORY_INFO *)
-   ((char *)entryptr + next_offset);
-
-   if ((char *)entryptr + size > end_of_buf) {
+   if (entryptr + next_offset < entryptr ||
+   entryptr + next_offset > end_of_buf ||
+   entryptr + next_offset + size > end_of_buf) {
cifs_dbg(VFS, "malformed search entry would 
overflow\n");
break;
}
 
-   len = le32_to_cpu(entryptr->FileNameLength);
-   if ((char *)entryptr + len + size > end_of_buf) {
+   entryptr = entryptr + next_offset;
+   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",
 end_of_buf);
break;
}
 
-   *lastentry = (char *)entryptr;
+   *lastentry = entryptr;
entrycount++;
 
-   next_offset = le32_to_cpu(entryptr->NextEntryOffset);
+   next_offset = le32_to_cpu(dir_info->NextEntryOffset);
if (!next_offset)
break;
}