Unconditionally allocate a buffer big enough to hold a struct
authoranton <anton@openbsd.org>
Thu, 4 Feb 2021 06:57:19 +0000 (06:57 +0000)
committeranton <anton@openbsd.org>
Thu, 4 Feb 2021 06:57:19 +0000 (06:57 +0000)
usb_ctl_report.

Limiting the size of the buffer to the size of the requested report can
cause the ioctl(USB_GET_REPORT) command to fail with EFAULT as the
kernel will always copy sizeof(struct usb_ctl_report) bytes from the
address passed from user space. That is when the given address +
sizeof(struct usb_ctl_report) crosses a page boundary and the adjacent
page is not mapped.

ok mglocker@

usr.bin/usbhidctl/usbhid.c

index 335322c..921f211 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbhid.c,v 1.15 2019/06/28 13:35:05 deraadt Exp $     */
+/*     $OpenBSD: usbhid.c,v 1.16 2021/02/04 06:57:19 anton Exp $       */
 /*      $NetBSD: usbhid.c,v 1.22 2002/02/20 20:30:42 christos Exp $ */
 
 /*
@@ -394,13 +394,7 @@ allocreport(struct Sreport *report, report_desc_t rd, int repindex)
        report->size = reptsize;
 
        if (report->size > 0) {
-               /*
-                * Allocate a buffer with enough space for the
-                * report in the variable-sized data field.
-                */
-               report->buffer = malloc(sizeof(*report->buffer) -
-                                       sizeof(report->buffer->ucr_data) +
-                                       report->size);
+               report->buffer = malloc(sizeof(*report->buffer));
                if (report->buffer == NULL)
                        err(1, NULL);
        } else