summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2020-02-25 10:03:40 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2020-02-25 10:03:40 +0000
commitfe161e528ac3a8a647b7fbe3ad505acc04a7b904 (patch)
treea2ab6b23b88f0bf9a56390ad4743e279fc3b65ec
parent0cc026104910ec6f6a757228c8a21ed9b62843ec (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.c6
-rw-r--r--sys/dev/usb/utrh.c13
-rw-r--r--sys/dev/usb/utwitch.c16
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 */