Fix #7723 - crash in ext2 GRUB code because of variable size array in stack
This commit is contained in:
parent
ba25be4934
commit
65000a7fd9
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -72,7 +72,7 @@ RebuildGdb() {
|
|||
}
|
||||
|
||||
case "$1" in
|
||||
fs) RebuildFs; ;;
|
||||
grub|fs)RebuildFs; ;;
|
||||
bin) RebuildBin ; ;;
|
||||
gdb) RebuildGdb ; ;;
|
||||
sdb) RebuildSdb ; ;;
|
||||
|
|
Loading…
Reference in New Issue