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
|
@ -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;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <grub/file.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/safemath.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
|
@ -48,6 +49,7 @@ merge (char **dest, char **ps)
|
|||
int i;
|
||||
int j;
|
||||
char **p;
|
||||
grub_size_t sz;
|
||||
|
||||
if (! dest)
|
||||
return ps;
|
||||
|
@ -60,7 +62,12 @@ merge (char **dest, char **ps)
|
|||
for (j = 0; ps[j]; j++)
|
||||
;
|
||||
|
||||
p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
|
||||
if (grub_add (i, j, &sz) ||
|
||||
grub_add (sz, 1, &sz) ||
|
||||
grub_mul (sz, sizeof (char *), &sz))
|
||||
return dest;
|
||||
|
||||
p = grub_realloc (dest, sz);
|
||||
if (! p)
|
||||
{
|
||||
grub_free (dest);
|
||||
|
@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp)
|
|||
char ch;
|
||||
int i = 0;
|
||||
unsigned len = end - start;
|
||||
char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
|
||||
char *buffer;
|
||||
grub_size_t sz;
|
||||
|
||||
/* Worst case size is (len * 2 + 2 + 1). */
|
||||
if (grub_mul (len, 2, &sz) ||
|
||||
grub_add (sz, 3, &sz))
|
||||
return 1;
|
||||
|
||||
buffer = grub_malloc (sz);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
|
@ -226,6 +240,7 @@ match_devices_iter (const char *name, void *data)
|
|||
struct match_devices_ctx *ctx = data;
|
||||
char **t;
|
||||
char *buffer;
|
||||
grub_size_t sz;
|
||||
|
||||
/* skip partitions if asked to. */
|
||||
if (ctx->noparts && grub_strchr (name, ','))
|
||||
|
@ -239,11 +254,16 @@ match_devices_iter (const char *name, void *data)
|
|||
if (regexec (ctx->regexp, buffer, 0, 0, 0))
|
||||
{
|
||||
grub_dprintf ("expand", "not matched\n");
|
||||
fail:
|
||||
grub_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
|
||||
if (grub_add (ctx->ndev, 2, &sz) ||
|
||||
grub_mul (sz, sizeof (char *), &sz))
|
||||
goto fail;
|
||||
|
||||
t = grub_realloc (ctx->devs, sz);
|
||||
if (! t)
|
||||
{
|
||||
grub_free (buffer);
|
||||
|
@ -300,6 +320,7 @@ match_files_iter (const char *name,
|
|||
struct match_files_ctx *ctx = data;
|
||||
char **t;
|
||||
char *buffer;
|
||||
grub_size_t sz;
|
||||
|
||||
/* skip . and .. names */
|
||||
if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
|
||||
|
@ -315,9 +336,14 @@ match_files_iter (const char *name,
|
|||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2));
|
||||
if (! t)
|
||||
if (grub_add (ctx->nfile, 2, &sz) ||
|
||||
grub_mul (sz, sizeof (char *), &sz))
|
||||
goto fail;
|
||||
|
||||
t = grub_realloc (ctx->files, sz);
|
||||
if (!t)
|
||||
{
|
||||
fail:
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue