1From a1845e90fc19fb5e904091bad8a378f458798e4a Mon Sep 17 00:00:00 2001 2From: Peter Jones <pjones@redhat.com> 3Date: Sun, 19 Jul 2020 15:48:20 -0400 4Subject: [PATCH] lvm: Fix two more potential data-dependent alloc 5 overflows 6MIME-Version: 1.0 7Content-Type: text/plain; charset=UTF-8 8Content-Transfer-Encoding: 8bit 9 10It appears to be possible to make a (possibly invalid) lvm PV with 11a metadata size field that overflows our type when adding it to the 12address we've allocated. Even if it doesn't, it may be possible to do so 13with the math using the outcome of that as an operand. Check them both. 14 15Signed-off-by: Peter Jones <pjones@redhat.com> 16Signed-off-by: Darren Kenny <darren.kenny@oracle.com> 17Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 18Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 19--- 20 grub-core/disk/lvm.c | 48 ++++++++++++++++++++++++++++++++++++-------- 21 1 file changed, 40 insertions(+), 8 deletions(-) 22 23diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c 24index d1df640b3..139fafd47 100644 25--- a/grub-core/disk/lvm.c 26+++ b/grub-core/disk/lvm.c 27@@ -25,6 +25,7 @@ 28 #include <grub/lvm.h> 29 #include <grub/partition.h> 30 #include <grub/i18n.h> 31+#include <grub/safemath.h> 32 33 #ifdef GRUB_UTIL 34 #include <grub/emu/misc.h> 35@@ -102,10 +103,11 @@ grub_lvm_detect (grub_disk_t disk, 36 { 37 grub_err_t err; 38 grub_uint64_t mda_offset, mda_size; 39+ grub_size_t ptr; 40 char buf[GRUB_LVM_LABEL_SIZE]; 41 char vg_id[GRUB_LVM_ID_STRLEN+1]; 42 char pv_id[GRUB_LVM_ID_STRLEN+1]; 43- char *metadatabuf, *p, *q, *vgname; 44+ char *metadatabuf, *p, *q, *mda_end, *vgname; 45 struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf; 46 struct grub_lvm_pv_header *pvh; 47 struct grub_lvm_disk_locn *dlocn; 48@@ -205,19 +207,31 @@ grub_lvm_detect (grub_disk_t disk, 49 grub_le_to_cpu64 (rlocn->size) - 50 grub_le_to_cpu64 (mdah->size)); 51 } 52- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset); 53 54- while (*q != ' ' && q < metadatabuf + mda_size) 55- q++; 56- 57- if (q == metadatabuf + mda_size) 58+ if (grub_add ((grub_size_t)metadatabuf, 59+ (grub_size_t)grub_le_to_cpu64 (rlocn->offset), 60+ &ptr)) 61 { 62+ error_parsing_metadata: 63 #ifdef GRUB_UTIL 64 grub_util_info ("error parsing metadata"); 65 #endif 66 goto fail2; 67 } 68 69+ p = q = (char *)ptr; 70+ 71+ if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr)) 72+ goto error_parsing_metadata; 73+ 74+ mda_end = (char *)ptr; 75+ 76+ while (*q != ' ' && q < mda_end) 77+ q++; 78+ 79+ if (q == mda_end) 80+ goto error_parsing_metadata; 81+ 82 vgname_len = q - p; 83 vgname = grub_malloc (vgname_len + 1); 84 if (!vgname) 85@@ -367,8 +381,26 @@ grub_lvm_detect (grub_disk_t disk, 86 { 87 const char *iptr; 88 char *optr; 89- lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len 90- + 1 + 2 * s + 1); 91+ 92+ /* 93+ * This is kind of hard to read with our safe (but rather 94+ * baroque) math primatives, but it boils down to: 95+ * 96+ * sz0 = vgname_len * 2 + 1 + 97+ * s * 2 + 1 + 98+ * sizeof ("lvm/") - 1; 99+ */ 100+ grub_size_t sz0 = vgname_len, sz1 = s; 101+ 102+ if (grub_mul (sz0, 2, &sz0) || 103+ grub_add (sz0, 1, &sz0) || 104+ grub_mul (sz1, 2, &sz1) || 105+ grub_add (sz1, 1, &sz1) || 106+ grub_add (sz0, sz1, &sz0) || 107+ grub_add (sz0, sizeof ("lvm/") - 1, &sz0)) 108+ goto lvs_fail; 109+ 110+ lv->fullname = grub_malloc (sz0); 111 if (!lv->fullname) 112 goto lvs_fail; 113 114-- 1152.26.2 116 117