Module Name: src
Committed By: mlelstv
Date: Sun Aug 13 22:23:16 UTC 2017
Modified Files:
src/sys/dev: dksubr.c
Log Message:
validate length for discard operation and split operation when byte length
doesn't fit into 'int'.
To generate a diff of this commit:
cvs rdiff -u -r1.97 -r1.98 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.97 src/sys/dev/dksubr.c:1.98
--- src/sys/dev/dksubr.c:1.97 Thu Apr 27 17:07:22 2017
+++ src/sys/dev/dksubr.c Sun Aug 13 22:23:16 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: dksubr.c,v 1.97 2017/04/27 17:07:22 jdolecek Exp $ */
+/* $NetBSD: dksubr.c,v 1.98 2017/08/13 22:23:16 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.97 2017/04/27 17:07:22 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.98 2017/08/13 22:23:16 mlelstv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -497,7 +497,7 @@ dk_discard(struct dk_softc *dksc, dev_t
const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
unsigned secsize = dksc->sc_dkdev.dk_geom.dg_secsize;
struct buf tmp, *bp = &tmp;
- int error;
+ int maxsz, error;
DPRINTF_FOLLOW(("%s(%s, %p, 0x"PRIx64", %jd, %jd)\n", __func__,
dksc->sc_xname, dksc, (intmax_t)pos, (intmax_t)len));
@@ -507,22 +507,32 @@ dk_discard(struct dk_softc *dksc, dev_t
return ENXIO;
}
- if (secsize == 0 || (pos % secsize) != 0)
+ if (secsize == 0 || (pos % secsize) != 0 || (len % secsize) != 0)
return EINVAL;
- /* enough data to please the bounds checking code */
- bp->b_dev = dev;
- bp->b_blkno = (daddr_t)(pos / secsize);
- bp->b_bcount = len;
- bp->b_flags = B_WRITE;
+ /* largest value that b_bcount can store */
+ maxsz = rounddown(INT_MAX, secsize);
- error = dk_translate(dksc, bp);
- if (error >= 0)
- return error;
+ while (len > 0) {
+ /* enough data to please the bounds checking code */
+ bp->b_dev = dev;
+ bp->b_blkno = (daddr_t)(pos / secsize);
+ bp->b_bcount = min(len, maxsz);
+ bp->b_flags = B_WRITE;
+
+ error = dk_translate(dksc, bp);
+ if (error >= 0)
+ break;
+
+ error = dkd->d_discard(dksc->sc_dev,
+ (off_t)bp->b_rawblkno * secsize,
+ (off_t)bp->b_bcount);
+ if (error)
+ break;
- error = dkd->d_discard(dksc->sc_dev,
- (off_t)bp->b_rawblkno * secsize,
- (off_t)bp->b_bcount);
+ pos += bp->b_bcount;
+ len -= bp->b_bcount;
+ }
return error;
}