Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
grub2.19065
0005-malloc-Use-overflow-checking-primitives-wh...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0005-malloc-Use-overflow-checking-primitives-where-we-do-.patch of Package grub2.19065
From 790790798e8f0862d5ee64440acd424716030c86 Mon Sep 17 00:00:00 2001 From: Peter Jones <pjones@redhat.com> Date: Mon, 15 Jun 2020 12:28:27 -0400 Subject: [PATCH 5/7] 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> --- grub-core/commands/legacycfg.c | 29 +++++++++++++++---- grub-core/commands/wildcard.c | 36 ++++++++++++++++++++---- grub-core/disk/ldm.c | 32 +++++++++++++++------ grub-core/font/font.c | 7 ++++- grub-core/fs/btrfs.c | 28 +++++++++++++------ grub-core/fs/ext2.c | 10 ++++++- grub-core/fs/iso9660.c | 51 ++++++++++++++++++++++++---------- grub-core/fs/sfs.c | 27 ++++++++++++++---- grub-core/fs/squash4.c | 45 ++++++++++++++++++++++-------- grub-core/fs/udf.c | 41 +++++++++++++++++---------- grub-core/fs/xfs.c | 11 +++++--- grub-core/fs/zfs/zfs.c | 22 ++++++++++----- grub-core/fs/zfs/zfscrypt.c | 7 ++++- grub-core/lib/arg.c | 20 +++++++++++-- grub-core/loader/i386/bsd.c | 8 +++++- grub-core/net/dns.c | 9 +++++- grub-core/normal/charset.c | 10 +++++-- grub-core/normal/cmdline.c | 14 ++++++++-- grub-core/normal/menu_entry.c | 13 +++++++-- grub-core/script/argv.c | 16 +++++++++-- grub-core/script/lexer.c | 21 ++++++++++++-- grub-core/video/bitmap.c | 25 +++++++++++------ grub-core/video/readers/png.c | 13 +++++++-- 23 files changed, 382 insertions(+), 113 deletions(-) Index: grub-2.02/grub-core/commands/legacycfg.c =================================================================== --- grub-2.02.orig/grub-core/commands/legacycfg.c +++ grub-2.02/grub-core/commands/legacycfg.c @@ -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; Index: grub-2.02/grub-core/commands/wildcard.c =================================================================== --- grub-2.02.orig/grub-core/commands/wildcard.c +++ grub-2.02/grub-core/commands/wildcard.c @@ -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 cha 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, vo 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, vo 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; } Index: grub-2.02/grub-core/disk/ldm.c =================================================================== --- grub-2.02.orig/grub-core/disk/ldm.c +++ grub-2.02/grub-core/disk/ldm.c @@ -25,6 +25,7 @@ #include <grub/msdos_partition.h> #include <grub/gpt_partition.h> #include <grub/i18n.h> +#include <grub/safemath.h> #ifdef GRUB_UTIL #include <grub/emu/misc.h> @@ -289,6 +290,7 @@ make_vg (grub_disk_t disk, struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; + grub_size_t sz; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) @@ -350,7 +352,13 @@ make_vg (grub_disk_t disk, grub_free (lv); goto fail2; } - lv->name = grub_malloc (*ptr + 1); + if (grub_add (*ptr, 1, &sz)) + { + grub_free (lv->internal_id); + grub_free (lv); + goto fail2; + } + lv->name = grub_malloc (sz); if (!lv->name) { grub_free (lv->internal_id); @@ -599,10 +607,13 @@ make_vg (grub_disk_t disk, if (lv->segments->node_alloc == lv->segments->node_count) { void *t; - lv->segments->node_alloc *= 2; - t = grub_realloc (lv->segments->nodes, - sizeof (*lv->segments->nodes) - * lv->segments->node_alloc); + grub_size_t sz; + + if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) || + grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz)) + goto fail2; + + t = grub_realloc (lv->segments->nodes, sz); if (!t) goto fail2; lv->segments->nodes = t; @@ -723,10 +734,13 @@ make_vg (grub_disk_t disk, if (comp->segment_alloc == comp->segment_count) { void *t; - comp->segment_alloc *= 2; - t = grub_realloc (comp->segments, - comp->segment_alloc - * sizeof (*comp->segments)); + grub_size_t sz; + + if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) || + grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz)) + goto fail2; + + t = grub_realloc (comp->segments, sz); if (!t) goto fail2; comp->segments = t; Index: grub-2.02/grub-core/font/font.c =================================================================== --- grub-2.02.orig/grub-core/font/font.c +++ grub-2.02/grub-core/font/font.c @@ -30,6 +30,7 @@ #include <grub/unicode.h> #include <grub/fontformat.h> #include <grub/env.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -360,9 +361,13 @@ static char * read_section_as_string (struct font_file_section *section) { char *str; + grub_size_t sz; grub_ssize_t ret; - str = grub_malloc (section->length + 1); + if (grub_add (section->length, 1, &sz)) + return NULL; + + str = grub_malloc (sz); if (!str) return 0; Index: grub-2.02/grub-core/fs/btrfs.c =================================================================== --- grub-2.02.orig/grub-core/fs/btrfs.c +++ grub-2.02/grub-core/fs/btrfs.c @@ -33,6 +33,7 @@ #include <grub/env.h> #include <grub/extcmd.h> #include <grub/list.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -321,9 +322,13 @@ save_ref (struct grub_btrfs_leaf_descrip if (desc->allocated < desc->depth) { void *newdata; - desc->allocated *= 2; - newdata = grub_realloc (desc->data, sizeof (desc->data[0]) - * desc->allocated); + grub_size_t sz; + + if (grub_mul (desc->allocated, 2, &desc->allocated) || + grub_mul (desc->allocated, sizeof (desc->data[0]), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + newdata = grub_realloc (desc->data, sz); if (!newdata) return grub_errno; desc->data = newdata; @@ -618,15 +623,20 @@ find_device (struct grub_btrfs_data *dat if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - data->n_devices_allocated = 2 * data->n_devices_attached + 1; - data->devices_attached - = grub_realloc (tmp = data->devices_attached, - data->n_devices_allocated - * sizeof (data->devices_attached[0])); + grub_size_t sz; + + if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || + grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || + grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) + goto fail; + + data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); if (!data->devices_attached) { - grub_device_close (ctx.dev_found); data->devices_attached = tmp; + + fail: + grub_device_close (ctx.dev_found); return NULL; } } Index: grub-2.02/grub-core/fs/ext2.c =================================================================== --- grub-2.02.orig/grub-core/fs/ext2.c +++ grub-2.02/grub-core/fs/ext2.c @@ -46,6 +46,7 @@ #include <grub/dl.h> #include <grub/types.h> #include <grub/fshelp.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -700,6 +701,7 @@ grub_ext2_read_symlink (grub_fshelp_node { char *symlink; struct grub_fshelp_node *diro = node; + grub_size_t sz; if (! diro->inode_read) { @@ -708,7 +710,13 @@ grub_ext2_read_symlink (grub_fshelp_node return 0; } - symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1); + if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return NULL; + } + + symlink = grub_malloc (sz); if (! symlink) return 0; Index: grub-2.02/grub-core/fs/iso9660.c =================================================================== --- grub-2.02.orig/grub-core/fs/iso9660.c +++ grub-2.02/grub-core/fs/iso9660.c @@ -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_su { 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_no 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_no * 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); Index: grub-2.02/grub-core/fs/sfs.c =================================================================== --- grub-2.02.orig/grub-core/fs/sfs.c +++ grub-2.02/grub-core/fs/sfs.c @@ -26,6 +26,7 @@ #include <grub/types.h> #include <grub/fshelp.h> #include <grub/charset.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -307,10 +308,15 @@ grub_sfs_read_block (grub_fshelp_node_t if (node->cache && node->cache_size >= node->cache_allocated) { struct cache_entry *e = node->cache; - e = grub_realloc (node->cache,node->cache_allocated * 2 - * sizeof (e[0])); + grub_size_t sz; + + if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz)) + goto fail; + + e = grub_realloc (node->cache, sz); if (!e) { + fail: grub_errno = 0; grub_free (node->cache); node->cache = 0; @@ -477,10 +483,16 @@ grub_sfs_create_node (struct grub_fshelp grub_size_t len = grub_strlen (name); grub_uint8_t *name_u8; int ret; + grub_size_t sz; + + if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || + grub_add (sz, 1, &sz)) + return 1; + *node = grub_malloc (sizeof (**node)); if (!*node) return 1; - name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + name_u8 = grub_malloc (sz); if (!name_u8) { grub_free (*node); @@ -724,8 +736,13 @@ grub_sfs_label (grub_device_t device, ch data = grub_sfs_mount (disk); if (data) { - grub_size_t len = grub_strlen (data->label); - *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + grub_size_t sz, len = grub_strlen (data->label); + + if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || + grub_add (sz, 1, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + *label = grub_malloc (sz); if (*label) *grub_latin1_to_utf8 ((grub_uint8_t *) *label, (const grub_uint8_t *) data->label, Index: grub-2.02/grub-core/fs/squash4.c =================================================================== --- grub-2.02.orig/grub-core/fs/squash4.c +++ grub-2.02/grub-core/fs/squash4.c @@ -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_no { 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_nod { 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_nod { 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_nod 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_nod 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); Index: grub-2.02/grub-core/fs/udf.c =================================================================== --- grub-2.02.orig/grub-core/fs/udf.c +++ grub-2.02/grub-core/fs/udf.c @@ -28,6 +28,7 @@ #include <grub/charset.h> #include <grub/datetime.h> #include <grub/udf.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -853,9 +854,19 @@ read_string (const grub_uint8_t *raw, gr utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; } if (!outbuf) - outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); + { + grub_size_t size; + + if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) || + grub_add (size, 1, &size)) + goto fail; + + outbuf = grub_malloc (size); + } if (outbuf) *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0'; + + fail: grub_free (utf16); return outbuf; } @@ -949,7 +960,7 @@ grub_udf_read_symlink (grub_fshelp_node_ grub_size_t sz = U64 (node->block.fe.file_size); grub_uint8_t *raw; const grub_uint8_t *ptr; - char *out, *optr; + char *out = NULL, *optr; if (sz < 4) return NULL; @@ -957,14 +968,16 @@ grub_udf_read_symlink (grub_fshelp_node_ if (!raw) return NULL; if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) - { - grub_free (raw); - return NULL; - } + goto fail_1; - out = grub_malloc (sz * 2 + 1); + if (grub_mul (sz, 2, &sz) || + grub_add (sz, 1, &sz)) + goto fail_0; + + out = grub_malloc (sz); if (!out) { + fail_0: grub_free (raw); return NULL; } @@ -975,17 +988,17 @@ grub_udf_read_symlink (grub_fshelp_node_ { grub_size_t s; if ((grub_size_t) (ptr - raw + 4) > sz) - goto fail; + goto fail_1; if (!(ptr[2] == 0 && ptr[3] == 0)) - goto fail; + goto fail_1; s = 4 + ptr[1]; if ((grub_size_t) (ptr - raw + s) > sz) - goto fail; + goto fail_1; switch (*ptr) { case 1: if (ptr[1]) - goto fail; + goto fail_1; /* Fallthrough. */ case 2: /* in 4 bytes. out: 1 byte. */ @@ -1010,11 +1023,11 @@ grub_udf_read_symlink (grub_fshelp_node_ if (optr != out) *optr++ = '/'; if (!read_string (ptr + 4, s - 4, optr)) - goto fail; + goto fail_1; optr += grub_strlen (optr); break; default: - goto fail; + goto fail_1; } ptr += s; } @@ -1022,7 +1035,7 @@ grub_udf_read_symlink (grub_fshelp_node_ grub_free (raw); return out; - fail: + fail_1: grub_free (raw); grub_free (out); grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); Index: grub-2.02/grub-core/fs/xfs.c =================================================================== --- grub-2.02.orig/grub-core/fs/xfs.c +++ grub-2.02/grub-core/fs/xfs.c @@ -25,6 +25,7 @@ #include <grub/dl.h> #include <grub/types.h> #include <grub/fshelp.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -887,6 +888,7 @@ static struct grub_xfs_data * grub_xfs_mount (grub_disk_t disk) { struct grub_xfs_data *data = 0; + grub_size_t sz; data = grub_zalloc (sizeof (struct grub_xfs_data)); if (!data) @@ -901,10 +903,11 @@ grub_xfs_mount (grub_disk_t disk) if (!grub_xfs_sb_valid(data)) goto fail; - data = grub_realloc (data, - sizeof (struct grub_xfs_data) - - sizeof (struct grub_xfs_inode) - + grub_xfs_inode_size(data) + 1); + if (grub_add (grub_xfs_inode_size (data), + sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz)) + goto fail; + + data = grub_realloc (data, sz); if (! data) goto fail; Index: grub-2.02/grub-core/fs/zfs/zfs.c =================================================================== --- grub-2.02.orig/grub-core/fs/zfs/zfs.c +++ grub-2.02/grub-core/fs/zfs/zfs.c @@ -55,6 +55,7 @@ #include <grub/deflate.h> #include <grub/crypto.h> #include <grub/i18n.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -773,11 +774,14 @@ fill_vdev_info (struct grub_zfs_data *da if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - data->n_devices_allocated = 2 * data->n_devices_attached + 1; - data->devices_attached - = grub_realloc (tmp = data->devices_attached, - data->n_devices_allocated - * sizeof (data->devices_attached[0])); + grub_size_t sz; + + if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || + grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || + grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); if (!data->devices_attached) { data->devices_attached = tmp; @@ -3468,14 +3472,18 @@ grub_zfs_nvlist_lookup_nvlist (const cha { char *nvpair; char *ret; - grub_size_t size; + grub_size_t size, sz; int found; found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, &size, 0); if (!found) return 0; - ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t)); + + if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz)) + return 0; + + ret = grub_zalloc (sz); if (!ret) return 0; grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); Index: grub-2.02/grub-core/fs/zfs/zfscrypt.c =================================================================== --- grub-2.02.orig/grub-core/fs/zfs/zfscrypt.c +++ grub-2.02/grub-core/fs/zfs/zfscrypt.c @@ -22,6 +22,7 @@ #include <grub/misc.h> #include <grub/disk.h> #include <grub/partition.h> +#include <grub/safemath.h> #include <grub/dl.h> #include <grub/types.h> #include <grub/zfs/zfs.h> @@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in, int passphrase) { struct grub_zfs_wrap_key *key; + grub_size_t sz; + if (!passphrase && keylen > 32) keylen = 32; - key = grub_malloc (sizeof (*key) + keylen); + if (grub_add (sizeof (*key), keylen, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + key = grub_malloc (sz); if (!key) return grub_errno; key->is_passphrase = passphrase; Index: grub-2.02/grub-core/lib/arg.c =================================================================== --- grub-2.02.orig/grub-core/lib/arg.c +++ grub-2.02/grub-core/lib/arg.c @@ -23,6 +23,7 @@ #include <grub/term.h> #include <grub/extcmd.h> #include <grub/i18n.h> +#include <grub/safemath.h> /* Built-in parser for default options. */ static const struct grub_arg_option help_options[] = @@ -216,7 +217,13 @@ static inline grub_err_t add_arg (char ***argl, int *num, char *s) { char **p = *argl; - *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *)); + grub_size_t sz; + + if (grub_add (++(*num), 1, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + *argl = grub_realloc (*argl, sz); if (! *argl) { grub_free (p); @@ -431,6 +438,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd grub_size_t argcnt; struct grub_arg_list *list; const struct grub_arg_option *options; + grub_size_t sz0, sz1; options = extcmd->options; if (! options) @@ -443,7 +451,15 @@ grub_arg_list_alloc(grub_extcmd_t extcmd argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ } - list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); + if (grub_mul (sizeof (*list), i, &sz0) || + grub_mul (sizeof (char *), argcnt, &sz1) || + grub_add (sz0, sz1, &sz0)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return 0; + } + + list = grub_zalloc (sz0); if (! list) return 0; Index: grub-2.02/grub-core/loader/i386/bsd.c =================================================================== --- grub-2.02.orig/grub-core/loader/i386/bsd.c +++ grub-2.02/grub-core/loader/i386/bsd.c @@ -35,6 +35,7 @@ #include <grub/ns8250.h> #include <grub/bsdlabel.h> #include <grub/crypto.h> +#include <grub/safemath.h> #ifdef GRUB_MACHINE_PCBIOS #include <grub/machine/int.h> #endif @@ -1006,11 +1007,16 @@ grub_netbsd_add_modules (void) struct grub_netbsd_btinfo_modules *mods; unsigned i; grub_err_t err; + grub_size_t sz; for (mod = netbsd_mods; mod; mod = mod->next) modcnt++; - mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt); + if (grub_mul (modcnt, sizeof (mods->mods[0]), &sz) || + grub_add (sz, sizeof (*mods), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + mods = grub_malloc (sz); if (!mods) return grub_errno; Index: grub-2.02/grub-core/net/dns.c =================================================================== --- grub-2.02.orig/grub-core/net/dns.c +++ grub-2.02/grub-core/net/dns.c @@ -22,6 +22,7 @@ #include <grub/i18n.h> #include <grub/err.h> #include <grub/time.h> +#include <grub/safemath.h> struct dns_cache_element { @@ -51,9 +52,15 @@ grub_net_add_dns_server (const struct gr { int na = dns_servers_alloc * 2; struct grub_net_network_level_address *ns; + grub_size_t sz; + if (na < 8) na = 8; - ns = grub_realloc (dns_servers, na * sizeof (ns[0])); + + if (grub_mul (na, sizeof (ns[0]), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + ns = grub_realloc (dns_servers, sz); if (!ns) return grub_errno; dns_servers_alloc = na; Index: grub-2.02/grub-core/normal/charset.c =================================================================== --- grub-2.02.orig/grub-core/normal/charset.c +++ grub-2.02/grub-core/normal/charset.c @@ -48,6 +48,7 @@ #include <grub/unicode.h> #include <grub/term.h> #include <grub/normal.h> +#include <grub/safemath.h> #if HAVE_FONT_SOURCE #include "widthspec.h" @@ -464,6 +465,7 @@ grub_unicode_aglomerate_comb (const grub { struct grub_unicode_combining *n; unsigned j; + grub_size_t sz; if (!haveout) continue; @@ -477,10 +479,14 @@ grub_unicode_aglomerate_comb (const grub n = out->combining_inline; else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline)) { - n = grub_realloc (out->combining_ptr, - sizeof (n[0]) * (out->ncomb + 1)); + if (grub_add (out->ncomb, 1, &sz) || + grub_mul (sz, sizeof (n[0]), &sz)) + goto fail; + + n = grub_realloc (out->combining_ptr, sz); if (!n) { + fail: grub_errno = GRUB_ERR_NONE; continue; } Index: grub-2.02/grub-core/normal/cmdline.c =================================================================== --- grub-2.02.orig/grub-core/normal/cmdline.c +++ grub-2.02/grub-core/normal/cmdline.c @@ -28,6 +28,7 @@ #include <grub/env.h> #include <grub/i18n.h> #include <grub/charset.h> +#include <grub/safemath.h> static grub_uint32_t *kill_buf; @@ -307,12 +308,21 @@ cl_insert (struct cmdline_term *cl_terms if (len + (*llen) >= (*max_len)) { grub_uint32_t *nbuf; - (*max_len) *= 2; - nbuf = grub_realloc ((*buf), sizeof (grub_uint32_t) * (*max_len)); + grub_size_t sz; + + if (grub_mul (*max_len, 2, max_len) || + grub_mul (*max_len, sizeof (grub_uint32_t), &sz)) + { + grub_errno = GRUB_ERR_OUT_OF_RANGE; + goto fail; + } + + nbuf = grub_realloc ((*buf), sz); if (nbuf) (*buf) = nbuf; else { + fail: grub_print_error (); grub_errno = GRUB_ERR_NONE; (*max_len) /= 2; Index: grub-2.02/grub-core/normal/menu_entry.c =================================================================== --- grub-2.02.orig/grub-core/normal/menu_entry.c +++ grub-2.02/grub-core/normal/menu_entry.c @@ -27,6 +27,7 @@ #include <grub/auth.h> #include <grub/i18n.h> #include <grub/charset.h> +#include <grub/safemath.h> enum update_mode { @@ -113,10 +114,18 @@ ensure_space (struct line *linep, int ex { if (linep->max_len < linep->len + extra) { - linep->max_len = 2 * (linep->len + extra); - linep->buf = grub_realloc (linep->buf, (linep->max_len + 1) * sizeof (linep->buf[0])); + grub_size_t sz0, sz1; + + if (grub_add (linep->len, extra, &sz0) || + grub_mul (sz0, 2, &sz0) || + grub_add (sz0, 1, &sz1) || + grub_mul (sz1, sizeof (linep->buf[0]), &sz1)) + return 0; + + linep->buf = grub_realloc (linep->buf, sz1); if (! linep->buf) return 0; + linep->max_len = sz0; } return 1; Index: grub-2.02/grub-core/script/argv.c =================================================================== --- grub-2.02.orig/grub-core/script/argv.c +++ grub-2.02/grub-core/script/argv.c @@ -20,6 +20,7 @@ #include <grub/mm.h> #include <grub/misc.h> #include <grub/script_sh.h> +#include <grub/safemath.h> /* Return nearest power of two that is >= v. */ static unsigned @@ -81,11 +82,16 @@ int grub_script_argv_next (struct grub_script_argv *argv) { char **p = argv->args; + grub_size_t sz; if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) return 0; - p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); + if (grub_add (argv->argc, 2, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + return 1; + + p = grub_realloc (p, round_up_exp (sz)); if (! p) return 1; @@ -105,13 +111,19 @@ grub_script_argv_append (struct grub_scr { grub_size_t a; char *p = argv->args[argv->argc - 1]; + grub_size_t sz; if (! s) return 0; a = p ? grub_strlen (p) : 0; - p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char))); + if (grub_add (a, slen, &sz) || + grub_add (sz, 1, &sz) || + grub_mul (sz, sizeof (char), &sz)) + return 1; + + p = grub_realloc (p, round_up_exp (sz)); if (! p) return 1; Index: grub-2.02/grub-core/script/lexer.c =================================================================== --- grub-2.02.orig/grub-core/script/lexer.c +++ grub-2.02/grub-core/script/lexer.c @@ -24,6 +24,7 @@ #include <grub/mm.h> #include <grub/script_sh.h> #include <grub/i18n.h> +#include <grub/safemath.h> #define yytext_ptr char * #include "grub_script.tab.h" @@ -110,10 +111,14 @@ grub_script_lexer_record (struct grub_pa old = lexer->recording; if (lexer->recordlen < len) lexer->recordlen = len; - lexer->recordlen *= 2; + + if (grub_mul (lexer->recordlen, 2, &lexer->recordlen)) + goto fail; + lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); if (!lexer->recording) { + fail: grub_free (old); lexer->recordpos = 0; lexer->recordlen = 0; @@ -130,7 +135,7 @@ int grub_script_lexer_yywrap (struct grub_parser_param *parserstate, const char *input) { - grub_size_t len = 0; + grub_size_t len = 0, sz; char *p = 0; char *line = 0; YY_BUFFER_STATE buffer; @@ -168,12 +173,22 @@ grub_script_lexer_yywrap (struct grub_pa } else if (len && line[len - 1] != '\n') { - p = grub_realloc (line, len + 2); + if (grub_add (len, 2, &sz)) + { + grub_free (line); + grub_script_yyerror (parserstate, N_("overflow is detected")); + return 1; + } + + p = grub_realloc (line, sz); if (p) { p[len++] = '\n'; p[len] = '\0'; } + else + grub_free (line); + line = p; } Index: grub-2.02/grub-core/video/bitmap.c =================================================================== --- grub-2.02.orig/grub-core/video/bitmap.c +++ grub-2.02/grub-core/video/bitmap.c @@ -23,6 +23,7 @@ #include <grub/mm.h> #include <grub/misc.h> #include <grub/i18n.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,7 +59,7 @@ grub_video_bitmap_create (struct grub_vi enum grub_video_blit_format blit_format) { struct grub_video_mode_info *mode_info; - unsigned int size; + grub_size_t size; if (!bitmap) return grub_error (GRUB_ERR_BUG, "invalid argument"); @@ -137,19 +138,25 @@ grub_video_bitmap_create (struct grub_vi mode_info->pitch = width * mode_info->bytes_per_pixel; - /* Calculate size needed for the data. */ - size = (width * mode_info->bytes_per_pixel) * height; + /* Calculate size needed for the data. */ + if (grub_mul (width, mode_info->bytes_per_pixel, &size) || + grub_mul (size, height, &size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + goto fail; + } (*bitmap)->data = grub_zalloc (size); if (! (*bitmap)->data) - { - grub_free (*bitmap); - *bitmap = 0; - - return grub_errno; - } + goto fail; return GRUB_ERR_NONE; + + fail: + grub_free (*bitmap); + *bitmap = NULL; + + return grub_errno; } /* Frees all resources allocated by bitmap. */ Index: grub-2.02/grub-core/video/readers/png.c =================================================================== --- grub-2.02.orig/grub-core/video/readers/png.c +++ grub-2.02/grub-core/video/readers/png.c @@ -23,6 +23,7 @@ #include <grub/mm.h> #include <grub/misc.h> #include <grub/bufio.h> +#include <grub/safemath.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -301,9 +302,17 @@ grub_png_decode_image_header (struct gru data->bpp <<= 1; data->color_bits = color_bits; - data->row_bytes = data->image_width * data->bpp; + + if (grub_mul (data->image_width, data->bpp, &data->row_bytes)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + if (data->color_bits <= 4) - data->row_bytes = (data->image_width * data->color_bits + 7) / 8; + { + if (grub_mul (data->image_width, data->color_bits + 7, &data->row_bytes)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + data->row_bytes >>= 3; + } #ifndef GRUB_CPU_WORDS_BIGENDIAN if (data->is_16bit || data->is_gray || data->is_palette)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor