From: Greg Kroah-Hartman Date: Tue, 12 May 2026 12:51:42 +0000 (+0200) Subject: 7.0-stable patches X-Git-Tag: v6.12.88~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=45479c5597b5807edf4a9f5fa9ef4763c2b5b511;p=thirdparty%2Fkernel%2Fstable-queue.git 7.0-stable patches added patches: bluetooth-btmtk-validate-wmt-event-skb-length-before-struct-access.patch bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch bluetooth-hci_event-fix-oob-read-and-infinite-loop-in-hci_le_create_big_complete_evt.patch bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_get_sndtimeo_cb.patch bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_new_connection_cb.patch bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_state_change_cb.patch bluetooth-virtio_bt-clamp-rx-length-before-skb_put.patch bluetooth-virtio_bt-validate-rx-pkt_type-header-length.patch io_uring-kbuf-support-min-length-left-for-incremental-buffers.patch io_uring-tw-serialize-ctx-retry_llist-with-uring_lock.patch ipv6-xfrm6-release-dst-on-error-in-xfrm6_rcv_encap.patch loongarch-kvm-fix-missing-emulate_fail-in-kvm_emu_mmio_read.patch powerpc-kdump-fix-kasan-sanitization-flag-for-core_-bits-.o.patch rust-allow-clippy-collapsible_if-globally.patch rust-allow-clippy-collapsible_match-globally.patch rust-drm-gem-clean-up-gem-state-in-init-failure-case.patch rust-pin-init-internal-move-alignment-check-to-make_field_check.patch sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch selinux-allow-multiple-opens-of-sys-fs-selinux-policy.patch selinux-don-t-reserve-xattr-slot-when-we-won-t-fill-it.patch selinux-fix-avdcache-auditing.patch selinux-prune-sys-fs-selinux-checkreqprot.patch selinux-prune-sys-fs-selinux-disable.patch selinux-prune-sys-fs-selinux-user.patch selinux-shrink-critical-section-in-sel_write_load.patch selinux-use-sk-blob-accessor-in-socket-permission-helpers.patch spi-s3c64xx-fix-null-deref-on-driver-unbind.patch spi-sun4i-fix-controller-deregistration.patch spi-sun6i-fix-controller-deregistration.patch spi-syncuacer-fix-controller-deregistration.patch spi-tegra114-fix-controller-deregistration.patch spi-tegra20-sflash-fix-controller-deregistration.patch spi-ti-qspi-fix-controller-deregistration.patch spi-zynq-qspi-fix-controller-deregistration.patch spi-zynqmp-gqspi-fix-controller-deregistration.patch staging-rtl8723bs-os_dep-avoid-null-pointer-dereference-in-rtw_cbuf_alloc.patch staging-vme_user-fix-root-device-leak-on-init-failure.patch x86-efi-restore-irq-state-in-efi-page-fault-handler.patch xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch xfrm-provide-message-size-for-xfrm_msg_mapping.patch --- diff --git a/queue-7.0/bluetooth-btmtk-validate-wmt-event-skb-length-before-struct-access.patch b/queue-7.0/bluetooth-btmtk-validate-wmt-event-skb-length-before-struct-access.patch new file mode 100644 index 0000000000..5192a93cd5 --- /dev/null +++ b/queue-7.0/bluetooth-btmtk-validate-wmt-event-skb-length-before-struct-access.patch @@ -0,0 +1,58 @@ +From 634a4408c0615c523cf7531790f4f14a422b9206 Mon Sep 17 00:00:00 2001 +From: Tristan Madani +Date: Tue, 21 Apr 2026 11:14:54 +0000 +Subject: Bluetooth: btmtk: validate WMT event SKB length before struct access + +From: Tristan Madani + +commit 634a4408c0615c523cf7531790f4f14a422b9206 upstream. + +btmtk_usb_hci_wmt_sync() casts the WMT event response SKB data to +struct btmtk_hci_wmt_evt (7 bytes) and struct btmtk_hci_wmt_evt_funcc +(9 bytes) without first checking that the SKB contains enough data. +A short firmware response causes out-of-bounds reads from SKB tailroom. + +Use skb_pull_data() to validate and advance past the base WMT event +header. For the FUNC_CTRL case, pull the additional status field bytes +before accessing them. + +Fixes: d019930b0049 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c") +Cc: stable@vger.kernel.org +Signed-off-by: Tristan Madani +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btmtk.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -654,8 +654,13 @@ static int btmtk_usb_hci_wmt_sync(struct + if (data->evt_skb == NULL) + goto err_free_wc; + +- /* Parse and handle the return WMT event */ +- wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data; ++ wmt_evt = skb_pull_data(data->evt_skb, sizeof(*wmt_evt)); ++ if (!wmt_evt) { ++ bt_dev_err(hdev, "WMT event too short (%u bytes)", ++ data->evt_skb->len); ++ err = -EINVAL; ++ goto err_free_skb; ++ } + if (wmt_evt->whdr.op != hdr->op) { + bt_dev_err(hdev, "Wrong op received %d expected %d", + wmt_evt->whdr.op, hdr->op); +@@ -671,6 +676,12 @@ static int btmtk_usb_hci_wmt_sync(struct + status = BTMTK_WMT_PATCH_DONE; + break; + case BTMTK_WMT_FUNC_CTRL: ++ if (!skb_pull_data(data->evt_skb, ++ sizeof(wmt_evt_funcc->status))) { ++ err = -EINVAL; ++ goto err_free_skb; ++ } ++ + wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; + if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) + status = BTMTK_WMT_ON_DONE; diff --git a/queue-7.0/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch b/queue-7.0/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch new file mode 100644 index 0000000000..8bbd03465f --- /dev/null +++ b/queue-7.0/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch @@ -0,0 +1,91 @@ +From 0beddb0c380bed5f5b8e61ddbe14635bb73d0b41 Mon Sep 17 00:00:00 2001 +From: David Carlier +Date: Sun, 12 Apr 2026 21:29:16 +0100 +Subject: Bluetooth: hci_conn: fix potential UAF in create_big_sync + +From: David Carlier + +commit 0beddb0c380bed5f5b8e61ddbe14635bb73d0b41 upstream. + +Add hci_conn_valid() check in create_big_sync() to detect stale +connections before proceeding with BIG creation. Handle the +resulting -ECANCELED in create_big_complete() and re-validate the +connection under hci_dev_lock() before dereferencing, matching the +pattern used by create_le_conn_complete() and create_pa_complete(). + +Keep the hci_conn object alive across the async boundary by taking +a reference via hci_conn_get() when queueing create_big_sync(), and +dropping it in the completion callback. The refcount and the lock +are complementary: the refcount keeps the object allocated, while +hci_dev_lock() serializes hci_conn_hash_del()'s list_del_rcu() on +hdev->conn_hash, as required by hci_conn_del(). + +hci_conn_put() is called outside hci_dev_unlock() so the final put +(which resolves to kfree() via bt_link_release) does not run under +hdev->lock, though the release path would be safe either way. + +Without this, create_big_complete() would unconditionally +dereference the conn pointer on error, causing a use-after-free +via hci_connect_cfm() and hci_conn_del(). + +Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections") +Cc: stable@vger.kernel.org +Co-developed-by: Luiz Augusto von Dentz +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: David Carlier +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/hci_conn.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -2130,6 +2130,9 @@ static int create_big_sync(struct hci_de + u32 flags = 0; + int err; + ++ if (!hci_conn_valid(hdev, conn)) ++ return -ECANCELED; ++ + if (qos->bcast.out.phys == BIT(1)) + flags |= MGMT_ADV_FLAG_SEC_2M; + +@@ -2204,11 +2207,24 @@ static void create_big_complete(struct h + + bt_dev_dbg(hdev, "conn %p", conn); + ++ if (err == -ECANCELED) ++ goto done; ++ ++ hci_dev_lock(hdev); ++ ++ if (!hci_conn_valid(hdev, conn)) ++ goto unlock; ++ + if (err) { + bt_dev_err(hdev, "Unable to create BIG: %d", err); + hci_connect_cfm(conn, err); + hci_conn_del(conn); + } ++ ++unlock: ++ hci_dev_unlock(hdev); ++done: ++ hci_conn_put(conn); + } + + struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, +@@ -2336,10 +2352,11 @@ struct hci_conn *hci_connect_bis(struct + BT_BOUND, &data); + + /* Queue start periodic advertising and create BIG */ +- err = hci_cmd_sync_queue(hdev, create_big_sync, conn, ++ err = hci_cmd_sync_queue(hdev, create_big_sync, hci_conn_get(conn), + create_big_complete); + if (err < 0) { + hci_conn_drop(conn); ++ hci_conn_put(conn); + return ERR_PTR(err); + } + diff --git a/queue-7.0/bluetooth-hci_event-fix-oob-read-and-infinite-loop-in-hci_le_create_big_complete_evt.patch b/queue-7.0/bluetooth-hci_event-fix-oob-read-and-infinite-loop-in-hci_le_create_big_complete_evt.patch new file mode 100644 index 0000000000..5e651007b1 --- /dev/null +++ b/queue-7.0/bluetooth-hci_event-fix-oob-read-and-infinite-loop-in-hci_le_create_big_complete_evt.patch @@ -0,0 +1,80 @@ +From 5ddb8014261137cadaf83ab5617a588d80a22586 Mon Sep 17 00:00:00 2001 +From: Luiz Augusto von Dentz +Date: Fri, 10 Apr 2026 15:29:52 -0400 +Subject: Bluetooth: hci_event: Fix OOB read and infinite loop in hci_le_create_big_complete_evt + +From: Luiz Augusto von Dentz + +commit 5ddb8014261137cadaf83ab5617a588d80a22586 upstream. + +hci_le_create_big_complete_evt() iterates over BT_BOUND connections for +a BIG handle using a while loop, accessing ev->bis_handle[i++] on each +iteration. However, there is no check that i stays within ev->num_bis +before the array access. + +When a controller sends a LE_Create_BIG_Complete event with fewer +bis_handle entries than there are BT_BOUND connections for that BIG, +or with num_bis=0, the loop reads beyond the valid bis_handle[] flex +array into adjacent heap memory. Since the out-of-bounds values +typically exceed HCI_CONN_HANDLE_MAX (0x0EFF), hci_conn_set_handle() +rejects them and the connection remains in BT_BOUND state. The same +connection is then found again by hci_conn_hash_lookup_big_state(), +creating an infinite loop with hci_dev_lock held. + +Fix this by terminating the BIG if in case not all BIS could be setup +properly. + +Fixes: a0bfde167b50 ("Bluetooth: ISO: Add support for connecting multiple BISes") +Cc: stable@vger.kernel.org +Signed-off-by: ZhiTao Ou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/hci_event.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -7121,9 +7121,29 @@ static void hci_le_create_big_complete_e + continue; + } + ++ if (ev->num_bis <= i) { ++ bt_dev_err(hdev, ++ "Not enough BIS handles for BIG 0x%2.2x", ++ ev->handle); ++ ev->status = HCI_ERROR_UNSPECIFIED; ++ hci_connect_cfm(conn, ev->status); ++ hci_conn_del(conn); ++ continue; ++ } ++ + if (hci_conn_set_handle(conn, +- __le16_to_cpu(ev->bis_handle[i++]))) ++ __le16_to_cpu(ev->bis_handle[i++]))) { ++ bt_dev_err(hdev, ++ "Failed to set BIS handle for BIG 0x%2.2x", ++ ev->handle); ++ /* Force error so BIG gets terminated as not all BIS ++ * could be connected. ++ */ ++ ev->status = HCI_ERROR_UNSPECIFIED; ++ hci_connect_cfm(conn, ev->status); ++ hci_conn_del(conn); + continue; ++ } + + conn->state = BT_CONNECTED; + set_bit(HCI_CONN_BIG_CREATED, &conn->flags); +@@ -7132,7 +7152,10 @@ static void hci_le_create_big_complete_e + hci_iso_setup_path(conn); + } + +- if (!ev->status && !i) ++ /* If there is an unexpected error or if no BISes have been connected ++ * for the BIG, terminate it. ++ */ ++ if (ev->status == HCI_ERROR_UNSPECIFIED || (!ev->status && !i)) + /* If no BISes have been connected for the BIG, + * terminate. This is in case all bound connections + * have been closed before the BIG creation diff --git a/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_get_sndtimeo_cb.patch b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_get_sndtimeo_cb.patch new file mode 100644 index 0000000000..c90e9ebb11 --- /dev/null +++ b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_get_sndtimeo_cb.patch @@ -0,0 +1,33 @@ +From 78a88d43dab8d23aeef934ed8ce34d40e6b3d613 Mon Sep 17 00:00:00 2001 +From: Siwei Zhang +Date: Wed, 15 Apr 2026 16:53:36 -0400 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_get_sndtimeo_cb() + +From: Siwei Zhang + +commit 78a88d43dab8d23aeef934ed8ce34d40e6b3d613 upstream. + +Add the same NULL guard already present in +l2cap_sock_resume_cb() and l2cap_sock_ready_cb(). + +Fixes: 8d836d71e222 ("Bluetooth: Access sk_sndtimeo indirectly in l2cap_core.c") +Cc: stable@kernel.org +Signed-off-by: Siwei Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1764,6 +1764,9 @@ static long l2cap_sock_get_sndtimeo_cb(s + { + struct sock *sk = chan->data; + ++ if (!sk) ++ return 0; ++ + return READ_ONCE(sk->sk_sndtimeo); + } + diff --git a/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_new_connection_cb.patch b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_new_connection_cb.patch new file mode 100644 index 0000000000..a9f12110aa --- /dev/null +++ b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_new_connection_cb.patch @@ -0,0 +1,33 @@ +From 0a120d96166301d7a95be75b52f843837dbd1219 Mon Sep 17 00:00:00 2001 +From: Siwei Zhang +Date: Wed, 15 Apr 2026 16:49:59 -0400 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_new_connection_cb() + +From: Siwei Zhang + +commit 0a120d96166301d7a95be75b52f843837dbd1219 upstream. + +Add the same NULL guard already present in +l2cap_sock_resume_cb() and l2cap_sock_ready_cb(). + +Fixes: 80808e431e1e ("Bluetooth: Add l2cap_chan_ops abstraction") +Cc: stable@kernel.org +Signed-off-by: Siwei Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1498,6 +1498,9 @@ static struct l2cap_chan *l2cap_sock_new + { + struct sock *sk, *parent = chan->data; + ++ if (!parent) ++ return NULL; ++ + lock_sock(parent); + + /* Check for backlog size */ diff --git a/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_state_change_cb.patch b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_state_change_cb.patch new file mode 100644 index 0000000000..0a369676ec --- /dev/null +++ b/queue-7.0/bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_state_change_cb.patch @@ -0,0 +1,33 @@ +From 2ff1a41a912de8517b4482e946dd951b7d80edbf Mon Sep 17 00:00:00 2001 +From: Siwei Zhang +Date: Wed, 15 Apr 2026 16:51:36 -0400 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_state_change_cb() + +From: Siwei Zhang + +commit 2ff1a41a912de8517b4482e946dd951b7d80edbf upstream. + +Add the same NULL guard already present in +l2cap_sock_resume_cb() and l2cap_sock_ready_cb(). + +Fixes: 89bc500e41fc ("Bluetooth: Add state tracking to struct l2cap_chan") +Cc: stable@kernel.org +Signed-off-by: Siwei Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1660,6 +1660,9 @@ static void l2cap_sock_state_change_cb(s + { + struct sock *sk = chan->data; + ++ if (!sk) ++ return; ++ + sk->sk_state = state; + + if (err) diff --git a/queue-7.0/bluetooth-virtio_bt-clamp-rx-length-before-skb_put.patch b/queue-7.0/bluetooth-virtio_bt-clamp-rx-length-before-skb_put.patch new file mode 100644 index 0000000000..2374c59b4d --- /dev/null +++ b/queue-7.0/bluetooth-virtio_bt-clamp-rx-length-before-skb_put.patch @@ -0,0 +1,91 @@ +From 21bd244b6de5d2fe1063c23acc93fbdd2b20d112 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 21 Apr 2026 13:08:44 -0400 +Subject: Bluetooth: virtio_bt: clamp rx length before skb_put + +From: Michael Bommarito + +commit 21bd244b6de5d2fe1063c23acc93fbdd2b20d112 upstream. + +virtbt_rx_work() calls skb_put(skb, len) where len comes directly +from virtqueue_get_buf() with no validation against the buffer we +posted to the device. The RX skb is allocated in virtbt_add_inbuf() +and exposed to virtio as exactly 1000 bytes via sg_init_one(). + +Checking len against skb_tailroom(skb) is not sufficient because +alloc_skb() can leave more tailroom than the 1000 bytes actually +handed to the device. A malicious or buggy backend can therefore +report used.len between 1001 and skb_tailroom(skb), causing skb_put() +to include uninitialized kernel heap bytes that were never written by +the device. + +The same path also accepts len == 0, in which case skb_put(skb, 0) +leaves the skb empty but virtbt_rx_handle() still reads the pkt_type +byte from skb->data, consuming uninitialized memory. + +Define VIRTBT_RX_BUF_SIZE once and reuse it in alloc_skb() and +sg_init_one(), and gate virtbt_rx_work() on that same constant so +the bound checked matches the buffer actually exposed to the device. +Reject used.len == 0 in the same gate so an empty completion can +no longer reach virtbt_rx_handle(). + +Use bt_dev_err_ratelimited() because the length value comes from an +untrusted backend that can otherwise flood the kernel log. + +Same class of bug as commit c04db81cd028 ("net/9p: Fix buffer +overflow in USB transport layer"), which hardened the USB 9p +transport against unchecked device-reported length. + +Fixes: 160fbcf3bfb9 ("Bluetooth: virtio_bt: Use skb_put to set length") +Cc: stable@vger.kernel.org +Cc: Soenke Huster +Signed-off-by: Michael Bommarito +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/virtio_bt.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/bluetooth/virtio_bt.c ++++ b/drivers/bluetooth/virtio_bt.c +@@ -12,6 +12,7 @@ + #include + + #define VERSION "0.1" ++#define VIRTBT_RX_BUF_SIZE 1000 + + enum { + VIRTBT_VQ_TX, +@@ -33,11 +34,11 @@ static int virtbt_add_inbuf(struct virti + struct sk_buff *skb; + int err; + +- skb = alloc_skb(1000, GFP_KERNEL); ++ skb = alloc_skb(VIRTBT_RX_BUF_SIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + +- sg_init_one(sg, skb->data, 1000); ++ sg_init_one(sg, skb->data, VIRTBT_RX_BUF_SIZE); + + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); + if (err < 0) { +@@ -227,8 +228,15 @@ static void virtbt_rx_work(struct work_s + if (!skb) + return; + +- skb_put(skb, len); +- virtbt_rx_handle(vbt, skb); ++ if (!len || len > VIRTBT_RX_BUF_SIZE) { ++ bt_dev_err_ratelimited(vbt->hdev, ++ "rx reply len %u outside [1, %u]\n", ++ len, VIRTBT_RX_BUF_SIZE); ++ kfree_skb(skb); ++ } else { ++ skb_put(skb, len); ++ virtbt_rx_handle(vbt, skb); ++ } + + if (virtbt_add_inbuf(vbt) < 0) + return; diff --git a/queue-7.0/bluetooth-virtio_bt-validate-rx-pkt_type-header-length.patch b/queue-7.0/bluetooth-virtio_bt-validate-rx-pkt_type-header-length.patch new file mode 100644 index 0000000000..eb5d769036 --- /dev/null +++ b/queue-7.0/bluetooth-virtio_bt-validate-rx-pkt_type-header-length.patch @@ -0,0 +1,93 @@ +From daf23014e5d975e72ea9c02b5160d3fcf070ea47 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 21 Apr 2026 13:08:45 -0400 +Subject: Bluetooth: virtio_bt: validate rx pkt_type header length + +From: Michael Bommarito + +commit daf23014e5d975e72ea9c02b5160d3fcf070ea47 upstream. + +virtbt_rx_handle() reads the leading pkt_type byte from the RX skb +and forwards the remainder to hci_recv_frame() for every +event/ACL/SCO/ISO type, without checking that the remaining payload +is at least the fixed HCI header for that type. + +After the preceding patch bounds the backend-supplied used.len to +[1, VIRTBT_RX_BUF_SIZE], a one-byte completion still reaches +hci_recv_frame() with skb->len already pulled to 0. If the byte +happened to be HCI_ACLDATA_PKT, the ACL-vs-ISO classification +fast-path in hci_dev_classify_pkt_type() dereferences +hci_acl_hdr(skb)->handle whenever the HCI device has an active +CIS_LINK, BIS_LINK, or PA_LINK connection, reading two bytes of +uninitialized RX-buffer data. The same hazard exists for every +packet type the driver accepts because none of the switch cases in +virtbt_rx_handle() check skb->len against the per-type minimum HCI +header size before handing the frame to the core. + +After stripping pkt_type, require skb->len to cover the fixed +header size for the selected type (event 2, ACL 4, SCO 3, ISO 4) +before calling hci_recv_frame(); drop ratelimited otherwise. +Unknown pkt_type values still take the original kfree_skb() default +path. + +Use bt_dev_err_ratelimited() because both the length and pkt_type +values come from an untrusted backend that can otherwise flood the +kernel log. + +Fixes: 160fbcf3bfb9 ("Bluetooth: virtio_bt: Use skb_put to set length") +Cc: stable@vger.kernel.org +Cc: Soenke Huster +Signed-off-by: Michael Bommarito +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/virtio_bt.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +--- a/drivers/bluetooth/virtio_bt.c ++++ b/drivers/bluetooth/virtio_bt.c +@@ -198,6 +198,7 @@ static int virtbt_shutdown_generic(struc + + static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb) + { ++ size_t min_hdr; + __u8 pkt_type; + + pkt_type = *((__u8 *) skb->data); +@@ -205,16 +206,32 @@ static void virtbt_rx_handle(struct virt + + switch (pkt_type) { + case HCI_EVENT_PKT: ++ min_hdr = sizeof(struct hci_event_hdr); ++ break; + case HCI_ACLDATA_PKT: ++ min_hdr = sizeof(struct hci_acl_hdr); ++ break; + case HCI_SCODATA_PKT: ++ min_hdr = sizeof(struct hci_sco_hdr); ++ break; + case HCI_ISODATA_PKT: +- hci_skb_pkt_type(skb) = pkt_type; +- hci_recv_frame(vbt->hdev, skb); ++ min_hdr = sizeof(struct hci_iso_hdr); + break; + default: + kfree_skb(skb); +- break; ++ return; + } ++ ++ if (skb->len < min_hdr) { ++ bt_dev_err_ratelimited(vbt->hdev, ++ "rx pkt_type 0x%02x payload %u < hdr %zu\n", ++ pkt_type, skb->len, min_hdr); ++ kfree_skb(skb); ++ return; ++ } ++ ++ hci_skb_pkt_type(skb) = pkt_type; ++ hci_recv_frame(vbt->hdev, skb); + } + + static void virtbt_rx_work(struct work_struct *work) diff --git a/queue-7.0/io_uring-kbuf-support-min-length-left-for-incremental-buffers.patch b/queue-7.0/io_uring-kbuf-support-min-length-left-for-incremental-buffers.patch new file mode 100644 index 0000000000..7a0716e5b1 --- /dev/null +++ b/queue-7.0/io_uring-kbuf-support-min-length-left-for-incremental-buffers.patch @@ -0,0 +1,96 @@ +From 7deba791ad495ce1d7921683f4f7d1190fa210d1 Mon Sep 17 00:00:00 2001 +From: Martin Michaelis +Date: Thu, 23 Apr 2026 15:54:11 -0600 +Subject: io_uring/kbuf: support min length left for incremental buffers + +From: Martin Michaelis + +commit 7deba791ad495ce1d7921683f4f7d1190fa210d1 upstream. + +Incrementally consumed buffer rings are generally fully consumed, but +it's quite possible that the application has a minimum size it needs to +meet to avoid truncation. Currently that minimum limit is 1 byte, but +this should be a setting that is the hands of the application. For +recvmsg multishot, a prime use case for incrementally consumed buffers, +the application may get spurious -EFAULT returned at the end of an +incrementally consumed buffer, as less space is available than the +headers need. + +Grab a u32 field in struct io_uring_buf_reg, which the application can +use to inform the kernel of the minimum size that should be available +in an incrementally consumed buffer. If less than that is available, +the current buffer is fully processed and the next one will be picked. + +Cc: stable@vger.kernel.org +Fixes: ae98dbf43d75 ("io_uring/kbuf: add support for incremental buffer consumption") +Link: https://github.com/axboe/liburing/issues/1433 +Signed-off-by: Martin Michaelis +[axboe: write commit message, change io_buffer_list member name] +Reviewed-by: Gabriel Krisman Bertazi +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + include/uapi/linux/io_uring.h | 3 ++- + io_uring/kbuf.c | 8 +++++++- + io_uring/kbuf.h | 7 +++++++ + 3 files changed, 16 insertions(+), 2 deletions(-) + +--- a/include/uapi/linux/io_uring.h ++++ b/include/uapi/linux/io_uring.h +@@ -898,7 +898,8 @@ struct io_uring_buf_reg { + __u32 ring_entries; + __u16 bgid; + __u16 flags; +- __u64 resv[3]; ++ __u32 min_left; ++ __u32 resv[5]; + }; + + /* argument for IORING_REGISTER_PBUF_STATUS */ +--- a/io_uring/kbuf.c ++++ b/io_uring/kbuf.c +@@ -47,7 +47,7 @@ static bool io_kbuf_inc_commit(struct io + this_len = min_t(u32, len, buf_len); + buf_len -= this_len; + /* Stop looping for invalid buffer length of 0 */ +- if (buf_len || !this_len) { ++ if (buf_len > bl->min_left_sub_one || !this_len) { + WRITE_ONCE(buf->addr, READ_ONCE(buf->addr) + this_len); + WRITE_ONCE(buf->len, buf_len); + return false; +@@ -637,6 +637,10 @@ int io_register_pbuf_ring(struct io_ring + if (reg.ring_entries >= 65536) + return -EINVAL; + ++ /* minimum left byte count is a property of incremental buffers */ ++ if (!(reg.flags & IOU_PBUF_RING_INC) && reg.min_left) ++ return -EINVAL; ++ + bl = io_buffer_get_list(ctx, reg.bgid); + if (bl) { + /* if mapped buffer ring OR classic exists, don't allow */ +@@ -684,6 +688,8 @@ int io_register_pbuf_ring(struct io_ring + bl->mask = reg.ring_entries - 1; + bl->flags |= IOBL_BUF_RING; + bl->buf_ring = br; ++ if (reg.min_left) ++ bl->min_left_sub_one = reg.min_left - 1; + if (reg.flags & IOU_PBUF_RING_INC) + bl->flags |= IOBL_INC; + ret = io_buffer_add_list(ctx, bl, reg.bgid); +--- a/io_uring/kbuf.h ++++ b/io_uring/kbuf.h +@@ -33,6 +33,13 @@ struct io_buffer_list { + + __u16 flags; + ++ /* ++ * minimum required amount to be left to reuse an incrementally ++ * consumed buffer. If less than this is left at consumption time, ++ * buffer is done and head is incremented to the next buffer. ++ */ ++ __u32 min_left_sub_one; ++ + struct io_mapped_region region; + }; + diff --git a/queue-7.0/io_uring-tw-serialize-ctx-retry_llist-with-uring_lock.patch b/queue-7.0/io_uring-tw-serialize-ctx-retry_llist-with-uring_lock.patch new file mode 100644 index 0000000000..4cda4dbc7b --- /dev/null +++ b/queue-7.0/io_uring-tw-serialize-ctx-retry_llist-with-uring_lock.patch @@ -0,0 +1,57 @@ +From 17666e2d7592c3e85260cafd3950121524acc2c5 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 27 Apr 2026 14:29:02 -0600 +Subject: io_uring/tw: serialize ctx->retry_llist with ->uring_lock + +From: Jens Axboe + +commit 17666e2d7592c3e85260cafd3950121524acc2c5 upstream. + +The DEFER_TASKRUN local task work paths all run under ctx->uring_lock, +which serializes them with each other and with the rest of the ring's +hot paths. io_move_task_work_from_local() is the exception - it's called +from io_ring_exit_work() on a kworker without holding the lock and from +the iopoll cancelation side right after dropping it. + +->work_llist is fine with this, as it's only ever updated via the +expected paths. But the ->retry_llist is updated while runing, and hence +it could potentially race between normal task_work running and the +task-has-exited shutdown path. + +Simply grab ->uring_lock while moving the local work to the fallback +list for exit purposes, which nicely serializes it across both the +normal additions and the exit prune path. + +Cc: stable@vger.kernel.org +Fixes: f46b9cdb22f7 ("io_uring: limit local tw done") +Reported-by: Robert Femmer +Reported-by: Christian Reitter +Reported-by: Michael Rodler +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/tw.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/io_uring/tw.c ++++ b/io_uring/tw.c +@@ -273,8 +273,18 @@ void io_req_task_work_add_remote(struct + + void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx) + { +- struct llist_node *node = llist_del_all(&ctx->work_llist); ++ struct llist_node *node; + ++ /* ++ * Running the work items may utilize ->retry_llist as a means ++ * for capping the number of task_work entries run at the same ++ * time. But that list can potentially race with moving the work ++ * from here, if the task is exiting. As any normal task_work ++ * running holds ->uring_lock already, just guard this slow path ++ * with ->uring_lock to avoid racing on ->retry_llist. ++ */ ++ guard(mutex)(&ctx->uring_lock); ++ node = llist_del_all(&ctx->work_llist); + __io_fallback_tw(node, false); + node = llist_del_all(&ctx->retry_llist); + __io_fallback_tw(node, false); diff --git a/queue-7.0/ipv6-xfrm6-release-dst-on-error-in-xfrm6_rcv_encap.patch b/queue-7.0/ipv6-xfrm6-release-dst-on-error-in-xfrm6_rcv_encap.patch new file mode 100644 index 0000000000..22d7660771 --- /dev/null +++ b/queue-7.0/ipv6-xfrm6-release-dst-on-error-in-xfrm6_rcv_encap.patch @@ -0,0 +1,50 @@ +From bc0fcb9823cd0894934cf968b525c575833d7078 Mon Sep 17 00:00:00 2001 +From: Yilin Zhu +Date: Sun, 12 Apr 2026 13:07:54 +0800 +Subject: ipv6: xfrm6: release dst on error in xfrm6_rcv_encap() + +From: Yilin Zhu + +commit bc0fcb9823cd0894934cf968b525c575833d7078 upstream. + +xfrm6_rcv_encap() performs an IPv6 route lookup when the skb does not +already have a dst attached. ip6_route_input_lookup() returns a +referenced dst entry even when the lookup resolves to an error route. + +If dst->error is set, xfrm6_rcv_encap() drops the skb without attaching +the dst to the skb and without releasing the reference returned by the +lookup. Repeated packets hitting this path therefore leak dst entries. + +Release the dst before jumping to the drop path. + +Fixes: 0146dca70b87 ("xfrm: add support for UDPv6 encapsulation of ESP") +Cc: stable@kernel.org +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Ruide Cao +Signed-off-by: Yilin Zhu +Signed-off-by: Ren Wei +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/xfrm6_protocol.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/ipv6/xfrm6_protocol.c ++++ b/net/ipv6/xfrm6_protocol.c +@@ -88,8 +88,10 @@ int xfrm6_rcv_encap(struct sk_buff *skb, + + dst = ip6_route_input_lookup(dev_net(skb->dev), skb->dev, &fl6, + skb, flags); +- if (dst->error) ++ if (dst->error) { ++ dst_release(dst); + goto drop; ++ } + skb_dst_set(skb, dst); + } + diff --git a/queue-7.0/loongarch-kvm-fix-missing-emulate_fail-in-kvm_emu_mmio_read.patch b/queue-7.0/loongarch-kvm-fix-missing-emulate_fail-in-kvm_emu_mmio_read.patch new file mode 100644 index 0000000000..4432a2f5c1 --- /dev/null +++ b/queue-7.0/loongarch-kvm-fix-missing-emulate_fail-in-kvm_emu_mmio_read.patch @@ -0,0 +1,37 @@ +From f26faae96c411a70641e4d21b759475caa6122d5 Mon Sep 17 00:00:00 2001 +From: Tao Cui +Date: Mon, 4 May 2026 09:00:38 +0800 +Subject: LoongArch: KVM: Fix missing EMULATE_FAIL in kvm_emu_mmio_read() + +From: Tao Cui + +commit f26faae96c411a70641e4d21b759475caa6122d5 upstream. + +In the ldptr (0x24...0x27) opcode decoding path, the default case only +breaks out but without setting "ret" value to EMULATE_FAIL. This leaves +run->mmio.len uninitialized (stale from a previous MMIO operation) while +"ret" value remains EMULATE_DO_MMIO, causing the code to proceed with an +incorrect MMIO length. + +Add "ret = EMULATE_FAIL" to match the other default branches in the same +function (e.g. the 0x28...0x2e and 0x38 cases). + +Cc: stable@vger.kernel.org +Reviewed-by: Bibo Mao +Signed-off-by: Tao Cui +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kvm/exit.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/loongarch/kvm/exit.c ++++ b/arch/loongarch/kvm/exit.c +@@ -390,6 +390,7 @@ int kvm_emu_mmio_read(struct kvm_vcpu *v + run->mmio.len = 8; + break; + default: ++ ret = EMULATE_FAIL; + break; + } + break; diff --git a/queue-7.0/powerpc-kdump-fix-kasan-sanitization-flag-for-core_-bits-.o.patch b/queue-7.0/powerpc-kdump-fix-kasan-sanitization-flag-for-core_-bits-.o.patch new file mode 100644 index 0000000000..e8b671068c --- /dev/null +++ b/queue-7.0/powerpc-kdump-fix-kasan-sanitization-flag-for-core_-bits-.o.patch @@ -0,0 +1,52 @@ +From b3a97f9484080c6e71db9e803e3cc1bb372a9bc7 Mon Sep 17 00:00:00 2001 +From: Sourabh Jain +Date: Tue, 7 Apr 2026 18:13:44 +0530 +Subject: powerpc/kdump: fix KASAN sanitization flag for core_$(BITS).o +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Sourabh Jain + +commit b3a97f9484080c6e71db9e803e3cc1bb372a9bc7 upstream. + +KASAN instrumentation is intended to be disabled for the kexec core +code, but the existing Makefile entry misses the object suffix. As a +result, the flag is not applied correctly to core_$(BITS).o. + +So when KASAN is enabled, kexec_copy_flush and copy_segments in +kexec/core_64.c are instrumented, which can result in accesses to +shadow memory via normal address translation paths. Since these run +with the MMU disabled, such accesses may trigger page faults +(bad_page_fault) that cannot be handled in the kdump path, ultimately +causing a hang and preventing the kdump kernel from booting. The same +is true for kexec as well, since the same functions are used there. + +Update the entry to include the “.o” suffix so that KASAN +instrumentation is properly disabled for this object file. + +Fixes: 2ab2d5794f14 ("powerpc/kasan: Disable address sanitization in kexec paths") +Reported-by: Venkat Rao Bagalkote +Closes: https://lore.kernel.org/all/1dee8891-8bcc-46b4-93f3-fc3a774abd5b@linux.ibm.com/ +Cc: stable@vger.kernel.org +Reviewed-by: Ritesh Harjani (IBM) +Tested-by: Venkat Rao Bagalkote +Acked-by: Mahesh Salgaonkar +Reviewed-by: Aboorva Devarajan +Tested-by: Aboorva Devarajan +Signed-off-by: Sourabh Jain +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260407124349.1698552-1-sourabhjain@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kexec/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kexec/Makefile ++++ b/arch/powerpc/kexec/Makefile +@@ -16,4 +16,4 @@ GCOV_PROFILE_core_$(BITS).o := n + KCOV_INSTRUMENT_core_$(BITS).o := n + UBSAN_SANITIZE_core_$(BITS).o := n + KASAN_SANITIZE_core.o := n +-KASAN_SANITIZE_core_$(BITS) := n ++KASAN_SANITIZE_core_$(BITS).o := n diff --git a/queue-7.0/rust-allow-clippy-collapsible_if-globally.patch b/queue-7.0/rust-allow-clippy-collapsible_if-globally.patch new file mode 100644 index 0000000000..fcc56aefd5 --- /dev/null +++ b/queue-7.0/rust-allow-clippy-collapsible_if-globally.patch @@ -0,0 +1,50 @@ +From 2adc8664018c1cc595c7c0c98474a33c7fe32a85 Mon Sep 17 00:00:00 2001 +From: Miguel Ojeda +Date: Sun, 26 Apr 2026 16:42:01 +0200 +Subject: rust: allow `clippy::collapsible_if` globally + +From: Miguel Ojeda + +commit 2adc8664018c1cc595c7c0c98474a33c7fe32a85 upstream. + +Similar to `clippy::collapsible_match` (globally allowed in the previous +commit), the `clippy::collapsible_if` lint [1] can make code harder to +read in certain cases. + +Thus just let developers decide on their own. + +In addition, remove the existing `expect` we had. + +Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs). +Suggested-by: Gary Guo +Link: https://lore.kernel.org/rust-for-linux/DGROP5CHU1QZ.1OKJRAUZXE9WC@garyguo.net/ +Link: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if [1] +Reviewed-by: Gary Guo +Link: https://patch.msgid.link/20260426144201.227108-2-ojeda@kernel.org +Signed-off-by: Miguel Ojeda +Signed-off-by: Greg Kroah-Hartman +--- + Makefile | 1 + + drivers/android/binder/range_alloc/array.rs | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +--- a/Makefile ++++ b/Makefile +@@ -486,6 +486,7 @@ export rust_common_flags := --edition=20 + -Wclippy::as_ptr_cast_mut \ + -Wclippy::as_underscore \ + -Wclippy::cast_lossless \ ++ -Aclippy::collapsible_if \ + -Aclippy::collapsible_match \ + -Wclippy::ignored_unit_patterns \ + -Wclippy::mut_mut \ +--- a/drivers/android/binder/range_alloc/array.rs ++++ b/drivers/android/binder/range_alloc/array.rs +@@ -204,7 +204,6 @@ impl ArrayRangeAllocator { + // caller will mark them as unused, which means that they can be freed if the system comes + // under memory pressure. + let mut freed_range = FreedRange::interior_pages(offset, size); +- #[expect(clippy::collapsible_if)] // reads better like this + if offset % PAGE_SIZE != 0 { + if i == 0 || self.ranges[i - 1].endpoint() <= (offset & PAGE_MASK) { + freed_range.start_page_idx -= 1; diff --git a/queue-7.0/rust-allow-clippy-collapsible_match-globally.patch b/queue-7.0/rust-allow-clippy-collapsible_match-globally.patch new file mode 100644 index 0000000000..5354c547a2 --- /dev/null +++ b/queue-7.0/rust-allow-clippy-collapsible_match-globally.patch @@ -0,0 +1,73 @@ +From 838d852da8503372f3a1779bfbd1ccb93153ab4e Mon Sep 17 00:00:00 2001 +From: Miguel Ojeda +Date: Sun, 26 Apr 2026 16:42:00 +0200 +Subject: rust: allow `clippy::collapsible_match` globally + +From: Miguel Ojeda + +commit 838d852da8503372f3a1779bfbd1ccb93153ab4e upstream. + +The `clippy::collapsible_match` lint [1] can make code harder to read +in certain cases [2], e.g. + + CLIPPY P rust/libmacros.so - due to command line change + warning: this `if` can be collapsed into the outer `match` + --> rust/pin-init/internal/src/helpers.rs:91:17 + | + 91 | / if nesting == 1 { + 92 | | impl_generics.push(tt.clone()); + 93 | | impl_generics.push(tt); + 94 | | skip_until_comma = false; + 95 | | } + | |_________________^ + | + = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match + = note: `-W clippy::collapsible-match` implied by `-W clippy::all` + = help: to override `-W clippy::all` add `#[allow(clippy::collapsible_match)]` + help: collapse nested if block + | + 90 ~ TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' + 91 ~ && nesting == 1 => { + 92 | impl_generics.push(tt.clone()); + 93 | impl_generics.push(tt); + 94 | skip_until_comma = false; + 95 ~ } + | + +The lint does not have much upside -- when the suggestion may be a good +one, it would still read fine when nested anyway. And it is the kind of +lint that may easily bias people to just apply the suggestion instead +of allowing it. + +[ In addition, as Gary points out [3], the suggestion is also wrong [4] and + in the process of being fixed [5], possibly for Rust 1.97.0: + + Link: https://lore.kernel.org/rust-for-linux/DI3YV94TH9I3.1SOHW51552497@garyguo.net/ [3] + Link: https://github.com/rust-lang/rust-clippy/issues/16875 [4] + Link: https://github.com/rust-lang/rust-clippy/pull/16878 [5] + + - Miguel ] + +Thus just let developers decide on their own. + +Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs). +Link: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match [1] +Link: https://lore.kernel.org/rust-for-linux/CANiq72nWYJna_hdFxjQCQZK6yJBrr1Mb86iKavivV0U0BgufeA@mail.gmail.com/ [2] +Reviewed-by: Gary Guo +Link: https://patch.msgid.link/20260426144201.227108-1-ojeda@kernel.org +Signed-off-by: Miguel Ojeda +Signed-off-by: Greg Kroah-Hartman +--- + Makefile | 1 + + 1 file changed, 1 insertion(+) + +--- a/Makefile ++++ b/Makefile +@@ -486,6 +486,7 @@ export rust_common_flags := --edition=20 + -Wclippy::as_ptr_cast_mut \ + -Wclippy::as_underscore \ + -Wclippy::cast_lossless \ ++ -Aclippy::collapsible_match \ + -Wclippy::ignored_unit_patterns \ + -Wclippy::mut_mut \ + -Wclippy::needless_bitwise_bool \ diff --git a/queue-7.0/rust-drm-gem-clean-up-gem-state-in-init-failure-case.patch b/queue-7.0/rust-drm-gem-clean-up-gem-state-in-init-failure-case.patch new file mode 100644 index 0000000000..8a05165df1 --- /dev/null +++ b/queue-7.0/rust-drm-gem-clean-up-gem-state-in-init-failure-case.patch @@ -0,0 +1,51 @@ +From 2e42a17b8f6bc3c0cd69d7556b588011d3ec2394 Mon Sep 17 00:00:00 2001 +From: Eliot Courtney +Date: Thu, 23 Apr 2026 21:36:52 +0900 +Subject: rust: drm: gem: clean up GEM state in init failure case +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eliot Courtney + +commit 2e42a17b8f6bc3c0cd69d7556b588011d3ec2394 upstream. + +Currently, if `drm_gem_object_init` fails, the object is freed without +any cleanup. Perform the cleanup in that case. + +Cc: stable@vger.kernel.org +Fixes: c284d3e42338 ("rust: drm: gem: Add GEM object abstraction") +Signed-off-by: Eliot Courtney +Reviewed-by: Alice Ryhl +Reviewed-by: Onur Özkan +Link: https://patch.msgid.link/20260423-fix-gem-1-v1-1-e12e35f7bba9@nvidia.com +[ Move safety comment closer to unsafe block to avoid a clippy warning. + - Danilo ] +Signed-off-by: Danilo Krummrich +Signed-off-by: Greg Kroah-Hartman +--- + rust/kernel/drm/gem/mod.rs | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/rust/kernel/drm/gem/mod.rs ++++ b/rust/kernel/drm/gem/mod.rs +@@ -207,8 +207,17 @@ impl Object { + // SAFETY: `obj.as_raw()` is guaranteed to be valid by the initialization above. + unsafe { (*obj.as_raw()).funcs = &Self::OBJECT_FUNCS }; + +- // SAFETY: The arguments are all valid per the type invariants. +- to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })?; ++ if let Err(err) = ++ // SAFETY: The arguments are all valid per the type invariants. ++ to_result(unsafe { ++ bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) ++ }) ++ { ++ // SAFETY: `drm_gem_object_init()` initializes the private GEM object state before ++ // failing, so `drm_gem_private_object_fini()` is the matching cleanup. ++ unsafe { bindings::drm_gem_private_object_fini(obj.obj.get()) }; ++ return Err(err); ++ } + + // SAFETY: We will never move out of `Self` as `ARef` is always treated as pinned. + let ptr = KBox::into_raw(unsafe { Pin::into_inner_unchecked(obj) }); diff --git a/queue-7.0/rust-pin-init-internal-move-alignment-check-to-make_field_check.patch b/queue-7.0/rust-pin-init-internal-move-alignment-check-to-make_field_check.patch new file mode 100644 index 0000000000..3f39acd887 --- /dev/null +++ b/queue-7.0/rust-pin-init-internal-move-alignment-check-to-make_field_check.patch @@ -0,0 +1,125 @@ +From 83ac2870310b694775ab7e8f0244fdd94fc21926 Mon Sep 17 00:00:00 2001 +From: Gary Guo +Date: Mon, 27 Apr 2026 16:43:00 +0100 +Subject: rust: pin-init: internal: move alignment check to `make_field_check` + +From: Gary Guo + +commit 83ac2870310b694775ab7e8f0244fdd94fc21926 upstream. + +Instead of having the reference creation serving dual-purpose as both for +let bindings and alignment check, detangle them so that the alignment check +is done explicitly in `make_field_check`. This is more robust against +refactors that may change the way let bindings are created. + +Cc: stable@vger.kernel.org +Reviewed-by: Alice Ryhl +Signed-off-by: Gary Guo +Link: https://patch.msgid.link/20260427-pin-init-fix-v3-1-496a699674dd@garyguo.net +[ Reworded for typo. - Miguel ] +Signed-off-by: Miguel Ojeda +Signed-off-by: Greg Kroah-Hartman +--- + rust/pin-init/internal/src/init.rs | 78 +++++++++++++++++-------------------- + 1 file changed, 37 insertions(+), 41 deletions(-) + +--- a/rust/pin-init/internal/src/init.rs ++++ b/rust/pin-init/internal/src/init.rs +@@ -243,10 +243,6 @@ fn init_fields( + }); + // Again span for better diagnostics + let write = quote_spanned!(ident.span()=> ::core::ptr::write); +- // NOTE: the field accessor ensures that the initialized field is properly aligned. +- // Unaligned fields will cause the compiler to emit E0793. We do not support +- // unaligned fields since `Init::__init` requires an aligned pointer; the call to +- // `ptr::write` below has the same requirement. + let accessor = if pinned { + let project_ident = format_ident!("__project_{ident}"); + quote! { +@@ -361,49 +357,49 @@ fn init_fields( + } + } + +-/// Generate the check for ensuring that every field has been initialized. ++/// Generate the check for ensuring that every field has been initialized and aligned. + fn make_field_check( + fields: &Punctuated, + init_kind: InitKind, + path: &Path, + ) -> TokenStream { +- let field_attrs = fields ++ let field_attrs: Vec<_> = fields + .iter() +- .filter_map(|f| f.kind.ident().map(|_| &f.attrs)); +- let field_name = fields.iter().filter_map(|f| f.kind.ident()); +- match init_kind { +- InitKind::Normal => quote! { +- // We use unreachable code to ensure that all fields have been mentioned exactly once, +- // this struct initializer will still be type-checked and complain with a very natural +- // error message if a field is forgotten/mentioned more than once. +- #[allow(unreachable_code, clippy::diverging_sub_expression)] +- // SAFETY: this code is never executed. +- let _ = || unsafe { +- ::core::ptr::write(slot, #path { +- #( +- #(#field_attrs)* +- #field_name: ::core::panic!(), +- )* +- }) +- }; +- }, +- InitKind::Zeroing => quote! { +- // We use unreachable code to ensure that all fields have been mentioned at most once. +- // Since the user specified `..Zeroable::zeroed()` at the end, all missing fields will +- // be zeroed. This struct initializer will still be type-checked and complain with a +- // very natural error message if a field is mentioned more than once, or doesn't exist. +- #[allow(unreachable_code, clippy::diverging_sub_expression, unused_assignments)] +- // SAFETY: this code is never executed. +- let _ = || unsafe { +- ::core::ptr::write(slot, #path { +- #( +- #(#field_attrs)* +- #field_name: ::core::panic!(), +- )* +- ..::core::mem::zeroed() +- }) +- }; +- }, ++ .filter_map(|f| f.kind.ident().map(|_| &f.attrs)) ++ .collect(); ++ let field_name: Vec<_> = fields.iter().filter_map(|f| f.kind.ident()).collect(); ++ let zeroing_trailer = match init_kind { ++ InitKind::Normal => None, ++ InitKind::Zeroing => Some(quote! { ++ ..::core::mem::zeroed() ++ }), ++ }; ++ quote! { ++ #[allow(unreachable_code, clippy::diverging_sub_expression)] ++ // We use unreachable code to perform field checks. They're still checked by the compiler. ++ // SAFETY: this code is never executed. ++ let _ = || unsafe { ++ // Create references to ensure that the initialized field is properly aligned. ++ // Unaligned fields will cause the compiler to emit E0793. We do not support ++ // unaligned fields since `Init::__init` requires an aligned pointer; the call to ++ // `ptr::write` for value-initialization case has the same requirement. ++ #( ++ #(#field_attrs)* ++ let _ = &(*slot).#field_name; ++ )* ++ ++ // If the zeroing trailer is not present, this checks that all fields have been ++ // mentioned exactly once. If the zeroing trailer is present, all missing fields will be ++ // zeroed, so this checks that all fields have been mentioned at most once. The use of ++ // struct initializer will still generate very natural error messages for any misuse. ++ ::core::ptr::write(slot, #path { ++ #( ++ #(#field_attrs)* ++ #field_name: ::core::panic!(), ++ )* ++ #zeroing_trailer ++ }) ++ }; + } + } + diff --git a/queue-7.0/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch b/queue-7.0/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch new file mode 100644 index 0000000000..50ccfe0703 --- /dev/null +++ b/queue-7.0/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch @@ -0,0 +1,68 @@ +From 80afd4c84bc8f5e80145ce35279f5ce53f6043db Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 24 Apr 2026 14:31:35 -1000 +Subject: sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters + +From: Tejun Heo + +commit 80afd4c84bc8f5e80145ce35279f5ce53f6043db upstream. + +scx_group_set_{weight,idle,bandwidth}() cache scx_root before acquiring +scx_cgroup_ops_rwsem, so the pointer can be stale by the time the op runs. +If the loaded scheduler is disabled and freed (via RCU work) and another is +enabled between the naked load and the rwsem acquire, the reader sees +scx_cgroup_enabled=true (the new scheduler's) but dereferences the freed one +- UAF on SCX_HAS_OP(sch, ...) / SCX_CALL_OP(sch, ...). + +scx_cgroup_enabled is toggled only under scx_cgroup_ops_rwsem write +(scx_cgroup_{init,exit}), so reading scx_root inside the rwsem read section +correlates @sch with the enabled snapshot. + +Fixes: a5bd6ba30b33 ("sched_ext: Use cgroup_lock/unlock() to synchronize against cgroup operations") +Cc: stable@vger.kernel.org # v6.18+ +Reported-by: Chris Mason +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/ext.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -3430,9 +3430,10 @@ void scx_cgroup_cancel_attach(struct cgr + + void scx_group_set_weight(struct task_group *tg, unsigned long weight) + { +- struct scx_sched *sch = scx_root; ++ struct scx_sched *sch; + + percpu_down_read(&scx_cgroup_ops_rwsem); ++ sch = scx_root; + + if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_weight) && + tg->scx.weight != weight) +@@ -3446,9 +3447,10 @@ void scx_group_set_weight(struct task_gr + + void scx_group_set_idle(struct task_group *tg, bool idle) + { +- struct scx_sched *sch = scx_root; ++ struct scx_sched *sch; + + percpu_down_read(&scx_cgroup_ops_rwsem); ++ sch = scx_root; + + if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_idle)) + SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_idle, NULL, +@@ -3463,9 +3465,10 @@ void scx_group_set_idle(struct task_grou + void scx_group_set_bandwidth(struct task_group *tg, + u64 period_us, u64 quota_us, u64 burst_us) + { +- struct scx_sched *sch = scx_root; ++ struct scx_sched *sch; + + percpu_down_read(&scx_cgroup_ops_rwsem); ++ sch = scx_root; + + if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_bandwidth) && + (tg->scx.bw_period_us != period_us || diff --git a/queue-7.0/selinux-allow-multiple-opens-of-sys-fs-selinux-policy.patch b/queue-7.0/selinux-allow-multiple-opens-of-sys-fs-selinux-policy.patch new file mode 100644 index 0000000000..594de9fd90 --- /dev/null +++ b/queue-7.0/selinux-allow-multiple-opens-of-sys-fs-selinux-policy.patch @@ -0,0 +1,100 @@ +From a02cd6805562305f936e807da83e253b719dd965 Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 5 May 2026 10:06:38 -0400 +Subject: selinux: allow multiple opens of /sys/fs/selinux/policy + +From: Stephen Smalley + +commit a02cd6805562305f936e807da83e253b719dd965 upstream. + +Currently there can only be a single open of /sys/fs/selinux/policy at +any time. This allows any process to block any other process from +reading the kernel policy. The original motivation seems to have been +a mix of preventing an inconsistent view of the policy size and +preventing userspace from allocating kernel memory without bound, but +this is arguably equally bad. Eliminate the policy_opened flag and +shrink the critical section that the policy mutex is held. While we +are making changes here, drop a couple of extraneous BUG_ONs. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/selinux/20100726193414.19538.64028.stgit@paris.rdu.redhat.com/ +Signed-off-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/selinuxfs.c | 27 ++++----------------------- + 1 file changed, 4 insertions(+), 23 deletions(-) + +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -76,7 +76,6 @@ struct selinux_fs_info { + int *bool_pending_values; + struct dentry *class_dir; + unsigned long last_class_ino; +- bool policy_opened; + unsigned long last_ino; + struct super_block *sb; + }; +@@ -340,44 +339,31 @@ struct policy_load_memory { + + static int sel_open_policy(struct inode *inode, struct file *filp) + { +- struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; + struct policy_load_memory *plm = NULL; + int rc; + +- BUG_ON(filp->private_data); +- +- mutex_lock(&selinux_state.policy_mutex); +- + rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); + if (rc) +- goto err; ++ return rc; + +- rc = -EBUSY; +- if (fsi->policy_opened) +- goto err; +- +- rc = -ENOMEM; + plm = kzalloc_obj(*plm); + if (!plm) +- goto err; ++ return -ENOMEM; + ++ mutex_lock(&selinux_state.policy_mutex); + rc = security_read_policy(&plm->data, &plm->len); + if (rc) + goto err; +- + if ((size_t)i_size_read(inode) != plm->len) { + inode_lock(inode); + i_size_write(inode, plm->len); + inode_unlock(inode); + } +- +- fsi->policy_opened = 1; ++ mutex_unlock(&selinux_state.policy_mutex); + + filp->private_data = plm; + +- mutex_unlock(&selinux_state.policy_mutex); +- + return 0; + err: + mutex_unlock(&selinux_state.policy_mutex); +@@ -390,13 +376,8 @@ err: + + static int sel_release_policy(struct inode *inode, struct file *filp) + { +- struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; + struct policy_load_memory *plm = filp->private_data; + +- BUG_ON(!plm); +- +- fsi->policy_opened = 0; +- + vfree(plm->data); + kfree(plm); + diff --git a/queue-7.0/selinux-don-t-reserve-xattr-slot-when-we-won-t-fill-it.patch b/queue-7.0/selinux-don-t-reserve-xattr-slot-when-we-won-t-fill-it.patch new file mode 100644 index 0000000000..3680b8fae0 --- /dev/null +++ b/queue-7.0/selinux-don-t-reserve-xattr-slot-when-we-won-t-fill-it.patch @@ -0,0 +1,41 @@ +From 1e5a8eed7821e7a43a31b4c1b3675a91be6bc6f6 Mon Sep 17 00:00:00 2001 +From: David Windsor +Date: Sun, 26 Apr 2026 19:23:49 -0400 +Subject: selinux: don't reserve xattr slot when we won't fill it + +From: David Windsor + +commit 1e5a8eed7821e7a43a31b4c1b3675a91be6bc6f6 upstream. + +Move lsm_get_xattr_slot() below the SBLABEL_MNT check so we don't leave +a NULL-named slot in the array when returning -EOPNOTSUPP; filesystem +initxattrs() callbacks stop iterating at the first NULL ->name, silently +dropping xattrs installed by later LSMs. + +Cc: stable@vger.kernel.org +Signed-off-by: David Windsor +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/hooks.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -2965,7 +2965,7 @@ static int selinux_inode_init_security(s + { + const struct cred_security_struct *crsec = selinux_cred(current_cred()); + struct superblock_security_struct *sbsec; +- struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); ++ struct xattr *xattr; + u32 newsid, clen; + u16 newsclass; + int rc; +@@ -2991,6 +2991,7 @@ static int selinux_inode_init_security(s + !(sbsec->flags & SBLABEL_MNT)) + return -EOPNOTSUPP; + ++ xattr = lsm_get_xattr_slot(xattrs, xattr_count); + if (xattr) { + rc = security_sid_to_context_force(newsid, + &context, &clen); diff --git a/queue-7.0/selinux-fix-avdcache-auditing.patch b/queue-7.0/selinux-fix-avdcache-auditing.patch new file mode 100644 index 0000000000..231b7c8247 --- /dev/null +++ b/queue-7.0/selinux-fix-avdcache-auditing.patch @@ -0,0 +1,113 @@ +From f92d542577db878acfd21cc18dab23d03023b217 Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Fri, 10 Apr 2026 15:29:50 -0400 +Subject: selinux: fix avdcache auditing + +From: Stephen Smalley + +commit f92d542577db878acfd21cc18dab23d03023b217 upstream. + +The per-task avdcache was incorrectly saving and reusing the +audited vector computed by avc_audit_required() rather than +recomputing based on the currently requested permissions and +distinguishing the denied versus allowed cases. As a result, +some permission checks were not being audited, e.g. +directory write checks after a previously cached directory +search check. + +Cc: stable@vger.kernel.org +Fixes: dde3a5d0f4dce ("selinux: move avdcache to per-task security struct") +Signed-off-by: Stephen Smalley +[PM: line wrap tweaks] +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/hooks.c | 31 +++++++++++++------------------ + security/selinux/include/objsec.h | 4 +--- + 2 files changed, 14 insertions(+), 21 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3207,15 +3207,13 @@ static inline int task_avdcache_search(s + * @tsec: the task's security state + * @isec: the inode associated with the cache entry + * @avd: the AVD to cache +- * @audited: the permission audit bitmask to cache + * +- * Update the AVD cache in @tsec with the @avdc and @audited info associated ++ * Update the AVD cache in @tsec with the @avd info associated + * with @isec. + */ + static inline void task_avdcache_update(struct task_security_struct *tsec, + struct inode_security_struct *isec, +- struct av_decision *avd, +- u32 audited) ++ struct av_decision *avd) + { + int spot; + +@@ -3227,9 +3225,7 @@ static inline void task_avdcache_update( + spot = (tsec->avdcache.dir_spot + 1) & (TSEC_AVDC_DIR_SIZE - 1); + tsec->avdcache.dir_spot = spot; + tsec->avdcache.dir[spot].isid = isec->sid; +- tsec->avdcache.dir[spot].audited = audited; +- tsec->avdcache.dir[spot].allowed = avd->allowed; +- tsec->avdcache.dir[spot].permissive = avd->flags & AVD_FLAGS_PERMISSIVE; ++ tsec->avdcache.dir[spot].avd = *avd; + tsec->avdcache.permissive_neveraudit = + (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT)); + } +@@ -3250,6 +3246,7 @@ static int selinux_inode_permission(stru + struct task_security_struct *tsec; + struct inode_security_struct *isec; + struct avdc_entry *avdc; ++ struct av_decision avd, *avdp = &avd; + int rc, rc2; + u32 audited, denied; + +@@ -3271,23 +3268,21 @@ static int selinux_inode_permission(stru + rc = task_avdcache_search(tsec, isec, &avdc); + if (likely(!rc)) { + /* Cache hit. */ +- audited = perms & avdc->audited; +- denied = perms & ~avdc->allowed; +- if (unlikely(denied && enforcing_enabled() && +- !avdc->permissive)) ++ avdp = &avdc->avd; ++ denied = perms & ~avdp->allowed; ++ if (unlikely(denied) && enforcing_enabled() && ++ !(avdp->flags & AVD_FLAGS_PERMISSIVE)) + rc = -EACCES; + } else { +- struct av_decision avd; +- + /* Cache miss. */ + rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, +- perms, 0, &avd); +- audited = avc_audit_required(perms, &avd, rc, +- (requested & MAY_ACCESS) ? FILE__AUDIT_ACCESS : 0, +- &denied); +- task_avdcache_update(tsec, isec, &avd, audited); ++ perms, 0, avdp); ++ task_avdcache_update(tsec, isec, avdp); + } + ++ audited = avc_audit_required(perms, avdp, rc, ++ (requested & MAY_ACCESS) ? ++ FILE__AUDIT_ACCESS : 0, &denied); + if (likely(!audited)) + return rc; + +--- a/security/selinux/include/objsec.h ++++ b/security/selinux/include/objsec.h +@@ -32,9 +32,7 @@ + + struct avdc_entry { + u32 isid; /* inode SID */ +- u32 allowed; /* allowed permission bitmask */ +- u32 audited; /* audited permission bitmask */ +- bool permissive; /* AVC permissive flag */ ++ struct av_decision avd; /* av decision */ + }; + + struct cred_security_struct { diff --git a/queue-7.0/selinux-prune-sys-fs-selinux-checkreqprot.patch b/queue-7.0/selinux-prune-sys-fs-selinux-checkreqprot.patch new file mode 100644 index 0000000000..86073b82fb --- /dev/null +++ b/queue-7.0/selinux-prune-sys-fs-selinux-checkreqprot.patch @@ -0,0 +1,82 @@ +From 644132a48f4e28a1d949d162160869286f3e75de Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 5 May 2026 08:49:48 -0400 +Subject: selinux: prune /sys/fs/selinux/checkreqprot + +From: Stephen Smalley + +commit 644132a48f4e28a1d949d162160869286f3e75de upstream. + +commit a7e4676e8e2cb ("selinux: remove the 'checkreqprot' +functionality") removed the ability to modify the checkreqprot setting +but left everything except the updating of the checkreqprot value +intact. Aside from unnecessary processing, this could produce a local +DoS from log spam and incorrectly calls selinux_ima_measure_state() on +each write even though no state has changed. Prune it to just log an +error message once and return count (i.e. all bytes written +successfully) so that userspace never breaks. + +Cc: stable@vger.kernel.org +Signed-off-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/selinuxfs.c | 47 ++++++------------------------------------- + 1 file changed, 7 insertions(+), 40 deletions(-) + +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -687,46 +687,13 @@ static ssize_t sel_read_checkreqprot(str + static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + { +- char *page; +- ssize_t length; +- unsigned int new_value; +- +- length = avc_has_perm(current_sid(), SECINITSID_SECURITY, +- SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, +- NULL); +- if (length) +- return length; +- +- if (count >= PAGE_SIZE) +- return -ENOMEM; +- +- /* No partial writes. */ +- if (*ppos != 0) +- return -EINVAL; +- +- page = memdup_user_nul(buf, count); +- if (IS_ERR(page)) +- return PTR_ERR(page); +- +- if (sscanf(page, "%u", &new_value) != 1) { +- length = -EINVAL; +- goto out; +- } +- length = count; +- +- if (new_value) { +- char comm[sizeof(current->comm)]; +- +- strscpy(comm, current->comm); +- pr_err("SELinux: %s (%d) set checkreqprot to 1. This is no longer supported.\n", +- comm, current->pid); +- } +- +- selinux_ima_measure_state(); +- +-out: +- kfree(page); +- return length; ++ /* ++ * Setting checkreqprot is no longer supported, see ++ * https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-checkreqprot ++ */ ++ pr_err_once("SELinux: %s (%d) wrote to checkreqprot. This is no longer supported.\n", ++ current->comm, current->pid); ++ return count; + } + static const struct file_operations sel_checkreqprot_ops = { + .read = sel_read_checkreqprot, diff --git a/queue-7.0/selinux-prune-sys-fs-selinux-disable.patch b/queue-7.0/selinux-prune-sys-fs-selinux-disable.patch new file mode 100644 index 0000000000..1688f532e9 --- /dev/null +++ b/queue-7.0/selinux-prune-sys-fs-selinux-disable.patch @@ -0,0 +1,71 @@ +From 19cfa0099024bb9cd40f6d950caa7f47ff8e77f6 Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 5 May 2026 08:49:49 -0400 +Subject: selinux: prune /sys/fs/selinux/disable + +From: Stephen Smalley + +commit 19cfa0099024bb9cd40f6d950caa7f47ff8e77f6 upstream. + +Commit f22f9aaf6c3d ("selinux: remove the runtime disable +functionality") removed the underlying SELinux runtime disable +functionality but left everything else intact and started logging an +error message to warn any residual users. + +Prune it to just log an error message once and to return count +(i.e. all bytes written successfully) to avoid breaking +userspace. This also fixes a local DoS from logspam. + +Cc: stable@vger.kernel.org +Signed-off-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/selinuxfs.c | 36 +++++++----------------------------- + 1 file changed, 7 insertions(+), 29 deletions(-) + +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -272,35 +272,13 @@ static ssize_t sel_write_disable(struct + size_t count, loff_t *ppos) + + { +- char *page; +- ssize_t length; +- int new_value; +- +- if (count >= PAGE_SIZE) +- return -ENOMEM; +- +- /* No partial writes. */ +- if (*ppos != 0) +- return -EINVAL; +- +- page = memdup_user_nul(buf, count); +- if (IS_ERR(page)) +- return PTR_ERR(page); +- +- if (sscanf(page, "%d", &new_value) != 1) { +- length = -EINVAL; +- goto out; +- } +- length = count; +- +- if (new_value) { +- pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable\n"); +- pr_err("SELinux: Runtime disable is not supported, use selinux=0 on the kernel cmdline.\n"); +- } +- +-out: +- kfree(page); +- return length; ++ /* ++ * Setting disable is no longer supported, see ++ * https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable ++ */ ++ pr_err_once("SELinux: %s (%d) wrote to disable. This is no longer supported.\n", ++ current->comm, current->pid); ++ return count; + } + + static const struct file_operations sel_disable_ops = { diff --git a/queue-7.0/selinux-prune-sys-fs-selinux-user.patch b/queue-7.0/selinux-prune-sys-fs-selinux-user.patch new file mode 100644 index 0000000000..81283e57f2 --- /dev/null +++ b/queue-7.0/selinux-prune-sys-fs-selinux-user.patch @@ -0,0 +1,297 @@ +From ad1ac3d740cc6b858a99ab9c45c8c0574be7d1d3 Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 5 May 2026 08:49:50 -0400 +Subject: selinux: prune /sys/fs/selinux/user + +From: Stephen Smalley + +commit ad1ac3d740cc6b858a99ab9c45c8c0574be7d1d3 upstream. + +Remove the previously deprecated /sys/fs/selinux/user interface aside +from a residual stub for userspace compatibility. + +Commit d7b6918e22c7 ("selinux: Deprecate /sys/fs/selinux/user") started +the deprecation process for /sys/fs/selinux/user: + + The selinuxfs "user" node allows userspace to request a list + of security contexts that can be reached for a given SELinux + user from a given starting context. This was used by libselinux + when various login-style programs requested contexts for + users, but libselinux stopped using it in 2020. + Kernel support will be removed no sooner than Dec 2025. + +A pr_warn() message has been in place since Linux v6.13, and a 5 +second sleep was introduced since Linux v6.17 to help make it more +noticeable. + +We are now past the stated deadline of Dec 2025, so remove the +underlying functionality and replace it with a stub that returns a +'0\0' buffer to avoid breaking userspace. This also avoids a local DoS +from logspam and an uninterruptible sleep delay. + +Cc: stable@vger.kernel.org +Signed-off-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + .../{obsolete => removed}/sysfs-selinux-user | 0 + Documentation/ABI/obsolete/sysfs-selinux-user | 12 -- + Documentation/ABI/removed/sysfs-selinux-user | 12 ++ + security/selinux/include/security.h | 2 + security/selinux/selinuxfs.c | 68 +------------- + security/selinux/ss/services.c | 125 -------------------------- + 5 files changed, 17 insertions(+), 202 deletions(-) + rename Documentation/ABI/{obsolete => removed}/sysfs-selinux-user (100%) + +--- a/Documentation/ABI/obsolete/sysfs-selinux-user ++++ /dev/null +@@ -1,12 +0,0 @@ +-What: /sys/fs/selinux/user +-Date: April 2005 (predates git) +-KernelVersion: 2.6.12-rc2 (predates git) +-Contact: selinux@vger.kernel.org +-Description: +- +- The selinuxfs "user" node allows userspace to request a list +- of security contexts that can be reached for a given SELinux +- user from a given starting context. This was used by libselinux +- when various login-style programs requested contexts for +- users, but libselinux stopped using it in 2020. +- Kernel support will be removed no sooner than Dec 2025. +--- /dev/null ++++ b/Documentation/ABI/removed/sysfs-selinux-user +@@ -0,0 +1,12 @@ ++What: /sys/fs/selinux/user ++Date: April 2005 (predates git) ++KernelVersion: 2.6.12-rc2 (predates git) ++Contact: selinux@vger.kernel.org ++Description: ++ ++ The selinuxfs "user" node allows userspace to request a list ++ of security contexts that can be reached for a given SELinux ++ user from a given starting context. This was used by libselinux ++ when various login-style programs requested contexts for ++ users, but libselinux stopped using it in 2020. ++ Kernel support will be removed no sooner than Dec 2025. +--- a/security/selinux/include/security.h ++++ b/security/selinux/include/security.h +@@ -312,8 +312,6 @@ int security_context_to_sid_default(cons + int security_context_to_sid_force(const char *scontext, u32 scontext_len, + u32 *sid); + +-int security_get_user_sids(u32 fromsid, const char *username, u32 **sids, u32 *nel); +- + int security_port_sid(u8 protocol, u16 port, u32 *out_sid); + + int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid); +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -1016,69 +1016,11 @@ out: + + static ssize_t sel_write_user(struct file *file, char *buf, size_t size) + { +- char *con = NULL, *user = NULL, *ptr; +- u32 sid, *sids = NULL; +- ssize_t length; +- char *newcon; +- int rc; +- u32 i, len, nsids; +- +- pr_warn_ratelimited("SELinux: %s (%d) wrote to /sys/fs/selinux/user!" +- " This will not be supported in the future; please update your" +- " userspace.\n", current->comm, current->pid); +- ssleep(5); +- +- length = avc_has_perm(current_sid(), SECINITSID_SECURITY, +- SECCLASS_SECURITY, SECURITY__COMPUTE_USER, +- NULL); +- if (length) +- goto out; +- +- length = -ENOMEM; +- con = kzalloc(size + 1, GFP_KERNEL); +- if (!con) +- goto out; +- +- length = -ENOMEM; +- user = kzalloc(size + 1, GFP_KERNEL); +- if (!user) +- goto out; +- +- length = -EINVAL; +- if (sscanf(buf, "%s %s", con, user) != 2) +- goto out; +- +- length = security_context_str_to_sid(con, &sid, GFP_KERNEL); +- if (length) +- goto out; +- +- length = security_get_user_sids(sid, user, &sids, &nsids); +- if (length) +- goto out; +- +- length = sprintf(buf, "%u", nsids) + 1; +- ptr = buf + length; +- for (i = 0; i < nsids; i++) { +- rc = security_sid_to_context(sids[i], &newcon, &len); +- if (rc) { +- length = rc; +- goto out; +- } +- if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { +- kfree(newcon); +- length = -ERANGE; +- goto out; +- } +- memcpy(ptr, newcon, len); +- kfree(newcon); +- ptr += len; +- length += len; +- } +-out: +- kfree(sids); +- kfree(user); +- kfree(con); +- return length; ++ pr_err_once("SELinux: %s (%d) wrote to user. This is no longer supported.\n", ++ current->comm, current->pid); ++ buf[0] = '0'; ++ buf[1] = 0; ++ return 2; + } + + static ssize_t sel_write_member(struct file *file, char *buf, size_t size) +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -2746,131 +2746,6 @@ out: + return rc; + } + +-#define SIDS_NEL 25 +- +-/** +- * security_get_user_sids - Obtain reachable SIDs for a user. +- * @fromsid: starting SID +- * @username: username +- * @sids: array of reachable SIDs for user +- * @nel: number of elements in @sids +- * +- * Generate the set of SIDs for legal security contexts +- * for a given user that can be reached by @fromsid. +- * Set *@sids to point to a dynamically allocated +- * array containing the set of SIDs. Set *@nel to the +- * number of elements in the array. +- */ +- +-int security_get_user_sids(u32 fromsid, +- const char *username, +- u32 **sids, +- u32 *nel) +-{ +- struct selinux_policy *policy; +- struct policydb *policydb; +- struct sidtab *sidtab; +- struct context *fromcon, usercon; +- u32 *mysids = NULL, *mysids2, sid; +- u32 i, j, mynel, maxnel = SIDS_NEL; +- struct user_datum *user; +- struct role_datum *role; +- struct ebitmap_node *rnode, *tnode; +- int rc; +- +- *sids = NULL; +- *nel = 0; +- +- if (!selinux_initialized()) +- return 0; +- +- mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL); +- if (!mysids) +- return -ENOMEM; +- +-retry: +- mynel = 0; +- rcu_read_lock(); +- policy = rcu_dereference(selinux_state.policy); +- policydb = &policy->policydb; +- sidtab = policy->sidtab; +- +- context_init(&usercon); +- +- rc = -EINVAL; +- fromcon = sidtab_search(sidtab, fromsid); +- if (!fromcon) +- goto out_unlock; +- +- rc = -EINVAL; +- user = symtab_search(&policydb->p_users, username); +- if (!user) +- goto out_unlock; +- +- usercon.user = user->value; +- +- ebitmap_for_each_positive_bit(&user->roles, rnode, i) { +- role = policydb->role_val_to_struct[i]; +- usercon.role = i + 1; +- ebitmap_for_each_positive_bit(&role->types, tnode, j) { +- usercon.type = j + 1; +- +- if (mls_setup_user_range(policydb, fromcon, user, +- &usercon)) +- continue; +- +- rc = sidtab_context_to_sid(sidtab, &usercon, &sid); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out_unlock; +- if (mynel < maxnel) { +- mysids[mynel++] = sid; +- } else { +- rc = -ENOMEM; +- maxnel += SIDS_NEL; +- mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); +- if (!mysids2) +- goto out_unlock; +- memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); +- kfree(mysids); +- mysids = mysids2; +- mysids[mynel++] = sid; +- } +- } +- } +- rc = 0; +-out_unlock: +- rcu_read_unlock(); +- if (rc || !mynel) { +- kfree(mysids); +- return rc; +- } +- +- rc = -ENOMEM; +- mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL); +- if (!mysids2) { +- kfree(mysids); +- return rc; +- } +- for (i = 0, j = 0; i < mynel; i++) { +- struct av_decision dummy_avd; +- rc = avc_has_perm_noaudit(fromsid, mysids[i], +- SECCLASS_PROCESS, /* kernel value */ +- PROCESS__TRANSITION, AVC_STRICT, +- &dummy_avd); +- if (!rc) +- mysids2[j++] = mysids[i]; +- cond_resched(); +- } +- kfree(mysids); +- *sids = mysids2; +- *nel = j; +- return 0; +-} +- + /** + * __security_genfs_sid - Helper to obtain a SID for a file in a filesystem + * @policy: policy diff --git a/queue-7.0/selinux-shrink-critical-section-in-sel_write_load.patch b/queue-7.0/selinux-shrink-critical-section-in-sel_write_load.patch new file mode 100644 index 0000000000..fe0ddad05b --- /dev/null +++ b/queue-7.0/selinux-shrink-critical-section-in-sel_write_load.patch @@ -0,0 +1,76 @@ +From 868f31e4061eca8c3cd607d79d954d5e54f204aa Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Thu, 30 Apr 2026 14:36:52 -0400 +Subject: selinux: shrink critical section in sel_write_load() + +From: Stephen Smalley + +commit 868f31e4061eca8c3cd607d79d954d5e54f204aa upstream. + +Currently sel_write_load() takes the policy mutex earlier than +necessary. Move the taking of the mutex later. This avoids +holding it unnecessarily across the vmalloc() and copy_from_user() +of the policy data. + +Cc: stable@vger.kernel.org +Signed-off-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/selinuxfs.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -594,34 +594,31 @@ static ssize_t sel_write_load(struct fil + if (!count) + return -EINVAL; + +- mutex_lock(&selinux_state.policy_mutex); +- + length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); + if (length) +- goto out; ++ return length; + + data = vmalloc(count); +- if (!data) { +- length = -ENOMEM; +- goto out; +- } ++ if (!data) ++ return -ENOMEM; + if (copy_from_user(data, buf, count) != 0) { + length = -EFAULT; + goto out; + } + ++ mutex_lock(&selinux_state.policy_mutex); + length = security_load_policy(data, count, &load_state); + if (length) { + pr_warn_ratelimited("SELinux: failed to load policy\n"); +- goto out; ++ goto out_unlock; + } + fsi = file_inode(file)->i_sb->s_fs_info; + length = sel_make_policy_nodes(fsi, load_state.policy); + if (length) { + pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n"); + selinux_policy_cancel(&load_state); +- goto out; ++ goto out_unlock; + } + + selinux_policy_commit(&load_state); +@@ -631,8 +628,9 @@ static ssize_t sel_write_load(struct fil + from_kuid(&init_user_ns, audit_get_loginuid(current)), + audit_get_sessionid(current)); + +-out: ++out_unlock: + mutex_unlock(&selinux_state.policy_mutex); ++out: + vfree(data); + return length; + } diff --git a/queue-7.0/selinux-use-sk-blob-accessor-in-socket-permission-helpers.patch b/queue-7.0/selinux-use-sk-blob-accessor-in-socket-permission-helpers.patch new file mode 100644 index 0000000000..66147fd69a --- /dev/null +++ b/queue-7.0/selinux-use-sk-blob-accessor-in-socket-permission-helpers.patch @@ -0,0 +1,50 @@ +From 032e70aff025d7c519af9ab791cd084380619263 Mon Sep 17 00:00:00 2001 +From: Zongyao Chen +Date: Fri, 24 Apr 2026 15:37:53 +0800 +Subject: selinux: use sk blob accessor in socket permission helpers + +From: Zongyao Chen + +commit 032e70aff025d7c519af9ab791cd084380619263 upstream. + +SELinux socket state lives in the composite LSM socket blob. + +sock_has_perm() and nlmsg_sock_has_extended_perms() currently +dereference sk->sk_security directly, which assumes the SELinux socket +blob is at offset zero. + +In stacked configurations that assumption does not hold. If another LSM +allocates socket blob storage before SELinux, these helpers may read the +wrong blob and feed invalid SID and class values into AVC checks. + +Use selinux_sock() instead of accessing sk->sk_security directly. + +Fixes: d1d991efaf34 ("selinux: Add netlink xperm support") +Cc: stable@vger.kernel.org # v6.13+ +Signed-off-by: Zongyao Chen +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/hooks.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -4914,7 +4914,7 @@ static bool sock_skip_has_perm(u32 sid) + + static int sock_has_perm(struct sock *sk, u32 perms) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct common_audit_data ad; + struct lsm_network_audit net; + +@@ -6221,7 +6221,7 @@ static unsigned int selinux_ip_postroute + + static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_type) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct common_audit_data ad; + u8 driver; + u8 xperm; diff --git a/queue-7.0/series b/queue-7.0/series index 5f4cf12ef2..977dae9096 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -48,3 +48,44 @@ alsa-hda-realtek-fix-speaker-silence-after-s3-resume-on-xiaomi-mi-laptop-pro-15. alsa-firewire-tascam-do-not-drop-unread-control-events.patch alsa-core-serialize-deferred-fasync-state-checks.patch alsa-seq-fix-ump-group-16-filtering.patch +powerpc-kdump-fix-kasan-sanitization-flag-for-core_-bits-.o.patch +x86-efi-restore-irq-state-in-efi-page-fault-handler.patch +sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch +xfrm-provide-message-size-for-xfrm_msg_mapping.patch +xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch +ipv6-xfrm6-release-dst-on-error-in-xfrm6_rcv_encap.patch +xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch +selinux-fix-avdcache-auditing.patch +selinux-use-sk-blob-accessor-in-socket-permission-helpers.patch +selinux-don-t-reserve-xattr-slot-when-we-won-t-fill-it.patch +selinux-shrink-critical-section-in-sel_write_load.patch +selinux-prune-sys-fs-selinux-checkreqprot.patch +selinux-prune-sys-fs-selinux-disable.patch +selinux-prune-sys-fs-selinux-user.patch +selinux-allow-multiple-opens-of-sys-fs-selinux-policy.patch +io_uring-kbuf-support-min-length-left-for-incremental-buffers.patch +io_uring-tw-serialize-ctx-retry_llist-with-uring_lock.patch +loongarch-kvm-fix-missing-emulate_fail-in-kvm_emu_mmio_read.patch +bluetooth-virtio_bt-clamp-rx-length-before-skb_put.patch +bluetooth-virtio_bt-validate-rx-pkt_type-header-length.patch +bluetooth-btmtk-validate-wmt-event-skb-length-before-struct-access.patch +bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch +bluetooth-hci_event-fix-oob-read-and-infinite-loop-in-hci_le_create_big_complete_evt.patch +bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_new_connection_cb.patch +bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_state_change_cb.patch +bluetooth-l2cap-fix-null-ptr-deref-in-l2cap_sock_get_sndtimeo_cb.patch +rust-drm-gem-clean-up-gem-state-in-init-failure-case.patch +rust-allow-clippy-collapsible_match-globally.patch +rust-allow-clippy-collapsible_if-globally.patch +rust-pin-init-internal-move-alignment-check-to-make_field_check.patch +spi-syncuacer-fix-controller-deregistration.patch +spi-sun4i-fix-controller-deregistration.patch +spi-zynq-qspi-fix-controller-deregistration.patch +spi-ti-qspi-fix-controller-deregistration.patch +spi-sun6i-fix-controller-deregistration.patch +spi-tegra114-fix-controller-deregistration.patch +spi-zynqmp-gqspi-fix-controller-deregistration.patch +spi-tegra20-sflash-fix-controller-deregistration.patch +spi-s3c64xx-fix-null-deref-on-driver-unbind.patch +staging-rtl8723bs-os_dep-avoid-null-pointer-dereference-in-rtw_cbuf_alloc.patch +staging-vme_user-fix-root-device-leak-on-init-failure.patch diff --git a/queue-7.0/spi-s3c64xx-fix-null-deref-on-driver-unbind.patch b/queue-7.0/spi-s3c64xx-fix-null-deref-on-driver-unbind.patch new file mode 100644 index 0000000000..6e3d4beaf7 --- /dev/null +++ b/queue-7.0/spi-s3c64xx-fix-null-deref-on-driver-unbind.patch @@ -0,0 +1,45 @@ +From 45daacbead8a009844bd5dba6cfa731332184d17 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 11:49:25 +0200 +Subject: spi: s3c64xx: fix NULL-deref on driver unbind + +From: Johan Hovold + +commit 45daacbead8a009844bd5dba6cfa731332184d17 upstream. + +A change moving DMA channel allocation from probe() back to +s3c64xx_spi_prepare_transfer() failed to remove the corresponding +deallocation from remove(). + +Drop the bogus DMA channel release from remove() to avoid triggering a +NULL-pointer dereference on driver unbind. + +This issue was flagged by Sashiko when reviewing a controller +deregistration fix. + +Fixes: f52b03c70744 ("spi: s3c64xx: requests spi-dma channel only during data transfer") +Cc: stable@vger.kernel.org # 6.0 +Cc: Adithya K V +Link: https://sashiko.dev/#/patchset/20260410081757.503099-1-johan%40kernel.org +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410094925.518343-1-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-s3c64xx.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/spi/spi-s3c64xx.c ++++ b/drivers/spi/spi-s3c64xx.c +@@ -1401,11 +1401,6 @@ static void s3c64xx_spi_remove(struct pl + + writel(0, sdd->regs + S3C64XX_SPI_INT_EN); + +- if (!is_polling(sdd)) { +- dma_release_channel(sdd->rx_dma.ch); +- dma_release_channel(sdd->tx_dma.ch); +- } +- + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); diff --git a/queue-7.0/spi-sun4i-fix-controller-deregistration.patch b/queue-7.0/spi-sun4i-fix-controller-deregistration.patch new file mode 100644 index 0000000000..7d0d6c2a90 --- /dev/null +++ b/queue-7.0/spi-sun4i-fix-controller-deregistration.patch @@ -0,0 +1,50 @@ +From 42108a2f03e0fdeabe9d02d085bdb058baa1189f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:48 +0200 +Subject: spi: sun4i: fix controller deregistration + +From: Johan Hovold + +commit 42108a2f03e0fdeabe9d02d085bdb058baa1189f upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: b5f6517948cc ("spi: sunxi: Add Allwinner A10 SPI controller driver") +Cc: stable@vger.kernel.org # 3.15 +Cc: Maxime Ripard +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-19-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-sun4i.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-sun4i.c ++++ b/drivers/spi/spi-sun4i.c +@@ -504,7 +504,7 @@ static int sun4i_spi_probe(struct platfo + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret) { + dev_err(&pdev->dev, "cannot register SPI host\n"); + goto err_pm_disable; +@@ -522,7 +522,15 @@ err_free_host: + + static void sun4i_spi_remove(struct platform_device *pdev) + { ++ struct spi_controller *host = platform_get_drvdata(pdev); ++ ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + pm_runtime_force_suspend(&pdev->dev); ++ ++ spi_controller_put(host); + } + + static const struct of_device_id sun4i_spi_match[] = { diff --git a/queue-7.0/spi-sun6i-fix-controller-deregistration.patch b/queue-7.0/spi-sun6i-fix-controller-deregistration.patch new file mode 100644 index 0000000000..511825f4c5 --- /dev/null +++ b/queue-7.0/spi-sun6i-fix-controller-deregistration.patch @@ -0,0 +1,53 @@ +From d874a1c33aee0d88fb4ba2f8aeadaa9f1965209a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:49 +0200 +Subject: spi: sun6i: fix controller deregistration + +From: Johan Hovold + +commit d874a1c33aee0d88fb4ba2f8aeadaa9f1965209a upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: 3558fe900e8a ("spi: sunxi: Add Allwinner A31 SPI controller driver") +Cc: stable@vger.kernel.org # 3.15 +Cc: Maxime Ripard +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-20-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-sun6i.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-sun6i.c ++++ b/drivers/spi/spi-sun6i.c +@@ -742,7 +742,7 @@ static int sun6i_spi_probe(struct platfo + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret) { + dev_err(&pdev->dev, "cannot register SPI host\n"); + goto err_pm_disable; +@@ -768,12 +768,18 @@ static void sun6i_spi_remove(struct plat + { + struct spi_controller *host = platform_get_drvdata(pdev); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + pm_runtime_force_suspend(&pdev->dev); + + if (host->dma_tx) + dma_release_channel(host->dma_tx); + if (host->dma_rx) + dma_release_channel(host->dma_rx); ++ ++ spi_controller_put(host); + } + + static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = { diff --git a/queue-7.0/spi-syncuacer-fix-controller-deregistration.patch b/queue-7.0/spi-syncuacer-fix-controller-deregistration.patch new file mode 100644 index 0000000000..540a13c41c --- /dev/null +++ b/queue-7.0/spi-syncuacer-fix-controller-deregistration.patch @@ -0,0 +1,50 @@ +From 75d849c3452e9611de031db45b3149ba9a99035f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:50 +0200 +Subject: spi: syncuacer: fix controller deregistration + +From: Johan Hovold + +commit 75d849c3452e9611de031db45b3149ba9a99035f upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: b0823ee35cf9 ("spi: Add spi driver for Socionext SynQuacer platform") +Cc: stable@vger.kernel.org # 5.3 +Cc: Masahisa Kojima +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-21-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-synquacer.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-synquacer.c ++++ b/drivers/spi/spi-synquacer.c +@@ -716,7 +716,7 @@ static int synquacer_spi_probe(struct pl + pm_runtime_set_active(sspi->dev); + pm_runtime_enable(sspi->dev); + +- ret = devm_spi_register_controller(sspi->dev, host); ++ ret = spi_register_controller(host); + if (ret) + goto disable_pm; + +@@ -737,9 +737,15 @@ static void synquacer_spi_remove(struct + struct spi_controller *host = platform_get_drvdata(pdev); + struct synquacer_spi *sspi = spi_controller_get_devdata(host); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + pm_runtime_disable(sspi->dev); + + clk_disable_unprepare(sspi->clk); ++ ++ spi_controller_put(host); + } + + static int __maybe_unused synquacer_spi_suspend(struct device *dev) diff --git a/queue-7.0/spi-tegra114-fix-controller-deregistration.patch b/queue-7.0/spi-tegra114-fix-controller-deregistration.patch new file mode 100644 index 0000000000..b55d58f1df --- /dev/null +++ b/queue-7.0/spi-tegra114-fix-controller-deregistration.patch @@ -0,0 +1,54 @@ +From 9c9c27ff2058142d8f800de3186d6864184958de Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:51 +0200 +Subject: spi: tegra114: fix controller deregistration + +From: Johan Hovold + +commit 9c9c27ff2058142d8f800de3186d6864184958de upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: 5c8096439600 ("spi: tegra114: use devm_spi_register_master()") +Cc: stable@vger.kernel.org # 3.13 +Cc: Jingoo Han +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-tegra114.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -1415,7 +1415,7 @@ static int tegra_spi_probe(struct platfo + goto exit_pm_disable; + } + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret < 0) { + dev_err(&pdev->dev, "can not register to host err %d\n", ret); + goto exit_free_irq; +@@ -1441,6 +1441,10 @@ static void tegra_spi_remove(struct plat + struct spi_controller *host = platform_get_drvdata(pdev); + struct tegra_spi_data *tspi = spi_controller_get_devdata(host); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + free_irq(tspi->irq, tspi); + + if (tspi->tx_dma_chan) +@@ -1452,6 +1456,8 @@ static void tegra_spi_remove(struct plat + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_spi_runtime_suspend(&pdev->dev); ++ ++ spi_controller_put(host); + } + + #ifdef CONFIG_PM_SLEEP diff --git a/queue-7.0/spi-tegra20-sflash-fix-controller-deregistration.patch b/queue-7.0/spi-tegra20-sflash-fix-controller-deregistration.patch new file mode 100644 index 0000000000..8437081319 --- /dev/null +++ b/queue-7.0/spi-tegra20-sflash-fix-controller-deregistration.patch @@ -0,0 +1,52 @@ +From ad7310e983327f939dd6c4e801eab13238992572 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:52 +0200 +Subject: spi: tegra20-sflash: fix controller deregistration + +From: Johan Hovold + +commit ad7310e983327f939dd6c4e801eab13238992572 upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: f12f7318c44a ("spi: tegra20-sflash: use devm_spi_register_master()") +Cc: stable@vger.kernel.org # 3.13 +Cc: Jingoo Han +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-tegra20-sflash.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-tegra20-sflash.c ++++ b/drivers/spi/spi-tegra20-sflash.c +@@ -505,7 +505,7 @@ static int tegra_sflash_probe(struct pla + tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); + pm_runtime_put(&pdev->dev); + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret < 0) { + dev_err(&pdev->dev, "can not register to host err %d\n", ret); + goto exit_pm_disable; +@@ -528,11 +528,17 @@ static void tegra_sflash_remove(struct p + struct spi_controller *host = platform_get_drvdata(pdev); + struct tegra_sflash_data *tsd = spi_controller_get_devdata(host); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + free_irq(tsd->irq, tsd); + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_sflash_runtime_suspend(&pdev->dev); ++ ++ spi_controller_put(host); + } + + #ifdef CONFIG_PM_SLEEP diff --git a/queue-7.0/spi-ti-qspi-fix-controller-deregistration.patch b/queue-7.0/spi-ti-qspi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..71a79d3d30 --- /dev/null +++ b/queue-7.0/spi-ti-qspi-fix-controller-deregistration.patch @@ -0,0 +1,65 @@ +From 0c18a1bacbb1d8b8aa34d3d004a2cb8226c8b1ea Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:53 +0200 +Subject: spi: ti-qspi: fix controller deregistration + +From: Johan Hovold + +commit 0c18a1bacbb1d8b8aa34d3d004a2cb8226c8b1ea upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Note that the controller is suspended before disabling and releasing +resources since commit 3ac066e2227c ("spi: spi-ti-qspi: Suspend the +queue before removing the device") which avoids issues like unclocked +accesses but prevents SPI device drivers from doing I/O during +deregistration. + +Fixes: 3b3a80019ff1 ("spi: ti-qspi: one only one interrupt handler") +Cc: stable@vger.kernel.org # 3.13 +Cc: Sebastian Andrzej Siewior +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-24-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-ti-qspi.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/spi/spi-ti-qspi.c ++++ b/drivers/spi/spi-ti-qspi.c +@@ -888,7 +888,7 @@ no_dma: + qspi->mmap_enabled = false; + qspi->current_cs = -1; + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (!ret) + return 0; + +@@ -903,19 +903,17 @@ free_host: + static void ti_qspi_remove(struct platform_device *pdev) + { + struct ti_qspi *qspi = platform_get_drvdata(pdev); +- int rc; + +- rc = spi_controller_suspend(qspi->host); +- if (rc) { +- dev_alert(&pdev->dev, "spi_controller_suspend() failed (%pe)\n", +- ERR_PTR(rc)); +- return; +- } ++ spi_controller_get(qspi->host); ++ ++ spi_unregister_controller(qspi->host); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + ti_qspi_dma_cleanup(qspi); ++ ++ spi_controller_put(qspi->host); + } + + static const struct dev_pm_ops ti_qspi_pm_ops = { diff --git a/queue-7.0/spi-zynq-qspi-fix-controller-deregistration.patch b/queue-7.0/spi-zynq-qspi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..6dc23df3b3 --- /dev/null +++ b/queue-7.0/spi-zynq-qspi-fix-controller-deregistration.patch @@ -0,0 +1,69 @@ +From c9c012706c9fa8ca6d129a9161caf92ab625a3fd Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:56 +0200 +Subject: spi: zynq-qspi: fix controller deregistration + +From: Johan Hovold + +commit c9c012706c9fa8ca6d129a9161caf92ab625a3fd upstream. + +Make sure to deregister the controller before disabling it during driver +unbind. + +Note that clocks were also disabled before the recent commit +1f8fd9490e31 ("spi: zynq-qspi: Simplify clock handling with +devm_clk_get_enabled()"). + +Fixes: 67dca5e580f1 ("spi: spi-mem: Add support for Zynq QSPI controller") +Cc: stable@vger.kernel.org # 5.2: 8eb2fd00f65a +Cc: stable@vger.kernel.org # 5.2 +Cc: Naga Sureshkumar Relli +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-zynq-qspi.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/spi/spi-zynq-qspi.c ++++ b/drivers/spi/spi-zynq-qspi.c +@@ -643,7 +643,7 @@ static int zynq_qspi_probe(struct platfo + + xqspi = spi_controller_get_devdata(ctlr); + xqspi->dev = dev; +- platform_set_drvdata(pdev, xqspi); ++ platform_set_drvdata(pdev, ctlr); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(xqspi->regs)) { + ret = PTR_ERR(xqspi->regs); +@@ -702,9 +702,9 @@ static int zynq_qspi_probe(struct platfo + /* QSPI controller initializations */ + zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); + +- ret = devm_spi_register_controller(&pdev->dev, ctlr); ++ ret = spi_register_controller(ctlr); + if (ret) { +- dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); ++ dev_err(&pdev->dev, "failed to register controller\n"); + goto remove_ctlr; + } + +@@ -728,9 +728,16 @@ remove_ctlr: + */ + static void zynq_qspi_remove(struct platform_device *pdev) + { +- struct zynq_qspi *xqspi = platform_get_drvdata(pdev); ++ struct spi_controller *ctlr = platform_get_drvdata(pdev); ++ struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); ++ ++ spi_controller_get(ctlr); ++ ++ spi_unregister_controller(ctlr); + + zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); ++ ++ spi_controller_put(ctlr); + } + + static const struct of_device_id zynq_qspi_of_match[] = { diff --git a/queue-7.0/spi-zynqmp-gqspi-fix-controller-deregistration.patch b/queue-7.0/spi-zynqmp-gqspi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..53015fbba2 --- /dev/null +++ b/queue-7.0/spi-zynqmp-gqspi-fix-controller-deregistration.patch @@ -0,0 +1,44 @@ +From 6895fc4faafc9082e15e4e624b23dd5f0c98feb5 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 10 Apr 2026 10:17:55 +0200 +Subject: spi: zynqmp-gqspi: fix controller deregistration + +From: Johan Hovold + +commit 6895fc4faafc9082e15e4e624b23dd5f0c98feb5 upstream. + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: dfe11a11d523 ("spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller") +Cc: stable@vger.kernel.org # 4.2: 64640f6c972e +Cc: stable@vger.kernel.org # 4.2 +Cc: Ranjit Waghmode +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-26-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-zynqmp-gqspi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-zynqmp-gqspi.c ++++ b/drivers/spi/spi-zynqmp-gqspi.c +@@ -1324,7 +1324,7 @@ static int zynqmp_qspi_probe(struct plat + ctlr->dev.of_node = np; + ctlr->auto_runtime_pm = true; + +- ret = devm_spi_register_controller(&pdev->dev, ctlr); ++ ret = spi_register_controller(ctlr); + if (ret) { + dev_err(&pdev->dev, "spi_register_controller failed\n"); + goto clk_dis_all; +@@ -1362,6 +1362,8 @@ static void zynqmp_qspi_remove(struct pl + + pm_runtime_get_sync(&pdev->dev); + ++ spi_unregister_controller(xqspi->ctlr); ++ + zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0); + + pm_runtime_disable(&pdev->dev); diff --git a/queue-7.0/staging-rtl8723bs-os_dep-avoid-null-pointer-dereference-in-rtw_cbuf_alloc.patch b/queue-7.0/staging-rtl8723bs-os_dep-avoid-null-pointer-dereference-in-rtw_cbuf_alloc.patch new file mode 100644 index 0000000000..d2c5422394 --- /dev/null +++ b/queue-7.0/staging-rtl8723bs-os_dep-avoid-null-pointer-dereference-in-rtw_cbuf_alloc.patch @@ -0,0 +1,39 @@ +From bc851db06045a40c18233dd76ef0562d7f8bb6db Mon Sep 17 00:00:00 2001 +From: Shyam Sunder Reddy Padira +Date: Tue, 14 Apr 2026 12:43:06 +0530 +Subject: staging: rtl8723bs: os_dep: avoid NULL pointer dereference in rtw_cbuf_alloc + +From: Shyam Sunder Reddy Padira + +commit bc851db06045a40c18233dd76ef0562d7f8bb6db upstream. + +The return value of kzalloc_flex() is used without +ensuring that the allocation succeeded, and the +pointer is dereferenced unconditionally. + +Guard the access to the allocated structure to +avoid a potential NULL pointer dereference if the +allocation fails. + +Fixes: 980cd426a257 ("staging: rtl8723bs: replace rtw_zmalloc() with kzalloc()") +Cc: stable +Signed-off-by: Shyam Sunder Reddy Padira +Reviewed-by: Dan Carpenter +Link: https://patch.msgid.link/20260414071308.4781-2-shyamsunderreddypadira@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/os_dep/osdep_service.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c ++++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c +@@ -194,7 +194,8 @@ struct rtw_cbuf *rtw_cbuf_alloc(u32 size + struct rtw_cbuf *cbuf; + + cbuf = kzalloc_flex(*cbuf, bufs, size); +- cbuf->size = size; ++ if (cbuf) ++ cbuf->size = size; + + return cbuf; + } diff --git a/queue-7.0/staging-vme_user-fix-root-device-leak-on-init-failure.patch b/queue-7.0/staging-vme_user-fix-root-device-leak-on-init-failure.patch new file mode 100644 index 0000000000..af5ffc70c3 --- /dev/null +++ b/queue-7.0/staging-vme_user-fix-root-device-leak-on-init-failure.patch @@ -0,0 +1,33 @@ +From 32c91e8ee039777d0b95b914633fc6a42607959c Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 24 Apr 2026 12:49:10 +0200 +Subject: staging: vme_user: fix root device leak on init failure + +From: Johan Hovold + +commit 32c91e8ee039777d0b95b914633fc6a42607959c upstream. + +Make sure to deregister and free the root device in case module +initialisation fails. + +Fixes: 658bcdae9c67 ("vme: Adding Fake VME driver") +Cc: stable@vger.kernel.org # 4.9 +Cc: Martyn Welch +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260424104910.2619349-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/vme_user/vme_fake.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/staging/vme_user/vme_fake.c ++++ b/drivers/staging/vme_user/vme_fake.c +@@ -1230,6 +1230,8 @@ err_master: + err_driver: + kfree(fake_bridge); + err_struct: ++ root_device_unregister(vme_root); ++ + return retval; + } + diff --git a/queue-7.0/x86-efi-restore-irq-state-in-efi-page-fault-handler.patch b/queue-7.0/x86-efi-restore-irq-state-in-efi-page-fault-handler.patch new file mode 100644 index 0000000000..434cfb05a3 --- /dev/null +++ b/queue-7.0/x86-efi-restore-irq-state-in-efi-page-fault-handler.patch @@ -0,0 +1,100 @@ +From 2c340aab5485ebe9e33c01437dd4815ef33c8df5 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Fri, 1 May 2026 09:16:38 +0200 +Subject: x86/efi: Restore IRQ state in EFI page fault handler + +From: Ard Biesheuvel + +commit 2c340aab5485ebe9e33c01437dd4815ef33c8df5 upstream. + +The kernel's softirq API does not permit re-enabling softirqs while IRQs +are disabled. The reason for this is that local_bh_enable() will not +only re-enable delivery of softirqs over the back of IRQs, it will also +handle any pending softirqs immediately, regardless of whether IRQs are +enabled at that point. + +For this reason, commit + + d02198550423 ("x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs") + +disables softirqs only when IRQs are enabled, as it is not permitted +otherwise, but also unnecessary, given that asynchronous softirq +delivery never happens to begin with while IRQs are disabled. + +However, this does mean that entering a kernel mode FPU section with +IRQs enabled and leaving it with IRQs disabled leads to problems, as +identified by Sashiko [0]: the EFI page fault handler is called from +page_fault_oops() with IRQs disabled, and thus ends the kernel mode FPU +section with IRQs disabled as well, regardless of whether IRQs were +enabled when it was started. This may result in schedule() being called +with a non-zero preempt_count, causing a BUG(). + +So take care to re-enable IRQs when handling any EFI page faults if they +were taken with IRQs enabled. + +[0] https://sashiko.dev/#/patchset/20260430074107.27051-1-ivan.hu%40canonical.com + +Cc: Eric Biggers +Cc: Ivan Hu +Cc: x86@kernel.org +Cc: +Fixes: d02198550423 ("x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs") +Reviewed-by: Eric Biggers +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/efi.h | 3 ++- + arch/x86/mm/fault.c | 2 +- + arch/x86/platform/efi/quirks.c | 11 ++++++++++- + 3 files changed, 13 insertions(+), 3 deletions(-) + +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -137,7 +137,8 @@ extern void __init efi_dump_pagetable(vo + extern void __init efi_apply_memmap_quirks(void); + 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_crash_gracefully_on_page_fault(unsigned long phys_addr, ++ const struct pt_regs *regs); + extern void efi_unmap_boot_services(void); + + void arch_efi_call_virt_setup(void); +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -686,7 +686,7 @@ page_fault_oops(struct pt_regs *regs, un + * avoid hanging the system. + */ + if (IS_ENABLED(CONFIG_EFI)) +- efi_crash_gracefully_on_page_fault(address); ++ efi_crash_gracefully_on_page_fault(address, regs); + + /* Only not-present faults should be handled by KFENCE. */ + if (!(error_code & X86_PF_PROT) && +--- a/arch/x86/platform/efi/quirks.c ++++ b/arch/x86/platform/efi/quirks.c +@@ -761,7 +761,8 @@ int efi_capsule_setup_info(struct capsul + * @return: Returns, if the page fault is not handled. This function + * will never return if the page fault is handled successfully. + */ +-void efi_crash_gracefully_on_page_fault(unsigned long phys_addr) ++void efi_crash_gracefully_on_page_fault(unsigned long phys_addr, ++ const struct pt_regs *regs) + { + if (!IS_ENABLED(CONFIG_X86_64)) + return; +@@ -811,6 +812,14 @@ void efi_crash_gracefully_on_page_fault( + } + + /* ++ * The API does not permit entering a kernel mode FPU section with ++ * interrupts enabled and leaving it with interrupts disabled. So ++ * re-enable interrupts now if they were enabled when the page fault ++ * occurred. ++ */ ++ local_irq_restore(regs->flags); ++ ++ /* + * Before calling EFI Runtime Service, the kernel has switched the + * calling process to efi_mm. Hence, switch back to task_mm. + */ diff --git a/queue-7.0/xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch b/queue-7.0/xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch new file mode 100644 index 0000000000..42724a701e --- /dev/null +++ b/queue-7.0/xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch @@ -0,0 +1,128 @@ +From ec54093e6a8f87e800bb6aa15eb7fc1e33faa524 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Sun, 19 Apr 2026 18:35:42 -0400 +Subject: xfrm: ah: account for ESN high bits in async callbacks + +From: Michael Bommarito + +commit ec54093e6a8f87e800bb6aa15eb7fc1e33faa524 upstream. + +AH allocates its temporary auth/ICV layout differently when ESN is enabled: +the async ahash setup appends a 4-byte seqhi slot before the ICV or +auth_data area, but the async completion callbacks still reconstruct the +temporary layout as if seqhi were absent. + +With an async AH implementation selected, that makes AH copy or compare +the wrong bytes on both the IPv4 and IPv6 paths. In UML repro on IPv4 AH +with ESN and forced async hmac(sha1), ping fails with 100% packet loss, +and the callback logs show the pre-fix drift: + + ah4 output_done: esn=1 err=0 icv_off=20 expected_off=24 + ah4 input_done: esn=1 auth_off=20 expected_auth_off=24 icv_off=32 expected_icv_off=36 + +Reconstruct the callback-side layout the same way the setup path built it +by skipping the ESN seqhi slot before locating the saved auth_data or ICV. +Per RFC 4302, the ESN high-order 32 bits participate in the AH ICV +computation, so the async callbacks must account for the seqhi slot. + +Post-fix, the same IPv4 AH+ESN+forced-async-hmac(sha1) UML repro shows +the corrected offset (ah4 output_done: esn=1 err=0 icv_off=24 +expected_off=24) and ping succeeds; net/ipv4/ah4.o and net/ipv6/ah6.o +build clean at W=1. IPv6 AH+ESN was not exercised at runtime, and the +change has not been tested against a real async hardware AH engine. + +Fixes: d4d573d0334d ("{IPv4,xfrm} Add ESN support for AH egress part") +Fixes: d8b2a8600b0e ("{IPv4,xfrm} Add ESN support for AH ingress part") +Fixes: 26dd70c3fad3 ("{IPv6,xfrm} Add ESN support for AH egress part") +Fixes: 8d6da6f32557 ("{IPv6,xfrm} Add ESN support for AH ingress part") +Cc: stable@vger.kernel.org +Assisted-by: Codex:gpt-5-4 +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ah4.c | 14 ++++++++++++-- + net/ipv6/ah6.c | 14 ++++++++++++-- + 2 files changed, 24 insertions(+), 4 deletions(-) + +--- a/net/ipv4/ah4.c ++++ b/net/ipv4/ah4.c +@@ -124,9 +124,14 @@ static void ah_output_done(void *data, i + struct iphdr *top_iph = ip_hdr(skb); + struct ip_auth_hdr *ah = ip_auth_hdr(skb); + int ihl = ip_hdrlen(skb); ++ int seqhi_len = 0; ++ __be32 *seqhi; + ++ if (x->props.flags & XFRM_STATE_ESN) ++ seqhi_len = sizeof(*seqhi); + iph = AH_SKB_CB(skb)->tmp; +- icv = ah_tmp_icv(iph, ihl); ++ seqhi = (__be32 *)((char *)iph + ihl); ++ icv = ah_tmp_icv(seqhi, seqhi_len); + memcpy(ah->auth_data, icv, ahp->icv_trunc_len); + + top_iph->tos = iph->tos; +@@ -270,12 +275,17 @@ static void ah_input_done(void *data, in + struct ip_auth_hdr *ah = ip_auth_hdr(skb); + int ihl = ip_hdrlen(skb); + int ah_hlen = (ah->hdrlen + 2) << 2; ++ int seqhi_len = 0; ++ __be32 *seqhi; + + if (err) + goto out; + ++ if (x->props.flags & XFRM_STATE_ESN) ++ seqhi_len = sizeof(*seqhi); + work_iph = AH_SKB_CB(skb)->tmp; +- auth_data = ah_tmp_auth(work_iph, ihl); ++ seqhi = (__be32 *)((char *)work_iph + ihl); ++ auth_data = ah_tmp_auth(seqhi, seqhi_len); + icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len); + + err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; +--- a/net/ipv6/ah6.c ++++ b/net/ipv6/ah6.c +@@ -317,14 +317,19 @@ static void ah6_output_done(void *data, + struct ipv6hdr *top_iph = ipv6_hdr(skb); + struct ip_auth_hdr *ah = ip_auth_hdr(skb); + struct tmp_ext *iph_ext; ++ int seqhi_len = 0; ++ __be32 *seqhi; + + extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr); + if (extlen) + extlen += sizeof(*iph_ext); + ++ if (x->props.flags & XFRM_STATE_ESN) ++ seqhi_len = sizeof(*seqhi); + iph_base = AH_SKB_CB(skb)->tmp; + iph_ext = ah_tmp_ext(iph_base); +- icv = ah_tmp_icv(iph_ext, extlen); ++ seqhi = (__be32 *)((char *)iph_ext + extlen); ++ icv = ah_tmp_icv(seqhi, seqhi_len); + + memcpy(ah->auth_data, icv, ahp->icv_trunc_len); + memcpy(top_iph, iph_base, IPV6HDR_BASELEN); +@@ -471,13 +476,18 @@ static void ah6_input_done(void *data, i + struct ip_auth_hdr *ah = ip_auth_hdr(skb); + int hdr_len = skb_network_header_len(skb); + int ah_hlen = ipv6_authlen(ah); ++ int seqhi_len = 0; ++ __be32 *seqhi; + + if (err) + goto out; + ++ if (x->props.flags & XFRM_STATE_ESN) ++ seqhi_len = sizeof(*seqhi); + work_iph = AH_SKB_CB(skb)->tmp; + auth_data = ah_tmp_auth(work_iph, hdr_len); +- icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len); ++ seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len); ++ icv = ah_tmp_icv(seqhi, seqhi_len); + + err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; + if (err) diff --git a/queue-7.0/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch b/queue-7.0/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch new file mode 100644 index 0000000000..65c7e41171 --- /dev/null +++ b/queue-7.0/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch @@ -0,0 +1,119 @@ +From 14acf9652e5690de3c7486c6db5fb8dafd0a32a3 Mon Sep 17 00:00:00 2001 +From: Michal Kosiorek +Date: Wed, 29 Apr 2026 10:54:51 +0200 +Subject: xfrm: defensively unhash xfrm_state lists in __xfrm_state_delete + +From: Michal Kosiorek + +commit 14acf9652e5690de3c7486c6db5fb8dafd0a32a3 upstream. + +KASAN reproduces a slab-use-after-free in __xfrm_state_delete()'s +hlist_del_rcu calls under syzkaller load on linux-6.12.y stable +(reproduced on 6.12.47, also reachable via the same code path on +torvalds/master and on the ipsec tree). Nine unique signatures cluster +in the xfrm_state lifecycle, the load-bearing one being: + + BUG: KASAN: slab-use-after-free in __hlist_del include/linux/list.h:990 [inline] + BUG: KASAN: slab-use-after-free in hlist_del_rcu include/linux/rculist.h:516 [inline] + BUG: KASAN: slab-use-after-free in __xfrm_state_delete net/xfrm/xfrm_state.c + Write of size 8 at addr ffff8881198bcb70 by task kworker/u8:9/435 + + Workqueue: netns cleanup_net + Call Trace: + __hlist_del / hlist_del_rcu + __xfrm_state_delete + xfrm_state_delete + xfrm_state_flush + xfrm_state_fini + ops_exit_list + cleanup_net + +The other observed signatures hit the same slab object from +__xfrm_state_lookup, xfrm_alloc_spi, __xfrm_state_insert and an OOB +write variant of __xfrm_state_delete, all on the byseq/byspi +hash chains. + +__xfrm_state_delete() guards its byseq and byspi unhashes with +value-based predicates: + + if (x->km.seq) + hlist_del_rcu(&x->byseq); + if (x->id.spi) + hlist_del_rcu(&x->byspi); + +while everywhere else in the file (e.g. state_cache, state_cache_input) +the safer hlist_unhashed() check is used. xfrm_alloc_spi() sets +x->id.spi = newspi inside xfrm_state_lock and then immediately inserts +into byspi, but a path that observes x->id.spi != 0 outside of +xfrm_state_lock can still skip-or-hit the byspi unhash inconsistently +with whether x is actually on the list. The same holds for x->km.seq +versus byseq, and the bydst/bysrc unhashes have no predicate at all, +so a second __xfrm_state_delete() on the same object writes through +LIST_POISON pprev. + +The defensive change here: + + - Use hlist_del_init_rcu() instead of hlist_del_rcu() on bydst, + bysrc, byseq and byspi so a second deletion is a no-op rather + than a write through LIST_POISON pprev. The byseq/byspi nodes + are already initialised in xfrm_state_alloc(). + - Test hlist_unhashed() rather than the value predicate for + byseq/byspi, so the unhash decision tracks list state rather than + mutable scalar fields. + +Empirical verification: applied this patch on top of v6.12.47, rebuilt, +and re-ran the same syzkaller harness for 1h16m on a previously-crashy +configuration that produced ~100 hits each of slab-use-after-free +Read in xfrm_alloc_spi / Read in __xfrm_state_lookup / Write in +__xfrm_state_delete. After the patch, 7.1M execs across 32 VMs at +~1550 exec/sec produced zero xfrm_state UAF/OOB hits. /proc/slabinfo +confirms the xfrm_state slab is actively allocated and freed during +the run (~143 KiB resident), so the fuzzer is still exercising those +code paths -- they just no longer crash. + +Reproduction: + + - Linux 6.12.47 x86_64 + KASAN_GENERIC + KASAN_INLINE + KCOV + - syzkaller @ 746545b8b1e4c3a128db8652b340d3df90ce61db + - 32 QEMU/KVM VMs x 2 vCPU on AWS c5.metal bare metal + - 9 unique signatures collected in ~9h, all within xfrm_state + lifecycle + +Fixes: fe9f1d8779cb ("xfrm: add state hashtable keyed by seq") +Fixes: 7b4dc3600e48 ("[XFRM]: Do not add a state whose SPI is zero to the SPI hash.") +Reported-by: Michal Kosiorek +Tested-by: Michal Kosiorek +Cc: stable@vger.kernel.org +Signed-off-by: Michal Kosiorek +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_state.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -818,17 +818,17 @@ int __xfrm_state_delete(struct xfrm_stat + + spin_lock(&net->xfrm.xfrm_state_lock); + list_del(&x->km.all); +- hlist_del_rcu(&x->bydst); +- hlist_del_rcu(&x->bysrc); +- if (x->km.seq) +- hlist_del_rcu(&x->byseq); ++ hlist_del_init_rcu(&x->bydst); ++ hlist_del_init_rcu(&x->bysrc); ++ if (!hlist_unhashed(&x->byseq)) ++ hlist_del_init_rcu(&x->byseq); + if (!hlist_unhashed(&x->state_cache)) + hlist_del_rcu(&x->state_cache); + if (!hlist_unhashed(&x->state_cache_input)) + hlist_del_rcu(&x->state_cache_input); + +- if (x->id.spi) +- hlist_del_rcu(&x->byspi); ++ if (!hlist_unhashed(&x->byspi)) ++ hlist_del_init_rcu(&x->byspi); + net->xfrm.state_num--; + xfrm_nat_keepalive_state_updated(x); + spin_unlock(&net->xfrm.xfrm_state_lock); diff --git a/queue-7.0/xfrm-provide-message-size-for-xfrm_msg_mapping.patch b/queue-7.0/xfrm-provide-message-size-for-xfrm_msg_mapping.patch new file mode 100644 index 0000000000..354a1e8728 --- /dev/null +++ b/queue-7.0/xfrm-provide-message-size-for-xfrm_msg_mapping.patch @@ -0,0 +1,40 @@ +From 28465227c80fe417b4013c432be1f3737cb9f9a3 Mon Sep 17 00:00:00 2001 +From: Ruijie Li +Date: Wed, 29 Apr 2026 00:41:43 +0800 +Subject: xfrm: provide message size for XFRM_MSG_MAPPING + +From: Ruijie Li + +commit 28465227c80fe417b4013c432be1f3737cb9f9a3 upstream. + +The compat 64=>32 translation path handles XFRM_MSG_MAPPING, but +xfrm_msg_min[] does not provide the native payload size for this +message type. + +Add the missing XFRM_MSG_MAPPING entry so compat translation can size +and translate mapping notifications correctly. + +Fixes: 5461fc0c8d9f ("xfrm/compat: Add 64=>32-bit messages translator") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Signed-off-by: Ruijie Li +Signed-off-by: Ren Wei +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_user.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -3323,6 +3323,7 @@ const int xfrm_msg_min[XFRM_NR_MSGTYPES] + [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), + [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32), + [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), ++ [XFRM_MSG_MAPPING - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_mapping), + [XFRM_MSG_SETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default), + [XFRM_MSG_GETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default), + };