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);