changeset 9956:1705cb23ec4b

6779206 a read(2) access to /devices/ramdisk:a after the boot is over causes panic
author William Roche <William.Roche@Sun.COM>
date Tue, 23 Jun 2009 23:08:42 +0100
parents 0df5d471a4c5
children 8769ec0debbf
files usr/src/uts/common/io/ramdisk.c usr/src/uts/sparc/os/bootops.c
diffstat 2 files changed, 35 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/ramdisk.c	Tue Jun 23 11:52:41 2009 -0700
+++ b/usr/src/uts/common/io/ramdisk.c	Tue Jun 23 23:08:42 2009 +0100
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -85,6 +85,14 @@
 #include <vm/seg_kmem.h>
 
 /*
+ * Flag to disable the use of real ramdisks (in the OBP - on Sparc) when
+ * the associated memory is no longer available - set in the bootops section.
+ */
+#ifdef __sparc
+extern int bootops_obp_ramdisk_disabled;
+#endif /* __sparc */
+
+/*
  * An opaque handle where information about our set of ramdisk devices lives.
  */
 static void	*rd_statep;
@@ -820,6 +828,11 @@
 				goto attach_failed;
 			}
 		} else {
+#ifdef __sparc
+			if (bootops_obp_ramdisk_disabled)
+				goto attach_failed;
+#endif /* __sparc */
+
 			RD_STRIP_PREFIX(name, ddi_node_name(dip));
 
 			if (strlen(name) > RD_NAME_LEN) {
@@ -1073,6 +1086,13 @@
 	}
 }
 
+/*
+ * On Sparc, this function deals with both pseudo ramdisks and OBP ramdisks.
+ * In the case where we freed the "bootarchive" ramdisk in bop_free_archive(),
+ * we stop allowing access to the OBP ramdisks. To do so, we set the
+ * bootops_obp_ramdisk_disabled flag to true, and we check if the operation
+ * is for an OBP ramdisk. In this case we indicate an ENXIO error.
+ */
 static int
 rd_strategy(struct buf *bp)
 {
@@ -1082,7 +1102,13 @@
 	rsp = ddi_get_soft_state(rd_statep, getminor(bp->b_edev));
 	offset = bp->b_blkno * DEV_BSIZE;
 
+#ifdef __sparc
+	if (rsp == NULL ||
+	    (bootops_obp_ramdisk_disabled &&
+	    (rsp->rd_dip != rd_dip || rd_dip == NULL))) { /* OBP ramdisk */
+#else /* __sparc */
 	if (rsp == NULL) {
+#endif /* __sparc */
 		bp->b_error = ENXIO;
 		bp->b_flags |= B_ERROR;
 	} else if (offset >= rsp->rd_size) {
--- a/usr/src/uts/sparc/os/bootops.c	Tue Jun 23 11:52:41 2009 -0700
+++ b/usr/src/uts/sparc/os/bootops.c	Tue Jun 23 23:08:42 2009 +0100
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Definitions of interfaces that provide services from the secondary
  * boot program to its clients (primarily Solaris, krtld, kmdb and their
@@ -49,6 +47,11 @@
 struct bootops kbootops;
 
 pnode_t chosennode;
+/*
+ * Flag to disable the use of real ramdisks (in the OBP - on Sparc) when
+ * the associated memory is no longer available.
+ */
+int bootops_obp_ramdisk_disabled = 0;
 
 #define	FAKE_ROOT	(pnode_t)1
 
@@ -522,6 +525,8 @@
 	    prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1)
 		prom_panic("can't free boot archive");
 
+	bootops_obp_ramdisk_disabled = 1;
+
 #if !defined(C_OBP)
 	if (alloc_size == 0)
 		prom_free((caddr_t)(uintptr_t)arbase, arsize);