]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Aug 2026 00:53:55 +0000 (09:53 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Aug 2026 00:53:55 +0000 (09:53 +0900)
added patches:
alsa-usb-audio-fix-oob-write-on-type-ii-inbound-urbs.patch
input-evdev-sanitize-event-type-index-when-fetching-event-masks.patch
net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch
usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.patch
usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch
vt-add-permission-check-for-kdskbmeta-ioctl.patch
vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch

queue-5.10/alsa-usb-audio-fix-oob-write-on-type-ii-inbound-urbs.patch [new file with mode: 0644]
queue-5.10/input-evdev-sanitize-event-type-index-when-fetching-event-masks.patch [new file with mode: 0644]
queue-5.10/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.patch [new file with mode: 0644]
queue-5.10/usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch [new file with mode: 0644]
queue-5.10/vt-add-permission-check-for-kdskbmeta-ioctl.patch [new file with mode: 0644]
queue-5.10/vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch [new file with mode: 0644]

diff --git a/queue-5.10/alsa-usb-audio-fix-oob-write-on-type-ii-inbound-urbs.patch b/queue-5.10/alsa-usb-audio-fix-oob-write-on-type-ii-inbound-urbs.patch
new file mode 100644 (file)
index 0000000..0a2b6aa
--- /dev/null
@@ -0,0 +1,109 @@
+From 69ee44e1a23be62318189dc4b37fa4ad94053269 Mon Sep 17 00:00:00 2001
+From: Baul Lee <baul.lee@xbow.com>
+Date: Wed, 5 Aug 2026 10:34:41 +0900
+Subject: ALSA: usb-audio: fix OOB write on Type II inbound URBs
+
+From: Baul Lee <baul.lee@xbow.com>
+
+commit 69ee44e1a23be62318189dc4b37fa4ad94053269 upstream.
+
+data_ep_set_params() sizes each URB transfer buffer before it adds the
+Format Type II transfer delimiter:
+
+       u->packets = urb_packs;
+       u->buffer_size = maxsize * u->packets;
+
+       if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
+               u->packets++; /* for transfer delimiter */
+       u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+
+buffer_size is computed from the pre-increment packet count and never
+recomputed, so for a Type II endpoint the buffer is one packet short of
+the packet count the URB is built with.
+
+prepare_inbound_urb() then lays out one iso frame per packet and never
+consults buffer_size:
+
+       offs = 0;
+       for (i = 0; i < urb_ctx->packets; i++) {
+               urb->iso_frame_desc[i].offset = offs;
+               urb->iso_frame_desc[i].length = ep->curpacksize;
+               offs += ep->curpacksize;
+       }
+
+       urb->transfer_buffer_length = offs;
+       urb->number_of_packets = urb_ctx->packets;
+
+The last descriptor therefore points one packet past the end of the
+transfer buffer, where the host controller writes device data on every
+inbound transfer.  prepare_silent_urb() and prepare_playback_urb() bound
+their fill loops by ctx->buffer_size, so only capture is affected.
+
+fmt_type comes from the device's audio streaming descriptors, so any
+device advertising a Type II capture format hits this once userspace sets
+hw_params on the stream.
+
+KASAN on 7.2.0-rc5 (arm64) with a dummy_hcd/raw-gadget device, one report
+per inbound transfer:
+
+  BUG: KASAN: slab-out-of-bounds in dummy_timer
+  Write of size 64 at addr ffff0000186171c0 by task cons02/166
+   __asan_memcpy
+   dummy_timer
+   hrtimer_run_softirq
+  Allocated by task 166:
+   usb_alloc_coherent
+   snd_usb_endpoint_set_params
+  The buggy address is located 0 bytes to the right of
+   allocated 64-byte region [ffff000018617180, ffff0000186171c0)
+
+Compute buffer_size after the delimiter packet has been accounted for,
+and bound the fill loop by buffer_size, as prepare_silent_urb() already
+does on the outbound side.  This grows every Type II URB allocation by
+one maxsize packet.
+
+Discovered by XBOW, triaged by Baul Lee <baul.lee@xbow.com>
+
+Fixes: 8fdff6a319e7 ("ALSA: snd-usb: implement new endpoint streaming model")
+Reported-by: Federico Kirschbaum <federico.kirschbaum@xbow.com>
+Reported-by: Baul Lee <baul.lee@xbow.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Baul Lee <baul.lee@xbow.com>
+Link: https://patch.msgid.link/20260805013441.38245-1-baul.lee@xbow.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/endpoint.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -301,13 +301,15 @@ static inline void prepare_inbound_urb(s
+       case SND_USB_ENDPOINT_TYPE_DATA:
+               offs = 0;
+               for (i = 0; i < urb_ctx->packets; i++) {
++                      if (offs + ep->curpacksize > urb_ctx->buffer_size)
++                              break;
+                       urb->iso_frame_desc[i].offset = offs;
+                       urb->iso_frame_desc[i].length = ep->curpacksize;
+                       offs += ep->curpacksize;
+               }
+               urb->transfer_buffer_length = offs;
+-              urb->number_of_packets = urb_ctx->packets;
++              urb->number_of_packets = i;
+               break;
+       case SND_USB_ENDPOINT_TYPE_SYNC:
+@@ -961,10 +963,10 @@ static int data_ep_set_params(struct snd
+               u->index = i;
+               u->ep = ep;
+               u->packets = urb_packs;
+-              u->buffer_size = maxsize * u->packets;
+               if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
+                       u->packets++; /* for transfer delimiter */
++              u->buffer_size = maxsize * u->packets;
+               u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+               if (!u->urb)
+                       goto out_of_memory;
diff --git a/queue-5.10/input-evdev-sanitize-event-type-index-when-fetching-event-masks.patch b/queue-5.10/input-evdev-sanitize-event-type-index-when-fetching-event-masks.patch
new file mode 100644 (file)
index 0000000..0db8369
--- /dev/null
@@ -0,0 +1,59 @@
+From 3abd29c61d2ef37c4102cf755b18be53bb9dbea6 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Mon, 3 Aug 2026 18:41:49 -0700
+Subject: Input: evdev - sanitize event type index when fetching event masks
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 3abd29c61d2ef37c4102cf755b18be53bb9dbea6 upstream.
+
+The user-supplied event type index passed to EVIOCGMASK / EVIOCSMASK
+ioctls is used to index the static counts array in evdev_get_mask_cnt()
+and client evmasks array in evdev_get_mask().
+
+While the event type is architecturally bounded by EV_CNT, speculative
+execution may mispredict bounds checks and perform out-of-bounds loads.
+
+Sanitize the event type index in evdev_get_mask_cnt() branchlessly using
+array_index_mask_nospec(). This clamps the index to 0 for safe array
+access and forces the returned count to 0 speculatively when the index
+is out of bounds.
+
+We do not need additional array_index_nospec() calls in evdev_get_mask()
+because evdev_get_mask_cnt() speculatively forces the count (and
+resulting xfer_size) to 0 for out-of-bounds types, preventing any
+speculative memory access to client evmasks array.
+
+Reported-by: "Wagenaar, C.C.J. (Chris)" <c.c.j.wagenaar@vu.nl>
+Cc: stable@vger.kernel.org
+Assisted-by: Antigravity:gemini-3.6-flash
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/anFCAfvxwXB5eJF1@google.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/evdev.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/input/evdev.c
++++ b/drivers/input/evdev.c
+@@ -21,6 +21,7 @@
+ #include <linux/init.h>
+ #include <linux/input/mt.h>
+ #include <linux/major.h>
++#include <linux/nospec.h>
+ #include <linux/device.h>
+ #include <linux/cdev.h>
+ #include "input-compat.h"
+@@ -67,8 +68,10 @@ static size_t evdev_get_mask_cnt(unsigne
+               [EV_SND]        = SND_CNT,
+               [EV_FF]         = FF_CNT,
+       };
++      unsigned long mask = array_index_mask_nospec(type, EV_CNT);
+-      return (type < EV_CNT) ? counts[type] : 0;
++      /* Returns 0 for out-of-bounds types, including speculatively */
++      return counts[type & mask] & mask;
+ }
+ /* requires the buffer lock to be held */
diff --git a/queue-5.10/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch b/queue-5.10/net-usb-ipheth-fix-carrier_work-uaf-on-disconnect.patch
new file mode 100644 (file)
index 0000000..33cfe1d
--- /dev/null
@@ -0,0 +1,104 @@
+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 f30f30fb9c2163676810ba9b1bfb989478650c2e..6ed63c26212a8fbf00fdbb2403406ebe4231f270 100644 (file)
@@ -340,3 +340,10 @@ sctp-extract-sctp_v4_err_handle-function-from-sctp_v.patch
 tls-don-t-abort-the-connection-on-signal-interrupted.patch
 spi-spi-fsl-dspi-avoid-setup_accel-logic-for-dma-tra.patch
 alsa-usb-audio-evaluate-packsize-caps-at-the-right-p.patch
+input-evdev-sanitize-event-type-index-when-fetching-event-masks.patch
+alsa-usb-audio-fix-oob-write-on-type-ii-inbound-urbs.patch
+usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.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
diff --git a/queue-5.10/usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.patch b/queue-5.10/usb-atm-cxacru-properly-kill-rcv_urb-on-error-in-cxacru_cm.patch
new file mode 100644 (file)
index 0000000..e30008c
--- /dev/null
@@ -0,0 +1,66 @@
+From c2f811314be351d86b6ab41e9297ae80d8da6f86 Mon Sep 17 00:00:00 2001
+From: Aleksandr Nogikh <nogikh@google.com>
+Date: Fri, 31 Jul 2026 10:15:20 +0000
+Subject: usb: atm: cxacru: properly kill rcv_urb on error in cxacru_cm()
+
+From: Aleksandr Nogikh <nogikh@google.com>
+
+commit c2f811314be351d86b6ab41e9297ae80d8da6f86 upstream.
+
+If cxacru_cm() encounters an error while submitting or waiting for snd_urb,
+it aborts and returns the error without killing the already submitted
+rcv_urb. This leaves the rcv_urb active.
+
+When this happens during initialization (e.g., in cxacru_atm_start()), the
+driver may ignore the error and proceed to call cxacru_poll_status(), which
+invokes cxacru_cm() again. Attempting to submit the still-active rcv_urb
+triggers a warning in usb_submit_urb():
+
+cxacru 1-1:1.0: send of cm 0x84 failed (-104)
+ATM dev 0: cxacru_atm_start: CHIP_ADSL_LINE_START returned -104
+------------[ cut here ]------------
+URB ffff88812658d200 submitted while active
+WARNING: drivers/usb/core/urb.c:379 at usb_submit_urb+0x79/0x18b0
+drivers/usb/core/urb.c:379
+...
+Call Trace:
+ <TASK>
+ cxacru_cm+0x21a/0xf10 drivers/usb/atm/cxacru.c:631
+ cxacru_cm_get_array drivers/usb/atm/cxacru.c:722 [inline]
+ cxacru_poll_status+0x178/0x1110 drivers/usb/atm/cxacru.c:828
+ cxacru_atm_start+0x185/0x360 drivers/usb/atm/cxacru.c:814
+ usbatm_atm_init+0x144/0x3a0 drivers/usb/atm/usbatm.c:927
+ usbatm_usb_probe+0x15cb/0x1db0 drivers/usb/atm/usbatm.c:1178
+ cxacru_usb_probe+0x17f/0x220 drivers/usb/atm/cxacru.c:1370
+...
+
+To fix this, ensure that rcv_urb is properly killed if cxacru_cm() aborts
+early. We can safely call usb_kill_urb() on rcv_urb in the error path, as
+it is safe to call even if the URB is not active (e.g., if it failed to
+submit in the first place, or if it already completed).
+
+Fixes: 1b0e61465234 ("[PATCH] USB ATM: driver for the Conexant AccessRunner chipset cxacru")
+Cc: stable <stable@kernel.org>
+Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
+Reported-by: syzbot+c9dff578c3a41775176a@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=c9dff578c3a41775176a
+Link: https://syzkaller.appspot.com/ai_job?id=75fec6f2-c8a6-43b1-b184-4d26baba86cc
+Signed-off-by: Aleksandr Nogikh <nogikh@google.com>
+Link: https://patch.msgid.link/91edfa4c-a63d-400c-9f00-31f3e1f98c00@mail.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/atm/cxacru.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -700,6 +700,8 @@ static int cxacru_cm(struct cxacru_data
+       ret = offd;
+       usb_dbg(instance->usbatm, "cm %#x\n", cm);
+ fail:
++      if (ret < 0)
++              usb_kill_urb(instance->rcv_urb);
+       mutex_unlock(&instance->cm_serialize);
+ err:
+       return ret;
diff --git a/queue-5.10/usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch b/queue-5.10/usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch
new file mode 100644 (file)
index 0000000..4c38310
--- /dev/null
@@ -0,0 +1,42 @@
+From 6b1c8a9403a26cb0fed7a648916c74dc236da591 Mon Sep 17 00:00:00 2001
+From: Sonali Pradhan <sonalipradhan@google.com>
+Date: Mon, 20 Jul 2026 16:56:54 +0000
+Subject: usb: gadget: f_ncm: Use unsigned int for ndp_index
+
+From: Sonali Pradhan <sonalipradhan@google.com>
+
+commit 6b1c8a9403a26cb0fed7a648916c74dc236da591 upstream.
+
+The variable ndp_index is declared as a signed integer, but it stores
+the return value of get_ncm(), which is unsigned.
+
+A malicious host can supply a large offset that overflows the signed
+ndp_index, making it negative. Because ndp_index is compared against
+unsigned bounds, this negative value bypasses sanity checks and leads
+to an out-of-bounds read when calculating the address of the NDP
+block (ntb_ptr + ndp_index).
+
+Fix this by changing ndp_index to unsigned int to ensure consistent
+unsigned comparisons throughout the function.
+
+Fixes: 370af734dfaf ("usb: gadget: NCM: RX function support multiple NDPs")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Sonali Pradhan <sonalipradhan@google.com>
+Link: https://patch.msgid.link/20260720165654.2224591-1-sonalipradhan@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -1183,7 +1183,7 @@ static int ncm_unwrap_ntb(struct gether
+       unsigned char   *ntb_ptr = skb->data;
+       __le16          *tmp;
+       unsigned        index, index2;
+-      int             ndp_index;
++      unsigned int    ndp_index;
+       unsigned        dg_len, dg_len2;
+       unsigned        ndp_len;
+       unsigned        block_len;
diff --git a/queue-5.10/vt-add-permission-check-for-kdskbmeta-ioctl.patch b/queue-5.10/vt-add-permission-check-for-kdskbmeta-ioctl.patch
new file mode 100644 (file)
index 0000000..ed4284e
--- /dev/null
@@ -0,0 +1,34 @@
+From a7ad0034453ba4c353f9b8f810ee2569de33d283 Mon Sep 17 00:00:00 2001
+From: Joshua Rogers <linux@joshua.hu>
+Date: Fri, 31 Jul 2026 09:56:17 +0200
+Subject: vt: add permission check for KDSKBMETA ioctl
+
+From: Joshua Rogers <linux@joshua.hu>
+
+commit a7ad0034453ba4c353f9b8f810ee2569de33d283 upstream.
+
+KDSKBMETA modifies keyboard meta mode but lacks the !perm check that all
+other keyboard setter ioctls in vt_k_ioctl() enforce, allowing a process
+to change meta mode on a non-controlling console without authorization.
+
+Assisted-by: AISLE:Snapshot
+Cc: stable <stable@kernel.org>
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Link: https://patch.msgid.link/20260731-tty-vt-stuff-v1-2-be99b9da8e30@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/vt/vt_ioctl.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/tty/vt/vt_ioctl.c
++++ b/drivers/tty/vt/vt_ioctl.c
+@@ -408,6 +408,8 @@ static int vt_k_ioctl(struct tty_struct
+       /* this could be folded into KDSKBMODE, but for compatibility
+          reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
+       case KDSKBMETA:
++              if (!perm)
++                      return -EPERM;
+               return vt_do_kdskbmeta(console, arg);
+       case KDGKBMETA:
diff --git a/queue-5.10/vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch b/queue-5.10/vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch
new file mode 100644 (file)
index 0000000..2e240e7
--- /dev/null
@@ -0,0 +1,48 @@
+From e25d47a526939ad44b75f778b8a7500562b84fc1 Mon Sep 17 00:00:00 2001
+From: Joshua Rogers <linux@joshua.hu>
+Date: Fri, 31 Jul 2026 09:56:16 +0200
+Subject: vt: stabilize tty reference in kbd_keycode with tty_port_tty_get
+
+From: Joshua Rogers <linux@joshua.hu>
+
+commit e25d47a526939ad44b75f778b8a7500562b84fc1 upstream.
+
+kbd_keycode() reads vc->port.tty without acquiring a tty reference,
+racing against con_shutdown() which clears port.tty under a different
+lock. Use tty_port_tty_get()/tty_kref_put() to hold a proper reference
+for the duration the tty pointer is needed.
+
+Assisted-by: AISLE:Snapshot
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Cc: stable <stable@kernel.org>
+Link: https://patch.msgid.link/20260731-tty-vt-stuff-v1-1-be99b9da8e30@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/vt/keyboard.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -1367,7 +1367,7 @@ static void kbd_keycode(unsigned int key
+       struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
+       int rc;
+-      tty = vc->port.tty;
++      tty = tty_port_tty_get(&vc->port);
+       if (tty && (!tty->driver_data)) {
+               /* No driver data? Strange. Okay we fix it then. */
+@@ -1430,9 +1430,12 @@ static void kbd_keycode(unsigned int key
+                * characters get aren't echoed locally. This makes key repeat
+                * usable with slow applications and under heavy loads.
+                */
++              tty_kref_put(tty);
+               return;
+       }
++      tty_kref_put(tty);
++
+       param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
+       param.ledstate = kbd->ledflagstate;
+       key_map = key_maps[shift_final];