368 lines
11 KiB
Diff
368 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Alec Brown <alec.r.brown@oracle.com>
|
|
Date: Wed, 22 Jan 2025 02:55:09 +0000
|
|
Subject: [PATCH] disk: Use safe math macros to prevent overflows
|
|
|
|
Replace direct arithmetic operations with macros from include/grub/safemath.h
|
|
to prevent potential overflow issues when calculating the memory sizes.
|
|
|
|
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
grub-core/disk/cryptodisk.c | 36 ++++++++++++++++++------
|
|
grub-core/disk/diskfilter.c | 9 ++++--
|
|
grub-core/disk/ieee1275/ofdisk.c | 60 ++++++++++++++++++++++++++++++++++------
|
|
grub-core/disk/ldm.c | 37 +++++++++++++++++++++----
|
|
grub-core/disk/memdisk.c | 7 ++++-
|
|
5 files changed, 123 insertions(+), 26 deletions(-)
|
|
|
|
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
|
index 78a902515..871640685 100644
|
|
--- a/grub-core/disk/cryptodisk.c
|
|
+++ b/grub-core/disk/cryptodisk.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <grub/file.h>
|
|
#include <grub/procfs.h>
|
|
#include <grub/partition.h>
|
|
+#include <grub/safemath.h>
|
|
|
|
#ifdef GRUB_UTIL
|
|
#include <grub/emu/hostdisk.h>
|
|
@@ -1039,7 +1040,7 @@ static char *
|
|
luks_script_get (grub_size_t *sz)
|
|
{
|
|
grub_cryptodisk_t i;
|
|
- grub_size_t size = 0;
|
|
+ grub_size_t size = 0, mul;
|
|
char *ptr, *ret;
|
|
|
|
*sz = 0;
|
|
@@ -1047,16 +1048,33 @@ luks_script_get (grub_size_t *sz)
|
|
for (i = cryptodisk_list; i != NULL; i = i->next)
|
|
if (grub_strcmp (i->modname, "luks") == 0)
|
|
{
|
|
- size += sizeof ("luks_mount ");
|
|
- size += grub_strlen (i->uuid);
|
|
- size += grub_strlen (i->cipher->cipher->name);
|
|
- size += 54;
|
|
- if (i->essiv_hash)
|
|
- size += grub_strlen (i->essiv_hash->name);
|
|
- size += i->keysize * 2;
|
|
+ if (grub_add (size, grub_strlen (i->modname), &size) ||
|
|
+ grub_add (size, sizeof ("_mount") + 60, &size) ||
|
|
+ grub_add (size, grub_strlen (i->uuid), &size) ||
|
|
+ grub_add (size, grub_strlen (i->cipher->cipher->name), &size) ||
|
|
+ grub_mul (i->keysize, 2, &mul) ||
|
|
+ grub_add (size, mul, &size))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
|
+ return 0;
|
|
+ }
|
|
+ if (i->essiv_hash)
|
|
+ {
|
|
+ if (grub_add (size, grub_strlen (i->essiv_hash->name), &size))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
- ret = grub_malloc (size + 1);
|
|
+ if (grub_add (size, 1, &size))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ ret = grub_malloc (size);
|
|
if (!ret)
|
|
return 0;
|
|
|
|
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
|
|
index 2be019269..a881aa2c9 100644
|
|
--- a/grub-core/disk/diskfilter.c
|
|
+++ b/grub-core/disk/diskfilter.c
|
|
@@ -24,6 +24,7 @@
|
|
#include <grub/misc.h>
|
|
#include <grub/diskfilter.h>
|
|
#include <grub/partition.h>
|
|
+#include <grub/safemath.h>
|
|
#ifdef GRUB_UTIL
|
|
#include <grub/i18n.h>
|
|
#include <grub/util/misc.h>
|
|
@@ -1013,7 +1014,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
|
{
|
|
struct grub_diskfilter_vg *array;
|
|
int i;
|
|
- grub_size_t j;
|
|
+ grub_size_t j, sz;
|
|
grub_uint64_t totsize;
|
|
struct grub_diskfilter_pv *pv;
|
|
grub_err_t err;
|
|
@@ -1107,7 +1108,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
|
}
|
|
array->lvs->vg = array;
|
|
|
|
- array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
|
|
+ if (grub_mul (uuidlen, 2, &sz) ||
|
|
+ grub_add (sz, sizeof ("mduuid/"), &sz))
|
|
+ goto fail;
|
|
+
|
|
+ array->lvs->idname = grub_malloc (sz);
|
|
if (!array->lvs->idname)
|
|
goto fail;
|
|
|
|
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
|
|
index 98325ca98..c1b07d087 100644
|
|
--- a/grub-core/disk/ieee1275/ofdisk.c
|
|
+++ b/grub-core/disk/ieee1275/ofdisk.c
|
|
@@ -24,6 +24,7 @@
|
|
#include <grub/ieee1275/ofdisk.h>
|
|
#include <grub/i18n.h>
|
|
#include <grub/time.h>
|
|
+#include <grub/safemath.h>
|
|
|
|
static char *last_devpath;
|
|
static grub_ieee1275_ihandle_t last_ihandle;
|
|
@@ -80,6 +81,7 @@ ofdisk_hash_add_real (char *devpath)
|
|
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
|
|
const char *iptr;
|
|
char *optr;
|
|
+ grub_size_t sz;
|
|
|
|
p = grub_zalloc (sizeof (*p));
|
|
if (!p)
|
|
@@ -87,8 +89,14 @@ ofdisk_hash_add_real (char *devpath)
|
|
|
|
p->devpath = devpath;
|
|
|
|
- p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
|
|
- + 2 * grub_strlen (p->devpath));
|
|
+ if (grub_mul (grub_strlen (p->devpath), 2, &sz) ||
|
|
+ grub_add (sz, sizeof ("ieee1275/"), &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ p->grub_devpath = grub_malloc (sz);
|
|
|
|
if (!p->grub_devpath)
|
|
{
|
|
@@ -98,7 +106,13 @@ ofdisk_hash_add_real (char *devpath)
|
|
|
|
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
|
|
{
|
|
- p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
|
|
+ if (grub_add (grub_strlen (p->devpath), 3, &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of an open path"));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ p->open_path = grub_malloc (sz);
|
|
if (!p->open_path)
|
|
{
|
|
grub_free (p->grub_devpath);
|
|
@@ -224,7 +238,7 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
|
args;
|
|
char *buf, *bufptr;
|
|
unsigned i;
|
|
-
|
|
+ grub_size_t sz;
|
|
|
|
RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle)
|
|
if (! ihandle)
|
|
@@ -245,7 +259,14 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
|
return;
|
|
}
|
|
|
|
- buf = grub_malloc (grub_strlen (alias->path) + 32);
|
|
+ if (grub_add (grub_strlen (alias->path), 32, &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for vscsi");
|
|
+ grub_ieee1275_close (ihandle);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ buf = grub_malloc (sz);
|
|
if (!buf)
|
|
return;
|
|
bufptr = grub_stpcpy (buf, alias->path);
|
|
@@ -289,9 +310,15 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
|
grub_uint64_t *table;
|
|
grub_uint16_t table_size;
|
|
grub_ieee1275_ihandle_t ihandle;
|
|
+ grub_size_t sz;
|
|
|
|
- buf = grub_malloc (grub_strlen (alias->path) +
|
|
- sizeof ("/disk@7766554433221100"));
|
|
+ if (grub_add (grub_strlen (alias->path), sizeof ("/disk@7766554433221100"), &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for sas_ioa");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ buf = grub_malloc (sz);
|
|
if (!buf)
|
|
return;
|
|
bufptr = grub_stpcpy (buf, alias->path);
|
|
@@ -431,9 +458,17 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
|
static char *
|
|
compute_dev_path (const char *name)
|
|
{
|
|
- char *devpath = grub_malloc (grub_strlen (name) + 3);
|
|
+ char *devpath;
|
|
char *p, c;
|
|
+ grub_size_t sz;
|
|
|
|
+ if (grub_add (grub_strlen (name), 3, &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ devpath = grub_malloc (sz);
|
|
if (!devpath)
|
|
return NULL;
|
|
|
|
@@ -660,6 +695,7 @@ insert_bootpath (void)
|
|
char *bootpath;
|
|
grub_ssize_t bootpath_size;
|
|
char *type;
|
|
+ grub_size_t sz;
|
|
|
|
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
|
|
&bootpath_size)
|
|
@@ -670,7 +706,13 @@ insert_bootpath (void)
|
|
return;
|
|
}
|
|
|
|
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
|
|
+ if (grub_add (bootpath_size, 64, &sz))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining bootpath size"));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ bootpath = (char *) grub_malloc (sz);
|
|
if (! bootpath)
|
|
{
|
|
grub_print_error ();
|
|
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
|
|
index e82e9899f..973fbfdcb 100644
|
|
--- a/grub-core/disk/ldm.c
|
|
+++ b/grub-core/disk/ldm.c
|
|
@@ -220,6 +220,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)
|
|
@@ -251,7 +252,13 @@ make_vg (grub_disk_t disk,
|
|
grub_free (pv);
|
|
goto fail2;
|
|
}
|
|
- pv->internal_id = grub_malloc (ptr[0] + 2);
|
|
+ if (grub_add (ptr[0], 2, &sz))
|
|
+ {
|
|
+ grub_free (pv);
|
|
+ goto fail2;
|
|
+ }
|
|
+
|
|
+ pv->internal_id = grub_malloc (sz);
|
|
if (!pv->internal_id)
|
|
{
|
|
grub_free (pv);
|
|
@@ -276,7 +283,15 @@ make_vg (grub_disk_t disk,
|
|
goto fail2;
|
|
}
|
|
pv->id.uuidlen = *ptr;
|
|
- pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
|
|
+
|
|
+ if (grub_add (pv->id.uuidlen, 1, &sz))
|
|
+ {
|
|
+ grub_free (pv->internal_id);
|
|
+ grub_free (pv);
|
|
+ goto fail2;
|
|
+ }
|
|
+
|
|
+ pv->id.uuid = grub_malloc (sz);
|
|
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
|
pv->id.uuid[pv->id.uuidlen] = 0;
|
|
|
|
@@ -343,7 +358,13 @@ make_vg (grub_disk_t disk,
|
|
grub_free (lv);
|
|
goto fail2;
|
|
}
|
|
- lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
|
+ if (grub_add (ptr[0], 2, &sz))
|
|
+ {
|
|
+ grub_free (lv->segments);
|
|
+ grub_free (lv);
|
|
+ goto fail2;
|
|
+ }
|
|
+ lv->internal_id = grub_malloc (sz);
|
|
if (!lv->internal_id)
|
|
{
|
|
grub_free (lv);
|
|
@@ -455,6 +476,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)
|
|
@@ -489,7 +511,13 @@ make_vg (grub_disk_t disk,
|
|
{
|
|
goto fail2;
|
|
}
|
|
- comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
|
+ if (grub_add (ptr[0], 2, &sz))
|
|
+ {
|
|
+ grub_free (comp);
|
|
+ goto fail2;
|
|
+ }
|
|
+ comp->internal_id = grub_malloc (sz);
|
|
+
|
|
if (!comp->internal_id)
|
|
{
|
|
grub_free (comp);
|
|
@@ -639,7 +667,6 @@ make_vg (grub_disk_t disk,
|
|
if (lv->segments->node_alloc == lv->segments->node_count)
|
|
{
|
|
void *t;
|
|
- 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))
|
|
diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c
|
|
index e5ffc01bf..18863305e 100644
|
|
--- a/grub-core/disk/memdisk.c
|
|
+++ b/grub-core/disk/memdisk.c
|
|
@@ -23,6 +23,7 @@
|
|
#include <grub/misc.h>
|
|
#include <grub/mm.h>
|
|
#include <grub/types.h>
|
|
+#include <grub/safemath.h>
|
|
|
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
|
@@ -96,7 +97,11 @@ GRUB_MOD_INIT(memdisk)
|
|
|
|
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
|
|
|
- memdisk_size = header->size - sizeof (struct grub_module_header);
|
|
+ if (grub_sub (header->size, sizeof (struct grub_module_header), &memdisk_size))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while obtaining memdisk size");
|
|
+ return;
|
|
+ }
|
|
memdisk_addr = grub_malloc (memdisk_size);
|
|
|
|
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|