--- /dev/null
+From 38a01c9700b0dcafe97dfa9dc7531bf4a245deff Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 17:51:17 +0100
+Subject: can: ems_usb: ems_usb_read_bulk_callback(): check the proper length of a message
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 38a01c9700b0dcafe97dfa9dc7531bf4a245deff upstream.
+
+When looking at the data in a USB urb, the actual_length is the size of
+the buffer passed to the driver, not the transfer_buffer_length which is
+set by the driver as the max size of the buffer.
+
+When parsing the messages in ems_usb_read_bulk_callback() properly check
+the size both at the beginning of parsing the message to make sure it is
+big enough for the expected structure, and at the end of the message to
+make sure we don't overflow past the end of the buffer for the next
+message.
+
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022316-answering-strainer-a5db@gregkh
+Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/ems_usb.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/ems_usb.c
++++ b/drivers/net/can/usb/ems_usb.c
+@@ -445,6 +445,11 @@ static void ems_usb_read_bulk_callback(s
+ start = CPC_HEADER_SIZE;
+
+ while (msg_count) {
++ if (start + CPC_MSG_HEADER_LEN > urb->actual_length) {
++ netdev_err(netdev, "format error\n");
++ break;
++ }
++
+ msg = (struct ems_cpc_msg *)&ibuf[start];
+
+ switch (msg->type) {
+@@ -474,7 +479,7 @@ static void ems_usb_read_bulk_callback(s
+ start += CPC_MSG_HEADER_LEN + msg->length;
+ msg_count--;
+
+- if (start > urb->transfer_buffer_length) {
++ if (start > urb->actual_length) {
+ netdev_err(netdev, "format error\n");
+ break;
+ }
--- /dev/null
+From 1e446fd0582ad8be9f6dafb115fc2e7245f9bea7 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 17:30:20 +0100
+Subject: can: ucan: Fix infinite loop from zero-length messages
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 1e446fd0582ad8be9f6dafb115fc2e7245f9bea7 upstream.
+
+If a broken ucan device gets a message with the message length field set
+to 0, then the driver will loop for forever in
+ucan_read_bulk_callback(), hanging the system. If the length is 0, just
+skip the message and go on to the next one.
+
+This has been fixed in the kvaser_usb driver in the past in commit
+0c73772cd2b8 ("can: kvaser_usb: leaf: Fix potential infinite loop in
+command parsers"), so there must be some broken devices out there like
+this somewhere.
+
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022319-huff-absurd-6a18@gregkh
+Fixes: 9f2d3eae88d2 ("can: ucan: add driver for Theobroma Systems UCAN devices")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/ucan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/ucan.c
++++ b/drivers/net/can/usb/ucan.c
+@@ -749,7 +749,7 @@ static void ucan_read_bulk_callback(stru
+ len = le16_to_cpu(m->len);
+
+ /* check sanity (length of content) */
+- if (urb->actual_length - pos < len) {
++ if ((len == 0) || (urb->actual_length - pos < len)) {
+ netdev_warn(up->netdev,
+ "invalid message (short; no data; l:%d)\n",
+ urb->actual_length);
--- /dev/null
+From 5eaad4f768266f1f17e01232ffe2ef009f8129b7 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 17:39:20 +0100
+Subject: can: usb: etas_es58x: correctly anchor the urb in the read bulk callback
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 5eaad4f768266f1f17e01232ffe2ef009f8129b7 upstream.
+
+When submitting an urb, that is using the anchor pattern, it needs to be
+anchored before submitting it otherwise it could be leaked if
+usb_kill_anchored_urbs() is called. This logic is correctly done
+elsewhere in the driver, except in the read bulk callback so do that
+here also.
+
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
+Tested-by: Vincent Mailhol <mailhol@kernel.org>
+Link: https://patch.msgid.link/2026022320-poser-stiffly-9d84@gregkh
+Fixes: 8537257874e9 ("can: etas_es58x: add core support for ETAS ES58X CAN USB interfaces")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/etas_es58x/es58x_core.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
++++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
+@@ -1461,12 +1461,18 @@ static void es58x_read_bulk_callback(str
+ }
+
+ resubmit_urb:
++ usb_anchor_urb(urb, &es58x_dev->rx_urbs);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
++ if (!ret)
++ return;
++
++ usb_unanchor_urb(urb);
++
+ if (ret == -ENODEV) {
+ for (i = 0; i < es58x_dev->num_can_ch; i++)
+ if (es58x_dev->netdev[i])
+ netif_device_detach(es58x_dev->netdev[i]);
+- } else if (ret)
++ } else
+ dev_err_ratelimited(dev,
+ "Failed resubmitting read bulk urb: %pe\n",
+ ERR_PTR(ret));
--- /dev/null
+From 952caa5da10bed22be09612433964f6877ba0dde Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:10:32 +0100
+Subject: can: usb: f81604: correctly anchor the urb in the read bulk callback
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 952caa5da10bed22be09612433964f6877ba0dde upstream.
+
+When submitting an urb, that is using the anchor pattern, it needs to be
+anchored before submitting it otherwise it could be leaked if
+usb_kill_anchored_urbs() is called. This logic is correctly done
+elsewhere in the driver, except in the read bulk callback so do that
+here also.
+
+Cc: Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022334-starlight-scaling-2cea@gregkh
+Fixes: 88da17436973 ("can: usb: f81604: add Fintek F81604 support")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/f81604.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/can/usb/f81604.c
++++ b/drivers/net/can/usb/f81604.c
+@@ -413,6 +413,7 @@ static void f81604_read_bulk_callback(st
+ {
+ struct f81604_can_frame *frame = urb->transfer_buffer;
+ struct net_device *netdev = urb->context;
++ struct f81604_port_priv *priv = netdev_priv(netdev);
+ int ret;
+
+ if (!netif_device_present(netdev))
+@@ -445,10 +446,15 @@ static void f81604_read_bulk_callback(st
+ f81604_process_rx_packet(netdev, frame);
+
+ resubmit_urb:
++ usb_anchor_urb(urb, &priv->urbs_anchor);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
++ if (!ret)
++ return;
++ usb_unanchor_urb(urb);
++
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+- else if (ret)
++ else
+ netdev_err(netdev,
+ "%s: failed to resubmit read bulk urb: %pe\n",
+ __func__, ERR_PTR(ret));
+@@ -646,10 +652,15 @@ static void f81604_read_int_callback(str
+ f81604_handle_tx(priv, data);
+
+ resubmit_urb:
++ usb_anchor_urb(urb, &priv->urbs_anchor);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
++ if (!ret)
++ return;
++ usb_unanchor_urb(urb);
++
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+- else if (ret)
++ else
+ netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
+ __func__, ERR_PTR(ret));
+ }
--- /dev/null
+From 51f94780720fa90c424f67e3e9784cb8ef8190e5 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:10:31 +0100
+Subject: can: usb: f81604: handle bulk write errors properly
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 51f94780720fa90c424f67e3e9784cb8ef8190e5 upstream.
+
+If a write urb fails then more needs to be done other than just logging
+the message, otherwise the transmission could be stalled. Properly
+increment the error counters and wake up the queues so that data will
+continue to flow.
+
+Cc: Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022334-slackness-dynamic-9195@gregkh
+Fixes: 88da17436973 ("can: usb: f81604: add Fintek F81604 support")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/f81604.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/can/usb/f81604.c
++++ b/drivers/net/can/usb/f81604.c
+@@ -891,9 +891,27 @@ static void f81604_write_bulk_callback(s
+ if (!netif_device_present(netdev))
+ return;
+
+- if (urb->status)
+- netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
+- ERR_PTR(urb->status));
++ if (!urb->status)
++ return;
++
++ switch (urb->status) {
++ case -ENOENT:
++ case -ECONNRESET:
++ case -ESHUTDOWN:
++ return;
++ default:
++ break;
++ }
++
++ if (net_ratelimit())
++ netdev_err(netdev, "%s: Tx URB error: %pe\n", __func__,
++ ERR_PTR(urb->status));
++
++ can_free_echo_skb(netdev, 0, NULL);
++ netdev->stats.tx_dropped++;
++ netdev->stats.tx_errors++;
++
++ netif_wake_queue(netdev);
+ }
+
+ static void f81604_clear_reg_work(struct work_struct *work)
--- /dev/null
+From 7299b1b39a255f6092ce4ec0b65f66e9d6a357af Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:10:30 +0100
+Subject: can: usb: f81604: handle short interrupt urb messages properly
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 7299b1b39a255f6092ce4ec0b65f66e9d6a357af upstream.
+
+If an interrupt urb is received that is not the correct length, properly
+detect it and don't attempt to treat the data as valid.
+
+Cc: Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Vincent Mailhol <mailhol@kernel.org>
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022331-opal-evaluator-a928@gregkh
+Fixes: 88da17436973 ("can: usb: f81604: add Fintek F81604 support")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/f81604.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/can/usb/f81604.c
++++ b/drivers/net/can/usb/f81604.c
+@@ -626,6 +626,12 @@ static void f81604_read_int_callback(str
+ netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
+ ERR_PTR(urb->status));
+
++ if (urb->actual_length < sizeof(*data)) {
++ netdev_warn(netdev, "%s: short int URB: %u < %zu\n",
++ __func__, urb->actual_length, sizeof(*data));
++ goto resubmit_urb;
++ }
++
+ switch (urb->status) {
+ case 0: /* success */
+ break;
--- /dev/null
+From fdcfce93073d990ed4b71752e31ad1c1d6e9d58b Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Mon, 23 Feb 2026 20:59:33 +0100
+Subject: eventpoll: Fix integer overflow in ep_loop_check_proc()
+
+From: Jann Horn <jannh@google.com>
+
+commit fdcfce93073d990ed4b71752e31ad1c1d6e9d58b upstream.
+
+If a recursive call to ep_loop_check_proc() hits the `result = INT_MAX`,
+an integer overflow will occur in the calling ep_loop_check_proc() at
+`result = max(result, ep_loop_check_proc(ep_tovisit, depth + 1) + 1)`,
+breaking the recursion depth check.
+
+Fix it by using a different placeholder value that can't lead to an
+overflow.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: f2e467a48287 ("eventpoll: Fix semi-unbounded recursion")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Link: https://patch.msgid.link/20260223-epoll-int-overflow-v1-1-452f35132224@google.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/eventpoll.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -2061,7 +2061,8 @@ static int ep_poll(struct eventpoll *ep,
+ * @ep: the &struct eventpoll to be currently checked.
+ * @depth: Current depth of the path being checked.
+ *
+- * Return: depth of the subtree, or INT_MAX if we found a loop or went too deep.
++ * Return: depth of the subtree, or a value bigger than EP_MAX_NESTS if we found
++ * a loop or went too deep.
+ */
+ static int ep_loop_check_proc(struct eventpoll *ep, int depth)
+ {
+@@ -2080,7 +2081,7 @@ static int ep_loop_check_proc(struct eve
+ struct eventpoll *ep_tovisit;
+ ep_tovisit = epi->ffd.file->private_data;
+ if (ep_tovisit == inserting_into || depth > EP_MAX_NESTS)
+- result = INT_MAX;
++ result = EP_MAX_NESTS+1;
+ else
+ result = max(result, ep_loop_check_proc(ep_tovisit, depth + 1) + 1);
+ if (result > EP_MAX_NESTS)
--- /dev/null
+From ecfa6f34492c493a9a1dc2900f3edeb01c79946b Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Thu, 19 Feb 2026 15:33:54 +0100
+Subject: HID: Add HID_CLAIMED_INPUT guards in raw_event callbacks missing them
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit ecfa6f34492c493a9a1dc2900f3edeb01c79946b upstream.
+
+In commit 2ff5baa9b527 ("HID: appleir: Fix potential NULL dereference at
+raw event handle"), we handle the fact that raw event callbacks
+can happen even for a HID device that has not been "claimed" causing a
+crash if a broken device were attempted to be connected to the system.
+
+Fix up the remaining in-tree HID drivers that forgot to add this same
+check to resolve the same issue.
+
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Benjamin Tissoires <bentiss@kernel.org>
+Cc: Bastien Nocera <hadess@hadess.net>
+Cc: linux-input@vger.kernel.org
+Cc: stable <stable@kernel.org>
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-cmedia.c | 2 +-
+ drivers/hid/hid-creative-sb0540.c | 2 +-
+ drivers/hid/hid-zydacron.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/hid/hid-cmedia.c
++++ b/drivers/hid/hid-cmedia.c
+@@ -99,7 +99,7 @@ static int cmhid_raw_event(struct hid_de
+ {
+ struct cmhid *cm = hid_get_drvdata(hid);
+
+- if (len != CM6533_JD_RAWEV_LEN)
++ if (len != CM6533_JD_RAWEV_LEN || !(hid->claimed & HID_CLAIMED_INPUT))
+ goto out;
+ if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx)))
+ goto out;
+--- a/drivers/hid/hid-creative-sb0540.c
++++ b/drivers/hid/hid-creative-sb0540.c
+@@ -153,7 +153,7 @@ static int creative_sb0540_raw_event(str
+ u64 code, main_code;
+ int key;
+
+- if (len != 6)
++ if (len != 6 || !(hid->claimed & HID_CLAIMED_INPUT))
+ return 0;
+
+ /* From daemons/hw_hiddev.c sb0540_rec() in lirc */
+--- a/drivers/hid/hid-zydacron.c
++++ b/drivers/hid/hid-zydacron.c
+@@ -114,7 +114,7 @@ static int zc_raw_event(struct hid_devic
+ unsigned key;
+ unsigned short index;
+
+- if (report->id == data[0]) {
++ if (report->id == data[0] && (hdev->claimed & HID_CLAIMED_INPUT)) {
+
+ /* break keys */
+ for (index = 0; index < 4; index++) {
--- /dev/null
+From ec3070f01fa30f2c5547d645dbb76174304bf0e4 Mon Sep 17 00:00:00 2001
+From: Werner Sembach <wse@tuxedocomputers.com>
+Date: Thu, 8 Jan 2026 17:09:54 +0100
+Subject: HID: multitouch: Keep latency normal on deactivate for reactivation gesture
+
+From: Werner Sembach <wse@tuxedocomputers.com>
+
+commit ec3070f01fa30f2c5547d645dbb76174304bf0e4 upstream.
+
+Uniwill devices have a built in gesture in the touchpad to de- and
+reactivate it by double taping the upper left corner. This gesture stops
+working when latency is set to high, so this patch keeps the latency on
+normal.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
+[jkosina@suse.com: change bit from 24 to 25]
+[jkosina@suse.com: update shortlog]
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-multitouch.c | 32 +++++++++++++++++++++++++++++---
+ 1 file changed, 29 insertions(+), 3 deletions(-)
+
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -77,6 +77,7 @@ MODULE_LICENSE("GPL");
+ #define MT_QUIRK_ORIENTATION_INVERT BIT(22)
+ #define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
+ #define MT_QUIRK_YOGABOOK9I BIT(24)
++#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(25)
+
+ #define MT_INPUTMODE_TOUCHSCREEN 0x02
+ #define MT_INPUTMODE_TOUCHPAD 0x03
+@@ -214,6 +215,7 @@ static void mt_post_parse(struct mt_devi
+ #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
+ #define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017
+ #define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018
++#define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019
+
+ /* vendor specific classes */
+ #define MT_CLS_3M 0x0101
+@@ -334,6 +336,15 @@ static const struct mt_class mt_classes[
+ MT_QUIRK_CONTACT_CNT_ACCURATE |
+ MT_QUIRK_WIN8_PTP_BUTTONS,
+ .export_all_inputs = true },
++ { .name = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
++ .quirks = MT_QUIRK_ALWAYS_VALID |
++ MT_QUIRK_IGNORE_DUPLICATES |
++ MT_QUIRK_HOVERING |
++ MT_QUIRK_CONTACT_CNT_ACCURATE |
++ MT_QUIRK_STICKY_FINGERS |
++ MT_QUIRK_WIN8_PTP_BUTTONS |
++ MT_QUIRK_KEEP_LATENCY_ON_CLOSE,
++ .export_all_inputs = true },
+
+ /*
+ * vendor specific classes
+@@ -849,7 +860,8 @@ static int mt_touch_input_mapping(struct
+ if ((cls->name == MT_CLS_WIN_8 ||
+ cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
+ cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU ||
+- cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP) &&
++ cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP ||
++ cls->name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE) &&
+ (field->application == HID_DG_TOUCHPAD ||
+ field->application == HID_DG_TOUCHSCREEN))
+ app->quirks |= MT_QUIRK_CONFIDENCE;
+@@ -1762,7 +1774,8 @@ static int mt_input_configured(struct hi
+ int ret;
+
+ if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
+- td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) {
++ td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
++ td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) {
+ if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
+ td->is_haptic_touchpad = false;
+ } else {
+@@ -2075,7 +2088,12 @@ static void mt_on_hid_hw_open(struct hid
+
+ static void mt_on_hid_hw_close(struct hid_device *hdev)
+ {
+- mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
++ struct mt_device *td = hid_get_drvdata(hdev);
++
++ if (td->mtclass.quirks & MT_QUIRK_KEEP_LATENCY_ON_CLOSE)
++ mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_NONE);
++ else
++ mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
+ }
+
+ /*
+@@ -2461,6 +2479,14 @@ static const struct hid_device_id mt_dev
+ MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
+ USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+
++ /* Uniwill touchpads */
++ { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
++ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
++ USB_VENDOR_ID_PIXART, 0x0255) },
++ { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
++ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
++ USB_VENDOR_ID_PIXART, 0x0274) },
++
+ /* VTL panels */
+ { .driver_data = MT_CLS_VTL,
+ MT_USB_DEVICE(USB_VENDOR_ID_VTL,
--- /dev/null
+From 97d5c8f5c09a604c4873c8348f58de3cea69a7df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= <tomasz.pakula.oficjalny@gmail.com>
+Date: Wed, 4 Feb 2026 22:44:55 +0100
+Subject: HID: pidff: Fix condition effect bit clearing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+commit 97d5c8f5c09a604c4873c8348f58de3cea69a7df upstream.
+
+As reported by MPDarkGuy on discord, NULL pointer dereferences were
+happening because not all the conditional effects bits were cleared.
+
+Properly clear all conditional effect bits from ffbit
+
+Fixes: 7f3d7bc0df4b ("HID: pidff: Better quirk assigment when searching for fields")
+Cc: stable@vger.kernel.org # 6.18.x
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -1452,10 +1452,13 @@ static int pidff_init_fields(struct pidf
+ hid_warn(pidff->hid, "unknown ramp effect layout\n");
+
+ if (PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
+- if (test_and_clear_bit(FF_SPRING, dev->ffbit) ||
+- test_and_clear_bit(FF_DAMPER, dev->ffbit) ||
+- test_and_clear_bit(FF_FRICTION, dev->ffbit) ||
+- test_and_clear_bit(FF_INERTIA, dev->ffbit))
++ bool test = false;
++
++ test |= test_and_clear_bit(FF_SPRING, dev->ffbit);
++ test |= test_and_clear_bit(FF_DAMPER, dev->ffbit);
++ test |= test_and_clear_bit(FF_FRICTION, dev->ffbit);
++ test |= test_and_clear_bit(FF_INERTIA, dev->ffbit);
++ if (test)
+ hid_warn(pidff->hid, "unknown condition effect layout\n");
+ }
+
--- /dev/null
+From bfbc0b5b32a8f28ce284add619bf226716a59bc0 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Tue, 24 Feb 2026 11:51:16 -0700
+Subject: media: dvb-core: fix wrong reinitialization of ringbuffer on reopen
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit bfbc0b5b32a8f28ce284add619bf226716a59bc0 upstream.
+
+dvb_dvr_open() calls dvb_ringbuffer_init() when a new reader opens the
+DVR device. dvb_ringbuffer_init() calls init_waitqueue_head(), which
+reinitializes the waitqueue list head to empty.
+
+Since dmxdev->dvr_buffer.queue is a shared waitqueue (all opens of the
+same DVR device share it), this orphans any existing waitqueue entries
+from io_uring poll or epoll, leaving them with stale prev/next pointers
+while the list head is reset to {self, self}.
+
+The waitqueue and spinlock in dvr_buffer are already properly
+initialized once in dvb_dmxdev_init(). The open path only needs to
+reset the buffer data pointer, size, and read/write positions.
+
+Replace the dvb_ringbuffer_init() call in dvb_dvr_open() with direct
+assignment of data/size and a call to dvb_ringbuffer_reset(), which
+properly resets pread, pwrite, and error with correct memory ordering
+without touching the waitqueue or spinlock.
+
+Cc: stable@vger.kernel.org
+Fixes: 34731df288a5f ("V4L/DVB (3501): Dmxdev: use dvb_ringbuffer")
+Reported-by: syzbot+ab12f0c08dd7ab8d057c@syzkaller.appspotmail.com
+Tested-by: syzbot+ab12f0c08dd7ab8d057c@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/698a26d3.050a0220.3b3015.007d.GAE@google.com/
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/dvb-core/dmxdev.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/dvb-core/dmxdev.c
++++ b/drivers/media/dvb-core/dmxdev.c
+@@ -168,7 +168,9 @@ static int dvb_dvr_open(struct inode *in
+ mutex_unlock(&dmxdev->mutex);
+ return -ENOMEM;
+ }
+- dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
++ dmxdev->dvr_buffer.data = mem;
++ dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE;
++ dvb_ringbuffer_reset(&dmxdev->dvr_buffer);
+ if (dmxdev->may_do_mmap)
+ dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
+ file->f_flags & O_NONBLOCK);
--- /dev/null
+From 4a403d7aa9074f527f064ef0806aaab38d14b07c Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Thu, 29 Jan 2026 14:52:22 +0100
+Subject: namespace: fix proc mount iteration
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 4a403d7aa9074f527f064ef0806aaab38d14b07c upstream.
+
+The m->index isn't updated when m->show() overflows and retains its
+value before the current mount causing a restart to start at the same
+value. If that happens in short order to due a quickly expanding mount
+table this would cause the same mount to be shown again and again.
+
+Ensure that *pos always equals the mount id of the mount that was
+returned by start/next. On restart after overflow mnt_find_id_at(*pos)
+finds the exact mount. This should avoid duplicates, avoid skips and
+should handle concurrent modification just fine.
+
+Cc: <stable@vger.kernel.org>
+Fixed: 2eea9ce4310d8 ("mounts: keep list of mounts in an rbtree")
+Link: https://patch.msgid.link/20260129-geleckt-treuhand-4bb940acacd9@brauner
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/namespace.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -1537,23 +1537,33 @@ static struct mount *mnt_find_id_at_reve
+ static void *m_start(struct seq_file *m, loff_t *pos)
+ {
+ struct proc_mounts *p = m->private;
++ struct mount *mnt;
+
+ down_read(&namespace_sem);
+
+- return mnt_find_id_at(p->ns, *pos);
++ mnt = mnt_find_id_at(p->ns, *pos);
++ if (mnt)
++ *pos = mnt->mnt_id_unique;
++ return mnt;
+ }
+
+ static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+- struct mount *next = NULL, *mnt = v;
++ struct mount *mnt = v;
+ struct rb_node *node = rb_next(&mnt->mnt_node);
+
+- ++*pos;
+ if (node) {
+- next = node_to_mount(node);
++ struct mount *next = node_to_mount(node);
+ *pos = next->mnt_id_unique;
++ return next;
+ }
+- return next;
++
++ /*
++ * No more mounts. Set pos past current mount's ID so that if
++ * iteration restarts, mnt_find_id_at() returns NULL.
++ */
++ *pos = mnt->mnt_id_unique + 1;
++ return NULL;
+ }
+
+ static void m_stop(struct seq_file *m, void *v)
--- /dev/null
+From c58b6c29a4c9b8125e8ad3bca0637e00b71e2693 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:59:26 +0100
+Subject: net: usb: kalmia: validate USB endpoints
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit c58b6c29a4c9b8125e8ad3bca0637e00b71e2693 upstream.
+
+The kalmia driver should validate that the device it is probing has the
+proper number and types of USB endpoints it is expecting before it binds
+to it. If a malicious device were to not have the same urbs the driver
+will crash later on when it blindly accesses these endpoints.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Fixes: d40261236e8e ("net/usb: Add Samsung Kalmia driver for Samsung GT-B3730")
+Link: https://patch.msgid.link/2026022326-shack-headstone-ef6f@gregkh
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/kalmia.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/usb/kalmia.c
++++ b/drivers/net/usb/kalmia.c
+@@ -132,11 +132,18 @@ kalmia_bind(struct usbnet *dev, struct u
+ {
+ int status;
+ u8 ethernet_addr[ETH_ALEN];
++ static const u8 ep_addr[] = {
++ 1 | USB_DIR_IN,
++ 2 | USB_DIR_OUT,
++ 0};
+
+ /* Don't bind to AT command interface */
+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+ return -EINVAL;
+
++ if (!usb_check_bulk_endpoints(intf, ep_addr))
++ return -ENODEV;
++
+ dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK);
+ dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK);
+ dev->status = NULL;
--- /dev/null
+From 4b063c002ca759d1b299988ee23f564c9609c875 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 14:00:06 +0100
+Subject: net: usb: kaweth: validate USB endpoints
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 4b063c002ca759d1b299988ee23f564c9609c875 upstream.
+
+The kaweth driver should validate that the device it is probing has the
+proper number and types of USB endpoints it is expecting before it binds
+to it. If a malicious device were to not have the same urbs the driver
+will crash later on when it blindly accesses these endpoints.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://patch.msgid.link/2026022305-substance-virtual-c728@gregkh
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/kaweth.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -883,6 +883,13 @@ static int kaweth_probe(
+ const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ int result = 0;
+ int rv = -EIO;
++ static const u8 bulk_ep_addr[] = {
++ 1 | USB_DIR_IN,
++ 2 | USB_DIR_OUT,
++ 0};
++ static const u8 int_ep_addr[] = {
++ 3 | USB_DIR_IN,
++ 0};
+
+ dev_dbg(dev,
+ "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
+@@ -896,6 +903,12 @@ static int kaweth_probe(
+ (int)udev->descriptor.bLength,
+ (int)udev->descriptor.bDescriptorType);
+
++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
++ !usb_check_int_endpoints(intf, int_ep_addr)) {
++ dev_err(dev, "couldn't find required endpoints\n");
++ return -ENODEV;
++ }
++
+ netdev = alloc_etherdev(sizeof(*kaweth));
+ if (!netdev)
+ return -ENOMEM;
--- /dev/null
+From 11de1d3ae5565ed22ef1f89d73d8f2d00322c699 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:58:48 +0100
+Subject: net: usb: pegasus: validate USB endpoints
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 11de1d3ae5565ed22ef1f89d73d8f2d00322c699 upstream.
+
+The pegasus driver should validate that the device it is probing has the
+proper number and types of USB endpoints it is expecting before it binds
+to it. If a malicious device were to not have the same urbs the driver
+will crash later on when it blindly accesses these endpoints.
+
+Cc: Petko Manolov <petkan@nucleusys.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026022347-legibly-attest-cc5c@gregkh
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/pegasus.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/pegasus.c
++++ b/drivers/net/usb/pegasus.c
+@@ -815,8 +815,19 @@ static void unlink_all_urbs(pegasus_t *p
+
+ static int alloc_urbs(pegasus_t *pegasus)
+ {
++ static const u8 bulk_ep_addr[] = {
++ 1 | USB_DIR_IN,
++ 2 | USB_DIR_OUT,
++ 0};
++ static const u8 int_ep_addr[] = {
++ 3 | USB_DIR_IN,
++ 0};
+ int res = -ENOMEM;
+
++ if (!usb_check_bulk_endpoints(pegasus->intf, bulk_ep_addr) ||
++ !usb_check_int_endpoints(pegasus->intf, int_ep_addr))
++ return -ENODEV;
++
+ pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pegasus->rx_urb) {
+ return res;
+@@ -1171,6 +1182,7 @@ static int pegasus_probe(struct usb_inte
+
+ pegasus = netdev_priv(net);
+ pegasus->dev_index = dev_index;
++ pegasus->intf = intf;
+
+ res = alloc_urbs(pegasus);
+ if (res < 0) {
+@@ -1182,7 +1194,6 @@ static int pegasus_probe(struct usb_inte
+
+ INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
+
+- pegasus->intf = intf;
+ pegasus->usb = dev;
+ pegasus->net = net;
+
--- /dev/null
+From 12133a483dfa832241fbbf09321109a0ea8a520e Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 12:28:30 +0100
+Subject: nfc: pn533: properly drop the usb interface reference on disconnect
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 12133a483dfa832241fbbf09321109a0ea8a520e upstream.
+
+When the device is disconnected from the driver, there is a "dangling"
+reference count on the usb interface that was grabbed in the probe
+callback. Fix this up by properly dropping the reference after we are
+done with it.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Fixes: c46ee38620a2 ("NFC: pn533: add NXP pn533 nfc device driver")
+Link: https://patch.msgid.link/2026022329-flashing-ought-7573@gregkh
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nfc/pn533/usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nfc/pn533/usb.c
++++ b/drivers/nfc/pn533/usb.c
+@@ -628,6 +628,7 @@ static void pn533_usb_disconnect(struct
+ usb_free_urb(phy->out_urb);
+ usb_free_urb(phy->ack_urb);
+ kfree(phy->ack_buffer);
++ usb_put_dev(phy->udev);
+
+ nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n");
+ }
accel-rocket-fix-unwinding-in-error-path-in-rocket_c.patch
accel-rocket-fix-unwinding-in-error-path-in-rocket_p.patch
kvm-x86-add-x2apic-features-to-control-eoi-broadcast.patch
+eventpoll-fix-integer-overflow-in-ep_loop_check_proc.patch
+namespace-fix-proc-mount-iteration.patch
+media-dvb-core-fix-wrong-reinitialization-of-ringbuffer-on-reopen.patch
+nfc-pn533-properly-drop-the-usb-interface-reference-on-disconnect.patch
+net-usb-kaweth-validate-usb-endpoints.patch
+net-usb-kalmia-validate-usb-endpoints.patch
+net-usb-pegasus-validate-usb-endpoints.patch
+can-ems_usb-ems_usb_read_bulk_callback-check-the-proper-length-of-a-message.patch
+can-usb-f81604-correctly-anchor-the-urb-in-the-read-bulk-callback.patch
+can-ucan-fix-infinite-loop-from-zero-length-messages.patch
+can-usb-etas_es58x-correctly-anchor-the-urb-in-the-read-bulk-callback.patch
+can-usb-f81604-handle-short-interrupt-urb-messages-properly.patch
+can-usb-f81604-handle-bulk-write-errors-properly.patch
+hid-add-hid_claimed_input-guards-in-raw_event-callbacks-missing-them.patch
+hid-pidff-fix-condition-effect-bit-clearing.patch
+hid-multitouch-keep-latency-normal-on-deactivate-for-reactivation-gesture.patch
+x86-efi-defer-freeing-of-boot-services-memory.patch
--- /dev/null
+From a4b0bf6a40f3c107c67a24fbc614510ef5719980 Mon Sep 17 00:00:00 2001
+From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
+Date: Wed, 25 Feb 2026 08:55:55 +0200
+Subject: x86/efi: defer freeing of boot services memory
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+commit a4b0bf6a40f3c107c67a24fbc614510ef5719980 upstream.
+
+efi_free_boot_services() frees memory occupied by EFI_BOOT_SERVICES_CODE
+and EFI_BOOT_SERVICES_DATA using memblock_free_late().
+
+There are two issue with that: memblock_free_late() should be used for
+memory allocated with memblock_alloc() while the memory reserved with
+memblock_reserve() should be freed with free_reserved_area().
+
+More acutely, with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
+efi_free_boot_services() is called before deferred initialization of the
+memory map is complete.
+
+Benjamin Herrenschmidt reports that this causes a leak of ~140MB of
+RAM on EC2 t3a.nano instances which only have 512MB or RAM.
+
+If the freed memory resides in the areas that memory map for them is
+still uninitialized, they won't be actually freed because
+memblock_free_late() calls memblock_free_pages() and the latter skips
+uninitialized pages.
+
+Using free_reserved_area() at this point is also problematic because
+__free_page() accesses the buddy of the freed page and that again might
+end up in uninitialized part of the memory map.
+
+Delaying the entire efi_free_boot_services() could be problematic
+because in addition to freeing boot services memory it updates
+efi.memmap without any synchronization and that's undesirable late in
+boot when there is concurrency.
+
+More robust approach is to only defer freeing of the EFI boot services
+memory.
+
+Split efi_free_boot_services() in two. First efi_unmap_boot_services()
+collects ranges that should be freed into an array then
+efi_free_boot_services() later frees them after deferred init is complete.
+
+Link: https://lore.kernel.org/all/ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org
+Fixes: 916f676f8dc0 ("x86, efi: Retain boot service code until after switching to virtual mode")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Reviewed-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/efi.h | 2 -
+ arch/x86/platform/efi/efi.c | 2 -
+ arch/x86/platform/efi/quirks.c | 55 ++++++++++++++++++++++++++++++++++--
+ drivers/firmware/efi/mokvar-table.c | 2 -
+ 4 files changed, 55 insertions(+), 6 deletions(-)
+
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quir
+ extern int __init efi_reuse_config(u64 tables, int nr_tables);
+ extern void efi_delete_dummy_variable(void);
+ extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr);
+-extern void efi_free_boot_services(void);
++extern void efi_unmap_boot_services(void);
+
+ void arch_efi_call_virt_setup(void);
+ void arch_efi_call_virt_teardown(void);
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -837,7 +837,7 @@ static void __init __efi_enter_virtual_m
+ }
+
+ efi_check_for_embedded_firmwares();
+- efi_free_boot_services();
++ efi_unmap_boot_services();
+
+ if (!efi_is_mixed())
+ efi_native_runtime_setup();
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -341,7 +341,7 @@ void __init efi_reserve_boot_services(vo
+
+ /*
+ * Because the following memblock_reserve() is paired
+- * with memblock_free_late() for this region in
++ * with free_reserved_area() for this region in
+ * efi_free_boot_services(), we must be extremely
+ * careful not to reserve, and subsequently free,
+ * critical regions of memory (like the kernel image) or
+@@ -404,17 +404,33 @@ static void __init efi_unmap_pages(efi_m
+ pr_err("Failed to unmap VA mapping for 0x%llx\n", va);
+ }
+
+-void __init efi_free_boot_services(void)
++struct efi_freeable_range {
++ u64 start;
++ u64 end;
++};
++
++static struct efi_freeable_range *ranges_to_free;
++
++void __init efi_unmap_boot_services(void)
+ {
+ struct efi_memory_map_data data = { 0 };
+ efi_memory_desc_t *md;
+ int num_entries = 0;
++ int idx = 0;
++ size_t sz;
+ void *new, *new_md;
+
+ /* Keep all regions for /sys/kernel/debug/efi */
+ if (efi_enabled(EFI_DBG))
+ return;
+
++ sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ ranges_to_free = kzalloc(sz, GFP_KERNEL);
++ if (!ranges_to_free) {
++ pr_err("Failed to allocate storage for freeable EFI regions\n");
++ return;
++ }
++
+ for_each_efi_memory_desc(md) {
+ unsigned long long start = md->phys_addr;
+ unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+@@ -471,7 +487,15 @@ void __init efi_free_boot_services(void)
+ start = SZ_1M;
+ }
+
+- memblock_free_late(start, size);
++ /*
++ * With CONFIG_DEFERRED_STRUCT_PAGE_INIT parts of the memory
++ * map are still not initialized and we can't reliably free
++ * memory here.
++ * Queue the ranges to free at a later point.
++ */
++ ranges_to_free[idx].start = start;
++ ranges_to_free[idx].end = start + size;
++ idx++;
+ }
+
+ if (!num_entries)
+@@ -512,6 +536,31 @@ void __init efi_free_boot_services(void)
+ }
+ }
+
++static int __init efi_free_boot_services(void)
++{
++ struct efi_freeable_range *range = ranges_to_free;
++ unsigned long freed = 0;
++
++ if (!ranges_to_free)
++ return 0;
++
++ while (range->start) {
++ void *start = phys_to_virt(range->start);
++ void *end = phys_to_virt(range->end);
++
++ free_reserved_area(start, end, -1, NULL);
++ freed += (end - start);
++ range++;
++ }
++ kfree(ranges_to_free);
++
++ if (freed)
++ pr_info("Freeing EFI boot services memory: %ldK\n", freed / SZ_1K);
++
++ return 0;
++}
++arch_initcall(efi_free_boot_services);
++
+ /*
+ * A number of config table entries get remapped to virtual addresses
+ * after entering EFI virtual mode. However, the kexec kernel requires
+--- a/drivers/firmware/efi/mokvar-table.c
++++ b/drivers/firmware/efi/mokvar-table.c
+@@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj;
+ * as an alternative to ordinary EFI variables, due to platform-dependent
+ * limitations. The memory occupied by this table is marked as reserved.
+ *
+- * This routine must be called before efi_free_boot_services() in order
++ * This routine must be called before efi_unmap_boot_services() in order
+ * to guarantee that it can mark the table as reserved.
+ *
+ * Implicit inputs: