Module Name:    src
Committed By:   bouyer
Date:           Fri May 20 19:32:44 UTC 2011

Modified Files:
        src/sys/arch/x68k/x68k [netbsd-5]: disksubr.c

Log Message:
Pull up following revision(s) (requested by tsutsui in ticket #1621):
        sys/arch/x68k/x68k/disksubr.c: revision 1.34
Fix buffer overrun in readdisklabel(9) (and writedisklabel(9))
that causes unexpected panic during installation and
DIAGNOSTIC pool assertions.
Also fix bp->b_flags in writedisklabel(9) error path.
The problem was reported from Y.Sugahara during XM6i development,
and this fix is confirmed on both X68030 (by me) and XM6i (by Sugahara).
XXX: broken dkbad support (which makes struct cpu_disklabel larger
XXX: than 512 bytes) should be removed...


To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.33.20.1 src/sys/arch/x68k/x68k/disksubr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x68k/x68k/disksubr.c
diff -u src/sys/arch/x68k/x68k/disksubr.c:1.33 src/sys/arch/x68k/x68k/disksubr.c:1.33.20.1
--- src/sys/arch/x68k/x68k/disksubr.c:1.33	Wed Jan  2 11:48:32 2008
+++ src/sys/arch/x68k/x68k/disksubr.c	Fri May 20 19:32:44 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: disksubr.c,v 1.33 2008/01/02 11:48:32 ad Exp $	*/
+/*	$NetBSD: disksubr.c,v 1.33.20.1 2011/05/20 19:32:44 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.33 2008/01/02 11:48:32 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.33.20.1 2011/05/20 19:32:44 bouyer Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -69,7 +69,7 @@
 	struct buf *bp;
 	struct disklabel *dlp;
 	const char *msg = NULL;
-	int i, labelsz;
+	int i, bsdlabelsz, humanlabelsz;
 
 	if (osdep)
 		dp = osdep->dosparts;
@@ -90,15 +90,19 @@
 	lp->d_partitions[0].p_offset = 0;
 
 	/* get a buffer and initialize it */
-	bp = geteblk((int)lp->d_secsize);
+	bsdlabelsz =
+	    howmany(LABELOFFSET + sizeof(struct disklabel), lp->d_secsize)
+	    * lp->d_secsize;
+	humanlabelsz =
+	    howmany(sizeof(struct cpu_disklabel), lp->d_secsize)
+	    * lp->d_secsize;
+	bp = geteblk(MAX(bsdlabelsz, humanlabelsz));
 	bp->b_dev = dev;
 
 	/* read BSD disklabel first */
 	bp->b_blkno = LABELSECTOR;
 	bp->b_cylinder = LABELSECTOR/lp->d_secpercyl;
-	labelsz = howmany(LABELOFFSET+sizeof(struct disklabel), lp->d_secsize)
-		* lp->d_secsize;
-	bp->b_bcount = labelsz;	/* to support < 512B/sector disks */
+	bp->b_bcount = bsdlabelsz;	/* to support < 512B/sector disks */
 	bp->b_flags |= B_READ;
 	(*strat)(bp);
 
@@ -109,7 +113,7 @@
 	}
 	for (dlp = (struct disklabel *)bp->b_data;
 	     dlp <= (struct disklabel *)
-		((char *)bp->b_data + labelsz - sizeof(*dlp));
+		((char *)bp->b_data + bsdlabelsz - sizeof(*dlp));
 	     dlp = (struct disklabel *)((uint8_t *)dlp + sizeof(long))) {
 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
 			if (msg == NULL)
@@ -135,9 +139,7 @@
 	bp->b_blkno = DOSPARTOFF * DEF_BSIZE / lp->d_secsize;
 				/* DOSPARTOFF in DEV_BSIZE unit */
 	bp->b_cylinder = DOSBBSECTOR / lp->d_secpercyl;
-	labelsz = howmany(sizeof(struct cpu_disklabel),
-			  lp->d_secsize) * lp->d_secsize;
-	bp->b_bcount = labelsz;	/* to support < 512B/sector disks */
+	bp->b_bcount = humanlabelsz;	/* to support < 512B/sector disks */
 	bp->b_oflags &= ~(BO_DONE);
 	(*strat)(bp);
 
@@ -313,7 +315,7 @@
 	struct dos_partition *dp = 0;
 	struct buf *bp;
 	struct disklabel *dlp;
-	int error, labelsz, i;
+	int error, bsdlabelsz, humanlabelsz, i;
 	const char *np;
 
 	if (osdep)
@@ -326,15 +328,19 @@
 		parttbl_consistency_check(lp, dp);
 
 	/* get a buffer and initialize it */
-	bp = geteblk((int)lp->d_secsize);
+	bsdlabelsz =
+	    howmany(LABELOFFSET + sizeof(struct disklabel), lp->d_secsize)
+	    * lp->d_secsize;
+	humanlabelsz =
+	    howmany(sizeof(struct cpu_disklabel), lp->d_secsize)
+	    * lp->d_secsize;
+	bp = geteblk(MAX(bsdlabelsz, humanlabelsz));
 	bp->b_dev = dev;
 
 	/* attempt to write BSD disklabel first */
 	bp->b_blkno = LABELSECTOR;
 	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
-	labelsz = howmany(LABELOFFSET+sizeof(struct disklabel), lp->d_secsize)
-		* lp->d_secsize;
-	bp->b_bcount = labelsz;	/* to support < 512B/sector disks */
+	bp->b_bcount = bsdlabelsz;	/* to support < 512B/sector disks */
 	bp->b_flags |= B_READ;
 	(*strat)(bp);
 
@@ -344,7 +350,7 @@
 	error = ESRCH;
 	for (dlp = (struct disklabel *)bp->b_data;
 	     dlp <= (struct disklabel *)
-		((char *)bp->b_data + labelsz - sizeof(*dlp));
+		((char *)bp->b_data + bsdlabelsz - sizeof(*dlp));
 	     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
 		    dkcksum(dlp) == 0) {
@@ -370,6 +376,7 @@
 		bp->b_blkno = DOSBBSECTOR;
 		bp->b_bcount = lp->d_secsize;
 		bp->b_oflags &= ~(BO_DONE);
+		bp->b_flags &= ~(B_WRITE);
 		bp->b_flags |= B_READ;
 		bp->b_cylinder = DOSBBSECTOR / lp->d_secpercyl;
 		(*strat)(bp);
@@ -379,10 +386,9 @@
 
 		/* read the partition table */
 		bp->b_blkno = DOSPARTOFF;
-		labelsz = howmany(sizeof(struct cpu_disklabel),
-				  lp->d_secsize) * lp->d_secsize;
-		bp->b_bcount = labelsz;
+		bp->b_bcount = humanlabelsz;
 		bp->b_oflags &= ~(BO_DONE);
+		bp->b_flags &= ~(B_WRITE);
 		bp->b_flags |= B_READ;
 		bp->b_cylinder = DOSPARTOFF / lp->d_secpercyl;
 		(*strat)(bp);

Reply via email to