CVE-2017-9763 (C, published 2017-06-19T16:29Z)
Description: value: The grub_ext2_read_block function in fs/ext2.c in GNU GRUB before 2013-11-12, as used in shlr/grub/fs/ext2.c in radare2 1.5.0, allows remote attackers to cause a denial of service (excessive stack use and application crash) via a crafted binary file, related to use of a variable-size stack array.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-119 \u2014 Improper Restriction of Operations within the Bounds of a Memory Buffer
The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Repository: https://github.com/radare/radare2
Files changed:
libr/core/cmd_mount.c
shlr/grub/fs/ext2.c
shlr/grub/fs/fshelp.c
shlr/grub/grubfs.c
sys/rebuild.sh
Commit message: Fix #7723 - crash in ext2 GRUB code because of variable size array in stack


Vulnerable code:
		if (input[0]==' ')
			if (!r_fs_mount (core->fs, ptr, input, off))
			if (!(ptr = r_fs_name (core->fs, core->offset)))
			else if (!r_fs_mount (core->fs, ptr, input, core->offset))
                          0, EXT2_BLOCK_SIZE(data), buf))
#ifndef _MSC_VER
	  char buf[EXT2_BLOCK_SIZE (data)];
#else
	  char * buf = grub_malloc (EXT2_BLOCK_SIZE(data));
#endif
          if (fileblock >= grub_le_to_cpu16 (ext[i].len))
          else
      if (! indir)
			  0, blksz, indir))
      if (! indir)
			  0, blksz, indir))
			  0, blksz, indir))
#ifndef _MSC_VER
	char fpath[grub_strlen (currpath) + 1];
#else
#endif
	  if (grub_errno)
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
	if (disk != NULL) {
		const int blocksize = 512; // unhardcode 512
		int ret;
		RIOBind *iob = disk->data;
		if (bio) iob = bio;
		//printf ("io %p\n", file->root->iob.io);
		ret = iob->read_at (iob->io, delta+(blocksize*sector),
			(ut8*)buf, size*blocksize);
		if (ret == -1)
			return 1;
		//printf ("DISK PTR = %p\n", disk->data);
		//printf ("\nBUF: %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
	} else eprintf ("oops. no disk\n");
	return 0; // 0 is ok
		if (gf->file && gf->file->device)
fs)     RebuildFs; ;;

Fixed code:
		if (input[0]==' ') {
		}
			if (!r_fs_mount (core->fs, ptr, input, off)) {
			}
			if (!(ptr = r_fs_name (core->fs, core->offset))) {
			} else if (!r_fs_mount (core->fs, ptr, input, core->offset)) {
			}
#include <stdlib.h>
                          0, EXT2_BLOCK_SIZE(data), buf)) {
      }
	  char * buf = grub_malloc (EXT2_BLOCK_SIZE (data));
          if (!buf) {
              return -1;
          }
	  free (buf);
          if (fileblock >= grub_le_to_cpu16 (ext[i].len)) {
  	    free (buf);
          } else
  	    free (buf);
  	    free (buf);
free (buf);
      if (! indir) {
}
			  0, blksz, indir)) {
}
      if (! indir) {
}
			  0, blksz, indir)) {
}
			  0, blksz, indir)) {
}
free (fpath);
free (fpath);
	  if (grub_errno) {
free (fpath);
}
free (fpath);
free (fpath);
free (fpath);
free (fpath);
free (fpath);
/* radare - LGPL - Copyright 2011-2017 pancake<nopcode.org> */
	if (!disk) {
		eprintf ("oops. no disk\n");
		return 1;
	}
	const int blocksize = 512; // TODO unhardcode 512
	RIOBind *iob = disk->data;
	if (bio) {
		iob = bio;
	}
	//printf ("io %p\n", file->root->iob.io);
	if (iob->read_at (iob->io, delta+(blocksize*sector), (ut8*)buf, size*blocksize) == -1) {
		return 1;
	}
	return 0;
		if (gf->file && gf->file->device) {
		}
grub|fs)RebuildFs; ;;