--- /dev/null
+From bf74aa86e111aa3b2fbb25db37e3a3fab71b5b68 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 12 Aug 2019 14:57:14 +0200
+Subject: can: bcm: switch timer to HRTIMER_MODE_SOFT and remove hrtimer_tasklet
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit bf74aa86e111aa3b2fbb25db37e3a3fab71b5b68 upstream.
+
+This patch switches the timer to HRTIMER_MODE_SOFT, which executed the
+timer callback in softirq context and removes the hrtimer_tasklet.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Ziyang Xuan <william.xuanziyang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/can/bcm.c | 156 +++++++++++++++++++---------------------------------------
+ 1 file changed, 52 insertions(+), 104 deletions(-)
+
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -105,7 +105,6 @@ struct bcm_op {
+ unsigned long frames_abs, frames_filtered;
+ struct bcm_timeval ival1, ival2;
+ struct hrtimer timer, thrtimer;
+- struct tasklet_struct tsklet, thrtsklet;
+ ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
+ int rx_ifindex;
+ int cfsiz;
+@@ -374,25 +373,34 @@ static void bcm_send_to_user(struct bcm_
+ }
+ }
+
+-static void bcm_tx_start_timer(struct bcm_op *op)
++static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
+ {
++ ktime_t ival;
++
+ if (op->kt_ival1 && op->count)
+- hrtimer_start(&op->timer,
+- ktime_add(ktime_get(), op->kt_ival1),
+- HRTIMER_MODE_ABS);
++ ival = op->kt_ival1;
+ else if (op->kt_ival2)
+- hrtimer_start(&op->timer,
+- ktime_add(ktime_get(), op->kt_ival2),
+- HRTIMER_MODE_ABS);
++ ival = op->kt_ival2;
++ else
++ return false;
++
++ hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
++ return true;
+ }
+
+-static void bcm_tx_timeout_tsklet(unsigned long data)
++static void bcm_tx_start_timer(struct bcm_op *op)
+ {
+- struct bcm_op *op = (struct bcm_op *)data;
++ if (bcm_tx_set_expiry(op, &op->timer))
++ hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS_SOFT);
++}
++
++/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
++static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
++{
++ struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+ struct bcm_msg_head msg_head;
+
+ if (op->kt_ival1 && (op->count > 0)) {
+-
+ op->count--;
+ if (!op->count && (op->flags & TX_COUNTEVT)) {
+
+@@ -410,22 +418,12 @@ static void bcm_tx_timeout_tsklet(unsign
+ }
+ bcm_can_tx(op);
+
+- } else if (op->kt_ival2)
++ } else if (op->kt_ival2) {
+ bcm_can_tx(op);
++ }
+
+- bcm_tx_start_timer(op);
+-}
+-
+-/*
+- * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
+- */
+-static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
+-{
+- struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+-
+- tasklet_schedule(&op->tsklet);
+-
+- return HRTIMER_NORESTART;
++ return bcm_tx_set_expiry(op, &op->timer) ?
++ HRTIMER_RESTART : HRTIMER_NORESTART;
+ }
+
+ /*
+@@ -492,7 +490,7 @@ static void bcm_rx_update_and_send(struc
+ /* do not send the saved data - only start throttle timer */
+ hrtimer_start(&op->thrtimer,
+ ktime_add(op->kt_lastmsg, op->kt_ival2),
+- HRTIMER_MODE_ABS);
++ HRTIMER_MODE_ABS_SOFT);
+ return;
+ }
+
+@@ -551,14 +549,21 @@ static void bcm_rx_starttimer(struct bcm
+ return;
+
+ if (op->kt_ival1)
+- hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
++ hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL_SOFT);
+ }
+
+-static void bcm_rx_timeout_tsklet(unsigned long data)
++/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
++static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+ {
+- struct bcm_op *op = (struct bcm_op *)data;
++ struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+ struct bcm_msg_head msg_head;
+
++ /* if user wants to be informed, when cyclic CAN-Messages come back */
++ if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
++ /* clear received CAN frames to indicate 'nothing received' */
++ memset(op->last_frames, 0, op->nframes * op->cfsiz);
++ }
++
+ /* create notification to user */
+ memset(&msg_head, 0, sizeof(msg_head));
+ msg_head.opcode = RX_TIMEOUT;
+@@ -570,25 +575,6 @@ static void bcm_rx_timeout_tsklet(unsign
+ msg_head.nframes = 0;
+
+ bcm_send_to_user(op, &msg_head, NULL, 0);
+-}
+-
+-/*
+- * bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out
+- */
+-static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+-{
+- struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+-
+- /* schedule before NET_RX_SOFTIRQ */
+- tasklet_hi_schedule(&op->tsklet);
+-
+- /* no restart of the timer is done here! */
+-
+- /* if user wants to be informed, when cyclic CAN-Messages come back */
+- if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
+- /* clear received CAN frames to indicate 'nothing received' */
+- memset(op->last_frames, 0, op->nframes * op->cfsiz);
+- }
+
+ return HRTIMER_NORESTART;
+ }
+@@ -596,14 +582,12 @@ static enum hrtimer_restart bcm_rx_timeo
+ /*
+ * bcm_rx_do_flush - helper for bcm_rx_thr_flush
+ */
+-static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
+- unsigned int index)
++static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
+ {
+ struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
+
+ if ((op->last_frames) && (lcf->flags & RX_THR)) {
+- if (update)
+- bcm_rx_changed(op, lcf);
++ bcm_rx_changed(op, lcf);
+ return 1;
+ }
+ return 0;
+@@ -611,11 +595,8 @@ static inline int bcm_rx_do_flush(struct
+
+ /*
+ * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
+- *
+- * update == 0 : just check if throttled data is available (any irq context)
+- * update == 1 : check and send throttled data to userspace (soft_irq context)
+ */
+-static int bcm_rx_thr_flush(struct bcm_op *op, int update)
++static int bcm_rx_thr_flush(struct bcm_op *op)
+ {
+ int updated = 0;
+
+@@ -624,24 +605,16 @@ static int bcm_rx_thr_flush(struct bcm_o
+
+ /* for MUX filter we start at index 1 */
+ for (i = 1; i < op->nframes; i++)
+- updated += bcm_rx_do_flush(op, update, i);
++ updated += bcm_rx_do_flush(op, i);
+
+ } else {
+ /* for RX_FILTER_ID and simple filter */
+- updated += bcm_rx_do_flush(op, update, 0);
++ updated += bcm_rx_do_flush(op, 0);
+ }
+
+ return updated;
+ }
+
+-static void bcm_rx_thr_tsklet(unsigned long data)
+-{
+- struct bcm_op *op = (struct bcm_op *)data;
+-
+- /* push the changed data to the userspace */
+- bcm_rx_thr_flush(op, 1);
+-}
+-
+ /*
+ * bcm_rx_thr_handler - the time for blocked content updates is over now:
+ * Check for throttled data and send it to the userspace
+@@ -650,9 +623,7 @@ static enum hrtimer_restart bcm_rx_thr_h
+ {
+ struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
+
+- tasklet_schedule(&op->thrtsklet);
+-
+- if (bcm_rx_thr_flush(op, 0)) {
++ if (bcm_rx_thr_flush(op)) {
+ hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
+ return HRTIMER_RESTART;
+ } else {
+@@ -748,23 +719,8 @@ static struct bcm_op *bcm_find_op(struct
+
+ static void bcm_remove_op(struct bcm_op *op)
+ {
+- if (op->tsklet.func) {
+- while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
+- test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
+- hrtimer_active(&op->timer)) {
+- hrtimer_cancel(&op->timer);
+- tasklet_kill(&op->tsklet);
+- }
+- }
+-
+- if (op->thrtsklet.func) {
+- while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
+- test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
+- hrtimer_active(&op->thrtimer)) {
+- hrtimer_cancel(&op->thrtimer);
+- tasklet_kill(&op->thrtsklet);
+- }
+- }
++ hrtimer_cancel(&op->timer);
++ hrtimer_cancel(&op->thrtimer);
+
+ if ((op->frames) && (op->frames != &op->sframe))
+ kfree(op->frames);
+@@ -998,15 +954,13 @@ static int bcm_tx_setup(struct bcm_msg_h
+ op->ifindex = ifindex;
+
+ /* initialize uninitialized (kzalloc) structure */
+- hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&op->timer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL_SOFT);
+ op->timer.function = bcm_tx_timeout_handler;
+
+- /* initialize tasklet for tx countevent notification */
+- tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
+- (unsigned long) op);
+-
+ /* currently unused in tx_ops */
+- hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL_SOFT);
+
+ /* add this bcm_op to the list of the tx_ops */
+ list_add(&op->list, &bo->tx_ops);
+@@ -1175,20 +1129,14 @@ static int bcm_rx_setup(struct bcm_msg_h
+ op->rx_ifindex = ifindex;
+
+ /* initialize uninitialized (kzalloc) structure */
+- hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&op->timer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL_SOFT);
+ op->timer.function = bcm_rx_timeout_handler;
+
+- /* initialize tasklet for rx timeout notification */
+- tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet,
+- (unsigned long) op);
+-
+- hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL_SOFT);
+ op->thrtimer.function = bcm_rx_thr_handler;
+
+- /* initialize tasklet for rx throttle handling */
+- tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
+- (unsigned long) op);
+-
+ /* add this bcm_op to the list of the rx_ops */
+ list_add(&op->list, &bo->rx_ops);
+
+@@ -1234,12 +1182,12 @@ static int bcm_rx_setup(struct bcm_msg_h
+ */
+ op->kt_lastmsg = 0;
+ hrtimer_cancel(&op->thrtimer);
+- bcm_rx_thr_flush(op, 1);
++ bcm_rx_thr_flush(op);
+ }
+
+ if ((op->flags & STARTTIMER) && op->kt_ival1)
+ hrtimer_start(&op->timer, op->kt_ival1,
+- HRTIMER_MODE_REL);
++ HRTIMER_MODE_REL_SOFT);
+ }
+
+ /* now we can register for can_ids, if we added a new bcm_op */
--- /dev/null
+From 0f663729bb4afc92a9986b66131ebd5b8a9254d1 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Sat, 1 Jan 2022 14:52:14 -0500
+Subject: USB: core: Fix bug in resuming hub's handling of wakeup requests
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 0f663729bb4afc92a9986b66131ebd5b8a9254d1 upstream.
+
+Bugzilla #213839 reports a 7-port hub that doesn't work properly when
+devices are plugged into some of the ports; the kernel goes into an
+unending disconnect/reinitialize loop as shown in the bug report.
+
+This "7-port hub" comprises two four-port hubs with one plugged into
+the other; the failures occur when a device is plugged into one of the
+downstream hub's ports. (These hubs have other problems too. For
+example, they bill themselves as USB-2.0 compliant but they only run
+at full speed.)
+
+It turns out that the failures are caused by bugs in both the kernel
+and the hub. The hub's bug is that it reports a different
+bmAttributes value in its configuration descriptor following a remote
+wakeup (0xe0 before, 0xc0 after -- the wakeup-support bit has
+changed).
+
+The kernel's bug is inside the hub driver's resume handler. When
+hub_activate() sees that one of the hub's downstream ports got a
+wakeup request from a child device, it notes this fact by setting the
+corresponding bit in the hub->change_bits variable. But this variable
+is meant for connection changes, not wakeup events; setting it causes
+the driver to believe the downstream port has been disconnected and
+then connected again (in addition to having received a wakeup
+request).
+
+Because of this, the hub driver then tries to check whether the device
+currently plugged into the downstream port is the same as the device
+that had been attached there before. Normally this check succeeds and
+wakeup handling continues with no harm done (which is why the bug
+remained undetected until now). But with these dodgy hubs, the check
+fails because the config descriptor has changed. This causes the hub
+driver to reinitialize the child device, leading to the
+disconnect/reinitialize loop described in the bug report.
+
+The proper way to note reception of a downstream wakeup request is
+to set a bit in the hub->event_bits variable instead of
+hub->change_bits. That way the hub driver will realize that something
+has happened to the port but will not think the port and child device
+have been disconnected. This patch makes that change.
+
+Cc: <stable@vger.kernel.org>
+Tested-by: Jonathan McDowell <noodles@earth.li>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/YdCw7nSfWYPKWQoD@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hub.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1197,7 +1197,7 @@ static void hub_activate(struct usb_hub
+ */
+ if (portchange || (hub_is_superspeed(hub->hdev) &&
+ port_resumed))
+- set_bit(port1, hub->change_bits);
++ set_bit(port1, hub->event_bits);
+
+ } else if (udev->persist_enabled) {
+ #ifdef CONFIG_PM
--- /dev/null
+From 1d7d4c07932e04355d6e6528d44a2f2c9e354346 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 31 Dec 2021 21:07:12 -0500
+Subject: USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 1d7d4c07932e04355d6e6528d44a2f2c9e354346 upstream.
+
+When the USB core code for getting root-hub status reports was
+originally written, it was assumed that the hub driver would be its
+only caller. But this isn't true now; user programs can use usbfs to
+communicate with root hubs and get status reports. When they do this,
+they may use a transfer_buffer that is smaller than the data returned
+by the HCD, which will lead to a buffer overflow error when
+usb_hcd_poll_rh_status() tries to store the status data. This was
+discovered by syzbot:
+
+BUG: KASAN: slab-out-of-bounds in memcpy include/linux/fortify-string.h:225 [inline]
+BUG: KASAN: slab-out-of-bounds in usb_hcd_poll_rh_status+0x5f4/0x780 drivers/usb/core/hcd.c:776
+Write of size 2 at addr ffff88801da403c0 by task syz-executor133/4062
+
+This patch fixes the bug by reducing the amount of status data if it
+won't fit in the transfer_buffer. If some data gets discarded then
+the URB's completion status is set to -EOVERFLOW rather than 0, to let
+the user know what happened.
+
+Reported-and-tested-by: syzbot+3ae6a2b06f131ab9849f@syzkaller.appspotmail.com
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/Yc+3UIQJ2STbxNua@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hcd.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -750,6 +750,7 @@ void usb_hcd_poll_rh_status(struct usb_h
+ {
+ struct urb *urb;
+ int length;
++ int status;
+ unsigned long flags;
+ char buffer[6]; /* Any root hubs with > 31 ports? */
+
+@@ -767,11 +768,17 @@ void usb_hcd_poll_rh_status(struct usb_h
+ if (urb) {
+ clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
+ hcd->status_urb = NULL;
++ if (urb->transfer_buffer_length >= length) {
++ status = 0;
++ } else {
++ status = -EOVERFLOW;
++ length = urb->transfer_buffer_length;
++ }
+ urb->actual_length = length;
+ memcpy(urb->transfer_buffer, buffer, length);
+
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+- usb_hcd_giveback_urb(hcd, urb, 0);
++ usb_hcd_giveback_urb(hcd, urb, status);
+ } else {
+ length = 0;
+ set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);