Mon Mar 28 12:44:37 2022 UTC ()
uhidev(9): Define UHIDEV_MAXREPID = 255.

Report ids are limited by the HID spec to a single byte.

- Clamp max report id in report descriptor to this.

- Prune dead refcnt-overflow error branches.  Assert instead.


(riastradh)
diff -r1.91 -r1.92 src/sys/dev/usb/uhidev.c
diff -r1.26 -r1.27 src/sys/dev/usb/uhidev.h

cvs diff -r1.91 -r1.92 src/sys/dev/usb/uhidev.c (expand / switch to unified diff)

--- src/sys/dev/usb/uhidev.c 2022/03/28 12:44:28 1.91
+++ src/sys/dev/usb/uhidev.c 2022/03/28 12:44:37 1.92
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $ */ 1/* $NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001, 2012 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 Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). 9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "opt_usb.h" 41#include "opt_usb.h"
42#endif 42#endif
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/types.h> 45#include <sys/types.h>
46 46
47#include <sys/atomic.h> 47#include <sys/atomic.h>
48#include <sys/conf.h> 48#include <sys/conf.h>
49#include <sys/device.h> 49#include <sys/device.h>
50#include <sys/ioctl.h> 50#include <sys/ioctl.h>
51#include <sys/kernel.h> 51#include <sys/kernel.h>
@@ -448,27 +448,27 @@ uhidev_attach(device_t parent, device_t  @@ -448,27 +448,27 @@ uhidev_attach(device_t parent, device_t
448static int 448static int
449uhidev_maxrepid(void *buf, int len) 449uhidev_maxrepid(void *buf, int len)
450{ 450{
451 struct hid_data *d; 451 struct hid_data *d;
452 struct hid_item h; 452 struct hid_item h;
453 int maxid; 453 int maxid;
454 454
455 maxid = -1; 455 maxid = -1;
456 h.report_ID = 0; 456 h.report_ID = 0;
457 for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) 457 for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); )
458 if ((int)h.report_ID > maxid) 458 if ((int)h.report_ID > maxid)
459 maxid = h.report_ID; 459 maxid = h.report_ID;
460 hid_end_parse(d); 460 hid_end_parse(d);
461 return maxid; 461 return MIN(maxid, UHIDEV_MAXREPID);
462} 462}
463 463
464static int 464static int
465uhidevprint(void *aux, const char *pnp) 465uhidevprint(void *aux, const char *pnp)
466{ 466{
467 struct uhidev_attach_arg *uha = aux; 467 struct uhidev_attach_arg *uha = aux;
468 468
469 if (pnp) 469 if (pnp)
470 aprint_normal("uhid at %s", pnp); 470 aprint_normal("uhid at %s", pnp);
471 if (uha->reportid != 0) 471 if (uha->reportid != 0)
472 aprint_normal(" reportid %d", uha->reportid); 472 aprint_normal(" reportid %d", uha->reportid);
473 return UNCONF; 473 return UNCONF;
474} 474}
@@ -661,61 +661,58 @@ uhidev_config_exit(struct uhidev_softc * @@ -661,61 +661,58 @@ uhidev_config_exit(struct uhidev_softc *
661 * Ensure the pipes of the softc are open. Caller must hold 661 * Ensure the pipes of the softc are open. Caller must hold
662 * sc_lock, which may be released and reacquired. 662 * sc_lock, which may be released and reacquired.
663 */ 663 */
664static int 664static int
665uhidev_open_pipes(struct uhidev_softc *sc) 665uhidev_open_pipes(struct uhidev_softc *sc)
666{ 666{
667 usbd_status err; 667 usbd_status err;
668 int error; 668 int error;
669 669
670 KASSERT(mutex_owned(&sc->sc_lock)); 670 KASSERT(mutex_owned(&sc->sc_lock));
671 671
672 /* 672 /*
673 * If the pipes are already open, just increment the reference 673 * If the pipes are already open, just increment the reference
674 * count, or fail if it would overflow. 674 * count. The reference count is limited by the number of
 675 * report ids, so this can't overflow.
675 */ 676 */
676 if (sc->sc_refcnt) { 677 if (sc->sc_refcnt) {
677 if (sc->sc_refcnt == INT_MAX) 678 KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID);
678 return EBUSY; 
679 sc->sc_refcnt++; 679 sc->sc_refcnt++;
680 return 0; 680 return 0;
681 } 681 }
682 682
683 /* 683 /*
684 * If there's no input data to prepare, don't bother with the 684 * If there's no input data to prepare, don't bother with the
685 * pipes. We assume any device that does output also does 685 * pipes. We assume any device that does output also does
686 * input; if you have a device where this is wrong, then 686 * input; if you have a device where this is wrong, then
687 * uhidev_write will fail gracefully (it checks sc->sc_opipe), 687 * uhidev_write will fail gracefully (it checks sc->sc_opipe),
688 * and you can use that device to test the changes needed to 688 * and you can use that device to test the changes needed to
689 * open the output pipe here. 689 * open the output pipe here.
690 */ 690 */
691 if (sc->sc_isize == 0) 691 if (sc->sc_isize == 0)
692 return 0; 692 return 0;
693 693
694 /* 694 /*
695 * Lock the configuration and release sc_lock -- we may sleep 695 * Lock the configuration and release sc_lock -- we may sleep
696 * to allocate. If someone else got in first, we're done; 696 * to allocate. If someone else got in first, we're done;
697 * otherwise open the pipes. 697 * otherwise open the pipes.
698 */ 698 */
699 error = uhidev_config_enter(sc); 699 error = uhidev_config_enter(sc);
700 if (error) 700 if (error)
701 goto out; 701 goto out;
702 if (sc->sc_refcnt) { 702 if (sc->sc_refcnt) {
703 if (sc->sc_refcnt == INT_MAX) { 703 KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID);
704 error = EBUSY; 704 sc->sc_refcnt++;
705 } else { 705 error = 0;
706 sc->sc_refcnt++; 
707 error = 0; 
708 } 
709 goto out0; 706 goto out0;
710 } 707 }
711 mutex_exit(&sc->sc_lock); 708 mutex_exit(&sc->sc_lock);
712 709
713 /* Allocate an input buffer. */ 710 /* Allocate an input buffer. */
714 sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); 711 sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP);
715 712
716 /* Set up input interrupt pipe. */ 713 /* Set up input interrupt pipe. */
717 DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, 714 DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize,
718 sc->sc_iep_addr)); 715 sc->sc_iep_addr));
719 716
720 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, 717 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr,
721 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, 718 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf,

