diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2020-02-25 10:03:40 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2020-02-25 10:03:40 +0000 |
commit | fe161e528ac3a8a647b7fbe3ad505acc04a7b904 (patch) | |
tree | a2ab6b23b88f0bf9a56390ad4743e279fc3b65ec | |
parent | 0cc026104910ec6f6a757228c8a21ed9b62843ec (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@.
-rw-r--r-- | sys/dev/usb/ucycom.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/utrh.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/utwitch.c | 16 |
3 files changed, 22 insertions, 13 deletions
diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c index d4fe0d932fa..ca6d6e9c6b2 100644 --- a/sys/dev/usb/ucycom.c +++ b/sys/dev/usb/ucycom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ucycom.c,v 1.37 2017/12/30 20:46:59 guenther Exp $ */ +/* $OpenBSD: ucycom.c,v 1.38 2020/02/25 10:03:39 mpi Exp $ */ /* $NetBSD: ucycom.c,v 1.3 2005/08/05 07:27:47 skrll Exp $ */ /* @@ -374,6 +374,7 @@ ucycom_param(void *addr, int portno, struct termios *t) { struct ucycom_softc *sc = addr; uint8_t report[5]; + size_t rlen; uint32_t baud = 0; uint8_t cfg; @@ -443,8 +444,9 @@ ucycom_param(void *addr, int portno, struct termios *t) report[2] = (baud >> 16) & 0xff; report[3] = (baud >> 24) & 0xff; report[4] = cfg; + rlen = MIN(sc->sc_flen, sizeof(report)); if (uhidev_set_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, rlen) != rlen) return EIO; sc->sc_baud = baud; return (0); diff --git a/sys/dev/usb/utrh.c b/sys/dev/usb/utrh.c index 719b27249f0..cd6f43c06d9 100644 --- a/sys/dev/usb/utrh.c +++ b/sys/dev/usb/utrh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utrh.c,v 1.22 2019/11/12 07:47:30 mpi Exp $ */ +/* $OpenBSD: utrh.c,v 1.23 2020/02/25 10:03:39 mpi Exp $ */ /* * Copyright (c) 2009 Yojiro UO <yuo@nui.org> @@ -203,21 +203,24 @@ utrh_refresh(void *arg) { struct utrh_softc *sc = arg; unsigned int temp_tick, humidity_tick; - int temp, rh; + int temp, rh, flen, olen; uint8_t ledbuf[7]; + flen = MIN(sc->sc_flen, sizeof(ledbuf)); + /* turn on LED 1*/ bzero(ledbuf, sizeof(ledbuf)); ledbuf[0] = 0x3; ledbuf[1] = 0x1; if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT, - sc->sc_hdev.sc_report_id, ledbuf, sc->sc_flen) != sc->sc_flen) + sc->sc_hdev.sc_report_id, ledbuf, flen) != flen) printf("LED request failed\n"); /* issue query */ uint8_t cmdbuf[] = {0x31, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00}; + olen = MIN(sc->sc_olen, sizeof(cmdbuf)); if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, - sc->sc_hdev.sc_report_id, cmdbuf, sc->sc_olen) != sc->sc_flen) + sc->sc_hdev.sc_report_id, cmdbuf, olen) != olen) return; /* wait till sensor data are updated, 1s will be enough */ @@ -226,7 +229,7 @@ utrh_refresh(void *arg) /* turn off LED 1 */ ledbuf[1] = 0x0; if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT, - sc->sc_hdev.sc_report_id, ledbuf, sc->sc_flen) != sc->sc_flen) + sc->sc_hdev.sc_report_id, ledbuf, flen) != flen) printf("LED request failed\n"); temp_tick = (sc->sc_ibuf[2] * 256 + sc->sc_ibuf[3]) & 0x3fff; diff --git a/sys/dev/usb/utwitch.c b/sys/dev/usb/utwitch.c index d077c8185e8..cc8396a21dd 100644 --- a/sys/dev/usb/utwitch.c +++ b/sys/dev/usb/utwitch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utwitch.c,v 1.19 2020/02/13 18:19:07 jasper Exp $ */ +/* $OpenBSD: utwitch.c,v 1.20 2020/02/25 10:03:39 mpi Exp $ */ /* * Copyright (c) 2010 Yojiro UO <yuo@nui.org> @@ -56,7 +56,6 @@ struct utwitch_softc { struct usbd_device *sc_udev; /* uhidev parameters */ - size_t sc_flen; /* feature report length */ size_t sc_ilen; /* input report length */ size_t sc_olen; /* output report length */ @@ -134,7 +133,6 @@ utwitch_attach(struct device *parent, struct device *self, void *aux) repid = uha->reportid; sc->sc_ilen = hid_report_size(desc, size, hid_input, repid); sc->sc_olen = hid_report_size(desc, size, hid_output, repid); - sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); err = uhidev_open(&sc->sc_hdev); if (err) { @@ -266,13 +264,15 @@ void utwitch_set_mode(struct utwitch_softc *sc, uint8_t val) { uint8_t req[8]; + int olen; + olen = MIN(sc->sc_olen, sizeof(req)); memset(req, CMD_PADDING, sizeof(req)); req[0] = CMD_MODE; req[1] = val; req[2] = CMD_EOF; if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, - sc->sc_hdev.sc_report_id, req, sc->sc_olen) != sc->sc_olen) { + sc->sc_hdev.sc_report_id, req, olen) != olen) { printf("uhidev_set_report error:EIO\n"); return; } @@ -285,14 +285,16 @@ void utwitch_read_value_request(struct utwitch_softc *sc) { uint8_t req[8]; + int olen; + olen = MIN(sc->sc_olen, sizeof(req)); memset(req, CMD_PADDING, sizeof(req)); req[0] = CMD_READ; req[1] = CMD_EOF; sc->issueing_cmd = CMD_READ; sc->accepted_cmd = CMD_NONE; if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, - sc->sc_hdev.sc_report_id, req, sc->sc_olen) != sc->sc_olen) + sc->sc_hdev.sc_report_id, req, olen) != olen) return; /* wait till sensor data are updated, 500ms will be enough */ @@ -304,7 +306,9 @@ utwitch_write_value_request(struct utwitch_softc *sc, uint32_t val) { uint32_t v; uint8_t req[8]; + int olen; + olen = MIN(sc->sc_olen, sizeof(req)); req[0] = CMD_WRITE; req[1] = 0; req[6] = CMD_EOF; @@ -315,7 +319,7 @@ utwitch_write_value_request(struct utwitch_softc *sc, uint32_t val) sc->issueing_cmd = CMD_WRITE; sc->accepted_cmd = CMD_NONE; if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, - sc->sc_hdev.sc_report_id, req, sc->sc_olen) != sc->sc_olen) + sc->sc_hdev.sc_report_id, req, olen) != olen) return; /* wait till sensor data are updated, 250ms will be enough */ |