malloc: Use overflow checking primitives where we do complex allocations
This attempts to fix the places where we do the following where arithmetic_expr may include unvalidated data: X = grub_malloc(arithmetic_expr); It accomplishes this by doing the arithmetic ahead of time using grub_add(), grub_sub(), grub_mul() and testing for overflow before proceeding. Among other issues, this fixes: - allocation of integer overflow in grub_video_bitmap_create() reported by Chris Coulson, - allocation of integer overflow in grub_png_decode_image_header() reported by Chris Coulson, - allocation of integer overflow in grub_squash_read_symlink() reported by Chris Coulson, - allocation of integer overflow in grub_ext2_read_symlink() reported by Chris Coulson, - allocation of integer overflow in read_section_as_string() reported by Chris Coulson. Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311 Signed-off-by: Peter Jones <pjones@redhat.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
f725fa7cb2
commit
3f05d693d1
23 changed files with 382 additions and 113 deletions
|
@ -26,6 +26,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/deflate.h>
|
||||
#include <grub/safemath.h>
|
||||
#include <minilzo.h>
|
||||
|
||||
#include "xz.h"
|
||||
|
@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
|
|||
{
|
||||
char *ret;
|
||||
grub_err_t err;
|
||||
ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
|
||||
grub_size_t sz;
|
||||
|
||||
if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = grub_malloc (sz);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
err = read_chunk (node->data, ret,
|
||||
grub_le_to_cpu32 (node->ino.symlink.namelen),
|
||||
|
@ -506,11 +517,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
{
|
||||
grub_fshelp_node_t node;
|
||||
node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
grub_size_t sz;
|
||||
|
||||
if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
|
||||
grub_add (sz, sizeof (*node), &sz))
|
||||
return 0;
|
||||
|
||||
node = grub_malloc (sz);
|
||||
if (!node)
|
||||
return 0;
|
||||
grub_memcpy (node, dir,
|
||||
sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
grub_memcpy (node, dir, sz);
|
||||
if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
|
||||
return 1;
|
||||
|
||||
|
@ -518,12 +534,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
{
|
||||
grub_err_t err;
|
||||
|
||||
node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
|
||||
grub_add (sz, sizeof (*node), &sz))
|
||||
return 0;
|
||||
|
||||
node = grub_malloc (sz);
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
grub_memcpy (node, dir,
|
||||
sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
grub_memcpy (node, dir, sz);
|
||||
|
||||
node->stsize--;
|
||||
err = read_chunk (dir->data, &node->ino, sizeof (node->ino),
|
||||
|
@ -557,6 +576,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG;
|
||||
struct grub_squash_dirent di;
|
||||
struct grub_squash_inode ino;
|
||||
grub_size_t sz;
|
||||
|
||||
err = read_chunk (dir->data, &di, sizeof (di),
|
||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||
|
@ -589,13 +609,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
|
||||
filetype = GRUB_FSHELP_SYMLINK;
|
||||
|
||||
node = grub_malloc (sizeof (*node)
|
||||
+ (dir->stsize + 1) * sizeof (dir->stack[0]));
|
||||
if (grub_add (dir->stsize, 1, &sz) ||
|
||||
grub_mul (sz, sizeof (dir->stack[0]), &sz) ||
|
||||
grub_add (sz, sizeof (*node), &sz))
|
||||
return 0;
|
||||
|
||||
node = grub_malloc (sz);
|
||||
if (! node)
|
||||
return 0;
|
||||
|
||||
grub_memcpy (node, dir,
|
||||
sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
|
||||
grub_memcpy (node, dir, sz - sizeof(dir->stack[0]));
|
||||
|
||||
node->ino = ino;
|
||||
node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue