]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Nov 2019 08:26:02 +0000 (09:26 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Nov 2019 08:26:02 +0000 (09:26 +0100)
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

queue-4.4/hid-fix-assumption-that-devices-have-inputs.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/usb-gadget-reject-endpoints-with-0-maxpacket-value.patch [new file with mode: 0644]
queue-4.4/usb-ldusb-fix-control-message-timeout.patch [new file with mode: 0644]
queue-4.4/usb-ldusb-fix-ring-buffer-locking.patch [new file with mode: 0644]
queue-4.4/usb-serial-whiteheat-fix-line-speed-endianness.patch [new file with mode: 0644]
queue-4.4/usb-serial-whiteheat-fix-potential-slab-corruption.patch [new file with mode: 0644]

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 (file)
index 0000000..b9fe7fd
--- /dev/null
@@ -0,0 +1,332 @@
+From d9d4b1e46d9543a82c23f6df03f4ad697dab361b Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Thu, 3 Oct 2019 14:53:59 -0400
+Subject: HID: Fix assumption that devices have inputs
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+CC: <stable@vger.kernel.org>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)
index 33dc58ab93131e37700280f914468da49f08bba1..08664387fded3e70c400089ad282efc927d0ed8d 100644 (file)
@@ -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 (file)
index 0000000..786f976
--- /dev/null
@@ -0,0 +1,55 @@
+From 54f83b8c8ea9b22082a496deadf90447a326954e Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Oct 2019 10:54:26 -0400
+Subject: USB: gadget: Reject endpoints with 0 maxpacket value
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Reported-and-tested-by: syzbot+8ab8bf161038a8768553@syzkaller.appspotmail.com
+CC: <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910281052370.1485-100000@iolanthe.rowland.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..df107ae
--- /dev/null
@@ -0,0 +1,34 @@
+From 52403cfbc635d28195167618690595013776ebde Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 22 Oct 2019 17:31:27 +0200
+Subject: USB: ldusb: fix control-message timeout
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <stable@vger.kernel.org>     # 2.6.13
+Reported-by: syzbot+a4fbb3bb76cda0ea4e58@syzkaller.appspotmail.com
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20191022153127.22295-1-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..f2c9b63
--- /dev/null
@@ -0,0 +1,48 @@
+From d98ee2a19c3334e9343df3ce254b496f1fc428eb Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 22 Oct 2019 16:32:02 +0200
+Subject: USB: ldusb: fix ring-buffer locking
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <stable@vger.kernel.org>     # 2.6.13
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20191022143203.5260-2-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..1859165
--- /dev/null
@@ -0,0 +1,63 @@
+From 84968291d7924261c6a0624b9a72f952398e258b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 29 Oct 2019 11:23:54 +0100
+Subject: USB: serial: whiteheat: fix line-speed endianness
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <johan@kernel.org>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20191029102354.2733-3-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..a708d78
--- /dev/null
@@ -0,0 +1,35 @@
+From 1251dab9e0a2c4d0d2d48370ba5baa095a5e8774 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 29 Oct 2019 11:23:53 +0100
+Subject: USB: serial: whiteheat: fix potential slab corruption
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <stable@vger.kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20191029102354.2733-2-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;