From: Greg Kroah-Hartman Date: Mon, 4 Nov 2019 08:26:02 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.4.199~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=22ca3e04c24f306f7c8d98ad2138f9cd3c44bace;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: hid-fix-assumption-that-devices-have-inputs.patch usb-gadget-reject-endpoints-with-0-maxpacket-value.patch usb-ldusb-fix-control-message-timeout.patch usb-ldusb-fix-ring-buffer-locking.patch usb-serial-whiteheat-fix-line-speed-endianness.patch usb-serial-whiteheat-fix-potential-slab-corruption.patch --- diff --git a/queue-4.4/hid-fix-assumption-that-devices-have-inputs.patch b/queue-4.4/hid-fix-assumption-that-devices-have-inputs.patch new file mode 100644 index 00000000000..b9fe7fd265f --- /dev/null +++ b/queue-4.4/hid-fix-assumption-that-devices-have-inputs.patch @@ -0,0 +1,332 @@ +From d9d4b1e46d9543a82c23f6df03f4ad697dab361b Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Thu, 3 Oct 2019 14:53:59 -0400 +Subject: HID: Fix assumption that devices have inputs + +From: Alan Stern + +commit d9d4b1e46d9543a82c23f6df03f4ad697dab361b upstream. + +The syzbot fuzzer found a slab-out-of-bounds write bug in the hid-gaff +driver. The problem is caused by the driver's assumption that the +device must have an input report. While this will be true for all +normal HID input devices, a suitably malicious device can violate the +assumption. + +The same assumption is present in over a dozen other HID drivers. +This patch fixes them by checking that the list of hid_inputs for the +hid_device is nonempty before allowing it to be used. + +Reported-and-tested-by: syzbot+403741a091bf41d4ae79@syzkaller.appspotmail.com +Signed-off-by: Alan Stern +CC: +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-axff.c | 11 +++++++++-- + drivers/hid/hid-dr.c | 12 +++++++++--- + drivers/hid/hid-emsff.c | 12 +++++++++--- + drivers/hid/hid-gaff.c | 12 +++++++++--- + drivers/hid/hid-holtekff.c | 12 +++++++++--- + drivers/hid/hid-lg2ff.c | 12 +++++++++--- + drivers/hid/hid-lg3ff.c | 11 +++++++++-- + drivers/hid/hid-lg4ff.c | 11 +++++++++-- + drivers/hid/hid-lgff.c | 11 +++++++++-- + drivers/hid/hid-sony.c | 12 +++++++++--- + drivers/hid/hid-tmff.c | 12 +++++++++--- + drivers/hid/hid-zpff.c | 12 +++++++++--- + 12 files changed, 108 insertions(+), 32 deletions(-) + +--- a/drivers/hid/hid-axff.c ++++ b/drivers/hid/hid-axff.c +@@ -75,13 +75,20 @@ static int axff_init(struct hid_device * + { + struct axff_device *axff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int field_count = 0; + int i, j; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-dr.c ++++ b/drivers/hid/hid-dr.c +@@ -87,13 +87,19 @@ static int drff_init(struct hid_device * + { + struct drff_device *drff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-emsff.c ++++ b/drivers/hid/hid-emsff.c +@@ -59,13 +59,19 @@ static int emsff_init(struct hid_device + { + struct emsff_device *emsff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-gaff.c ++++ b/drivers/hid/hid-gaff.c +@@ -77,14 +77,20 @@ static int gaff_init(struct hid_device * + { + struct gaff_device *gaff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct list_head *report_ptr = report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-holtekff.c ++++ b/drivers/hid/hid-holtekff.c +@@ -140,13 +140,19 @@ static int holtekff_init(struct hid_devi + { + struct holtekff_device *holtekff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output report found\n"); + return -ENODEV; +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -62,11 +62,17 @@ int lg2ff_init(struct hid_device *hid) + { + struct lg2ff_device *lg2ff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -129,12 +129,19 @@ static const signed short ff3_joystick_a + + int lg3ff_init(struct hid_device *hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -1158,8 +1158,8 @@ static int lg4ff_handle_multimode_wheel( + + int lg4ff_init(struct hid_device *hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); +@@ -1171,6 +1171,13 @@ int lg4ff_init(struct hid_device *hid) + int mmode_ret, mmode_idx = -1; + u16 real_product_id; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -1; +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -127,12 +127,19 @@ static void hid_lgff_set_autocenter(stru + + int lgff_init(struct hid_device* hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff_joystick; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1960,9 +1960,15 @@ static int sony_play_effect(struct input + + static int sony_init_ff(struct sony_sc *sc) + { +- struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; ++ ++ if (list_empty(&sc->hdev->inputs)) { ++ hid_err(sc->hdev, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; + + input_set_capability(input_dev, EV_FF, FF_RUMBLE); + return input_ff_create_memless(input_dev, NULL, sony_play_effect); +--- a/drivers/hid/hid-tmff.c ++++ b/drivers/hid/hid-tmff.c +@@ -136,12 +136,18 @@ static int tmff_init(struct hid_device * + struct tmff_device *tmff; + struct hid_report *report; + struct list_head *report_list; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; ++ + tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); + if (!tmff) + return -ENOMEM; +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -66,11 +66,17 @@ static int zpff_init(struct hid_device * + { + struct zpff_device *zpff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int i, error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + for (i = 0; i < 4; i++) { + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); + if (!report) diff --git a/queue-4.4/series b/queue-4.4/series index 33dc58ab931..08664387fde 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -26,3 +26,9 @@ fuse-flush-dirty-data-metadata-before-non-truncate-setattr.patch fuse-truncate-pending-writes-on-o_trunc.patch alsa-bebob-fix-prototype-of-helper-function-to-return-negative-value.patch uas-revert-commit-3ae62a42090f-uas-fix-alignment-of-scatter-gather-segments.patch +usb-gadget-reject-endpoints-with-0-maxpacket-value.patch +usb-ldusb-fix-ring-buffer-locking.patch +usb-ldusb-fix-control-message-timeout.patch +usb-serial-whiteheat-fix-potential-slab-corruption.patch +usb-serial-whiteheat-fix-line-speed-endianness.patch +hid-fix-assumption-that-devices-have-inputs.patch diff --git a/queue-4.4/usb-gadget-reject-endpoints-with-0-maxpacket-value.patch b/queue-4.4/usb-gadget-reject-endpoints-with-0-maxpacket-value.patch new file mode 100644 index 00000000000..786f976184f --- /dev/null +++ b/queue-4.4/usb-gadget-reject-endpoints-with-0-maxpacket-value.patch @@ -0,0 +1,55 @@ +From 54f83b8c8ea9b22082a496deadf90447a326954e Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 28 Oct 2019 10:54:26 -0400 +Subject: USB: gadget: Reject endpoints with 0 maxpacket value + +From: Alan Stern + +commit 54f83b8c8ea9b22082a496deadf90447a326954e upstream. + +Endpoints with a maxpacket length of 0 are probably useless. They +can't transfer any data, and it's not at all unlikely that a UDC will +crash or hang when trying to handle a non-zero-length usb_request for +such an endpoint. Indeed, dummy-hcd gets a divide error when trying +to calculate the remainder of a transfer length by the maxpacket +value, as discovered by the syzbot fuzzer. + +Currently the gadget core does not check for endpoints having a +maxpacket value of 0. This patch adds a check to usb_ep_enable(), +preventing such endpoints from being used. + +As far as I know, none of the gadget drivers in the kernel tries to +create an endpoint with maxpacket = 0, but until now there has been +nothing to prevent userspace programs under gadgetfs or configfs from +doing it. + +Signed-off-by: Alan Stern +Reported-and-tested-by: syzbot+8ab8bf161038a8768553@syzkaller.appspotmail.com +CC: +Acked-by: Felipe Balbi +Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910281052370.1485-100000@iolanthe.rowland.org +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/usb/gadget.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/include/linux/usb/gadget.h ++++ b/include/linux/usb/gadget.h +@@ -270,6 +270,16 @@ static inline int usb_ep_enable(struct u + if (ep->enabled) + return 0; + ++ /* UDC drivers can't handle endpoints with maxpacket size 0 */ ++ if (usb_endpoint_maxp(ep->desc) == 0) { ++ /* ++ * We should log an error message here, but we can't call ++ * dev_err() because there's no way to find the gadget ++ * given only ep. ++ */ ++ return -EINVAL; ++ } ++ + ret = ep->ops->enable(ep, ep->desc); + if (ret) + return ret; diff --git a/queue-4.4/usb-ldusb-fix-control-message-timeout.patch b/queue-4.4/usb-ldusb-fix-control-message-timeout.patch new file mode 100644 index 00000000000..df107aef455 --- /dev/null +++ b/queue-4.4/usb-ldusb-fix-control-message-timeout.patch @@ -0,0 +1,34 @@ +From 52403cfbc635d28195167618690595013776ebde Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 22 Oct 2019 17:31:27 +0200 +Subject: USB: ldusb: fix control-message timeout + +From: Johan Hovold + +commit 52403cfbc635d28195167618690595013776ebde upstream. + +USB control-message timeouts are specified in milliseconds, not jiffies. +Waiting 83 minutes for a transfer to complete is a bit excessive. + +Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") +Cc: stable # 2.6.13 +Reported-by: syzbot+a4fbb3bb76cda0ea4e58@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191022153127.22295-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/ldusb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/misc/ldusb.c ++++ b/drivers/usb/misc/ldusb.c +@@ -584,7 +584,7 @@ static ssize_t ld_usb_write(struct file + 1 << 8, 0, + dev->interrupt_out_buffer, + bytes_to_write, +- USB_CTRL_SET_TIMEOUT * HZ); ++ USB_CTRL_SET_TIMEOUT); + if (retval < 0) + dev_err(&dev->intf->dev, + "Couldn't submit HID_REQ_SET_REPORT %d\n", diff --git a/queue-4.4/usb-ldusb-fix-ring-buffer-locking.patch b/queue-4.4/usb-ldusb-fix-ring-buffer-locking.patch new file mode 100644 index 00000000000..f2c9b63dcbb --- /dev/null +++ b/queue-4.4/usb-ldusb-fix-ring-buffer-locking.patch @@ -0,0 +1,48 @@ +From d98ee2a19c3334e9343df3ce254b496f1fc428eb Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 22 Oct 2019 16:32:02 +0200 +Subject: USB: ldusb: fix ring-buffer locking + +From: Johan Hovold + +commit d98ee2a19c3334e9343df3ce254b496f1fc428eb upstream. + +The custom ring-buffer implementation was merged without any locking or +explicit memory barriers, but a spinlock was later added by commit +9d33efd9a791 ("USB: ldusb bugfix"). + +The lock did not cover the update of the tail index once the entry had +been processed, something which could lead to memory corruption on +weakly ordered architectures or due to compiler optimisations. + +Specifically, a completion handler running on another CPU might observe +the incremented tail index and update the entry before ld_usb_read() is +done with it. + +Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") +Fixes: 9d33efd9a791 ("USB: ldusb bugfix") +Cc: stable # 2.6.13 +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191022143203.5260-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/ldusb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/misc/ldusb.c ++++ b/drivers/usb/misc/ldusb.c +@@ -499,11 +499,11 @@ static ssize_t ld_usb_read(struct file * + retval = -EFAULT; + goto unlock_exit; + } +- dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; +- + retval = bytes_to_read; + + spin_lock_irq(&dev->rbsl); ++ dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; ++ + if (dev->buffer_overflow) { + dev->buffer_overflow = 0; + spin_unlock_irq(&dev->rbsl); diff --git a/queue-4.4/usb-serial-whiteheat-fix-line-speed-endianness.patch b/queue-4.4/usb-serial-whiteheat-fix-line-speed-endianness.patch new file mode 100644 index 00000000000..1859165b422 --- /dev/null +++ b/queue-4.4/usb-serial-whiteheat-fix-line-speed-endianness.patch @@ -0,0 +1,63 @@ +From 84968291d7924261c6a0624b9a72f952398e258b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 29 Oct 2019 11:23:54 +0100 +Subject: USB: serial: whiteheat: fix line-speed endianness + +From: Johan Hovold + +commit 84968291d7924261c6a0624b9a72f952398e258b upstream. + +Add missing endianness conversion when setting the line speed so that +this driver might work also on big-endian machines. + +Also use an unsigned format specifier in the corresponding debug +message. + +Signed-off-by: Johan Hovold +Cc: stable +Link: https://lore.kernel.org/r/20191029102354.2733-3-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/whiteheat.c | 9 ++++++--- + drivers/usb/serial/whiteheat.h | 2 +- + 2 files changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -681,6 +681,7 @@ static void firm_setup_port(struct tty_s + struct device *dev = &port->dev; + struct whiteheat_port_settings port_settings; + unsigned int cflag = tty->termios.c_cflag; ++ speed_t baud; + + port_settings.port = port->port_number + 1; + +@@ -741,11 +742,13 @@ static void firm_setup_port(struct tty_s + dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff); + + /* get the baud rate wanted */ +- port_settings.baud = tty_get_baud_rate(tty); +- dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud); ++ baud = tty_get_baud_rate(tty); ++ port_settings.baud = cpu_to_le32(baud); ++ dev_dbg(dev, "%s - baud rate = %u\n", __func__, baud); + + /* fixme: should set validated settings */ +- tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud); ++ tty_encode_baud_rate(tty, baud, baud); ++ + /* handle any settings that aren't specified in the tty structure */ + port_settings.lloop = 0; + +--- a/drivers/usb/serial/whiteheat.h ++++ b/drivers/usb/serial/whiteheat.h +@@ -91,7 +91,7 @@ struct whiteheat_simple { + + struct whiteheat_port_settings { + __u8 port; /* port number (1 to N) */ +- __u32 baud; /* any value 7 - 460800, firmware calculates ++ __le32 baud; /* any value 7 - 460800, firmware calculates + best fit; arrives little endian */ + __u8 bits; /* 5, 6, 7, or 8 */ + __u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */ diff --git a/queue-4.4/usb-serial-whiteheat-fix-potential-slab-corruption.patch b/queue-4.4/usb-serial-whiteheat-fix-potential-slab-corruption.patch new file mode 100644 index 00000000000..a708d785644 --- /dev/null +++ b/queue-4.4/usb-serial-whiteheat-fix-potential-slab-corruption.patch @@ -0,0 +1,35 @@ +From 1251dab9e0a2c4d0d2d48370ba5baa095a5e8774 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 29 Oct 2019 11:23:53 +0100 +Subject: USB: serial: whiteheat: fix potential slab corruption + +From: Johan Hovold + +commit 1251dab9e0a2c4d0d2d48370ba5baa095a5e8774 upstream. + +Fix a user-controlled slab buffer overflow due to a missing sanity check +on the bulk-out transfer buffer used for control requests. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191029102354.2733-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/whiteheat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -604,6 +604,10 @@ static int firm_send_command(struct usb_ + + command_port = port->serial->port[COMMAND_PORT]; + command_info = usb_get_serial_port_data(command_port); ++ ++ if (command_port->bulk_out_size < datasize + 1) ++ return -EIO; ++ + mutex_lock(&command_info->mutex); + command_info->command_finished = false; +