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