changeset 13836:37bf491c434c

3027 installgrub can segfault when encountering bogus data on disk Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Hans Rosenfeld <hans.rosenfeld@nexenta.com>
date Thu, 02 Aug 2012 04:58:41 -0500
parents eea81edc4f14
children 76dc42aca3ef
files usr/src/cmd/boot/common/mboot_extra.c usr/src/cmd/boot/common/mboot_extra.h usr/src/cmd/boot/installboot/installboot.c usr/src/cmd/boot/installboot/installboot.h usr/src/cmd/boot/installgrub/installgrub.c usr/src/cmd/boot/installgrub/installgrub.h
diffstat 6 files changed, 25 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/boot/common/mboot_extra.c	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/common/mboot_extra.c	Thu Aug 02 04:58:41 2012 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -107,7 +108,7 @@
  * + payload chunks), find the extended information structure.
  */
 bblk_einfo_t *
-find_einfo(char *extra)
+find_einfo(char *extra, uint32_t size)
 {
 	bb_header_ext_t		*ext_header;
 	bblk_einfo_t		*einfo;
@@ -116,6 +117,12 @@
 	assert(extra != NULL);
 
 	ext_header = (bb_header_ext_t *)extra;
+	if (ext_header->size > size) {
+		BOOT_DEBUG("Unable to find extended versioning information, "
+		    "data size too big\n");
+		return (NULL);
+	}
+
 	cksum = compute_checksum(extra + sizeof (bb_header_ext_t),
 	    ext_header->size);
 	BOOT_DEBUG("Extended information header checksum is %x\n", cksum);
--- a/usr/src/cmd/boot/common/mboot_extra.h	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/common/mboot_extra.h	Thu Aug 02 04:58:41 2012 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef	_MBOOT_EXTRA_H
@@ -46,7 +47,7 @@
 } bb_header_ext_t;
 
 uint32_t compute_checksum(char *, uint32_t);
-bblk_einfo_t *find_einfo(char *);
+bblk_einfo_t *find_einfo(char *, uint32_t);
 int find_multiboot(char *, uint32_t, uint32_t *);
 void add_einfo(char *, char *, bblk_hs_t *, uint32_t);
 int compare_bootblocks(char *, char *, char **);
--- a/usr/src/cmd/boot/installboot/installboot.c	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/installboot/installboot.c	Thu Aug 02 04:58:41 2012 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -252,6 +253,8 @@
 	bblock->mboot = (multiboot_header_t *)(bblock->buf + bblock->mboot_off
 	    + BBLK_DATA_RSVD_SIZE);
 	bblock->extra = (char *)bblock->mboot + sizeof (multiboot_header_t);
+	bblock->extra_size = bblock->buf_size - bblock->mboot_off
+	    - BBLK_DATA_RSVD_SIZE - sizeof (multiboot_header_t);
 	return (BC_SUCCESS);
 }
 
@@ -279,7 +282,7 @@
 		return (B_TRUE);
 	}
 
-	einfo = find_einfo(bblock_disk.extra);
+	einfo = find_einfo(bblock_disk.extra, bblock_disk.extra_size);
 	if (einfo == NULL) {
 		BOOT_DEBUG("No extended information available\n");
 		return (B_TRUE);
@@ -716,7 +719,7 @@
 		goto out_dev;
 	}
 
-	einfo = find_einfo(bblock->extra);
+	einfo = find_einfo(bblock->extra, bblock->extra_size);
 	if (einfo == NULL) {
 		retval = BC_NOEINFO;
 		(void) fprintf(stderr, gettext("No extended information "
@@ -817,7 +820,7 @@
 		goto out_devs;
 	}
 
-	einfo_curr = find_einfo(bblock_curr->extra);
+	einfo_curr = find_einfo(bblock_curr->extra, bblock_curr->extra_size);
 	if (einfo_curr != NULL)
 		updt_str = einfo_get_string(einfo_curr);
 
--- a/usr/src/cmd/boot/installboot/installboot.h	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/installboot/installboot.h	Thu Aug 02 04:58:41 2012 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef	_INSTALLBOOT_H
@@ -52,6 +53,7 @@
 	uint32_t		mboot_off;
 	uint32_t		buf_size;
 	uint32_t		file_size;
+	uint32_t		extra_size;
 } ib_bootblock_t;
 
 typedef struct _ib_data {
--- a/usr/src/cmd/boot/installgrub/installgrub.c	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/installgrub/installgrub.c	Thu Aug 02 04:58:41 2012 -0500
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -403,7 +404,7 @@
 		goto out_dev;
 	}
 
-	einfo = find_einfo(stage2->extra);
+	einfo = find_einfo(stage2->extra, stage2->extra_size);
 	if (einfo == NULL) {
 		retval = BC_NOEINFO;
 		(void) fprintf(stderr, gettext("No extended information "
@@ -501,7 +502,7 @@
 		goto out_devs;
 	}
 
-	einfo_curr = find_einfo(stage2_curr->extra);
+	einfo_curr = find_einfo(stage2_curr->extra, stage2_curr->extra_size);
 	if (einfo_curr != NULL)
 		updt_str = einfo_get_string(einfo_curr);
 
@@ -1221,6 +1222,7 @@
 	stage2->mboot_off = mboot_off;
 	stage2->mboot = (multiboot_header_t *)(stage2->buf + stage2->mboot_off);
 	stage2->extra = stage2->buf + P2ROUNDUP(stage2->file_size, 8);
+	stage2->extra_size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
 
 	return (BC_SUCCESS);
 }
@@ -1251,7 +1253,7 @@
 	 * Look for the extended information structure in the extra payload
 	 * area.
 	 */
-	einfo = find_einfo(stage2_disk.extra);
+	einfo = find_einfo(stage2_disk.extra, stage2_disk.extra_size);
 	if (einfo == NULL) {
 		BOOT_DEBUG("No extended information available\n");
 		return (B_TRUE);
--- a/usr/src/cmd/boot/installgrub/installgrub.h	Mon Sep 24 06:37:22 2012 -0700
+++ b/usr/src/cmd/boot/installgrub/installgrub.h	Thu Aug 02 04:58:41 2012 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef	_INSTALLGRUB_H
@@ -53,6 +54,7 @@
 	multiboot_header_t	*mboot;
 	uint32_t		mboot_off;
 	uint32_t		file_size;
+	uint32_t		extra_size;
 	uint32_t		buf_size;
 	uint32_t		first_sector;
 	uint32_t		pcfs_first_sectors[2];