CVE-2017-9949 (published 2017-06-26T20:29Z)

The grub_memmove function in shlr/grub/kern/misc.c in radare2 1.5.0 allows remote attackers to cause a denial of service (stack-based buffer underflow and application crash) or possibly have unspecified other impact via a crafted binary file, possibly related to a buffer underflow in fs/ext2.c in GNU GRUB 2.02.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 7.8, HIGH (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/radare/radare2
commit_details: repo_url: https://github.com/radare/radare2
author: pancake
author_date: 2017-06-05 12:38:39+02:00
msg: Fix ext2 buffer overflow in r2_sbu_grub_memmove
repository: repo_url: https://github.com/radare/radare2
repo_name: radareorg/radare2
description: UNIX-like reverse engineering framework and command-line toolset
repo_language: C
owner: radare
file_changes: filename: Makefile
change_type: ModificationType.MODIFY
diff: @@ -23,9 +23,9 @@ CS_PATCHES=0
 else
 CS_TAR=
 CS_URL=$(GIT_PREFIX)github.com/aquynh/capstone.git
-CS_UPD=20170529
+CS_UPD=20170605
 CS_BRA=next
-CS_TIP=7982670984222e2d3bb8117da6225e06d119f56f
+CS_TIP=1910fd563539fba8498f07a36a0e74cfbdf42a7f
 # REVERT THIS COMMIT BECAUSE ITS WRONG
 CS_REV=
 CS_PATCHES=1

programming_language: Shell
filename: core.c
change_type: ModificationType.MODIFY
diff: @@ -182,6 +182,7 @@ static int _server_handle_vCont(libgdbr_t *g, int (*cmd_cb) (void*, const char*,
 			return send_msg (g, "E01");
 		}
 	}
+	return -1;
 }
 
 static int _server_handle_qAttached(libgdbr_t *g, int (*cmd_cb) (void*, const char*, char*, size_t), void *core_ptr) {

programming_language: C
filename: ext2.c
change_type: ModificationType.MODIFY
diff: @@ -432,10 +432,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
         }
     }
   /* Direct blocks.  */
-  if (fileblock < INDIRECT_BLOCKS)
+  if (fileblock < INDIRECT_BLOCKS) {
     blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
   /* Indirect.  */
-  else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
+  } else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
     {
       grub_uint32_t *indir;
 
@@ -679,23 +679,26 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
 
       if (dirent.namelen != 0)
 	{
-#ifndef _MSC_VER
-	  char filename[dirent.namelen + 1]; 
-#else
 	  char * filename = grub_malloc (dirent.namelen + 1);
-#endif
 	  struct grub_fshelp_node *fdiro;
 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
 
+if (!filename) {
+break;
+}
 	  grub_ext2_read_file (diro, 0, 0, 0,
 			       fpos + sizeof (struct ext2_dirent),
 			       dirent.namelen, filename);
-	  if (grub_errno)
+	  if (grub_errno) {
+            free (filename);
 	    return 0;
+	  }
 
 	  fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
-	  if (! fdiro)
+	  if (! fdiro) {
+            free (filename);
 	    return 0;
+          }
 
 	  fdiro->data = diro->data;
 	  fdiro->ino = grub_le_to_cpu32 (dirent.inode);
@@ -720,8 +723,8 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
 	      grub_ext2_read_inode (diro->data,
                                     grub_le_to_cpu32 (dirent.inode),
 				    &fdiro->inode);
-	      if (grub_errno)
-		{
+	      if (grub_errno) {
+                  free (filename);
 		  grub_free (fdiro);
 		  return 0;
 		}
@@ -739,8 +742,11 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
 		type = GRUB_FSHELP_REG;
 	    }
 
-	  if (hook (filename, type, fdiro, closure))
+	  if (hook (filename, type, fdiro, closure)) {
+            free (filename);
 	    return 1;
+          }
+          free (filename);
 	}
 
       fpos += grub_le_to_cpu16 (dirent.direntlen);

programming_language: C
filename: fshelp.c
change_type: ModificationType.MODIFY
diff: @@ -287,6 +287,10 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
   if (pos + len > filesize)
     len = filesize - pos;
 
+  if (len < 1 || len == 0xffffffff) {
+    return -1;
+  }
+
   blockcnt = ((len + pos) + blocksize - 1) >>
     (log2blocksize + GRUB_DISK_SECTOR_BITS);
 

programming_language: C
filename: rebuild.sh
change_type: ModificationType.MODIFY
diff: @@ -55,6 +55,11 @@ RebuildSdb() {
 	Rebuild libr/util
 }
 
+RebuildFs() {
+	Rebuild shlr/grub
+	Rebuild libr/fs
+}
+
 RebuildBin() {
 	Rebuild libr/bin
 	Rebuild libr/core
@@ -67,6 +72,7 @@ RebuildGdb() {
 }
 
 case "$1" in
+fs)     RebuildFs; ;;
 bin)    RebuildBin ; ;;
 gdb)    RebuildGdb ; ;;
 sdb)    RebuildSdb ; ;;

programming_language: Shell