Fix #7723 - crash in ext2 GRUB code because of variable size array in stack

This commit is contained in:
pancake 2017-06-12 09:57:30 +02:00
parent ba25be4934
commit 65000a7fd9
5 changed files with 59 additions and 39 deletions

View File

@ -35,8 +35,9 @@ static int cmd_mount(void *data, const char *_input) {
switch (*input) {
case ' ':
input++;
if (input[0]==' ')
if (input[0]==' ') {
input++;
}
ptr = strchr (input, ' ');
if (ptr) {
*ptr = 0;
@ -46,13 +47,15 @@ static int cmd_mount(void *data, const char *_input) {
*ptr2 = 0;
off = r_num_math (core->num, ptr2+1);
}
if (!r_fs_mount (core->fs, ptr, input, off))
if (!r_fs_mount (core->fs, ptr, input, off)) {
eprintf ("Cannot mount %s\n", input);
}
} else {
if (!(ptr = r_fs_name (core->fs, core->offset)))
if (!(ptr = r_fs_name (core->fs, core->offset))) {
eprintf ("Unknown filesystem type\n");
else if (!r_fs_mount (core->fs, ptr, input, core->offset))
} else if (!r_fs_mount (core->fs, ptr, input, core->offset)) {
eprintf ("Cannot mount %s\n", input);
}
free (ptr);
}
break;

View File

@ -42,6 +42,7 @@
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
#include <stdlib.h>
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
@ -367,8 +368,9 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf,
block = (block << 32) + grub_le_to_cpu32 (index[i].leaf);
if (grub_disk_read (data->disk,
block << LOG2_EXT2_BLOCK_SIZE (data),
0, EXT2_BLOCK_SIZE(data), buf))
0, EXT2_BLOCK_SIZE(data), buf)) {
return 0;
}
ext_block = (struct grub_ext4_extent_header *) buf;
}
@ -385,11 +387,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG)
{
#ifndef _MSC_VER
char buf[EXT2_BLOCK_SIZE (data)];
#else
char * buf = grub_malloc (EXT2_BLOCK_SIZE(data));
#endif
char * buf = grub_malloc (EXT2_BLOCK_SIZE (data));
if (!buf) {
return -1;
}
struct grub_ext4_extent_header *leaf;
struct grub_ext4_extent *ext;
int i;
@ -400,6 +401,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
if (! leaf)
{
grub_error (GRUB_ERR_BAD_FS, "invalid extent");
free (buf);
return -1;
}
@ -413,14 +415,16 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
if (--i >= 0)
{
fileblock -= grub_le_to_cpu32 (ext[i].block);
if (fileblock >= grub_le_to_cpu16 (ext[i].len))
if (fileblock >= grub_le_to_cpu16 (ext[i].len)) {
free (buf);
return 0;
else
} else
{
grub_disk_addr_t start;
start = grub_le_to_cpu16 (ext[i].start_hi);
start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
free (buf);
return fileblock + start;
}
@ -428,8 +432,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
else
{
grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
free (buf);
return -1;
}
free (buf);
}
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS) {
@ -440,15 +446,17 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_uint32_t *indir;
indir = grub_malloc (blksz);
if (! indir)
if (! indir) {
return grub_errno;
}
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.indir_block))
<< log2_blksz,
0, blksz, indir))
0, blksz, indir)) {
return grub_errno;
}
blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
grub_free (indir);
@ -463,22 +471,25 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_uint32_t *indir;
indir = grub_malloc (blksz);
if (! indir)
if (! indir) {
return grub_errno;
}
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.double_indir_block))
<< log2_blksz,
0, blksz, indir))
0, blksz, indir)) {
return grub_errno;
}
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[rblock / perblock]))
<< log2_blksz,
0, blksz, indir))
0, blksz, indir)) {
return grub_errno;
}
blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
grub_free (indir);

View File

@ -91,11 +91,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
grub_fshelp_node_t *currfound,
struct grub_fshelp_find_file_closure *c)
{
#ifndef _MSC_VER
char fpath[grub_strlen (currpath) + 1];
#else
char *fpath = grub_malloc (grub_strlen (currpath) + 1);
#endif
char *name = fpath;
char *next;
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
@ -113,6 +109,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
if (! *name)
{
*currfound = currnode;
free (fpath);
return 0;
}
@ -135,6 +132,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
if (type != GRUB_FSHELP_DIR)
{
free_node (currnode, c);
free (fpath);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
}
@ -146,8 +144,10 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
found = c->iterate_dir (currnode, iterate, &cc);
if (! found)
{
if (grub_errno)
if (grub_errno) {
free (fpath);
return grub_errno;
}
break;
}
@ -162,6 +162,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
{
free_node (currnode, c);
free_node (oldnode, c);
free (fpath);
return grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
}
@ -172,6 +173,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
if (!symlink)
{
free_node (oldnode, c);
free (fpath);
return grub_errno;
}
@ -190,6 +192,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
if (grub_errno)
{
free_node (oldnode, c);
free (fpath);
return grub_errno;
}
}
@ -201,12 +204,14 @@ find_file (const char *currpath, grub_fshelp_node_t currroot,
{
*currfound = currnode;
c->foundtype = type;
free (fpath);
return 0;
}
name = next;
}
free (fpath);
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
}

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
/* radare - LGPL - Copyright 2011-2017 pancake<nopcode.org> */
#include <r_io.h>
#include <r_fs.h>
@ -17,20 +17,20 @@ static void* empty (int sz) {
}
static grub_err_t read_foo (struct grub_disk *disk, grub_disk_addr_t sector, grub_size_t size, char *buf) {
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 (!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;
}
GrubFS *grubfs_new (struct grub_fs *myfs, void *data) {
@ -58,8 +58,9 @@ grub_disk_t grubfs_disk (void *data) {
void grubfs_free (GrubFS *gf) {
if (gf) {
if (gf->file && gf->file->device)
if (gf->file && gf->file->device) {
free (gf->file->device->disk);
}
//free (gf->file->device);
free (gf->file);
free (gf);

View File

@ -72,7 +72,7 @@ RebuildGdb() {
}
case "$1" in
fs) RebuildFs; ;;
grub|fs)RebuildFs; ;;
bin) RebuildBin ; ;;
gdb) RebuildGdb ; ;;
sdb) RebuildSdb ; ;;