Blob Blame History Raw
From e27fdbd6866a3dc9c6ee4d777d89c861f04368e7 Mon Sep 17 00:00:00 2001
From: Andrei Borzenkov <arvidjaar@gmail.com>
Date: Sat, 14 Feb 2015 17:55:35 +0300
Subject: [PATCH 283/506] diskfilter: fix crash in validate_lv for mdraid
 arrays

Commit 750f4bacd3262376ced3f837d8dc78f834ca233a put LV validation before
actual vg assignment. Make grub_diskfilter_make_raid to assign ->vg as
happens in other cases for consistency. Also clean up redundant code and add
explicit NULL lv->vg check in validate_lv.

Also fix segment validation in validate_lv; it became obvious when crash
was fixed.

Closes: 44199
---
 grub-core/disk/diskfilter.c | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 80966ac..ad558fa 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -496,13 +496,13 @@ validate_lv (struct grub_diskfilter_lv *lv)
   if (!lv)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
 
-  if (lv->vg->extent_size == 0)
+  if (!lv->vg || lv->vg->extent_size == 0)
     return grub_error (GRUB_ERR_READ_ERROR, "invalid volume");
 
   for (i = 0; i < lv->segment_count; i++)
     {
       grub_err_t err;
-      err = validate_segment (&lv->segments[1]);
+      err = validate_segment (&lv->segments[i]);
       if (err)
 	return err;
     }
@@ -941,8 +941,10 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
 
   for (lv = vg->lvs; lv; lv = lv->next)
     {
-      /* RAID 1 and single-disk RAID 0 don't use a chunksize but code assumes one so set
-	 one. */
+      grub_err_t err;
+
+      /* RAID 1 and single-disk RAID 0 don't use a chunksize but code
+         assumes one so set one. */
       for (i = 0; i < lv->segment_count; i++)
 	{
 	  if (lv->segments[i].type == 1)
@@ -952,17 +954,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
 	      && lv->segments[i].stripe_size == 0)
 	    lv->segments[i].stripe_size = 64;
 	}
-    }
-
-  for (lv = vg->lvs; lv; lv = lv->next)
-    {
-      grub_err_t err;
-
-      /* RAID 1 doesn't use a chunksize but code assumes one so set
-	 one. */
-      for (i = 0; i < lv->segment_count; i++)
-	if (lv->segments[i].type == 1)
-	  lv->segments[i].stripe_size = 64;
 
       err = validate_lv(lv);
       if (err)
@@ -1007,7 +998,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
 	      lv->fullname = tmp;
 	    }
 	}
-      lv->vg = vg;
     }
   /* Add our new array to the list.  */
   vg->next = array_list;
@@ -1101,6 +1091,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
   array->lvs->visible = 1;
   array->lvs->name = array->name;
   array->lvs->fullname = array->name;
+  array->lvs->vg = array;
 
   array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
   if (!array->lvs->idname)
-- 
2.4.3