Sat Aug 19 05:19:28 2017 UTC ()
Pull up following revision(s) (requested by mrg in ticket #1476):
	sys/dev/vnd.c: revision 1.260, 1.262 via patch
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.


(snj)
diff -r1.232.2.3.2.1 -r1.232.2.3.2.2 src/sys/dev/vnd.c

cvs diff -r1.232.2.3.2.1 -r1.232.2.3.2.2 src/sys/dev/vnd.c (expand / switch to unified diff)

--- src/sys/dev/vnd.c 2016/01/02 14:38:45 1.232.2.3.2.1
+++ src/sys/dev/vnd.c 2017/08/19 05:19:28 1.232.2.3.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vnd.c,v 1.232.2.3.2.1 2016/01/02 14:38:45 riz Exp $ */ 1/* $NetBSD: vnd.c,v 1.232.2.3.2.2 2017/08/19 05:19:28 snj Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe. 8 * by Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -81,27 +81,27 @@ @@ -81,27 +81,27 @@
81 * systems where the block-level operations are not implemented for 81 * systems where the block-level operations are not implemented for
82 * whatever reason. 82 * whatever reason.
83 * 83 *
84 * NOTE 2: There is a security issue involved with this driver. 84 * NOTE 2: There is a security issue involved with this driver.
85 * Once mounted all access to the contents of the "mapped" file via 85 * Once mounted all access to the contents of the "mapped" file via
86 * the special file is controlled by the permissions on the special 86 * the special file is controlled by the permissions on the special
87 * file, the protection of the mapped file is ignored (effectively, 87 * file, the protection of the mapped file is ignored (effectively,
88 * by using root credentials in all transactions). 88 * by using root credentials in all transactions).
89 * 89 *
90 * NOTE 3: Doesn't interact with leases, should it? 90 * NOTE 3: Doesn't interact with leases, should it?
91 */ 91 */
92 92
93#include <sys/cdefs.h> 93#include <sys/cdefs.h>
94__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.232.2.3.2.1 2016/01/02 14:38:45 riz Exp $"); 94__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.232.2.3.2.2 2017/08/19 05:19:28 snj Exp $");
95 95
96#if defined(_KERNEL_OPT) 96#if defined(_KERNEL_OPT)
97#include "opt_vnd.h" 97#include "opt_vnd.h"
98#include "opt_compat_netbsd.h" 98#include "opt_compat_netbsd.h"
99#endif 99#endif
100 100
101#include <sys/param.h> 101#include <sys/param.h>
102#include <sys/systm.h> 102#include <sys/systm.h>
103#include <sys/namei.h> 103#include <sys/namei.h>
104#include <sys/proc.h> 104#include <sys/proc.h>
105#include <sys/kthread.h> 105#include <sys/kthread.h>
106#include <sys/errno.h> 106#include <sys/errno.h>
107#include <sys/buf.h> 107#include <sys/buf.h>
@@ -1228,51 +1228,78 @@ vndioctl(dev_t dev, u_long cmd, void *da @@ -1228,51 +1228,78 @@ vndioctl(dev_t dev, u_long cmd, void *da
1228 /* allocate space for compresed file header */ 1228 /* allocate space for compresed file header */
1229 ch = malloc(sizeof(struct vnd_comp_header), 1229 ch = malloc(sizeof(struct vnd_comp_header),
1230 M_TEMP, M_WAITOK); 1230 M_TEMP, M_WAITOK);
1231  1231
1232 /* read compressed file header */ 1232 /* read compressed file header */
1233 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch, 1233 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch,
1234 sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE, 1234 sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE,
1235 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1235 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
1236 if (error) { 1236 if (error) {
1237 free(ch, M_TEMP); 1237 free(ch, M_TEMP);
1238 VOP_UNLOCK(nd.ni_vp); 1238 VOP_UNLOCK(nd.ni_vp);
1239 goto close_and_exit; 1239 goto close_and_exit;
1240 } 1240 }
 1241
 1242 if (ntohl(ch->block_size) == 0 ||
 1243 ntohl(ch->num_blocks) > UINT32_MAX - 1) {
 1244 free(ch, M_TEMP);
 1245 VOP_UNLOCK(nd.ni_vp);
 1246 goto close_and_exit;
 1247 }
1241  1248
1242 /* save some header info */ 1249 /* save some header info */
1243 vnd->sc_comp_blksz = ntohl(ch->block_size); 1250 vnd->sc_comp_blksz = ntohl(ch->block_size);
1244 /* note last offset is the file byte size */ 1251 /* note last offset is the file byte size */
1245 vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1; 1252 vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1;
1246 free(ch, M_TEMP); 1253 free(ch, M_TEMP);
1247 if (!DK_DEV_BSIZE_OK(vnd->sc_comp_blksz)) { 1254 if (!DK_DEV_BSIZE_OK(vnd->sc_comp_blksz)) {
1248 VOP_UNLOCK(nd.ni_vp); 1255 VOP_UNLOCK(nd.ni_vp);
1249 error = EINVAL; 1256 error = EINVAL;
1250 goto close_and_exit; 1257 goto close_and_exit;
1251 } 1258 }
1252 if (sizeof(struct vnd_comp_header) + 1259 KASSERT(0 < vnd->sc_comp_blksz);
1253 sizeof(u_int64_t) * vnd->sc_comp_numoffs > 1260 KASSERT(0 < vnd->sc_comp_numoffs);
1254 vattr.va_size) { 1261 /*
 1262 * @#^@!$& gcc -Wtype-limits refuses to let me
 1263 * write SIZE_MAX/sizeof(uint64_t) < numoffs,
 1264 * because the range of the type on amd64 makes
 1265 * the comparisons always false.
 1266 */
 1267#if SIZE_MAX <= UINT32_MAX*(64/CHAR_BIT)
 1268 if (SIZE_MAX/sizeof(uint64_t) < vnd->sc_comp_numoffs) {
 1269 VOP_UNLOCK(nd.ni_vp);
 1270 error = EINVAL;
 1271 goto close_and_exit;
 1272 }
 1273#endif
 1274 if ((vattr.va_size < sizeof(struct vnd_comp_header)) ||
 1275 (vattr.va_size - sizeof(struct vnd_comp_header) <
 1276 sizeof(uint64_t)*vnd->sc_comp_numoffs) ||
 1277 (UQUAD_MAX/vnd->sc_comp_blksz <
 1278 vnd->sc_comp_numoffs - 1)) {
1255 VOP_UNLOCK(nd.ni_vp); 1279 VOP_UNLOCK(nd.ni_vp);
1256 error = EINVAL; 1280 error = EINVAL;
1257 goto close_and_exit; 1281 goto close_and_exit;
1258 } 1282 }
1259  1283
1260 /* set decompressed file size */ 1284 /* set decompressed file size */
 1285 KASSERT(vnd->sc_comp_numoffs - 1 <=
 1286 UQUAD_MAX/vnd->sc_comp_blksz);
1261 vattr.va_size = 1287 vattr.va_size =
1262 ((u_quad_t)vnd->sc_comp_numoffs - 1) * 1288 ((u_quad_t)vnd->sc_comp_numoffs - 1) *
1263 (u_quad_t)vnd->sc_comp_blksz; 1289 (u_quad_t)vnd->sc_comp_blksz;
1264  1290
1265 /* allocate space for all the compressed offsets */ 1291 /* allocate space for all the compressed offsets */
 1292 __CTASSERT(UINT32_MAX <= UQUAD_MAX/sizeof(uint64_t));
1266 vnd->sc_comp_offsets = 1293 vnd->sc_comp_offsets =
1267 malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1294 malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs,
1268 M_DEVBUF, M_WAITOK); 1295 M_DEVBUF, M_WAITOK);
1269  1296
1270 /* read in the offsets */ 1297 /* read in the offsets */
1271 error = vn_rdwr(UIO_READ, nd.ni_vp, 1298 error = vn_rdwr(UIO_READ, nd.ni_vp,
1272 (void *)vnd->sc_comp_offsets, 1299 (void *)vnd->sc_comp_offsets,
1273 sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1300 sizeof(u_int64_t) * vnd->sc_comp_numoffs,
1274 sizeof(struct vnd_comp_header), UIO_SYSSPACE, 1301 sizeof(struct vnd_comp_header), UIO_SYSSPACE,
1275 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1302 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
1276 if (error) { 1303 if (error) {
1277 VOP_UNLOCK(nd.ni_vp); 1304 VOP_UNLOCK(nd.ni_vp);
1278 goto close_and_exit; 1305 goto close_and_exit;