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
|
@ -28,6 +28,7 @@
|
|||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -531,8 +532,13 @@ add_part (struct iterate_dir_ctx *ctx,
|
|||
int len2)
|
||||
{
|
||||
int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
|
||||
grub_size_t sz;
|
||||
|
||||
ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1);
|
||||
if (grub_add (size, len2, &sz) ||
|
||||
grub_add (sz, 1, &sz))
|
||||
return;
|
||||
|
||||
ctx->symlink = grub_realloc (ctx->symlink, sz);
|
||||
if (! ctx->symlink)
|
||||
return;
|
||||
|
||||
|
@ -560,17 +566,24 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
|||
{
|
||||
grub_size_t off = 0, csize = 1;
|
||||
char *old;
|
||||
grub_size_t sz;
|
||||
|
||||
csize = entry->len - 5;
|
||||
old = ctx->filename;
|
||||
if (ctx->filename_alloc)
|
||||
{
|
||||
off = grub_strlen (ctx->filename);
|
||||
ctx->filename = grub_realloc (ctx->filename, csize + off + 1);
|
||||
if (grub_add (csize, off, &sz) ||
|
||||
grub_add (sz, 1, &sz))
|
||||
return GRUB_ERR_OUT_OF_RANGE;
|
||||
ctx->filename = grub_realloc (ctx->filename, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
off = 0;
|
||||
ctx->filename = grub_zalloc (csize + 1);
|
||||
if (grub_add (csize, 1, &sz))
|
||||
return GRUB_ERR_OUT_OF_RANGE;
|
||||
ctx->filename = grub_zalloc (sz);
|
||||
}
|
||||
if (!ctx->filename)
|
||||
{
|
||||
|
@ -776,14 +789,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (node->have_dirents >= node->alloc_dirents)
|
||||
{
|
||||
struct grub_fshelp_node *new_node;
|
||||
node->alloc_dirents *= 2;
|
||||
new_node = grub_realloc (node,
|
||||
sizeof (struct grub_fshelp_node)
|
||||
+ ((node->alloc_dirents
|
||||
- ARRAY_SIZE (node->dirents))
|
||||
* sizeof (node->dirents[0])));
|
||||
grub_size_t sz;
|
||||
|
||||
if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) ||
|
||||
grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
|
||||
grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
|
||||
grub_add (sz, sizeof (struct grub_fshelp_node), &sz))
|
||||
goto fail_0;
|
||||
|
||||
new_node = grub_realloc (node, sz);
|
||||
if (!new_node)
|
||||
{
|
||||
fail_0:
|
||||
if (ctx.filename_alloc)
|
||||
grub_free (ctx.filename);
|
||||
grub_free (node);
|
||||
|
@ -799,14 +816,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
* sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1)
|
||||
{
|
||||
struct grub_fshelp_node *new_node;
|
||||
new_node = grub_realloc (node,
|
||||
sizeof (struct grub_fshelp_node)
|
||||
+ ((node->alloc_dirents
|
||||
- ARRAY_SIZE (node->dirents))
|
||||
* sizeof (node->dirents[0]))
|
||||
+ grub_strlen (ctx.symlink) + 1);
|
||||
grub_size_t sz;
|
||||
|
||||
if (grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
|
||||
grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
|
||||
grub_add (sz, sizeof (struct grub_fshelp_node) + 1, &sz) ||
|
||||
grub_add (sz, grub_strlen (ctx.symlink), &sz))
|
||||
goto fail_1;
|
||||
|
||||
new_node = grub_realloc (node, sz);
|
||||
if (!new_node)
|
||||
{
|
||||
fail_1:
|
||||
if (ctx.filename_alloc)
|
||||
grub_free (ctx.filename);
|
||||
grub_free (node);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue