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:
Peter Jones authored and Daniel Kiper committed 2020-07-29 16:55:47 +02:00
1 parent f725fa7cb2
commit 3f05d693d1
23 files changed
+382 -113

No files matched your search

+24 -5
View File
@@ -32,6 +32,7 @@
#include <grub/auth.h>
#include <grub/disk.h>
#include <grub/partition.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -104,13 +105,22 @@ legacy_file (const char *filename)
if (newsuffix)
{
char *t;
grub_size_t sz;
if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) ||
grub_add (sz, 1, &sz))
{
grub_errno = GRUB_ERR_OUT_OF_RANGE;
goto fail_0;
}
t = suffix;
suffix = grub_realloc (suffix, grub_strlen (suffix)
+ grub_strlen (newsuffix) + 1);
suffix = grub_realloc (suffix, sz);
if (!suffix)
{
grub_free (t);
fail_0:
grub_free (entrysrc);
grub_free (parsed);
grub_free (newsuffix);
@@ -154,13 +164,22 @@ legacy_file (const char *filename)
else
{
char *t;
grub_size_t sz;
if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) ||
grub_add (sz, 1, &sz))
{
grub_errno = GRUB_ERR_OUT_OF_RANGE;
goto fail_1;
}
t = entrysrc;
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
+ grub_strlen (parsed) + 1);
entrysrc = grub_realloc (entrysrc, sz);
if (!entrysrc)
{
grub_free (t);
fail_1:
grub_free (parsed);
grub_free (suffix);
return grub_errno;