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

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