Wed Jan 1 09:08:28 2020 UTC ()
Fix buffer overflows: validate the lengths at attach time, given that they
are apparently not supposed to be variable. Drop sc_ilen since it is
unused.


(maxv)
diff -r1.48 -r1.49 src/sys/dev/usb/ucycom.c

cvs diff -r1.48 -r1.49 src/sys/dev/usb/ucycom.c (expand / switch to unified diff)

--- src/sys/dev/usb/ucycom.c 2019/12/01 08:27:54 1.48
+++ src/sys/dev/usb/ucycom.c 2020/01/01 09:08:28 1.49
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ucycom.c,v 1.48 2019/12/01 08:27:54 maxv Exp $ */ 1/* $NetBSD: ucycom.c,v 1.49 2020/01/01 09:08:28 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005 The NetBSD Foundation, Inc. 4 * Copyright (c) 2005 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 Nick Hudson 8 * by Nick Hudson
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.
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31/* 31/*
32 * This code is based on the ucom driver. 32 * This code is based on the ucom driver.
33 */ 33 */
34 34
35/* 35/*
36 * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to 36 * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to
37 * RS232 bridges. 37 * RS232 bridges.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.48 2019/12/01 08:27:54 maxv Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.49 2020/01/01 09:08:28 maxv Exp $");
42 42
43#ifdef _KERNEL_OPT 43#ifdef _KERNEL_OPT
44#include "opt_usb.h" 44#include "opt_usb.h"
45#endif 45#endif
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/systm.h> 48#include <sys/systm.h>
49#include <sys/conf.h> 49#include <sys/conf.h>
50#include <sys/kernel.h> 50#include <sys/kernel.h>
51#include <sys/kmem.h> 51#include <sys/kmem.h>
52#include <sys/device.h> 52#include <sys/device.h>
53#include <sys/sysctl.h> 53#include <sys/sysctl.h>
54#include <sys/tty.h> 54#include <sys/tty.h>
@@ -111,31 +111,35 @@ int ucycomdebug = 20; @@ -111,31 +111,35 @@ int ucycomdebug = 20;
111#define UCYCOM_ERROR 0x08 111#define UCYCOM_ERROR 0x08
112#define UCYCOM_LMASK 0x07 112#define UCYCOM_LMASK 0x07
113 113
114/* Modem (Output) control byte */ 114/* Modem (Output) control byte */
115#define UCYCOM_DTR 0x20 115#define UCYCOM_DTR 0x20
116#define UCYCOM_RTS 0x10 116#define UCYCOM_RTS 0x10
117#define UCYCOM_ORESET 0x08 117#define UCYCOM_ORESET 0x08
118 118
119struct ucycom_softc { 119struct ucycom_softc {
120 struct uhidev sc_hdev; 120 struct uhidev sc_hdev;
121 121
122 struct tty *sc_tty; 122 struct tty *sc_tty;
123 123
 124 enum {
 125 UCYCOM_INIT_NONE,
 126 UCYCOM_INIT_INITED
 127 } sc_init_state;
 128
124 kmutex_t sc_lock; /* protects refcnt, others */ 129 kmutex_t sc_lock; /* protects refcnt, others */
125 130
126 /* uhidev parameters */ 131 /* uhidev parameters */
127 size_t sc_flen; /* feature report length */ 132 size_t sc_flen; /* feature report length */
128 size_t sc_ilen; /* input report length */ 
129 size_t sc_olen; /* output report length */ 133 size_t sc_olen; /* output report length */
130 134
131 uint8_t *sc_obuf; 135 uint8_t *sc_obuf;
132 int sc_wlen; 136 int sc_wlen;
133 137
134 /* settings */ 138 /* settings */
135 uint32_t sc_baud; 139 uint32_t sc_baud;
136 uint8_t sc_cfg; /* Data format */ 140 uint8_t sc_cfg; /* Data format */
137 uint8_t sc_mcr; /* Modem control */ 141 uint8_t sc_mcr; /* Modem control */
138 uint8_t sc_msr; /* Modem status */ 142 uint8_t sc_msr; /* Modem status */
139 int sc_swflags; 143 int sc_swflags;
140 144
141 /* flags */ 145 /* flags */
@@ -209,45 +213,52 @@ ucycom_match(device_t parent, cfdata_t m @@ -209,45 +213,52 @@ ucycom_match(device_t parent, cfdata_t m
209 213
210static void 214static void
211ucycom_attach(device_t parent, device_t self, void *aux) 215ucycom_attach(device_t parent, device_t self, void *aux)
212{ 216{
213 struct ucycom_softc *sc = device_private(self); 217 struct ucycom_softc *sc = device_private(self);
214 struct uhidev_attach_arg *uha = aux; 218 struct uhidev_attach_arg *uha = aux;
215 int size, repid; 219 int size, repid;
216 void *desc; 220 void *desc;
217 221
218 sc->sc_hdev.sc_dev = self; 222 sc->sc_hdev.sc_dev = self;
219 sc->sc_hdev.sc_intr = ucycom_intr; 223 sc->sc_hdev.sc_intr = ucycom_intr;
220 sc->sc_hdev.sc_parent = uha->parent; 224 sc->sc_hdev.sc_parent = uha->parent;
221 sc->sc_hdev.sc_report_id = uha->reportid; 225 sc->sc_hdev.sc_report_id = uha->reportid;
 226 sc->sc_init_state = UCYCOM_INIT_NONE;
222 227
223 uhidev_get_report_desc(uha->parent, &desc, &size); 228 uhidev_get_report_desc(uha->parent, &desc, &size);
224 repid = uha->reportid; 229 repid = uha->reportid;
225 sc->sc_ilen = hid_report_size(desc, size, hid_input, repid); 
226 sc->sc_olen = hid_report_size(desc, size, hid_output, repid); 230 sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
227 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); 231 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
228 232
 233 if (sc->sc_olen != 8 && sc->sc_olen != 32)
 234 return;
 235 if (sc->sc_flen != 5)
 236 return;
 237
229 sc->sc_msr = sc->sc_mcr = 0; 238 sc->sc_msr = sc->sc_mcr = 0;
230 239
231 /* set up tty */ 240 /* set up tty */
232 sc->sc_tty = tty_alloc(); 241 sc->sc_tty = tty_alloc();
233 sc->sc_tty->t_sc = sc; 242 sc->sc_tty->t_sc = sc;
234 sc->sc_tty->t_oproc = ucycomstart; 243 sc->sc_tty->t_oproc = ucycomstart;
235 sc->sc_tty->t_param = ucycomparam; 244 sc->sc_tty->t_param = ucycomparam;
236 245
237 tty_attach(sc->sc_tty); 246 tty_attach(sc->sc_tty);
238 247
239 /* Nothing interesting to report */ 248 /* Nothing interesting to report */
240 aprint_normal("\n"); 249 aprint_normal("\n");
 250
 251 sc->sc_init_state = UCYCOM_INIT_INITED;
241} 252}
242 253
243 254
244static int 255static int
245ucycom_detach(device_t self, int flags) 256ucycom_detach(device_t self, int flags)
246{ 257{
247 struct ucycom_softc *sc = device_private(self); 258 struct ucycom_softc *sc = device_private(self);
248 struct tty *tp = sc->sc_tty; 259 struct tty *tp = sc->sc_tty;
249 int maj, mn; 260 int maj, mn;
250 int s; 261 int s;
251 262
252 DPRINTF(("ucycom_detach: sc=%p flags=%d tp=%p\n", sc, flags, tp)); 263 DPRINTF(("ucycom_detach: sc=%p flags=%d tp=%p\n", sc, flags, tp));
253 264
@@ -324,30 +335,30 @@ ucycom_shutdown(struct ucycom_softc *sc) @@ -324,30 +335,30 @@ ucycom_shutdown(struct ucycom_softc *sc)
324static int 335static int
325ucycomopen(dev_t dev, int flag, int mode, struct lwp *l) 336ucycomopen(dev_t dev, int flag, int mode, struct lwp *l)
326{ 337{
327 struct ucycom_softc *sc = 338 struct ucycom_softc *sc =
328 device_lookup_private(&ucycom_cd, UCYCOMUNIT(dev)); 339 device_lookup_private(&ucycom_cd, UCYCOMUNIT(dev));
329 struct tty *tp; 340 struct tty *tp;
330 int s, err; 341 int s, err;
331 342
332 DPRINTF(("ucycomopen: unit=%d\n", UCYCOMUNIT(dev))); 343 DPRINTF(("ucycomopen: unit=%d\n", UCYCOMUNIT(dev)));
333 DPRINTF(("ucycomopen: sc=%p\n", sc)); 344 DPRINTF(("ucycomopen: sc=%p\n", sc));
334 345
335 if (sc == NULL) 346 if (sc == NULL)
336 return ENXIO; 347 return ENXIO;
337 
338 if (sc->sc_dying) 348 if (sc->sc_dying)
339 return EIO; 349 return EIO;
340 350 if (sc->sc_init_state != UCYCOM_INIT_INITED)
 351 return ENXIO;
341 if (!device_is_active(sc->sc_hdev.sc_dev)) 352 if (!device_is_active(sc->sc_hdev.sc_dev))
342 return ENXIO; 353 return ENXIO;
343 354
344 tp = sc->sc_tty; 355 tp = sc->sc_tty;
345 356
346 DPRINTF(("ucycomopen: tp=%p\n", tp)); 357 DPRINTF(("ucycomopen: tp=%p\n", tp));
347 358
348 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 359 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
349 return EBUSY; 360 return EBUSY;
350 361
351 s = spltty(); 362 s = spltty();
352 363
353 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 364 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {