dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

Blame SOURCES/0301-lvm-fix-two-more-potential-data-dependent-alloc-over.patch

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