cvs diff -r1.26 -r1.27 src/sys/dev/usb/uhidev.h (expand / switch to unified diff)

--- src/sys/dev/usb/uhidev.h 2022/03/28 12:44:17 1.26
+++ src/sys/dev/usb/uhidev.h 2022/03/28 12:44:37 1.27
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhidev.h,v 1.26 2022/03/28 12:44:17 riastradh Exp $ */ 1/* $NetBSD: uhidev.h,v 1.27 2022/03/28 12:44:37 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001 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 Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology. 9 * Carlstedt Research & Technology.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -44,15 +44,16 @@ struct uhidev_attach_arg { @@ -44,15 +44,16 @@ struct uhidev_attach_arg {
44}; 44};
45 45
46void uhidev_get_report_desc(struct uhidev *, void **, int *); 46void uhidev_get_report_desc(struct uhidev *, void **, int *);
47int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *); 47int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *);
48void uhidev_stop(struct uhidev *); 48void uhidev_stop(struct uhidev *);
49void uhidev_close(struct uhidev *); 49void uhidev_close(struct uhidev *);
50usbd_status uhidev_set_report(struct uhidev *, int, void *, int); 50usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
51usbd_status uhidev_get_report(struct uhidev *, int, void *, int); 51usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
52usbd_status uhidev_write(struct uhidev *, void *, int); 52usbd_status uhidev_write(struct uhidev *, void *, int);
53usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int, 53usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int,
54 usbd_callback, void *); 54 usbd_callback, void *);
55 55
56#define UHIDEV_OSIZE 64 56#define UHIDEV_OSIZE 64
 57#define UHIDEV_MAXREPID 255
57 58
58#endif /* _DEV_USB_UHIDEV_H_ */ 59#endif /* _DEV_USB_UHIDEV_H_ */