summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2020-02-14 14:55:31 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2020-02-14 14:55:31 +0000
commit27acc75eb27ce7e4a090279c98ecfa53b9a07bf8 (patch)
treeb2fdcdcb23d6823490e018ae59c5ccb1b2465122 /sys/dev/usb
parente8fbcde15c6527550bb779333bec26d7ef4598a4 (diff)
Prevent buffer overflows by not assuming the report length, given by
the hardware, is necessarily smaller than the length of the on-stack buffer. Original fix from Maxime Villard in NetBSD via deraadt@. Tested by matthieu@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/uthum.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/sys/dev/usb/uthum.c b/sys/dev/usb/uthum.c
index 4af3648e402..601abdc64ab 100644
--- a/sys/dev/usb/uthum.c
+++ b/sys/dev/usb/uthum.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthum.c,v 1.33 2020/01/13 10:01:24 mpi Exp $ */
+/* $OpenBSD: uthum.c,v 1.34 2020/02/14 14:55:30 mpi Exp $ */
/*
* Copyright (c) 2009, 2010 Yojiro UO <yuo@nui.org>
@@ -284,28 +284,29 @@ int
uthum_issue_cmd(struct uthum_softc *sc, uint8_t target_cmd, int delay)
{
uint8_t cmdbuf[32];
- int i, actlen;
+ int i, actlen, olen;
+
+ olen = MIN(sc->sc_olen, sizeof(cmdbuf));
bzero(cmdbuf, sizeof(cmdbuf));
memcpy(cmdbuf, cmd_issue, sizeof(cmd_issue));
actlen = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT,
- sc->sc_hdev.sc_report_id, cmdbuf, sc->sc_olen);
- if (actlen != sc->sc_olen)
+ sc->sc_hdev.sc_report_id, cmdbuf, olen);
+ if (actlen != olen)
return EIO;
bzero(cmdbuf, sizeof(cmdbuf));
cmdbuf[0] = target_cmd;
actlen = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT,
- sc->sc_hdev.sc_report_id, cmdbuf, sc->sc_olen);
- if (actlen != sc->sc_olen)
+ sc->sc_hdev.sc_report_id, cmdbuf, olen);
+ if (actlen != olen)
return EIO;
bzero(cmdbuf, sizeof(cmdbuf));
for (i = 0; i < 7; i++) {
actlen = uhidev_set_report(sc->sc_hdev.sc_parent,
- UHID_OUTPUT_REPORT, sc->sc_hdev.sc_report_id, cmdbuf,
- sc->sc_olen);
- if (actlen != sc->sc_olen)
+ UHID_OUTPUT_REPORT, sc->sc_hdev.sc_report_id, cmdbuf, olen);
+ if (actlen != olen)
return EIO;
}
@@ -322,6 +323,7 @@ uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
size_t len, int delay)
{
uint8_t cmdbuf[32], report[256];
+ int olen, flen;
/* if return buffer is null, do nothing */
if ((buf == NULL) || len == 0)
@@ -330,10 +332,12 @@ uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
if (uthum_issue_cmd(sc, target_cmd, 50))
return 0;
+ olen = MIN(sc->sc_olen, sizeof(cmdbuf));
+
bzero(cmdbuf, sizeof(cmdbuf));
memcpy(cmdbuf, cmd_query, sizeof(cmd_query));
if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT,
- sc->sc_hdev.sc_report_id, cmdbuf, sc->sc_olen) != sc->sc_olen)
+ sc->sc_hdev.sc_report_id, cmdbuf, olen) != olen)
return EIO;
/* wait if required */
@@ -342,8 +346,9 @@ uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
MSEC_TO_NSEC(delay));
/* get answer */
+ flen = MIN(sc->sc_flen, sizeof(report));
if (uhidev_get_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT,
- sc->sc_hdev.sc_report_id, report, sc->sc_flen) != sc->sc_flen)
+ sc->sc_hdev.sc_report_id, report, flen) != flen)
return EIO;
memcpy(buf, report, len);
return 0;