]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Aug 2026 12:24:59 +0000 (21:24 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Aug 2026 12:24:59 +0000 (21:24 +0900)
added patches:
input-evdev-fix-information-leak-in-evdev_pass_values.patch

queue-5.15/input-evdev-fix-information-leak-in-evdev_pass_values.patch [new file with mode: 0644]
queue-5.15/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch [deleted file]
queue-5.15/series

diff --git a/queue-5.15/input-evdev-fix-information-leak-in-evdev_pass_values.patch b/queue-5.15/input-evdev-fix-information-leak-in-evdev_pass_values.patch
new file mode 100644 (file)
index 0000000..ad9b9ba
--- /dev/null
@@ -0,0 +1,88 @@
+From 90f305f2c7a30257c683e13f4bf7c798eea992a0 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Wed, 29 Jul 2026 11:30:45 -0700
+Subject: Input: evdev - fix information leak in evdev_pass_values()
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 90f305f2c7a30257c683e13f4bf7c798eea992a0 upstream.
+
+In evdev_pass_values(), the input_event structure is allocated on the
+kernel stack and populated field-by-field. However, it is never fully
+initialized. On architectures where struct input_event contains explicit
+or implicit padding (such as the 32-bit __pad field on SPARC64), these
+padding bytes are left uninitialized.
+
+When this event structure is subsequently passed to the client buffer
+and later copied to userspace, the uninitialized padding bytes leak
+kernel stack memory, potentially exposing sensitive information.
+
+Similar issues exist in __evdev_queue_syn_dropped and __pass_event.
+
+Fix this by explicitly zeroing the entire event structure with memset()
+before populating its fields. This ensures all padding bytes are cleared
+before the data crosses the security boundary.
+
+Reported-by: sashiko-bot@kernel.org
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/ampGGKo4UMKru6f5@google.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/evdev.c |   22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/drivers/input/evdev.c
++++ b/drivers/input/evdev.c
+@@ -149,11 +149,11 @@ static void __evdev_queue_syn_dropped(st
+       struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
+       struct input_event ev;
++      memset(&ev, 0, sizeof(ev));
+       ev.input_event_sec = ts.tv_sec;
+       ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+       ev.type = EV_SYN;
+       ev.code = SYN_DROPPED;
+-      ev.value = 0;
+       client->buffer[client->head++] = ev;
+       client->head &= client->bufsize - 1;
+@@ -221,20 +221,20 @@ static void __pass_event(struct evdev_cl
+       client->head &= client->bufsize - 1;
+       if (unlikely(client->head == client->tail)) {
++              struct input_event ev;
++
++              memset(&ev, 0, sizeof(ev));
++              ev.input_event_sec = event->input_event_sec;
++              ev.input_event_usec = event->input_event_usec;
++              ev.type = EV_SYN;
++              ev.code = SYN_DROPPED;
++
+               /*
+                * This effectively "drops" all unconsumed events, leaving
+                * EV_SYN/SYN_DROPPED plus the newest event in the queue.
+                */
+               client->tail = (client->head - 2) & (client->bufsize - 1);
+-
+-              client->buffer[client->tail] = (struct input_event) {
+-                      .input_event_sec = event->input_event_sec,
+-                      .input_event_usec = event->input_event_usec,
+-                      .type = EV_SYN,
+-                      .code = SYN_DROPPED,
+-                      .value = 0,
+-              };
+-
++              client->buffer[client->tail] = ev;
+               client->packet_head = client->tail;
+       }
+@@ -256,6 +256,8 @@ static void evdev_pass_values(struct evd
+       if (client->revoked)
+               return;
++      memset(&event, 0, sizeof(event));
++
+       ts = ktime_to_timespec64(ev_time[client->clk_type]);
+       event.input_event_sec = ts.tv_sec;
+       event.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
diff --git a/queue-5.15/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch b/queue-5.15/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch
deleted file mode 100644 (file)
index 33cfe1d..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From fde39b8a521780391fb4e5bda2c0aa4928947f12 Mon Sep 17 00:00:00 2001
-From: Doruk Tan Ozturk <doruk@0sec.ai>
-Date: Sun, 2 Aug 2026 14:06:02 +0200
-Subject: net: usb: ipheth: fix carrier_work UAF on disconnect
-
-From: Doruk Tan Ozturk <doruk@0sec.ai>
-
-commit fde39b8a521780391fb4e5bda2c0aa4928947f12 upstream.
-
-ipheth_sndbulk_callback() re-arms the carrier-check work on any
-non-zero URB status:
-
-       else
-               schedule_delayed_work(&dev->carrier_work, 0);
-
-Nothing ties that to the interface being up, so the work can be armed
-again after ipheth_close() has already drained it, and stay armed
-until the netdev whose private area embeds it is freed.
-
-On unplug with a TX URB in flight, ipheth_disconnect() drains the work
-through unregister_netdev() -> ipheth_close() ->
-cancel_delayed_work_sync() and only then calls ipheth_kill_urbs().
-usb_kill_urb() completes the in-flight TX URB with -ENOENT, so
-ipheth_sndbulk_callback() runs after the drain and re-arms
-carrier_work.
-
-The same completion also re-arms the work if the interface is only
-brought down while a TX URB is in flight, and
-ipheth_carrier_check_work() then keeps re-queueing itself once a
-second. unregister_netdev() does not call ipheth_close() for an
-already-down interface, so nothing drains it on the later unplug
-either.
-
-In both cases free_netdev() frees the netdev while carrier_work is
-still pending, and ipheth_carrier_check_work() dereferences freed
-memory.
-
-Tie the work to the interface state instead of chasing the completion:
-disable it in ipheth_close() and enable it in ipheth_open(), so a
-schedule_delayed_work() from the URB completion is a no-op whenever
-the interface is not up. disable_delayed_work_sync() also waits for a
-running instance, so it fully replaces the cancel_delayed_work_sync()
-it takes the place of. The work starts out disabled in ipheth_probe()
-so the enable/disable counts balance from the first open.
-
-Reproduced under KASAN on linux-next (next-20260731) with dummy_hcd and
-raw-gadget standing in for the device, driving the second path above (the
-interface is already down, so unregister_netdev() does not call
-ipheth_close()): 15 of 15 unpatched boots report a slab-use-after-free in
-__run_timers(), freed by ipheth_disconnect() and re-armed from
-ipheth_sndbulk_callback() via queue_delayed_work_on(). The
-same trigger on a kernel differing only by this patch reports 0 of 15,
-and the carrier check still functions across open/close cycles.
-
-The reproducer needs an attached USB device that stops draining bulk OUT,
-plus a link down and unplug, driven as root. It is not a privilege
-boundary crossing and no exploit primitive was developed.
-
-Found by 0sec (https://0sec.ai).
-
-Fixes: bb1b40c7cb86 ("usbnet: ipheth: prevent TX queue timeouts when device not ready")
-Cc: stable@vger.kernel.org
-Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
-Link: https://patch.msgid.link/20260802120602.42595-1-doruk@0sec.ai
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/net/usb/ipheth.c |   11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
---- a/drivers/net/usb/ipheth.c
-+++ b/drivers/net/usb/ipheth.c
-@@ -346,6 +346,7 @@ static int ipheth_open(struct net_device
-       if (retval)
-               return retval;
-+      enable_delayed_work(&dev->carrier_work);
-       schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
-       return retval;
- }
-@@ -355,7 +356,11 @@ static int ipheth_close(struct net_devic
-       struct ipheth_device *dev = netdev_priv(net);
-       netif_stop_queue(net);
--      cancel_delayed_work_sync(&dev->carrier_work);
-+      /* A TX URB can still complete with an error after this point and
-+       * try to re-arm the carrier work. Disable it instead of cancelling
-+       * it, so that such a schedule_delayed_work() is a no-op.
-+       */
-+      disable_delayed_work_sync(&dev->carrier_work);
-       return 0;
- }
-@@ -483,6 +488,10 @@ static int ipheth_probe(struct usb_inter
-               goto err_get_macaddr;
-       INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);
-+      /* Armed only between ipheth_open() and ipheth_close(). Start out
-+       * disabled so the enable/disable counts balance from the first open.
-+       */
-+      disable_delayed_work(&dev->carrier_work);
-       retval = ipheth_alloc_urbs(dev);
-       if (retval) {
index 370537a8f79e6097b84b6e81d81ea418ce941de3..087d97579b357f6c57ec78a7f2e00e308a4dd2fd 100644 (file)
@@ -403,6 +403,6 @@ usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.patch
 thunderbolt-icm-preserve-usb4-proxy-data-valid-bit.patch
 usb-cdnsp-fix-incorrect-endian-conversions-for-apb-timeout-register.patch
 usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch
-net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch
 vt-add-permission-check-for-kdskbmeta-ioctl.patch
 vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch
+input-evdev-fix-information-leak-in-evdev_pass_values.patch