Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev validate length for discard operation and split oper...



details:   https://anonhg.NetBSD.org/src/rev/958552d58d95
branches:  trunk
changeset: 355776:958552d58d95
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sun Aug 13 22:23:16 2017 +0000

description:
validate length for discard operation and split operation when byte length
doesn't fit into 'int'.

diffstat:

 sys/dev/dksubr.c |  40 +++++++++++++++++++++++++---------------
 1 files changed, 25 insertions(+), 15 deletions(-)

diffs (72 lines):

diff -r 187a812476d3 -r 958552d58d95 sys/dev/dksubr.c
--- a/sys/dev/dksubr.c  Sun Aug 13 22:19:56 2017 +0000
+++ b/sys/dev/dksubr.c  Sun Aug 13 22:23:16 2017 +0000
@@ -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 @@
        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 @@
                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);
+
+       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)
-               return error;
+               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);
+               error = dkd->d_discard(dksc->sc_dev,
+                       (off_t)bp->b_rawblkno * secsize,
+                       (off_t)bp->b_bcount);
+               if (error)
+                       break;
+
+               pos += bp->b_bcount;
+               len -= bp->b_bcount;
+       }
 
        return error;
 }



Home | Main Index | Thread Index | Old Index