From 6a079d978c3c4c77da338b81880799146e47e6bf Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 21 Jan 2021 18:35:22 +1100
Subject: [PATCH] disk/lvm: Do not overread metadata

We could reach the end of valid metadata and not realize, leading to
some buffer overreads. Check if we have reached the end and bail.

Reference: http://git.savannah.gnu.org/cgit/grub.git/commit/?id=1155d7dffd3337942cb7583706b429d567d4db86

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index e5d6c3f..a44861f 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -351,17 +351,23 @@ grub_lvm_detect (grub_disk_t disk,
 	  while (1)
 	    {
 	      grub_ssize_t s;
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      pv = grub_zalloc (sizeof (*pv));
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto pvs_fail_noname;
+
 	      s = q - p;
 	      pv->name = grub_malloc (s + 1);
 	      grub_memcpy (pv->name, p, s);
@@ -404,6 +410,7 @@ grub_lvm_detect (grub_disk_t disk,
 	      continue;
 	    pvs_fail:
 	      grub_free (pv->name);
+	    pvs_fail_noname:
 	      grub_free (pv);
 	      goto fail4;
 	    }
@@ -425,18 +432,24 @@ grub_lvm_detect (grub_disk_t disk,
 	      struct grub_diskfilter_segment *seg;
 	      int is_pvmove;
 
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      lv = grub_zalloc (sizeof (*lv));
 
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto lvs_fail;
+
 	      s = q - p;
 	      lv->name = grub_strndup (p, s);
 	      if (!lv->name)
@@ -608,9 +621,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  stripe->name = grub_malloc (s + 1);
@@ -667,9 +683,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  lvname = grub_malloc (s + 1);
@@ -825,6 +844,8 @@ grub_lvm_detect (grub_disk_t disk,
 			goto cache_lv_fail;
 
 		      p3 = ++p2;
+		      if (p3 == mda_end)
+			goto cache_lv_fail;
 		      p3 = grub_strchr (p3, '"');
 		      if (!p3)
 			goto cache_lv_fail;
@@ -846,6 +867,8 @@ grub_lvm_detect (grub_disk_t disk,
 			goto cache_lv_fail;
 
 		      p3 = ++p2;
+		      if (p3 == mda_end)
+			goto cache_lv_fail;
 		      p3 = grub_strchr (p3, '"');
 		      if (!p3)
 			goto cache_lv_fail;
-- 
2.19.1

