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

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