Module Name: src Committed By: martin Date: Tue Aug 8 16:12:57 UTC 2017
Modified Files: src/sys/dev [netbsd-8]: vnd.c Log Message: Pull up following revision(s) (requested by spz in ticket #190): sys/dev/vnd.c: revision 1.260 sys/dev/vnd.c: revision 1.262 Put in a litany of judicious bounds checks around vnd headers. Thought I was done with this crap after I rewrote vndcompress(1)! >From Ilja Van Sprundel. Appease toxic bullshit warning from gcc. If you have a better way to write a useful bounds check that happens to always pass on LP64 but doesn't always on LP32, without making it fail to compile on LP64 or making it an #ifdef conditional on LP32, please put it in here instead. To generate a diff of this commit: cvs rdiff -u -r1.259 -r1.259.6.1 src/sys/dev/vnd.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/vnd.c diff -u src/sys/dev/vnd.c:1.259 src/sys/dev/vnd.c:1.259.6.1 --- src/sys/dev/vnd.c:1.259 Sat Mar 25 07:00:33 2017 +++ src/sys/dev/vnd.c Tue Aug 8 16:12:56 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vnd.c,v 1.259 2017/03/25 07:00:33 pgoyette Exp $ */ +/* $NetBSD: vnd.c,v 1.259.6.1 2017/08/08 16:12:56 martin Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.259 2017/03/25 07:00:33 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.259.6.1 2017/08/08 16:12:56 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_vnd.h" @@ -1284,6 +1284,13 @@ vndioctl(dev_t dev, u_long cmd, void *da goto close_and_exit; } + if (ntohl(ch->block_size) == 0 || + ntohl(ch->num_blocks) > UINT32_MAX - 1) { + free(ch, M_TEMP); + VOP_UNLOCK(nd.ni_vp); + goto close_and_exit; + } + /* save some header info */ vnd->sc_comp_blksz = ntohl(ch->block_size); /* note last offset is the file byte size */ @@ -1294,20 +1301,40 @@ vndioctl(dev_t dev, u_long cmd, void *da error = EINVAL; goto close_and_exit; } - if (sizeof(struct vnd_comp_header) + - sizeof(u_int64_t) * vnd->sc_comp_numoffs > - vattr.va_size) { + KASSERT(0 < vnd->sc_comp_blksz); + KASSERT(0 < vnd->sc_comp_numoffs); + /* + * @#^@!$& gcc -Wtype-limits refuses to let me + * write SIZE_MAX/sizeof(uint64_t) < numoffs, + * because the range of the type on amd64 makes + * the comparisons always false. + */ +#if SIZE_MAX <= UINT32_MAX*(64/CHAR_BIT) + if (SIZE_MAX/sizeof(uint64_t) < vnd->sc_comp_numoffs) { + VOP_UNLOCK(nd.ni_vp); + error = EINVAL; + goto close_and_exit; + } +#endif + if ((vattr.va_size < sizeof(struct vnd_comp_header)) || + (vattr.va_size - sizeof(struct vnd_comp_header) < + sizeof(uint64_t)*vnd->sc_comp_numoffs) || + (UQUAD_MAX/vnd->sc_comp_blksz < + vnd->sc_comp_numoffs - 1)) { VOP_UNLOCK(nd.ni_vp); error = EINVAL; goto close_and_exit; } /* set decompressed file size */ + KASSERT(vnd->sc_comp_numoffs - 1 <= + UQUAD_MAX/vnd->sc_comp_blksz); vattr.va_size = ((u_quad_t)vnd->sc_comp_numoffs - 1) * (u_quad_t)vnd->sc_comp_blksz; /* allocate space for all the compressed offsets */ + __CTASSERT(UINT32_MAX <= UQUAD_MAX/sizeof(uint64_t)); vnd->sc_comp_offsets = malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, M_DEVBUF, M_WAITOK);