Module Name: src Committed By: mlelstv Date: Mon Dec 29 12:03:40 UTC 2014
Modified Files: src/sys/dev: dksubr.c Log Message: align dk_strategy with checks from ld.c To generate a diff of this commit: cvs rdiff -u -r1.54 -r1.55 src/sys/dev/dksubr.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/dev/dksubr.c diff -u src/sys/dev/dksubr.c:1.54 src/sys/dev/dksubr.c:1.55 --- src/sys/dev/dksubr.c:1.54 Tue Nov 4 07:51:54 2014 +++ src/sys/dev/dksubr.c Mon Dec 29 12:03:39 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dksubr.c,v 1.54 2014/11/04 07:51:54 mlelstv Exp $ */ +/* $NetBSD: dksubr.c,v 1.55 2014/12/29 12:03:39 mlelstv Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 1999, 2002, 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.54 2014/11/04 07:51:54 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.55 2014/12/29 12:03:39 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -178,9 +178,13 @@ dk_close(struct dk_intf *di, struct dk_s void dk_strategy(struct dk_intf *di, struct dk_softc *dksc, struct buf *bp) { - int s; + int s, part; int wlabel; daddr_t blkno; + struct disklabel *lp; + struct disk *dk; + uint64_t numsecs; + unsigned secsize; DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n", di->di_dkname, dksc, bp)); @@ -192,10 +196,25 @@ dk_strategy(struct dk_intf *di, struct d return; } - /* XXX look for some more errors, c.f. ld.c */ + lp = dksc->sc_dkdev.dk_label; + dk = &dksc->sc_dkdev; + + part = DISKPART(bp->b_dev); + numsecs = dk->dk_geom.dg_secperunit; + secsize = dk->dk_geom.dg_secsize; bp->b_resid = bp->b_bcount; + /* + * The transfer must be a whole number of blocks and the offset must + * not be negative. + */ + if ((bp->b_bcount % secsize) != 0 || bp->b_blkno < 0) { + bp->b_error = EINVAL; + biodone(bp); + return; + } + /* If there is nothing to do, then we are done */ if (bp->b_bcount == 0) { biodone(bp); @@ -203,20 +222,21 @@ dk_strategy(struct dk_intf *di, struct d } wlabel = dksc->sc_flags & (DKF_WLABEL|DKF_LABELLING); - if (DISKPART(bp->b_dev) != RAW_PART && - bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) { - biodone(bp); - return; + if (part == RAW_PART) { + if (bounds_check_with_mediasize(bp, DEV_BSIZE, numsecs) <= 0) { + biodone(bp); + return; + } + } else { + if (bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) { + biodone(bp); + return; + } } blkno = bp->b_blkno; - if (DISKPART(bp->b_dev) != RAW_PART) { - struct partition *pp; - - pp = - &dksc->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]; - blkno += pp->p_offset; - } + if (part != RAW_PART) + blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset; bp->b_rawblkno = blkno; /*