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

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