|
|
9723a8 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
c294fc |
From: Peter Jones <pjones@redhat.com>
|
|
|
c294fc |
Date: Sun, 19 Jul 2020 15:48:20 -0400
|
|
|
9723a8 |
Subject: [PATCH] lvm: fix two more potential data-dependent alloc overflows
|
|
|
c294fc |
|
|
|
c294fc |
It appears to be possible to make a (possibly invalid) lvm PV with a
|
|
|
c294fc |
metadata size field that overflows our type when adding it to the
|
|
|
c294fc |
address we've allocated. Even if it doesn't, it may be possible to do
|
|
|
c294fc |
so with the math using the outcome of that as an operand. Check them
|
|
|
c294fc |
both.
|
|
|
c294fc |
|
|
|
c294fc |
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
|
c294fc |
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
|
|
c294fc |
Upstream-commit-id: 45ec6046ea0
|
|
|
c294fc |
---
|
|
|
9723a8 |
grub-core/disk/lvm.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
|
|
|
c294fc |
1 file changed, 40 insertions(+), 8 deletions(-)
|
|
|
c294fc |
|
|
|
c294fc |
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
|
|
c294fc |
index d1df640b311..ca09d469990 100644
|
|
|
c294fc |
--- a/grub-core/disk/lvm.c
|
|
|
c294fc |
+++ b/grub-core/disk/lvm.c
|
|
|
c294fc |
@@ -25,6 +25,7 @@
|
|
|
c294fc |
#include <grub/lvm.h>
|
|
|
c294fc |
#include <grub/partition.h>
|
|
|
c294fc |
#include <grub/i18n.h>
|
|
|
c294fc |
+#include <grub/safemath.h>
|
|
|
c294fc |
|
|
|
c294fc |
#ifdef GRUB_UTIL
|
|
|
c294fc |
#include <grub/emu/misc.h>
|
|
|
c294fc |
@@ -102,10 +103,12 @@ grub_lvm_detect (grub_disk_t disk,
|
|
|
c294fc |
{
|
|
|
c294fc |
grub_err_t err;
|
|
|
c294fc |
grub_uint64_t mda_offset, mda_size;
|
|
|
c294fc |
+ grub_size_t ptr;
|
|
|
c294fc |
char buf[GRUB_LVM_LABEL_SIZE];
|
|
|
c294fc |
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
|
|
c294fc |
char pv_id[GRUB_LVM_ID_STRLEN+1];
|
|
|
c294fc |
- char *metadatabuf, *p, *q, *vgname;
|
|
|
c294fc |
+ char *metadatabuf, *mda_end, *vgname;
|
|
|
c294fc |
+ char *p, *q;
|
|
|
c294fc |
struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
|
|
|
c294fc |
struct grub_lvm_pv_header *pvh;
|
|
|
c294fc |
struct grub_lvm_disk_locn *dlocn;
|
|
|
c294fc |
@@ -205,19 +208,31 @@ grub_lvm_detect (grub_disk_t disk,
|
|
|
c294fc |
grub_le_to_cpu64 (rlocn->size) -
|
|
|
c294fc |
grub_le_to_cpu64 (mdah->size));
|
|
|
c294fc |
}
|
|
|
c294fc |
- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
|
|
|
c294fc |
|
|
|
c294fc |
- while (*q != ' ' && q < metadatabuf + mda_size)
|
|
|
c294fc |
- q++;
|
|
|
c294fc |
-
|
|
|
c294fc |
- if (q == metadatabuf + mda_size)
|
|
|
c294fc |
+ if (grub_add ((grub_size_t)metadatabuf,
|
|
|
c294fc |
+ (grub_size_t)grub_le_to_cpu64 (rlocn->offset),
|
|
|
c294fc |
+ &ptr))
|
|
|
c294fc |
{
|
|
|
c294fc |
+error_parsing_metadata:
|
|
|
c294fc |
#ifdef GRUB_UTIL
|
|
|
c294fc |
grub_util_info ("error parsing metadata");
|
|
|
c294fc |
#endif
|
|
|
c294fc |
goto fail2;
|
|
|
c294fc |
}
|
|
|
c294fc |
|
|
|
c294fc |
+ p = q = (char *)ptr;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
|
|
|
c294fc |
+ goto error_parsing_metadata;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ mda_end = (char *)ptr;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ while (*q != ' ' && q < mda_end)
|
|
|
c294fc |
+ q++;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ if (q == mda_end)
|
|
|
c294fc |
+ goto error_parsing_metadata;
|
|
|
c294fc |
+
|
|
|
c294fc |
vgname_len = q - p;
|
|
|
c294fc |
vgname = grub_malloc (vgname_len + 1);
|
|
|
c294fc |
if (!vgname)
|
|
|
c294fc |
@@ -367,8 +382,25 @@ grub_lvm_detect (grub_disk_t disk,
|
|
|
c294fc |
{
|
|
|
c294fc |
const char *iptr;
|
|
|
c294fc |
char *optr;
|
|
|
c294fc |
- lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
|
|
|
c294fc |
- + 1 + 2 * s + 1);
|
|
|
c294fc |
+
|
|
|
c294fc |
+ /* this is kind of hard to read with our safe (but rather
|
|
|
c294fc |
+ * baroque) math primatives, but it boils down to:
|
|
|
c294fc |
+ *
|
|
|
c294fc |
+ * sz0 = vgname_len * 2 + 1
|
|
|
c294fc |
+ * + s * 2 + 1
|
|
|
c294fc |
+ * + sizeof ("lvm/") - 1;
|
|
|
c294fc |
+ */
|
|
|
c294fc |
+ grub_size_t sz0 = vgname_len, sz1 = s;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ if (grub_mul (sz0, 2, &sz0) ||
|
|
|
c294fc |
+ grub_add (sz0, 1, &sz0) ||
|
|
|
c294fc |
+ grub_mul (sz1, 2, &sz1) ||
|
|
|
c294fc |
+ grub_add (sz1, 1, &sz1) ||
|
|
|
c294fc |
+ grub_add (sz0, sz1, &sz0) ||
|
|
|
c294fc |
+ grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
|
|
|
c294fc |
+ goto lvs_fail;
|
|
|
c294fc |
+
|
|
|
c294fc |
+ lv->fullname = grub_malloc (sz0);
|
|
|
c294fc |
if (!lv->fullname)
|
|
|
c294fc |
goto lvs_fail;
|
|
|
c294fc |
|