Wed Jan 1 09:40:17 2020 UTC ()
Fix small read overflows when parsing HID tables. Noticed by kASan the
other day while I was playing with vHCI.


(maxv)
diff -r1.3 -r1.4 src/sys/dev/hid/hid.c

cvs diff -r1.3 -r1.4 src/sys/dev/hid/hid.c (expand / switch to unified diff)

--- src/sys/dev/hid/hid.c 2018/11/15 23:01:45 1.3
+++ src/sys/dev/hid/hid.c 2020/01/01 09:40:17 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: hid.c,v 1.3 2018/11/15 23:01:45 jakllsch Exp $ */ 1/* $NetBSD: hid.c,v 1.4 2020/01/01 09:40:17 maxv Exp $ */
2/* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */ 2/* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to The NetBSD Foundation 8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart@augustsson.net) at 9 * by Lennart Augustsson (lennart@augustsson.net) at
10 * Carlstedt Research & Technology. 10 * Carlstedt Research & Technology.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -22,27 +22,27 @@ @@ -22,27 +22,27 @@
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE. 31 * POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.3 2018/11/15 23:01:45 jakllsch Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.4 2020/01/01 09:40:17 maxv Exp $");
36 36
37#ifdef _KERNEL_OPT 37#ifdef _KERNEL_OPT
38#include "opt_usb.h" 38#include "opt_usb.h"
39#endif 39#endif
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/kernel.h> 43#include <sys/kernel.h>
44#include <sys/kmem.h> 44#include <sys/kmem.h>
45 45
46#include <dev/usb/usb.h> 46#include <dev/usb/usb.h>
47#include <dev/usb/usbhid.h> 47#include <dev/usb/usbhid.h>
48 48
@@ -139,47 +139,53 @@ hid_get_item(struct hid_data *s, struct  @@ -139,47 +139,53 @@ hid_get_item(struct hid_data *s, struct
139 c->loc.pos += c->loc.size; 139 c->loc.pos += c->loc.size;
140 h->next = NULL; 140 h->next = NULL;
141 DPRINTFN(5,("return multi\n")); 141 DPRINTFN(5,("return multi\n"));
142 return 1; 142 return 1;
143 } else { 143 } else {
144 c->loc.count = s->multimax; 144 c->loc.count = s->multimax;
145 s->multimax = 0; 145 s->multimax = 0;
146 s->nu = 0; 146 s->nu = 0;
147 hid_clear_local(c); 147 hid_clear_local(c);
148 } 148 }
149 } 149 }
150 for (;;) { 150 for (;;) {
151 p = s->p; 151 p = s->p;
152 if (p >= s->end) 
153 return 0; 
154 152
 153 if (p + 1 > s->end)
 154 return 0;
155 bSize = *p++; 155 bSize = *p++;
 156
156 if (bSize == 0xfe) { 157 if (bSize == 0xfe) {
157 /* long item */ 158 /* long item */
 159 if (p + 3 > s->end)
 160 return 0;
158 bSize = *p++; 161 bSize = *p++;
159 bSize |= *p++ << 8; 162 bSize |= *p++ << 8;
160 bTag = *p++; 163 bTag = *p++;
161 data = p; 
162 p += bSize; 
163 bType = 0xff; /* XXX what should it be */ 164 bType = 0xff; /* XXX what should it be */
164 } else { 165 } else {
165 /* short item */ 166 /* short item */
166 bTag = bSize >> 4; 167 bTag = bSize >> 4;
167 bType = (bSize >> 2) & 3; 168 bType = (bSize >> 2) & 3;
168 bSize &= 3; 169 bSize &= 3;
169 if (bSize == 3) bSize = 4; 170 if (bSize == 3)
170 data = p; 171 bSize = 4;
171 p += bSize; 
172 } 172 }
 173
 174 data = p;
 175 if (p + bSize > s->end)
 176 return 0;
 177 p += bSize;
 178
173 s->p = p; 179 s->p = p;
174 switch(bSize) { 180 switch(bSize) {
175 case 0: 181 case 0:
176 dval = 0; 182 dval = 0;
177 uval = dval; 183 uval = dval;
178 break; 184 break;
179 case 1: 185 case 1:
180 dval = *data++; 186 dval = *data++;
181 uval = dval; 187 uval = dval;
182 dval = (int8_t)dval; 188 dval = (int8_t)dval;
183 break; 189 break;
184 case 2: 190 case 2:
185 dval = *data++; 191 dval = *data++;