From: Sasha Levin Date: Sat, 15 Aug 2026 02:33:07 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch b/queue-5.10/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch new file mode 100644 index 0000000000..5a90ee398e --- /dev/null +++ b/queue-5.10/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch @@ -0,0 +1,68 @@ +From 994319004bd059be5934b0c0ee6fd898b3d317f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 23:46:59 +0000 +Subject: Bluetooth: 6lowpan: Fix using chan->conn as indication to no remote + netdev + +From: Luiz Augusto von Dentz + +[ Upstream commit d38eaf611839b85ade3dd3db309dbc8aaaaf0095 ] + +b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding +conn ref") don't reset the chan->conn to NULL anymore making the bt# +netdev not be remove once the last l2cap_chan_del is removed. + +Instead of restoring the original behavior this remove the logic of +keeping the interface after the last channel is removed because it +never worked as intended and the l2cap_chan_del always detach its +l2cap_conn which results in always removing the channel anyway. + +Fixes: b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 096f6fc5d30bf..a71855268d33f 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -804,20 +804,10 @@ static void chan_close_cb(struct l2cap_chan *chan) + struct lowpan_btle_dev *dev = NULL; + struct lowpan_peer *peer; + int err = -ENOENT; +- bool last = false, remove = true; ++ bool last = false; + + BT_DBG("chan %p conn %p", chan, chan->conn); + +- if (chan->conn && chan->conn->hcon) { +- if (!is_bt_6lowpan(chan->conn->hcon)) +- return; +- +- /* If conn is set, then the netdev is also there and we should +- * not remove it. +- */ +- remove = false; +- } +- + spin_lock(&devices_lock); + + list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +@@ -844,10 +834,8 @@ static void chan_close_cb(struct l2cap_chan *chan) + + ifdown(dev->netdev); + +- if (remove) { +- INIT_WORK(&entry->delete_netdev, delete_netdev); +- schedule_work(&entry->delete_netdev); +- } ++ INIT_WORK(&entry->delete_netdev, delete_netdev); ++ schedule_work(&entry->delete_netdev); + } else { + spin_unlock(&devices_lock); + } +-- +2.53.0 + diff --git a/queue-5.10/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch b/queue-5.10/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch new file mode 100644 index 0000000000..67d6365dfa --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch @@ -0,0 +1,255 @@ +From e987288d06d71bede0f78b919022b5513795a3ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 23:46:58 +0000 +Subject: Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref + +From: Marco Elver + +[ Upstream commit b66774b48dd98f07254951f74ea6f513efe7ff8b ] + +l2cap_chan_timeout() runs asynchronously and accesses chan->conn. If +the connection is torn down while the timer is running or pending, +chan->conn can be freed, leading to a use-after-free when the timer +worker attempts to lock conn->lock: + +| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| Write of size 8 at addr ffff8881298d9550 by task kworker/2:1/83 +| +| CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full) +| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 +| Workqueue: events l2cap_chan_timeout +| Call Trace: +| +| instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| l2cap_chan_timeout+0x5d/0x1b0 net/bluetooth/l2cap_core.c:422 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| +| Allocated by task 320: +| l2cap_conn_add+0xa7/0x820 net/bluetooth/l2cap_core.c:7075 +| l2cap_connect_cfm+0xdb/0xd70 net/bluetooth/l2cap_core.c:7452 +| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline] +| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760 +| hci_event_func net/bluetooth/hci_event.c:7796 [inline] +| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847 +| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| Freed by task 322: +| hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline] +| hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736 +| hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405 +| hci_dev_do_close net/bluetooth/hci_core.c:502 [inline] +| hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679 +| vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690 +| __fput+0x369/0x890 fs/file_table.c:510 +| task_work_run+0x160/0x1d0 kernel/task_work.c:233 +| get_signal+0xf5b/0x1120 kernel/signal.c:2810 +| arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337 +| __exit_to_user_mode_loop kernel/entry/common.c:64 [inline] +| exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98 +| do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100 +| entry_SYSCALL_64_after_hwframe+0x77/0x7f +| +| The buggy address belongs to the object at ffff8881298d9400 +| which belongs to the cache kmalloc-512 of size 512 +| The buggy address is located 336 bytes inside of +| freed 512-byte region [ffff8881298d9400, ffff8881298d9600) + +Fix it by having chan->conn hold a reference to l2cap_conn (via +l2cap_conn_get) when the channel is added to the connection, and +releasing it in the channel destructor. This ensures the l2cap_conn +remains alive as long as the channel exists. + +A new FLAG_DEL channel flag is introduced to indicate that the channel +has been deleted from its connection. l2cap_chan_del() atomically sets +this flag using test_and_set_bit() instead of setting chan->conn to +NULL. All asynchronous workers (l2cap_chan_timeout, l2cap_ack_timeout, +l2cap_monitor_timeout, l2cap_retrans_timeout) and l2cap_chan_send() +check FLAG_DEL to determine whether the channel has been torn down, +rather than testing chan->conn for NULL. + +Fixes: 8c8e620467a7 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()") +Cc: +Cc: Siwei Zhang +Cc: Luiz Augusto von Dentz +Assisted-by: Gemini:gemini-3.1-pro-preview +Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz +Change-Id: Ie9862976d25c3e6d386689cd198ebe5ab4cc5509 +Signed-off-by: Marco Elver +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Todd Kjos +--- + include/net/bluetooth/l2cap.h | 1 + + net/bluetooth/l2cap_core.c | 36 +++++++++++++++++++++-------------- + 2 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index d2db84b77bfbe..af590a802eba4 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -775,6 +775,7 @@ enum { + FLAG_ECRED_CONN_REQ_SENT, + FLAG_PENDING_SECURITY, + FLAG_HOLD_HCI_CONN, ++ FLAG_DEL, + }; + + /* Lock nesting levels for L2CAP channels. We need these because lockdep +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index c9c3bef3ae895..1c2114930f86f 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -435,7 +435,7 @@ static void l2cap_chan_timeout(struct work_struct *work) + + BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + +- if (!conn) { ++ if (!conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_put(chan); + return; + } +@@ -446,6 +446,9 @@ static void l2cap_chan_timeout(struct work_struct *work) + */ + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) + reason = ECONNREFUSED; + else if (chan->state == BT_CONNECT && +@@ -458,10 +461,11 @@ static void l2cap_chan_timeout(struct work_struct *work) + + chan->ops->close(chan); + ++unlock: + l2cap_chan_unlock(chan); +- l2cap_chan_put(chan); + + mutex_unlock(&conn->chan_lock); ++ l2cap_chan_put(chan); + } + + struct l2cap_chan *l2cap_chan_create(void) +@@ -511,6 +515,9 @@ static void l2cap_chan_destroy(struct kref *kref) + list_del(&chan->global_l); + write_unlock(&chan_list_lock); + ++ if (chan->conn) ++ l2cap_conn_put(chan->conn); ++ + kfree(chan); + } + +@@ -593,7 +600,7 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) + + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; + +- chan->conn = conn; ++ chan->conn = l2cap_conn_get(conn); + + switch (chan->chan_type) { + case L2CAP_CHAN_CONN_ORIENTED: +@@ -648,31 +655,28 @@ void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) + + void l2cap_chan_del(struct l2cap_chan *chan, int err) + { +- struct l2cap_conn *conn = chan->conn; +- + __clear_chan_timer(chan); + +- BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, ++ BT_DBG("chan %p, err %d, state %s", chan, err, + state_to_string(chan->state)); + + chan->ops->teardown(chan, err); + +- if (conn) { +- struct amp_mgr *mgr = conn->hcon->amp_mgr; ++ if (chan->conn && !test_and_set_bit(FLAG_DEL, &chan->flags)) { ++ struct amp_mgr *mgr = chan->conn->hcon->amp_mgr; ++ + /* Delete from channel list */ + list_del(&chan->list); + + l2cap_chan_put(chan); + +- chan->conn = NULL; +- + /* Reference was only held for non-fixed channels or + * fixed channels that explicitly requested it using the + * FLAG_HOLD_HCI_CONN flag. + */ + if (chan->chan_type != L2CAP_CHAN_FIXED || + test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) +- hci_conn_drop(conn->hcon); ++ hci_conn_drop(chan->conn->hcon); + + if (mgr && mgr->bredr_chan == chan) + mgr->bredr_chan = NULL; +@@ -2046,7 +2050,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -2067,7 +2071,7 @@ static void l2cap_retrans_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -2692,7 +2696,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) + int err; + struct sk_buff_head seg_queue; + +- if (!chan->conn) ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) + return -ENOTCONN; + + /* Connectionless channel */ +@@ -3293,12 +3297,16 @@ static void l2cap_ack_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + frames_to_ack = __seq_offset(chan, chan->buffer_seq, + chan->last_acked_seq); + + if (frames_to_ack) + l2cap_send_rr_or_rnr(chan, 0); + ++unlock: + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + } +-- +2.53.0 + diff --git a/queue-5.10/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-5.10/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..50cc25b7a7 --- /dev/null +++ b/queue-5.10/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,184 @@ +From 95bd200a1d6552218666e16c8a263c8243f6a7ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:44:30 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 82 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 56 insertions(+), 26 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index df86c0e494184..d772b8ab29817 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -3428,8 +3428,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -3438,41 +3441,68 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the following conditions are met: ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. ++ * ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) ++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-5.10/ima-fix-out-of-bounds-read-in-xattr_verify.patch b/queue-5.10/ima-fix-out-of-bounds-read-in-xattr_verify.patch new file mode 100644 index 0000000000..ff8dd86493 --- /dev/null +++ b/queue-5.10/ima-fix-out-of-bounds-read-in-xattr_verify.patch @@ -0,0 +1,65 @@ +From 34356fc73c598f4d1d783f0843ade8fd3da43765 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 16:06:14 -0300 +Subject: ima: fix out-of-bounds read in xattr_verify() + +From: Lincoln Wallace + +[ Upstream commit 5ff232d31106f45ac87c3b64e1d35a0667777797 ] + +The digest-length check in xattr_verify() mixes int and size_t: + + if (xattr_len - sizeof(xattr_value->type) - hash_start >= + iint->ima_hash->length) + +sizeof() yields size_t, so the usual arithmetic conversions promote +the whole left-hand side to unsigned 64-bit before the subtraction +runs. For a truncated xattr this underflows instead of going negative: +a 1-byte IMA_XATTR_DIGEST_NG xattr (xattr_len == 1, hash_start == 1) +turns "1 - 1 - 1" into SIZE_MAX, which is trivially >= ima_hash->length. +The check then passes and the following memcmp() reads +iint->ima_hash->length bytes starting past the end of the buffer +vfs_getxattr_alloc() allocated for it. + +Nothing upstream clamps xattr_len back into a safe range first: +ima_get_hash_algo() only special-cases xattr_len < 2 to pick a default +algorithm, and evm_verifyxattr() returns INTEGRITY_UNKNOWN rather than +failing when no HMAC key is loaded, so a truncated security.ima value +reaches the length check as-is. + +Rewrite the comparison so every operand stays a signed int and no +implicit conversion to size_t can occur. + +Fixes: 3ea7a56067e6 ("ima: provide hash algo info in the xattr") +Cc: stable@vger.kernel.org +Signed-off-by: Lincoln Wallace +Signed-off-by: Mimi Zohar +Signed-off-by: Lincoln Wallace +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_appraise.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c +index 7122a359a268e..615a20b9eb52b 100644 +--- a/security/integrity/ima/ima_appraise.c ++++ b/security/integrity/ima/ima_appraise.c +@@ -242,8 +242,13 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, + break; + } + clear_bit(IMA_DIGSIG, &iint->atomic_flags); +- if (xattr_len - sizeof(xattr_value->type) - hash_start >= +- iint->ima_hash->length) ++ /* ++ * Use addition, not subtraction: sizeof() forces unsigned ++ * math and a short xattr_len would wrap around, bypassing ++ * this bounds check. ++ */ ++ if (xattr_len >= (int)sizeof(xattr_value->type) + hash_start + ++ (int)iint->ima_hash->length) + /* + * xattr length may be longer. md5 hash in previous + * version occupied 20 bytes in xattr, instead of 16 +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index fd4a6e07d1..50857fa086 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -347,3 +347,7 @@ usb-gadget-f_ncm-use-unsigned-int-for-ndp_index.patch vt-add-permission-check-for-kdskbmeta-ioctl.patch vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch +bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch +bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch +ima-fix-out-of-bounds-read-in-xattr_verify.patch +futex-prevent-robust-futex-exit-race-some-more.patch diff --git a/queue-5.15/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch b/queue-5.15/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch new file mode 100644 index 0000000000..bf1ab5b587 --- /dev/null +++ b/queue-5.15/bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch @@ -0,0 +1,68 @@ +From 60edcb21d12be859eda6c53adbd2448e7e9a038b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 23:46:59 +0000 +Subject: Bluetooth: 6lowpan: Fix using chan->conn as indication to no remote + netdev + +From: Luiz Augusto von Dentz + +[ Upstream commit d38eaf611839b85ade3dd3db309dbc8aaaaf0095 ] + +b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding +conn ref") don't reset the chan->conn to NULL anymore making the bt# +netdev not be remove once the last l2cap_chan_del is removed. + +Instead of restoring the original behavior this remove the logic of +keeping the interface after the last channel is removed because it +never worked as intended and the l2cap_chan_del always detach its +l2cap_conn which results in always removing the channel anyway. + +Fixes: b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 9424d153f323f..d0b1882f5b4b7 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -775,20 +775,10 @@ static void chan_close_cb(struct l2cap_chan *chan) + struct lowpan_btle_dev *dev = NULL; + struct lowpan_peer *peer; + int err = -ENOENT; +- bool last = false, remove = true; ++ bool last = false; + + BT_DBG("chan %p conn %p", chan, chan->conn); + +- if (chan->conn && chan->conn->hcon) { +- if (!is_bt_6lowpan(chan->conn->hcon)) +- return; +- +- /* If conn is set, then the netdev is also there and we should +- * not remove it. +- */ +- remove = false; +- } +- + spin_lock(&devices_lock); + + list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +@@ -815,10 +805,8 @@ static void chan_close_cb(struct l2cap_chan *chan) + + ifdown(dev->netdev); + +- if (remove) { +- INIT_WORK(&entry->delete_netdev, delete_netdev); +- schedule_work(&entry->delete_netdev); +- } ++ INIT_WORK(&entry->delete_netdev, delete_netdev); ++ schedule_work(&entry->delete_netdev); + } else { + spin_unlock(&devices_lock); + } +-- +2.53.0 + diff --git a/queue-5.15/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch b/queue-5.15/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch new file mode 100644 index 0000000000..97f6005be8 --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch @@ -0,0 +1,255 @@ +From 3c5edd84502a2aeef719f310203d16d05bf27cd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 23:46:58 +0000 +Subject: Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref + +From: Marco Elver + +[ Upstream commit b66774b48dd98f07254951f74ea6f513efe7ff8b ] + +l2cap_chan_timeout() runs asynchronously and accesses chan->conn. If +the connection is torn down while the timer is running or pending, +chan->conn can be freed, leading to a use-after-free when the timer +worker attempts to lock conn->lock: + +| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| Write of size 8 at addr ffff8881298d9550 by task kworker/2:1/83 +| +| CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full) +| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 +| Workqueue: events l2cap_chan_timeout +| Call Trace: +| +| instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| l2cap_chan_timeout+0x5d/0x1b0 net/bluetooth/l2cap_core.c:422 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| +| Allocated by task 320: +| l2cap_conn_add+0xa7/0x820 net/bluetooth/l2cap_core.c:7075 +| l2cap_connect_cfm+0xdb/0xd70 net/bluetooth/l2cap_core.c:7452 +| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline] +| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760 +| hci_event_func net/bluetooth/hci_event.c:7796 [inline] +| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847 +| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| Freed by task 322: +| hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline] +| hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736 +| hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405 +| hci_dev_do_close net/bluetooth/hci_core.c:502 [inline] +| hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679 +| vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690 +| __fput+0x369/0x890 fs/file_table.c:510 +| task_work_run+0x160/0x1d0 kernel/task_work.c:233 +| get_signal+0xf5b/0x1120 kernel/signal.c:2810 +| arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337 +| __exit_to_user_mode_loop kernel/entry/common.c:64 [inline] +| exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98 +| do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100 +| entry_SYSCALL_64_after_hwframe+0x77/0x7f +| +| The buggy address belongs to the object at ffff8881298d9400 +| which belongs to the cache kmalloc-512 of size 512 +| The buggy address is located 336 bytes inside of +| freed 512-byte region [ffff8881298d9400, ffff8881298d9600) + +Fix it by having chan->conn hold a reference to l2cap_conn (via +l2cap_conn_get) when the channel is added to the connection, and +releasing it in the channel destructor. This ensures the l2cap_conn +remains alive as long as the channel exists. + +A new FLAG_DEL channel flag is introduced to indicate that the channel +has been deleted from its connection. l2cap_chan_del() atomically sets +this flag using test_and_set_bit() instead of setting chan->conn to +NULL. All asynchronous workers (l2cap_chan_timeout, l2cap_ack_timeout, +l2cap_monitor_timeout, l2cap_retrans_timeout) and l2cap_chan_send() +check FLAG_DEL to determine whether the channel has been torn down, +rather than testing chan->conn for NULL. + +Fixes: 8c8e620467a7 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()") +Cc: +Cc: Siwei Zhang +Cc: Luiz Augusto von Dentz +Assisted-by: Gemini:gemini-3.1-pro-preview +Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz +Change-Id: Ie9862976d25c3e6d386689cd198ebe5ab4cc5509 +Signed-off-by: Marco Elver +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Todd Kjos +--- + include/net/bluetooth/l2cap.h | 1 + + net/bluetooth/l2cap_core.c | 36 +++++++++++++++++++++-------------- + 2 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index beb690a162ff2..57315b9dc059e 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -776,6 +776,7 @@ enum { + FLAG_ECRED_CONN_REQ_SENT, + FLAG_PENDING_SECURITY, + FLAG_HOLD_HCI_CONN, ++ FLAG_DEL, + }; + + /* Lock nesting levels for L2CAP channels. We need these because lockdep +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 913c0d04a481a..bf031426c912e 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -435,7 +435,7 @@ static void l2cap_chan_timeout(struct work_struct *work) + + BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + +- if (!conn) { ++ if (!conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_put(chan); + return; + } +@@ -446,6 +446,9 @@ static void l2cap_chan_timeout(struct work_struct *work) + */ + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) + reason = ECONNREFUSED; + else if (chan->state == BT_CONNECT && +@@ -458,10 +461,11 @@ static void l2cap_chan_timeout(struct work_struct *work) + + chan->ops->close(chan); + ++unlock: + l2cap_chan_unlock(chan); +- l2cap_chan_put(chan); + + mutex_unlock(&conn->chan_lock); ++ l2cap_chan_put(chan); + } + + struct l2cap_chan *l2cap_chan_create(void) +@@ -511,6 +515,9 @@ static void l2cap_chan_destroy(struct kref *kref) + list_del(&chan->global_l); + write_unlock(&chan_list_lock); + ++ if (chan->conn) ++ l2cap_conn_put(chan->conn); ++ + kfree(chan); + } + +@@ -593,7 +600,7 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) + + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; + +- chan->conn = conn; ++ chan->conn = l2cap_conn_get(conn); + + switch (chan->chan_type) { + case L2CAP_CHAN_CONN_ORIENTED: +@@ -648,31 +655,28 @@ void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) + + void l2cap_chan_del(struct l2cap_chan *chan, int err) + { +- struct l2cap_conn *conn = chan->conn; +- + __clear_chan_timer(chan); + +- BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, ++ BT_DBG("chan %p, err %d, state %s", chan, err, + state_to_string(chan->state)); + + chan->ops->teardown(chan, err); + +- if (conn) { +- struct amp_mgr *mgr = conn->hcon->amp_mgr; ++ if (chan->conn && !test_and_set_bit(FLAG_DEL, &chan->flags)) { ++ struct amp_mgr *mgr = chan->conn->hcon->amp_mgr; ++ + /* Delete from channel list */ + list_del(&chan->list); + + l2cap_chan_put(chan); + +- chan->conn = NULL; +- + /* Reference was only held for non-fixed channels or + * fixed channels that explicitly requested it using the + * FLAG_HOLD_HCI_CONN flag. + */ + if (chan->chan_type != L2CAP_CHAN_FIXED || + test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) +- hci_conn_drop(conn->hcon); ++ hci_conn_drop(chan->conn->hcon); + + if (mgr && mgr->bredr_chan == chan) + mgr->bredr_chan = NULL; +@@ -2044,7 +2048,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -2065,7 +2069,7 @@ static void l2cap_retrans_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -2690,7 +2694,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) + int err; + struct sk_buff_head seg_queue; + +- if (!chan->conn) ++ if (!chan->conn || test_bit(FLAG_DEL, &chan->flags)) + return -ENOTCONN; + + /* Connectionless channel */ +@@ -3291,12 +3295,16 @@ static void l2cap_ack_timeout(struct work_struct *work) + + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + frames_to_ack = __seq_offset(chan, chan->buffer_seq, + chan->last_acked_seq); + + if (frames_to_ack) + l2cap_send_rr_or_rnr(chan, 0); + ++unlock: + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + } +-- +2.53.0 + diff --git a/queue-5.15/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-5.15/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..10442d7900 --- /dev/null +++ b/queue-5.15/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,184 @@ +From ba38d8143109ed3d5bb4e8942b1e23058e611851 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:44:30 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 82 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 56 insertions(+), 26 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index 8b4af13b8d262..8a3a27967973a 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -3660,8 +3660,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -3670,41 +3673,68 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the following conditions are met: ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. ++ * ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) ++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-5.15/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch b/queue-5.15/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch new file mode 100644 index 0000000000..341e2212e2 --- /dev/null +++ b/queue-5.15/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch @@ -0,0 +1,64 @@ +From d54431433732b7a91c9db29b802604018edd410b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 17:35:50 +0300 +Subject: pinctrl: renesas: rzg2l: Use -ENOTSUPP instead of -EOPNOTSUPP + +From: Claudiu Beznea + +commit c1492da3939c89372929e062d731f328f7693f1e upstream. + +The pinctrl and GPIO core code make exceptions for the -ENOTSUPP error +code. One such example is gpio_set_config_with_argument_optional(), +which returns success when gpio_set_config_with_argument() returns +-ENOTSUPP, but reports failure for all other error codes. + +Returning -EOPNOTSUPP from the pinctrl driver on the unsupported pinctrl +operation may lead to boot failures when pinctrl drivers implements +struct gpio_chip::set_config, the system uses GPIO hogs, and the +struct gpio_chip::set_config implementation returns -EOPNOTSUPP for the +unsupported operations. + +Return -ENOTSUPP for the unsupported pinctrl operation. + +Fixes: 560c633d378a ("pinctrl: renesas: rzg2l: Drop oen_read and oen_write callbacks") +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Cc: stable@vger.kernel.org +Signed-off-by: Claudiu Beznea +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Geert Uytterhoeven +Tested-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260515124008.2947838-2-claudiu.beznea@kernel.org +Signed-off-by: Geert Uytterhoeven +[claudiu.beznea: fixed conflict by dropping the code not present in + v5.15 stable] +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index f839bd3d0927a..eceba66ab0336 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -565,7 +565,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, + break; + } + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + } + +@@ -614,7 +614,7 @@ static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, + + /* Check config matching between to pin */ + if (i && prev_config != *config) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + prev_config = *config; + } +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 3b8f8b9742..1783532e36 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -407,3 +407,7 @@ ima-fix-out-of-bounds-read-in-xattr_verify.patch vt-add-permission-check-for-kdskbmeta-ioctl.patch vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch +bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holdin.patch +bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch +futex-prevent-robust-futex-exit-race-some-more.patch +pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch diff --git a/queue-6.1/fortify-disable-wstringop-overread-in-tests.patch b/queue-6.1/fortify-disable-wstringop-overread-in-tests.patch new file mode 100644 index 0000000000..b0820b7c3a --- /dev/null +++ b/queue-6.1/fortify-disable-wstringop-overread-in-tests.patch @@ -0,0 +1,61 @@ +From dbfe648ae003f6313e525126418cbeaf3a1ad30f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 13:23:46 -0700 +Subject: fortify: Disable -Wstringop-overread in tests + +From: Nathan Chancellor + +commit c1f3e770eec26d6f96dd6d2ea30555ba7c09a244 upstream. + +clang recently added support for -Wstringop-overread [1], which is on by +default like -Wfortify-source. This breaks the usage of -Werror in the +fortify tests, resulting in the following false positive warnings in the +kernel build: + + warning: unsafe memcmp() usage lacked '__read_overflow2' warning in lib/test_fortify/read_overflow2-memcmp.c + warning: unsafe memcmp() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memcmp.c + warning: unsafe memchr() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memchr.c + +Examining the fortify test logs shows a warning like the following in +each of the failed logs: + + In file included from lib/test_fortify/read_overflow2-memcmp.c:5: + lib/test_fortify/test_fortify.h:34:2: error: 'memcmp' reading 17 bytes from a region of size 16 [-Werror,-Wstringop-overread] + 34 | TEST; + | ^ + lib/test_fortify/read_overflow2-memcmp.c:3:2: note: expanded from macro 'TEST' + 3 | memcmp(large, small, sizeof(small) + 1) + | ^ + 1 error generated. + +Disable -Wstringop-overread for the fortify tests, as it defeats the +purpose of testing the Linux specific implementation of fortify, like +-Wfortify-source. + +Cc: stable@vger.kernel.org +Closes: https://github.com/ClangBuiltLinux/linux/issues/2168 +Link: https://github.com/llvm/llvm-project/commit/86f2e71cb8d165b59ad31a442b2391e23826133e [1] +Signed-off-by: Nathan Chancellor +Link: https://patch.msgid.link/20260623-fix-test_fortify-for-clang-stringop-overread-v1-1-15ee8342a953@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/test_fortify/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/test_fortify/Makefile b/lib/test_fortify/Makefile +index 7887e6126e79c..eba2ba0faeb6a 100644 +--- a/lib/test_fortify/Makefile ++++ b/lib/test_fortify/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + + ccflags-y := $(call cc-disable-warning,fortify-source) ++ccflags-y += $(call cc-disable-warning,stringop-overread) + + quiet_cmd_test_fortify = TEST $@ + cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ +-- +2.53.0 + diff --git a/queue-6.1/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch b/queue-6.1/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch new file mode 100644 index 0000000000..3f1e7b9a9a --- /dev/null +++ b/queue-6.1/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch @@ -0,0 +1,175 @@ +From 2929a56383185d19098e37448d6ac7ac8a3712d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Jul 2024 00:02:36 +0900 +Subject: fortify: refactor test_fortify Makefile to fix some build problems + +From: Masahiro Yamada + +commit 4e9903b0861c9df3464b82db4a7025863bac1897 upstream. + +There are some issues in the test_fortify Makefile code. + +Problem 1: cc-disable-warning invokes compiler dozens of times + +To see how many times the cc-disable-warning is evaluated, change +this code: + + $(call cc-disable-warning,fortify-source) + +to: + + $(call cc-disable-warning,$(shell touch /tmp/fortify-$$$$)fortify-source) + +Then, build the kernel with CONFIG_FORTIFY_SOURCE=y. You will see a +large number of '/tmp/fortify-' files created: + + $ ls -1 /tmp/fortify-* | wc + 80 80 1600 + +This means the compiler was invoked 80 times just for checking the +-Wno-fortify-source flag support. + +$(call cc-disable-warning,fortify-source) should be added to a simple +variable instead of a recursive variable. + +Problem 2: do not recompile string.o when the test code is updated + +The test cases are independent of the kernel. However, when the test +code is updated, $(obj)/string.o is rebuilt and vmlinux is relinked +due to this dependency: + + $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) + +always-y is suitable for building the log files. + +Problem 3: redundant code + + clean-files += $(addsuffix .o, $(TEST_FORTIFY_LOGS)) + +... is unneeded because the top Makefile globally cleans *.o files. + +This commit fixes these issues and makes the code readable. + +Signed-off-by: Masahiro Yamada +Link: https://lore.kernel.org/r/20240727150302.1823750-2-masahiroy@kernel.org +Signed-off-by: Kees Cook +[nathan: Fixed conflicts] +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/.gitignore | 2 -- + lib/Makefile | 34 +--------------------------------- + lib/test_fortify/.gitignore | 2 ++ + lib/test_fortify/Makefile | 28 ++++++++++++++++++++++++++++ + scripts/remove-stale-files | 2 ++ + 5 files changed, 33 insertions(+), 35 deletions(-) + create mode 100644 lib/test_fortify/.gitignore + create mode 100644 lib/test_fortify/Makefile + +diff --git a/lib/.gitignore b/lib/.gitignore +index 54596b634ecbf..101a4aa92fb53 100644 +--- a/lib/.gitignore ++++ b/lib/.gitignore +@@ -5,5 +5,3 @@ + /gen_crc32table + /gen_crc64table + /oid_registry_data.c +-/test_fortify.log +-/test_fortify/*.log +diff --git a/lib/Makefile b/lib/Makefile +index 6ae66e13f3194..1081d0c161159 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -394,36 +394,4 @@ CFLAGS_longest_symbol_kunit.o += $(call cc-disable-warning, missing-prototypes) + + obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o + +-# FORTIFY_SOURCE compile-time behavior tests +-TEST_FORTIFY_SRCS = $(wildcard $(srctree)/$(src)/test_fortify/*-*.c) +-TEST_FORTIFY_LOGS = $(patsubst $(srctree)/$(src)/%.c, %.log, $(TEST_FORTIFY_SRCS)) +-TEST_FORTIFY_LOG = test_fortify.log +- +-quiet_cmd_test_fortify = TEST $@ +- cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ +- $< $@ "$(NM)" $(CC) $(c_flags) \ +- $(call cc-disable-warning,fortify-source) \ +- -DKBUILD_EXTRA_WARN1 +- +-targets += $(TEST_FORTIFY_LOGS) +-clean-files += $(TEST_FORTIFY_LOGS) +-clean-files += $(addsuffix .o, $(TEST_FORTIFY_LOGS)) +-$(obj)/test_fortify/%.log: $(src)/test_fortify/%.c \ +- $(src)/test_fortify/test_fortify.h \ +- $(srctree)/include/linux/fortify-string.h \ +- $(srctree)/scripts/test_fortify.sh \ +- FORCE +- $(call if_changed,test_fortify) +- +-quiet_cmd_gen_fortify_log = GEN $@ +- cmd_gen_fortify_log = cat /dev/null > $@ || true +- +-targets += $(TEST_FORTIFY_LOG) +-clean-files += $(TEST_FORTIFY_LOG) +-$(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE +- $(call if_changed,gen_fortify_log) +- +-# Fake dependency to trigger the fortify tests. +-ifeq ($(CONFIG_FORTIFY_SOURCE),y) +-$(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) +-endif ++subdir-$(CONFIG_FORTIFY_SOURCE) += test_fortify +diff --git a/lib/test_fortify/.gitignore b/lib/test_fortify/.gitignore +new file mode 100644 +index 0000000000000..c1ba37d14b50e +--- /dev/null ++++ b/lib/test_fortify/.gitignore +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++/*.log +diff --git a/lib/test_fortify/Makefile b/lib/test_fortify/Makefile +new file mode 100644 +index 0000000000000..7887e6126e79c +--- /dev/null ++++ b/lib/test_fortify/Makefile +@@ -0,0 +1,28 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++ccflags-y := $(call cc-disable-warning,fortify-source) ++ ++quiet_cmd_test_fortify = TEST $@ ++ cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ ++ $< $@ "$(NM)" $(CC) $(c_flags) -DKBUILD_EXTRA_WARN1 ++ ++$(obj)/%.log: $(src)/%.c $(srctree)/scripts/test_fortify.sh \ ++ $(src)/test_fortify.h \ ++ $(srctree)/include/linux/fortify-string.h \ ++ FORCE ++ $(call if_changed,test_fortify) ++ ++logs = $(patsubst $(srctree)/$(src)/%.c, %.log, $(wildcard $(srctree)/$(src)/*-*.c)) ++targets += $(logs) ++ ++quiet_cmd_gen_fortify_log = CAT $@ ++ cmd_gen_fortify_log = cat $(or $(real-prereqs),/dev/null) > $@ ++ ++$(obj)/test_fortify.log: $(addprefix $(obj)/, $(logs)) FORCE ++ $(call if_changed,gen_fortify_log) ++ ++always-y += test_fortify.log ++ ++# Some architectures define __NO_FORTIFY if __SANITIZE_ADDRESS__ is undefined. ++# Pass CFLAGS_KASAN to avoid warnings. ++KASAN_SANITIZE := y +diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files +index ccadfa3afb2b8..c22fe4630bac0 100755 +--- a/scripts/remove-stale-files ++++ b/scripts/remove-stale-files +@@ -47,3 +47,5 @@ rm -f arch/riscv/purgatory/kexec-purgatory.c + rm -f scripts/extract-cert + + rm -f arch/x86/purgatory/kexec-purgatory.c ++ ++rm -f lib/test_fortify.log +-- +2.53.0 + diff --git a/queue-6.1/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-6.1/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..c66996d023 --- /dev/null +++ b/queue-6.1/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,184 @@ +From baa3fdf10274c908831b3ab72e1b8d472de29d31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:44:30 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 82 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 56 insertions(+), 26 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index d4141b0547187..b370fdea7c217 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -660,8 +660,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -670,41 +673,68 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the following conditions are met: ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. ++ * ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) ++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-6.1/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch b/queue-6.1/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch new file mode 100644 index 0000000000..b008168297 --- /dev/null +++ b/queue-6.1/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch @@ -0,0 +1,64 @@ +From 028219c31ec4c2a327646fb4508ca540439a32bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 17:35:51 +0300 +Subject: pinctrl: renesas: rzg2l: Use -ENOTSUPP instead of -EOPNOTSUPP + +From: Claudiu Beznea + +commit c1492da3939c89372929e062d731f328f7693f1e upstream. + +The pinctrl and GPIO core code make exceptions for the -ENOTSUPP error +code. One such example is gpio_set_config_with_argument_optional(), +which returns success when gpio_set_config_with_argument() returns +-ENOTSUPP, but reports failure for all other error codes. + +Returning -EOPNOTSUPP from the pinctrl driver on the unsupported pinctrl +operation may lead to boot failures when pinctrl drivers implements +struct gpio_chip::set_config, the system uses GPIO hogs, and the +struct gpio_chip::set_config implementation returns -EOPNOTSUPP for the +unsupported operations. + +Return -ENOTSUPP for the unsupported pinctrl operation. + +Fixes: 560c633d378a ("pinctrl: renesas: rzg2l: Drop oen_read and oen_write callbacks") +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Cc: stable@vger.kernel.org +Signed-off-by: Claudiu Beznea +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Geert Uytterhoeven +Tested-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260515124008.2947838-2-claudiu.beznea@kernel.org +Signed-off-by: Geert Uytterhoeven +[claudiu.beznea: fixed conflict by dropping the code not present in + v6.1 stable] +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index 1304ab0bcac1e..85bcc9bbe6770 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -708,7 +708,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, + } + + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + } + +@@ -757,7 +757,7 @@ static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, + + /* Check config matching between to pin */ + if (i && prev_config != *config) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + prev_config = *config; + } +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 89795a5a1f..5540a5059a 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -546,3 +546,7 @@ vt-add-permission-check-for-kdskbmeta-ioctl.patch vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch ima-fix-out-of-bounds-read-in-xattr_verify.patch +futex-prevent-robust-futex-exit-race-some-more.patch +fortify-refactor-test_fortify-makefile-to-fix-some-b.patch +fortify-disable-wstringop-overread-in-tests.patch +pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch diff --git a/queue-6.12/blk-mq-pop-cached-request-if-it-is-usable.patch b/queue-6.12/blk-mq-pop-cached-request-if-it-is-usable.patch new file mode 100644 index 0000000000..ad41c88d8c --- /dev/null +++ b/queue-6.12/blk-mq-pop-cached-request-if-it-is-usable.patch @@ -0,0 +1,121 @@ +From 88d6017a9a9476e1aae21470519120132e40e53b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:54:11 +0000 +Subject: blk-mq: pop cached request if it is usable + +From: Keith Busch + +[ Upstream commit dc278e9bf2b9513a763353e6b9cc21e0f532954e ] + +When submitting a bio to blk-mq, if the task should sleep after peeking +a cached request, but before it pops it, the plug flushes and calls +blk_mq_free_plug_rqs, freeing the cached_rqs. This creates a +use-after-free bug. Fix this by popping the cached request before any +possible blocking calls if it is suitable for use. + +Popping this request first holds a queue reference, so avoid any +serialization races with queue freezes and can safely proceed with +dispatching that request to the driver. This potentially increases a +timing window from when a driver wants to freeze its queue to when +requests stop being dispatched. That scenario is off the fast path +though, and drivers need to appropriately handle requests during a +freeze request anyway. + +The downside is the popped element needs to be individually freed when +we performed a bio plug merge. The cached request would have had to be +freed later anyway, but this patch does it inline with building the plug +list instead of after flushing it. + +Fixes: b0077e269f6c1 ("blk-mq: make sure active queue usage is held for bio_integrity_prep()") +Fixes: 7b4f36cd22a65 ("block: ensure we hold a queue reference when using queue limits") +Signed-off-by: Keith Busch +Link: https://patch.msgid.link/20260521190253.242065-1-kbusch@meta.com +Signed-off-by: Jens Axboe +[ fix contextual conflicts ] +Signed-off-by: Simon Liebold +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 34 +++++++++------------------------- + 1 file changed, 9 insertions(+), 25 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index c1dff0d9f9439..fd21976375ed4 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2989,7 +2989,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q, + /* + * Check if there is a suitable cached request and return it. + */ +-static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, ++static struct request *blk_mq_get_cached_request(struct blk_plug *plug, + struct request_queue *q, blk_opf_t opf) + { + enum hctx_type type = blk_mq_get_hctx_type(opf); +@@ -3005,27 +3005,10 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, + return NULL; + if (op_is_flush(rq->cmd_flags) != op_is_flush(opf)) + return NULL; ++ rq_list_pop(&plug->cached_rqs); + return rq; + } + +-static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug, +- struct bio *bio) +-{ +- if (rq_list_pop(&plug->cached_rqs) != rq) +- WARN_ON_ONCE(1); +- +- /* +- * If any qos ->throttle() end up blocking, we will have flushed the +- * plug and hence killed the cached_rq list as well. Pop this entry +- * before we throttle. +- */ +- rq_qos_throttle(rq->q, bio); +- +- blk_mq_rq_time_init(rq, 0); +- rq->cmd_flags = bio->bi_opf; +- INIT_LIST_HEAD(&rq->queuelist); +-} +- + static bool bio_unaligned(const struct bio *bio, struct request_queue *q) + { + unsigned int bs_mask = queue_logical_block_size(q) - 1; +@@ -3063,7 +3046,7 @@ void blk_mq_submit_bio(struct bio *bio) + /* + * If the plug has a cached request for this queue, try to use it. + */ +- rq = blk_mq_peek_cached_request(plug, q, bio->bi_opf); ++ rq = blk_mq_get_cached_request(plug, q, bio->bi_opf); + + /* + * A BIO that was released from a zone write plug has already been +@@ -3122,7 +3105,10 @@ void blk_mq_submit_bio(struct bio *bio) + + new_request: + if (rq) { +- blk_mq_use_cached_rq(rq, plug, bio); ++ rq_qos_throttle(rq->q, bio); ++ blk_mq_rq_time_init(rq, blk_time_get_ns()); ++ rq->cmd_flags = bio->bi_opf; ++ INIT_LIST_HEAD(&rq->queuelist); + } else { + rq = blk_mq_get_new_requests(q, plug, bio, nr_segs); + if (unlikely(!rq)) +@@ -3165,12 +3151,10 @@ void blk_mq_submit_bio(struct bio *bio) + return; + + queue_exit: +- /* +- * Don't drop the queue reference if we were trying to use a cached +- * request and thus didn't acquire one. +- */ + if (!rq) + blk_queue_exit(q); ++ else ++ blk_mq_free_request(rq); + } + + #ifdef CONFIG_BLK_MQ_STACKING +-- +2.53.0 + diff --git a/queue-6.12/blk-mq-reinsert-cached-request-to-the-list.patch b/queue-6.12/blk-mq-reinsert-cached-request-to-the-list.patch new file mode 100644 index 0000000000..eb8e01d22e --- /dev/null +++ b/queue-6.12/blk-mq-reinsert-cached-request-to-the-list.patch @@ -0,0 +1,45 @@ +From 8372bdd96a743e0ae80ef31951d5a976f0e49ba5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:54:12 +0000 +Subject: blk-mq: reinsert cached request to the list + +From: Keith Busch + +[ Upstream commit b051bb6bf0a231117036aa607cadf55be8e63910 ] + +A previous commit removed an optimization out of caution for a scenario +that turns out not to be real: all the "queue_exit" goto's are safe to +reinsert the request into the cached_rq's plug list as they are either +from a non-blocking path, or a successful merge that already holds the +queue reference. This optimization is most needed for small sequential +workloads that successfully merge into larger requests. + +Fixes: dc278e9bf2b9 ("blk-mq: pop cached request if it is usable") +Suggested-by: Ming Lei +Suggested-by: Christoph Hellwig +Signed-off-by: Keith Busch +Reviewed-by: Chaitanya Kulkarni +Link: https://patch.msgid.link/20260526153531.2365935-1-kbusch@meta.com +Signed-off-by: Jens Axboe +Signed-off-by: Simon Liebold +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index fd21976375ed4..6af42682af7d6 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3154,7 +3154,7 @@ void blk_mq_submit_bio(struct bio *bio) + if (!rq) + blk_queue_exit(q); + else +- blk_mq_free_request(rq); ++ rq_list_add_head(&plug->cached_rqs, rq); + } + + #ifdef CONFIG_BLK_MQ_STACKING +-- +2.53.0 + diff --git a/queue-6.12/block-reorder-the-request-allocation-code-in-blk_mq_.patch b/queue-6.12/block-reorder-the-request-allocation-code-in-blk_mq_.patch new file mode 100644 index 0000000000..391c048a80 --- /dev/null +++ b/queue-6.12/block-reorder-the-request-allocation-code-in-blk_mq_.patch @@ -0,0 +1,49 @@ +From 50e147cb107f006e51342db1a32f602b9c79e7fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:54:10 +0000 +Subject: block: Reorder the request allocation code in blk_mq_submit_bio() + +From: Bart Van Assche + +[ Upstream commit 44e41381591dc5b4ea67a9f170b4ec85c817586e ] + +Help the CPU branch predictor in case of a cache hit by handling the cache +hit scenario first. + +Reviewed-by: Damien Le Moal +Cc: Christoph Hellwig +Signed-off-by: Bart Van Assche +Reviewed-by: Christoph Hellwig +Reviewed-by: Chaitanya Kulkarni +Link: https://lore.kernel.org/r/20241218212246.1073149-2-bvanassche@acm.org +Signed-off-by: Jens Axboe +Stable-dep-of: dc278e9bf2b9 ("blk-mq: pop cached request if it is usable") +Signed-off-by: Simon Liebold +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 5bfaa8e4b9cf6..c1dff0d9f9439 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3121,12 +3121,12 @@ void blk_mq_submit_bio(struct bio *bio) + } + + new_request: +- if (!rq) { ++ if (rq) { ++ blk_mq_use_cached_rq(rq, plug, bio); ++ } else { + rq = blk_mq_get_new_requests(q, plug, bio, nr_segs); + if (unlikely(!rq)) + goto queue_exit; +- } else { +- blk_mq_use_cached_rq(rq, plug, bio); + } + + trace_block_getrq(bio); +-- +2.53.0 + diff --git a/queue-6.12/crypto-ccp-abort-doing-sev-init-if-snp-init-fails.patch b/queue-6.12/crypto-ccp-abort-doing-sev-init-if-snp-init-fails.patch new file mode 100644 index 0000000000..1c8703fab2 --- /dev/null +++ b/queue-6.12/crypto-ccp-abort-doing-sev-init-if-snp-init-fails.patch @@ -0,0 +1,53 @@ +From 40f53332b7fb64713f3b6507a01b056e12014f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 12:02:57 +0200 +Subject: crypto: ccp - Abort doing SEV INIT if SNP INIT fails + +From: Ashish Kalra + +commit 6131e119f5799bec55535530fa2fc44f5c7be1f1 upstream. + +If SNP host support (SYSCFG.SNPEn) is set, then the RMP table must +be initialized before calling SEV INIT. + +In other words, if SNP_INIT(_EX) is not issued or fails then +SEV INIT will fail if SNP host support (SYSCFG.SNPEn) is enabled. + +Signed-off-by: Ashish Kalra +Signed-off-by: Herbert Xu +Signed-off-by: Jack Wang +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/sev-dev.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 6e08378eb5fac..d6a0773d6da8f 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -1118,7 +1118,7 @@ static int __sev_snp_init_locked(int *error) + if (!sev_version_greater_or_equal(SNP_MIN_API_MAJOR, SNP_MIN_API_MINOR)) { + dev_dbg(sev->dev, "SEV-SNP support requires firmware version >= %d:%d\n", + SNP_MIN_API_MAJOR, SNP_MIN_API_MINOR); +- return 0; ++ return -EOPNOTSUPP; + } + + /* SNP_INIT requires MSR_VM_HSAVE_PA to be cleared on all CPUs. */ +@@ -1357,12 +1357,9 @@ static int _sev_platform_init_locked(struct sev_platform_init_args *args) + + rc = __sev_snp_init_locked(&args->error); + if (rc && rc != -ENODEV) { +- /* +- * Don't abort the probe if SNP INIT failed, +- * continue to initialize the legacy SEV firmware. +- */ + dev_err(sev->dev, "SEV-SNP: failed to INIT rc %d, error %#x\n", + rc, args->error); ++ return rc; + } + + /* Defer legacy SEV/SEV-ES support if allowed by caller/module. */ +-- +2.53.0 + diff --git a/queue-6.12/crypto-ccp-add-new-sev-snp-platform-shutdown-api.patch b/queue-6.12/crypto-ccp-add-new-sev-snp-platform-shutdown-api.patch new file mode 100644 index 0000000000..8bb766eb0b --- /dev/null +++ b/queue-6.12/crypto-ccp-add-new-sev-snp-platform-shutdown-api.patch @@ -0,0 +1,67 @@ +From e9961d5cca0c6a8f72b8b9539f3a299c86f2b894 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 12:02:54 +0200 +Subject: crypto: ccp - Add new SEV/SNP platform shutdown API + +From: Ashish Kalra + +commit f7b86e0e75bc234751cb7a82d888083a57ef28b2 upstream. + +Add new API interface to do SEV/SNP platform shutdown when KVM module +is unloaded. + +Reviewed-by: Dionna Glaze +Reviewed-by: Tom Lendacky +Signed-off-by: Ashish Kalra +Signed-off-by: Herbert Xu +Signed-off-by: Jack Wang +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/sev-dev.c | 9 +++++++++ + include/linux/psp-sev.h | 3 +++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index d668f9318c286..7c05cae7e5778 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -2444,6 +2444,15 @@ static void sev_firmware_shutdown(struct sev_device *sev) + mutex_unlock(&sev_cmd_mutex); + } + ++void sev_platform_shutdown(void) ++{ ++ if (!psp_master || !psp_master->sev_data) ++ return; ++ ++ sev_firmware_shutdown(psp_master->sev_data); ++} ++EXPORT_SYMBOL_GPL(sev_platform_shutdown); ++ + void sev_dev_destroy(struct psp_device *psp) + { + struct sev_device *sev = psp->sev_data; +diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h +index 613a8209bed27..6a4435cfa977e 100644 +--- a/include/linux/psp-sev.h ++++ b/include/linux/psp-sev.h +@@ -947,6 +947,7 @@ int sev_do_cmd(int cmd, void *data, int *psp_ret); + void *psp_copy_user_blob(u64 uaddr, u32 len); + void *snp_alloc_firmware_page(gfp_t mask); + void snp_free_firmware_page(void *addr); ++void sev_platform_shutdown(void); + + #else /* !CONFIG_CRYPTO_DEV_SP_PSP */ + +@@ -981,6 +982,8 @@ static inline void *snp_alloc_firmware_page(gfp_t mask) + + static inline void snp_free_firmware_page(void *addr) { } + ++static inline void sev_platform_shutdown(void) { } ++ + #endif /* CONFIG_CRYPTO_DEV_SP_PSP */ + + #endif /* __PSP_SEV_H__ */ +-- +2.53.0 + diff --git a/queue-6.12/crypto-ccp-fix-checks-for-snp_vlek_load-input-buffer.patch b/queue-6.12/crypto-ccp-fix-checks-for-snp_vlek_load-input-buffer.patch new file mode 100644 index 0000000000..13cd18ec00 --- /dev/null +++ b/queue-6.12/crypto-ccp-fix-checks-for-snp_vlek_load-input-buffer.patch @@ -0,0 +1,46 @@ +From 5fdd1b870ef013230b6e8a7d72b0e5702f886847 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 12:02:56 +0200 +Subject: crypto: ccp - Fix checks for SNP_VLEK_LOAD input buffer length + +From: Michael Roth + +commit ed53a5050f42a3243a7ed8dfa49030e54034b952 upstream. + +The SNP_VLEK_LOAD IOCTL currently fails due to sev_cmd_buffer_len() +returning the default expected buffer length of 0 instead of the correct +value, which would be sizeof(struct sev_user_data_snp_vlek_load). Add +specific handling for SNP_VLEK_LOAD so the correct expected size is +returned. + +Reported-by: Diego GonzalezVillalobos +Cc: Diego GonzalezVillalobos +Fixes: 332d2c1d713e ("crypto: ccp: Add the SNP_VLEK_LOAD command") +Signed-off-by: Michael Roth +Signed-off-by: Herbert Xu +[Jack: sev_cmd_buffer_len() in queue/6.12 does not yet have the + SEV_CMD_SNP_FEATURE_INFO case the upstream context line matched + against (it lands in a later, unrelated commit not queued here), + so the new SEV_CMD_SNP_VLEK_LOAD case was placed directly after + SEV_CMD_SNP_COMMIT instead. No functional difference from upstream.] +Signed-off-by: Jack Wang +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/sev-dev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 7c05cae7e5778..6e08378eb5fac 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -226,6 +226,7 @@ static int sev_cmd_buffer_len(int cmd) + case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); + case SEV_CMD_SNP_CONFIG: return sizeof(struct sev_user_data_snp_config); + case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit); ++ case SEV_CMD_SNP_VLEK_LOAD: return sizeof(struct sev_user_data_snp_vlek_load); + default: return 0; + } + +-- +2.53.0 + diff --git a/queue-6.12/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch b/queue-6.12/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch new file mode 100644 index 0000000000..0b4062c255 --- /dev/null +++ b/queue-6.12/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch @@ -0,0 +1,69 @@ +From be258c55a4e86c340afa4026146f1fd3dd67ee58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 19:18:10 +0530 +Subject: dt-bindings: crypto: qcom,ice: Fix missing power-domain and iface clk + +From: Harshal Dev + +[ Upstream commit e27264daac7d9ce892a2a5b4a864d6d9a3c9276a ] + +The DT bindings for inline-crypto engine do not specify the UFS_PHY_GDSC +power-domain and iface clock. Without enabling the iface clock and the +associated power-domain the ICE hardware cannot function correctly and +leads to unclocked hardware accesses being observed during probe. + +Extend and fix the DT bindings for inline-crypto engine by allowing +description of the iface clock and UFS_PHY_GDSC power-domain. + +This patch has been adapted from the mentioned upstream commit to drop +references to Eliza and Milos Qualcomm platforms which do not exist +on the stable tree. Thus, patch now fixes the original commit which +introduced the DT binding for Qualcomm inline-crypto engine. + +Fixes: f6ff91a47ac5 ("dt-bindings: crypto: Add Qualcomm Inline Crypto Engine") +Reviewed-by: Kuldeep Singh +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Harshal Dev +Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-1-5ccf5d7e2846@oss.qualcomm.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + .../crypto/qcom,inline-crypto-engine.yaml | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +index 0304f074cf085..2793afc7f85c4 100644 +--- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml ++++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +@@ -25,6 +25,16 @@ properties: + maxItems: 1 + + clocks: ++ minItems: 1 ++ maxItems: 2 ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: core ++ - const: iface ++ ++ power-domains: + maxItems: 1 + + required: +@@ -42,6 +52,10 @@ examples: + compatible = "qcom,sm8550-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x01d88000 0x8000>; +- clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; ++ clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, ++ <&gcc GCC_UFS_PHY_AHB_CLK>; ++ clock-names = "core", ++ "iface"; ++ power-domains = <&gcc UFS_PHY_GDSC>; + }; + ... +-- +2.53.0 + diff --git a/queue-6.12/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-6.12/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..71ad53e925 --- /dev/null +++ b/queue-6.12/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,187 @@ +From 592b9a8b09a3bf1db8b6586350402a7d0d0aa93e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:43:28 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 85 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 58 insertions(+), 27 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index 010607a991949..c37d2263c21fe 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -674,8 +674,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -684,42 +687,70 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: ++ * ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * In both cases the following conditions are met: ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, +- FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) { ++ futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, ++ FUTEX_BITSET_MATCH_ANY); ++ } + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-6.12/kunit-fortify-add-back-volatile-for-sizeof-constants.patch b/queue-6.12/kunit-fortify-add-back-volatile-for-sizeof-constants.patch new file mode 100644 index 0000000000..1fbc80c5e0 --- /dev/null +++ b/queue-6.12/kunit-fortify-add-back-volatile-for-sizeof-constants.patch @@ -0,0 +1,49 @@ +From 7874df6631cbe3ec2713335ba2f3f2c9046df5c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 22:12:54 -0700 +Subject: kunit/fortify: Add back "volatile" for sizeof() constants +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kees Cook + +commit 10299c07c94aa0997fa43523b53301e713a6415d upstream. + +It seems the Clang can see through OPTIMIZER_HIDE_VAR when the constant +is coming from sizeof. Adding "volatile" back to these variables solves +this false positive without reintroducing the issues that originally led +to switching to OPTIMIZER_HIDE_VAR in the first place[1]. + +Reported-by: Nathan Chancellor +Closes: https://github.com/ClangBuiltLinux/linux/issues/2075 [1] +Cc: Jannik Glückert +Suggested-by: Nathan Chancellor +Fixes: 6ee149f61bcc ("kunit/fortify: Replace "volatile" with OPTIMIZER_HIDE_VAR()") +Reviewed-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20250628234034.work.800-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/fortify_kunit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c +index 1541b2a1694e4..d0810e4e65e5b 100644 +--- a/lib/fortify_kunit.c ++++ b/lib/fortify_kunit.c +@@ -986,8 +986,8 @@ static void fortify_test_memcmp(struct kunit *test) + { + char one[] = "My mind is going ..."; + char two[] = "My mind is going ... I can feel it."; +- size_t one_len = sizeof(one) - 1; +- size_t two_len = sizeof(two) - 1; ++ volatile size_t one_len = sizeof(one) - 1; ++ volatile size_t two_len = sizeof(two) - 1; + + OPTIMIZER_HIDE_VAR(one_len); + OPTIMIZER_HIDE_VAR(two_len); +-- +2.53.0 + diff --git a/queue-6.12/kunit-fortify-replace-volatile-with-optimizer_hide_v.patch b/queue-6.12/kunit-fortify-replace-volatile-with-optimizer_hide_v.patch new file mode 100644 index 0000000000..1b1e5b45cb --- /dev/null +++ b/queue-6.12/kunit-fortify-replace-volatile-with-optimizer_hide_v.patch @@ -0,0 +1,320 @@ +From 43683d29ac964d3a2027b7f88f7a838bf538d8a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 22:12:53 -0700 +Subject: kunit/fortify: Replace "volatile" with OPTIMIZER_HIDE_VAR() + +From: Kees Cook + +commit 6ee149f61bcce39692f0335a01e99355d4cec8da upstream. + +It does seem that using "volatile" isn't going to be sane compared to +using OPTIMIZER_HIDE_VAR() going forward. Some strange interactions[1] +with the sanitizers have been observed in the self-test code, so replace +the logic. + +Reported-by: Nathan Chancellor +Closes: https://github.com/ClangBuiltLinux/linux/issues/2075 [1] +Link: https://lore.kernel.org/r/20250312000439.work.112-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/fortify_kunit.c | 139 ++++++++++++++++++++++++-------------------- + 1 file changed, 77 insertions(+), 62 deletions(-) + +diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c +index ecb638d4cde1e..1541b2a1694e4 100644 +--- a/lib/fortify_kunit.c ++++ b/lib/fortify_kunit.c +@@ -394,8 +394,6 @@ struct fortify_padding { + char buf[32]; + unsigned long bytes_after; + }; +-/* Force compiler into not being able to resolve size at compile-time. */ +-static volatile int unconst; + + static void fortify_test_strlen(struct kunit *test) + { +@@ -520,57 +518,56 @@ static void fortify_test_strncpy(struct kunit *test) + { + struct fortify_padding pad = { }; + char src[] = "Copy me fully into a small buffer and I will overflow!"; ++ size_t sizeof_buf = sizeof(pad.buf); ++ ++ OPTIMIZER_HIDE_VAR(sizeof_buf); + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strncpy() 1 less than of max size. */ +- KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, +- sizeof(pad.buf) + unconst - 1) ++ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf - 1) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Only last byte should be %NUL */ +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 3], '\0'); + + /* Legitimate (though unterminated) max-size strncpy. */ +- KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, +- sizeof(pad.buf) + unconst) ++ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* No trailing %NUL -- thanks strncpy API. */ +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + /* But we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Now verify that FORTIFY is working... */ +- KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, +- sizeof(pad.buf) + unconst + 1) ++ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf + 1) + == pad.buf); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And further... */ +- KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, +- sizeof(pad.buf) + unconst + 2) ++ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf + 2) + == pad.buf); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + } +@@ -579,55 +576,56 @@ static void fortify_test_strscpy(struct kunit *test) + { + struct fortify_padding pad = { }; + char src[] = "Copy me fully into a small buffer and I will overflow!"; ++ size_t sizeof_buf = sizeof(pad.buf); ++ size_t sizeof_src = sizeof(src); ++ ++ OPTIMIZER_HIDE_VAR(sizeof_buf); ++ OPTIMIZER_HIDE_VAR(sizeof_src); + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strscpy() 1 less than of max size. */ +- KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, +- sizeof(pad.buf) + unconst - 1), ++ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf - 1), + -E2BIG); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Keeping space for %NUL, last two bytes should be %NUL */ +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 3], '\0'); + + /* Legitimate max-size strscpy. */ +- KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, +- sizeof(pad.buf) + unconst), ++ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf), + -E2BIG); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* A trailing %NUL will exist. */ +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + + /* Now verify that FORTIFY is working... */ +- KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, +- sizeof(pad.buf) + unconst + 1), ++ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf + 1), + -E2BIG); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And much further... */ +- KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, +- sizeof(src) * 2 + unconst), ++ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_src * 2), + -E2BIG); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); +- KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); +- KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); ++ KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); ++ KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + } +@@ -767,7 +765,9 @@ static void fortify_test_strlcat(struct kunit *test) + struct fortify_padding pad = { }; + char src[sizeof(pad.buf)] = { }; + int i, partial; +- int len = sizeof(pad.buf) + unconst; ++ int len = sizeof(pad.buf); ++ ++ OPTIMIZER_HIDE_VAR(len); + + /* Fill 15 bytes with valid characters. */ + partial = sizeof(src) / 2 - 1; +@@ -857,28 +857,32 @@ struct fortify_zero_sized { + #define __fortify_test(memfunc) \ + static void fortify_test_##memfunc(struct kunit *test) \ + { \ +- struct fortify_zero_sized zero = { }; \ ++ struct fortify_zero_sized empty = { }; \ + struct fortify_padding pad = { }; \ + char srcA[sizeof(pad.buf) + 2]; \ + char srcB[sizeof(pad.buf) + 2]; \ +- size_t len = sizeof(pad.buf) + unconst; \ ++ size_t len = sizeof(pad.buf); \ ++ size_t zero = 0; \ ++ \ ++ OPTIMIZER_HIDE_VAR(len); \ ++ OPTIMIZER_HIDE_VAR(zero); \ + \ + memset(srcA, 'A', sizeof(srcA)); \ + KUNIT_ASSERT_EQ(test, srcA[0], 'A'); \ + memset(srcB, 'B', sizeof(srcB)); \ + KUNIT_ASSERT_EQ(test, srcB[0], 'B'); \ + \ +- memfunc(pad.buf, srcA, 0 + unconst); \ ++ memfunc(pad.buf, srcA, zero); \ + KUNIT_EXPECT_EQ(test, pad.buf[0], '\0'); \ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \ +- memfunc(pad.buf + 1, srcB, 1 + unconst); \ ++ memfunc(pad.buf + 1, srcB, zero + 1); \ + KUNIT_EXPECT_EQ(test, pad.buf[0], '\0'); \ + KUNIT_EXPECT_EQ(test, pad.buf[1], 'B'); \ + KUNIT_EXPECT_EQ(test, pad.buf[2], '\0'); \ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \ +- memfunc(pad.buf, srcA, 1 + unconst); \ ++ memfunc(pad.buf, srcA, zero + 1); \ + KUNIT_EXPECT_EQ(test, pad.buf[0], 'A'); \ + KUNIT_EXPECT_EQ(test, pad.buf[1], 'B'); \ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \ +@@ -904,10 +908,10 @@ static void fortify_test_##memfunc(struct kunit *test) \ + /* Reset error counter. */ \ + fortify_write_overflows = 0; \ + /* Copy nothing into nothing: no errors. */ \ +- memfunc(zero.buf, srcB, 0 + unconst); \ ++ memfunc(empty.buf, srcB, zero); \ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \ +- memfunc(zero.buf, srcB, 1 + unconst); \ ++ memfunc(empty.buf, srcB, zero + 1); \ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); \ + } +@@ -919,7 +923,9 @@ static void fortify_test_memscan(struct kunit *test) + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + strlen("Where oh where is "); + char needle = 'm'; +- size_t len = sizeof(haystack) + unconst; ++ size_t len = sizeof(haystack); ++ ++ OPTIMIZER_HIDE_VAR(len); + + KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len), + mem); +@@ -938,7 +944,9 @@ static void fortify_test_memchr(struct kunit *test) + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + strlen("Where oh where is "); + char needle = 'm'; +- size_t len = sizeof(haystack) + unconst; ++ size_t len = sizeof(haystack); ++ ++ OPTIMIZER_HIDE_VAR(len); + + KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len), + mem); +@@ -957,7 +965,9 @@ static void fortify_test_memchr_inv(struct kunit *test) + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + 1; + char needle = 'W'; +- size_t len = sizeof(haystack) + unconst; ++ size_t len = sizeof(haystack); ++ ++ OPTIMIZER_HIDE_VAR(len); + + /* Normal search is okay. */ + KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len), +@@ -976,8 +986,11 @@ static void fortify_test_memcmp(struct kunit *test) + { + char one[] = "My mind is going ..."; + char two[] = "My mind is going ... I can feel it."; +- size_t one_len = sizeof(one) + unconst - 1; +- size_t two_len = sizeof(two) + unconst - 1; ++ size_t one_len = sizeof(one) - 1; ++ size_t two_len = sizeof(two) - 1; ++ ++ OPTIMIZER_HIDE_VAR(one_len); ++ OPTIMIZER_HIDE_VAR(two_len); + + /* We match the first string (ignoring the %NUL). */ + KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len), 0); +@@ -998,7 +1011,9 @@ static void fortify_test_kmemdup(struct kunit *test) + { + char src[] = "I got Doom running on it!"; + char *copy; +- size_t len = sizeof(src) + unconst; ++ size_t len = sizeof(src); ++ ++ OPTIMIZER_HIDE_VAR(len); + + /* Copy is within bounds. */ + copy = kmemdup(src, len, GFP_KERNEL); +-- +2.53.0 + diff --git a/queue-6.12/kvm-s390-pci-fix-aisb-calculation.patch b/queue-6.12/kvm-s390-pci-fix-aisb-calculation.patch new file mode 100644 index 0000000000..807ce5cfc4 --- /dev/null +++ b/queue-6.12/kvm-s390-pci-fix-aisb-calculation.patch @@ -0,0 +1,46 @@ +From 2bde3cfb791c7b5f9fecffd9a1a162cadc0a05aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:40:43 -0700 +Subject: KVM: s390: pci: Fix aisb calculation + +From: Matthew Rosato + +[ Upstream commit 0cfe660559e857d7c00ab86c73e4510ce069086f ] + +The current implementation of aisb calculation will erroneously index +via an unsigned long * as well as multiply by 8B for every 64-bits in +the offset; only one or the other is required. This throws off aisb +calculations once the number of devices exceeds 64, and can result +in out-of-bounds access as well as failure to indicate summary bits +associated with those devices in guests. + +Fix this by converting to a physical address before applying the +offset, as is already done in arch/s390/pci/pci_irq.c. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Signed-off-by: Matthew Rosato +Reviewed-by: Niklas Schnelle +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolved merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index 61489016e4252..d9fcbf41025e0 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -167,7 +167,7 @@ static int kvm_zpci_set_airq(struct zpci_dev *zdev) + fib.fmt0.noi = airq_iv_end(zdev->aibv); + fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); + fib.fmt0.aibvo = 0; +- fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); ++ fib.fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8; + fib.fmt0.aisbo = zdev->aisb & 63; + fib.gd = zdev->gisa; + +-- +2.53.0 + diff --git a/queue-6.12/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch b/queue-6.12/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch new file mode 100644 index 0000000000..d5a23b9a20 --- /dev/null +++ b/queue-6.12/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch @@ -0,0 +1,141 @@ +From 4219e7334c12915f2364a06d434a3ff2092488ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:40:40 -0700 +Subject: KVM: s390: pci: Fix memory accounting for pinned/unpinned pages + +From: Farhan Ali + +[ Upstream commit 36f6999ecde3976731a8bfc0b8e667da6f593069 ] + +The account_mem() and unaccount_mem() functions call get_uid() which +increments the reference count of struct user_struct on every invocation. +But we don't decrement the count by calling free_uid(). It also +accounted/unaccounted the pages against the current->mm. But its possible +the unaccount_mem() can be called from a different process context than the +one that originally pinned the pages. + +Let's fix this by storing the pinning process user_struct and mm_struct +when accounting for pinned pages, and subsequently free these resources +when the pages are unpinned. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Christian Borntraeger +Reviewed-by: Matthew Rosato +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +[borntraeger@linux.ibm.com: Fixed whitespace] +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolve merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 48 ++++++++++++++++++++++++++++++++------------- + arch/s390/kvm/pci.h | 2 ++ + 2 files changed, 36 insertions(+), 14 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index 17fedfc7bb990..f887e11b0f1ef 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -191,34 +191,54 @@ static int kvm_zpci_clear_airq(struct zpci_dev *zdev) + return cc ? -EIO : 0; + } + +-static inline void unaccount_mem(unsigned long nr_pages) ++static inline void unaccount_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) + { +- struct user_struct *user = get_uid(current_user()); ++ struct user_struct *user = kzdev->user_account; ++ struct mm_struct *mm_account = kzdev->mm_account; + +- if (user) ++ if (user) { + atomic_long_sub(nr_pages, &user->locked_vm); +- if (current->mm) +- atomic64_sub(nr_pages, ¤t->mm->pinned_vm); ++ free_uid(user); ++ kzdev->user_account = NULL; ++ } ++ ++ if (mm_account) { ++ atomic64_sub(nr_pages, &mm_account->pinned_vm); ++ mmdrop(mm_account); ++ kzdev->mm_account = NULL; ++ } + } + +-static inline int account_mem(unsigned long nr_pages) ++static inline int account_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) + { + struct user_struct *user = get_uid(current_user()); + unsigned long page_limit, cur_pages, new_pages; ++ int rc = 0; + + page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + ++ cur_pages = atomic_long_read(&user->locked_vm); + do { +- cur_pages = atomic_long_read(&user->locked_vm); + new_pages = cur_pages + nr_pages; +- if (new_pages > page_limit) +- return -ENOMEM; +- } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, +- new_pages) != cur_pages); ++ if (new_pages > page_limit) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages)); ++ ++ if (current->mm) { ++ mmgrab(current->mm); ++ atomic64_add(nr_pages, ¤t->mm->pinned_vm); ++ } + +- atomic64_add(nr_pages, ¤t->mm->pinned_vm); ++ kzdev->user_account = user; ++ kzdev->mm_account = current->mm; + + return 0; ++ ++out: ++ free_uid(user); ++ return rc; + } + + static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, +@@ -295,7 +315,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + } + + /* Account for pinned pages, roll back on failure */ +- if (account_mem(pcount)) ++ if (account_mem(zdev->kzdev, pcount)) + goto unpin2; + + /* AISB must be allocated before we can fill in GAITE */ +@@ -424,7 +444,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) + pcount++; + } + if (pcount > 0) +- unaccount_mem(pcount); ++ unaccount_mem(kzdev, pcount); + out: + mutex_unlock(&aift->aift_lock); + +diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h +index ff0972dd5e71d..fdf8c7bf4ed08 100644 +--- a/arch/s390/kvm/pci.h ++++ b/arch/s390/kvm/pci.h +@@ -22,6 +22,8 @@ struct kvm_zdev { + struct kvm *kvm; + struct zpci_fib fib; + struct list_head entry; ++ struct user_struct *user_account; ++ struct mm_struct *mm_account; + }; + + struct zpci_gaite { +-- +2.53.0 + diff --git a/queue-6.12/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch b/queue-6.12/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch new file mode 100644 index 0000000000..ee4c0e5976 --- /dev/null +++ b/queue-6.12/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch @@ -0,0 +1,64 @@ +From 196a5df95aa1e38075ffc7dfed0873dfed5d4b57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:40:41 -0700 +Subject: KVM: s390: pci: Fix missing error codes and memory unaccounting + +From: Farhan Ali + +[ Upstream commit f86842e4d6c482300f4567f492d512c9ccf5bc4f ] + +In kvm_s390_pci_aif_enable() two error paths failed to set an error code, +causing the function to return 0 on failure. It also failed to rollback +memory accounting on failure. Fix both by propagating an error code on +failure and calling unaccount_mem() in the cleanup path. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Christian Borntraeger +Reviewed-by: Matthew Rosato +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolve merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index f887e11b0f1ef..a20fa27fa0301 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -315,14 +315,17 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + } + + /* Account for pinned pages, roll back on failure */ +- if (account_mem(zdev->kzdev, pcount)) ++ rc = account_mem(zdev->kzdev, pcount); ++ if (rc) + goto unpin2; + + /* AISB must be allocated before we can fill in GAITE */ + mutex_lock(&aift->aift_lock); + bit = airq_iv_alloc_bit(aift->sbv); +- if (bit == -1UL) ++ if (bit == -1UL) { ++ rc = -ENOMEM; + goto unlock; ++ } + zdev->aisb = bit; /* store the summary bit number */ + zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | + AIRQ_IV_BITLOCK | +@@ -374,6 +377,8 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + airq_iv_free_bit(aift->sbv, zdev->aisb); + zdev->aisb = 0; + unlock: ++ if (pcount > 0) ++ unaccount_mem(zdev->kzdev, pcount); + mutex_unlock(&aift->aift_lock); + unpin2: + if (fib->fmt0.sum == 1) +-- +2.53.0 + diff --git a/queue-6.12/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch b/queue-6.12/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch new file mode 100644 index 0000000000..9cd8eaf46a --- /dev/null +++ b/queue-6.12/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch @@ -0,0 +1,82 @@ +From 4e07fad4c0589670e5f539c1f6e51b6d58d4e34e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:40:42 -0700 +Subject: KVM: s390: pci: Fix resource leak on IRQ registration failure + +From: Farhan Ali + +[ Upstream commit 5580c9858f1e00f60191eb09c3add359836d60b6 ] + +Currently if kvm_zpci_set_airq() fails, kvm_s390_pci_aif_enable() returns +the error code but doesn't do any resource cleanup thus leaking resources. +Fix this by cleaning up all the resources such as the GAITE, AIBV, AISB and +unpinning any pinned pages. While at it, remove dead code that stored FIB +values that were never referenced. + +As part of the cleanup, we are also holding the aift_lock a bit longer, as +we hold the lock while executing the MPCIFC instruction. Though this is not +strictly necessary, it means we don't have to drop and re-acquire in the +error case. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Matthew Rosato +Reviewed-by: Christian Borntraeger +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolved merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index a20fa27fa0301..61489016e4252 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -359,19 +359,32 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + aift->kzdev[zdev->aisb] = zdev->kzdev; + spin_unlock_irq(&aift->gait_lock); + +- /* Update guest FIB for re-issue */ +- fib->fmt0.aisbo = zdev->aisb & 63; +- fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); +- fib->fmt0.isc = gisc; +- + /* Save some guest fib values in the host for later use */ +- zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc; ++ zdev->kzdev->fib.fmt0.isc = gisc; + zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv; +- mutex_unlock(&aift->aift_lock); + + /* Issue the clp to setup the irq now */ + rc = kvm_zpci_set_airq(zdev); +- return rc; ++ if (!rc) { ++ mutex_unlock(&aift->aift_lock); ++ return rc; ++ } ++ ++ /* Start cleanup */ ++ zdev->kzdev->fib.fmt0.isc = 0; ++ zdev->kzdev->fib.fmt0.aibv = 0; ++ ++ spin_lock_irq(&aift->gait_lock); ++ gaite->count--; ++ gaite->aisb = 0; ++ gaite->gisc = 0; ++ gaite->aisbo = 0; ++ gaite->gisa = 0; ++ aift->kzdev[zdev->aisb] = NULL; ++ spin_unlock_irq(&aift->gait_lock); ++ ++ airq_iv_release(zdev->aibv); ++ zdev->aibv = NULL; + + free_aisb: + airq_iv_free_bit(aift->sbv, zdev->aisb); +-- +2.53.0 + diff --git a/queue-6.12/kvm-svm-add-support-to-initialize-sev-snp-functional.patch b/queue-6.12/kvm-svm-add-support-to-initialize-sev-snp-functional.patch new file mode 100644 index 0000000000..0e8ac99897 --- /dev/null +++ b/queue-6.12/kvm-svm-add-support-to-initialize-sev-snp-functional.patch @@ -0,0 +1,73 @@ +From ac4cd9858f3ef5835ce96e798c9bde8de6797151 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 12:02:55 +0200 +Subject: KVM: SVM: Add support to initialize SEV/SNP functionality in KVM + +From: Ashish Kalra + +commit 6f1d5a3513c2370bbd6115dd430906bc2f4bdc53 upstream. + +Move platform initialization of SEV/SNP from CCP driver probe time to +KVM module load time so that KVM can do SEV/SNP platform initialization +explicitly if it actually wants to use SEV/SNP functionality. + +Add support for KVM to explicitly call into the CCP driver at load time +to initialize SEV/SNP. If required, this behavior can be altered with KVM +module parameters to not do SEV/SNP platform initialization at module load +time. Additionally, a corresponding SEV/SNP platform shutdown is invoked +during KVM module unload time. + +Continue to support SEV deferred initialization as the user may have the +file containing SEV persistent data for SEV INIT_EX available only later +after module load/init. + +Suggested-by: Sean Christopherson +Reviewed-by: Tom Lendacky +Signed-off-by: Ashish Kalra +Signed-off-by: Herbert Xu +Signed-off-by: Jack Wang +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/svm/sev.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c +index 6cec696461da2..bd0344bacaf1e 100644 +--- a/arch/x86/kvm/svm/sev.c ++++ b/arch/x86/kvm/svm/sev.c +@@ -2972,6 +2972,7 @@ void __init sev_set_cpu_caps(void) + void __init sev_hardware_setup(void) + { + unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count; ++ struct sev_platform_init_args init_args = {0}; + bool sev_snp_supported = false; + bool sev_es_supported = false; + bool sev_supported = false; +@@ -3088,6 +3089,15 @@ void __init sev_hardware_setup(void) + sev_supported_vmsa_features = 0; + if (sev_es_debug_swap_enabled) + sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; ++ ++ if (!sev_enabled) ++ return; ++ ++ /* ++ * Do both SNP and SEV initialization at KVM module load. ++ */ ++ init_args.probe = true; ++ sev_platform_init(&init_args); + } + + void sev_hardware_unsetup(void) +@@ -3103,6 +3113,8 @@ void sev_hardware_unsetup(void) + + misc_cg_set_capacity(MISC_CG_RES_SEV, 0); + misc_cg_set_capacity(MISC_CG_RES_SEV_ES, 0); ++ ++ sev_platform_shutdown(); + } + + int sev_cpu_init(struct svm_cpu_data *sd) +-- +2.53.0 + diff --git a/queue-6.12/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch b/queue-6.12/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch new file mode 100644 index 0000000000..03c808003c --- /dev/null +++ b/queue-6.12/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch @@ -0,0 +1,63 @@ +From 8469211c0b8e0aa204e2aaa813eab35fef62aaac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 17:35:52 +0300 +Subject: pinctrl: renesas: rzg2l: Use -ENOTSUPP instead of -EOPNOTSUPP + +From: Claudiu Beznea + +commit c1492da3939c89372929e062d731f328f7693f1e upstream. + +The pinctrl and GPIO core code make exceptions for the -ENOTSUPP error +code. One such example is gpio_set_config_with_argument_optional(), +which returns success when gpio_set_config_with_argument() returns +-ENOTSUPP, but reports failure for all other error codes. + +Returning -EOPNOTSUPP from the pinctrl driver on the unsupported pinctrl +operation may lead to boot failures when pinctrl drivers implements +struct gpio_chip::set_config, the system uses GPIO hogs, and the +struct gpio_chip::set_config implementation returns -EOPNOTSUPP for the +unsupported operations. + +Return -ENOTSUPP for the unsupported pinctrl operation. + +Fixes: 560c633d378a ("pinctrl: renesas: rzg2l: Drop oen_read and oen_write callbacks") +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Cc: stable@vger.kernel.org +Signed-off-by: Claudiu Beznea +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Geert Uytterhoeven +Tested-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260515124008.2947838-2-claudiu.beznea@kernel.org +Signed-off-by: Geert Uytterhoeven +[claudiu.beznea: fixed conflict by keeping the code v6.12 stable] +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index 17e27879fd623..6fd79907f17e9 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -1478,7 +1478,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, + break; + + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + } + +@@ -1560,7 +1560,7 @@ static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, + + /* Check config matching between to pin */ + if (i && prev_config != *config) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + prev_config = *config; + } +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 5ae93fd6d0..4606336adb 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -83,3 +83,19 @@ vt-add-permission-check-for-kdskbmeta-ioctl.patch vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch ima-fix-out-of-bounds-read-in-xattr_verify.patch +kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch +kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch +kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch +kvm-s390-pci-fix-aisb-calculation.patch +block-reorder-the-request-allocation-code-in-blk_mq_.patch +blk-mq-pop-cached-request-if-it-is-usable.patch +blk-mq-reinsert-cached-request-to-the-list.patch +dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch +crypto-ccp-add-new-sev-snp-platform-shutdown-api.patch +kvm-svm-add-support-to-initialize-sev-snp-functional.patch +crypto-ccp-fix-checks-for-snp_vlek_load-input-buffer.patch +crypto-ccp-abort-doing-sev-init-if-snp-init-fails.patch +futex-prevent-robust-futex-exit-race-some-more.patch +kunit-fortify-replace-volatile-with-optimizer_hide_v.patch +kunit-fortify-add-back-volatile-for-sizeof-constants.patch +pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch diff --git a/queue-6.18/blk-mq-pop-cached-request-if-it-is-usable.patch b/queue-6.18/blk-mq-pop-cached-request-if-it-is-usable.patch new file mode 100644 index 0000000000..f70a99c0ea --- /dev/null +++ b/queue-6.18/blk-mq-pop-cached-request-if-it-is-usable.patch @@ -0,0 +1,120 @@ +From 242b03f5a347db46357046f8b6828766bb1d2f16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 11:25:44 +0000 +Subject: blk-mq: pop cached request if it is usable + +From: Keith Busch + +[ Upstream commit dc278e9bf2b9513a763353e6b9cc21e0f532954e ] + +When submitting a bio to blk-mq, if the task should sleep after peeking +a cached request, but before it pops it, the plug flushes and calls +blk_mq_free_plug_rqs, freeing the cached_rqs. This creates a +use-after-free bug. Fix this by popping the cached request before any +possible blocking calls if it is suitable for use. + +Popping this request first holds a queue reference, so avoid any +serialization races with queue freezes and can safely proceed with +dispatching that request to the driver. This potentially increases a +timing window from when a driver wants to freeze its queue to when +requests stop being dispatched. That scenario is off the fast path +though, and drivers need to appropriately handle requests during a +freeze request anyway. + +The downside is the popped element needs to be individually freed when +we performed a bio plug merge. The cached request would have had to be +freed later anyway, but this patch does it inline with building the plug +list instead of after flushing it. + +Fixes: b0077e269f6c1 ("blk-mq: make sure active queue usage is held for bio_integrity_prep()") +Fixes: 7b4f36cd22a65 ("block: ensure we hold a queue reference when using queue limits") +Signed-off-by: Keith Busch +Link: https://patch.msgid.link/20260521190253.242065-1-kbusch@meta.com +Signed-off-by: Jens Axboe +Signed-off-by: Simon Liebold +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 34 +++++++++------------------------- + 1 file changed, 9 insertions(+), 25 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index ab05c5c9e6ae2..711d295d36db9 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3057,7 +3057,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q, + /* + * Check if there is a suitable cached request and return it. + */ +-static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, ++static struct request *blk_mq_get_cached_request(struct blk_plug *plug, + struct request_queue *q, blk_opf_t opf) + { + enum hctx_type type = blk_mq_get_hctx_type(opf); +@@ -3073,27 +3073,10 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, + return NULL; + if (op_is_flush(rq->cmd_flags) != op_is_flush(opf)) + return NULL; ++ rq_list_pop(&plug->cached_rqs); + return rq; + } + +-static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug, +- struct bio *bio) +-{ +- if (rq_list_pop(&plug->cached_rqs) != rq) +- WARN_ON_ONCE(1); +- +- /* +- * If any qos ->throttle() end up blocking, we will have flushed the +- * plug and hence killed the cached_rq list as well. Pop this entry +- * before we throttle. +- */ +- rq_qos_throttle(rq->q, bio); +- +- blk_mq_rq_time_init(rq, blk_time_get_ns()); +- rq->cmd_flags = bio->bi_opf; +- INIT_LIST_HEAD(&rq->queuelist); +-} +- + static bool bio_unaligned(const struct bio *bio, struct request_queue *q) + { + unsigned int bs_mask = queue_logical_block_size(q) - 1; +@@ -3131,7 +3114,7 @@ void blk_mq_submit_bio(struct bio *bio) + /* + * If the plug has a cached request for this queue, try to use it. + */ +- rq = blk_mq_peek_cached_request(plug, q, bio->bi_opf); ++ rq = blk_mq_get_cached_request(plug, q, bio->bi_opf); + + /* + * A BIO that was released from a zone write plug has already been +@@ -3189,7 +3172,10 @@ void blk_mq_submit_bio(struct bio *bio) + + new_request: + if (rq) { +- blk_mq_use_cached_rq(rq, plug, bio); ++ rq_qos_throttle(rq->q, bio); ++ blk_mq_rq_time_init(rq, blk_time_get_ns()); ++ rq->cmd_flags = bio->bi_opf; ++ INIT_LIST_HEAD(&rq->queuelist); + } else { + rq = blk_mq_get_new_requests(q, plug, bio); + if (unlikely(!rq)) { +@@ -3235,12 +3221,10 @@ void blk_mq_submit_bio(struct bio *bio) + return; + + queue_exit: +- /* +- * Don't drop the queue reference if we were trying to use a cached +- * request and thus didn't acquire one. +- */ + if (!rq) + blk_queue_exit(q); ++ else ++ blk_mq_free_request(rq); + } + + #ifdef CONFIG_BLK_MQ_STACKING +-- +2.53.0 + diff --git a/queue-6.18/blk-mq-reinsert-cached-request-to-the-list.patch b/queue-6.18/blk-mq-reinsert-cached-request-to-the-list.patch new file mode 100644 index 0000000000..f2ce47423b --- /dev/null +++ b/queue-6.18/blk-mq-reinsert-cached-request-to-the-list.patch @@ -0,0 +1,45 @@ +From ef1d3ece26b90f9387926b06621e20a31cd722ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 11:25:45 +0000 +Subject: blk-mq: reinsert cached request to the list + +From: Keith Busch + +[ Upstream commit b051bb6bf0a231117036aa607cadf55be8e63910 ] + +A previous commit removed an optimization out of caution for a scenario +that turns out not to be real: all the "queue_exit" goto's are safe to +reinsert the request into the cached_rq's plug list as they are either +from a non-blocking path, or a successful merge that already holds the +queue reference. This optimization is most needed for small sequential +workloads that successfully merge into larger requests. + +Fixes: dc278e9bf2b9 ("blk-mq: pop cached request if it is usable") +Suggested-by: Ming Lei +Suggested-by: Christoph Hellwig +Signed-off-by: Keith Busch +Reviewed-by: Chaitanya Kulkarni +Link: https://patch.msgid.link/20260526153531.2365935-1-kbusch@meta.com +Signed-off-by: Jens Axboe +Signed-off-by: Simon Liebold +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 711d295d36db9..56158b70d0c72 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3224,7 +3224,7 @@ void blk_mq_submit_bio(struct bio *bio) + if (!rq) + blk_queue_exit(q); + else +- blk_mq_free_request(rq); ++ rq_list_add_head(&plug->cached_rqs, rq); + } + + #ifdef CONFIG_BLK_MQ_STACKING +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch b/queue-6.18/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch new file mode 100644 index 0000000000..4d06933ac2 --- /dev/null +++ b/queue-6.18/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch @@ -0,0 +1,55 @@ +From 7e6bc05add108581dc85cc174c7d47fc55e66d75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Apr 2026 17:13:43 +0200 +Subject: Bluetooth: btrtl: fix RTL8761B/BU broken LE extended scan + +From: Alexej Sidorenko + +[ Upstream commit 5ead2063611ae56809b1b113ac44cef9547c81d7 ] + +RTL8761B and RTL8761BU devices report HCI version 5.1 but do not +support the LE Extended Scan commands. This causes repeated failures +with Opcode 0x2042 (LE Set Extended Scan Parameters) returning -EBUSY +when BlueZ attempts extended scanning while a connection is active. + +Set HCI_QUIRK_BROKEN_EXT_SCAN for CHIP_ID_8761B to make BlueZ fall +back to legacy LE scan commands which the firmware supports correctly. + +Tested with RTL8761BU (USB ID 0bda:a728) where the issue manifested +as continuous 'Opcode 0x2042 failed: -16' errors in dmesg whenever +a BLE connection was active. + +Signed-off-by: Alexej Sidorenko +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btrtl.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c +index a62eae7276d64..cb1c321910e2a 100644 +--- a/drivers/bluetooth/btrtl.c ++++ b/drivers/bluetooth/btrtl.c +@@ -1331,6 +1331,19 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) + if (!btrtl_dev->ic_info) + return; + ++ switch (btrtl_dev->project_id) { ++ case CHIP_ID_8761B: ++ /* RTL8761B/BU reports HCI version 5.1 but does not support ++ * the LE Extended Scan commands (Opcode 0x2042), causing ++ * repeated -EBUSY failures when BlueZ attempts extended ++ * scanning while a connection is active. ++ */ ++ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); ++ break; ++ default: ++ break; ++ } ++ + switch (btrtl_dev->ic_info->lmp_subver) { + case RTL_ROM_LMP_8703B: + /* 8723CS reports two pages for local ext features, +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch b/queue-6.18/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch new file mode 100644 index 0000000000..1f2764ca50 --- /dev/null +++ b/queue-6.18/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch @@ -0,0 +1,68 @@ +From cc17aeed470efb6479aa80ede4dc02d2cb88dc2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 14:39:34 +0200 +Subject: Bluetooth: btusb: Add TP-Link UB600 for Realtek 8761BUV + +From: Nils Helmig + +[ Upstream commit bc597f0cc44f0b173c50ee986a047219cd559ee9 ] + +Add the vendor/product ID (0x37ad, 0x0600) to usb_device_id table +for Realtek 8761BUV. + +The device info from /sys/kernel/debug/usb/devices as below. + +T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=37ad ProdID=0600 Rev= 2.00 +S: Manufacturer= +S: Product=TP-Link Bluetooth USB Adapter +S: SerialNumber=ACA7F14FD2A5 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Nils Helmig +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index cb8f14b9cae80..ea9df7dc23165 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -802,6 +802,8 @@ static const struct usb_device_id quirks_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2b89, 0x6275), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x37ad, 0x0600), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Additional Realtek 8821AE Bluetooth devices */ + { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, +-- +2.53.0 + diff --git a/queue-6.18/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch b/queue-6.18/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch new file mode 100644 index 0000000000..ab158b2f95 --- /dev/null +++ b/queue-6.18/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch @@ -0,0 +1,69 @@ +From 77f459e1dd6e9cb682c186cdd74ae2ef879ca191 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 19:27:54 +0530 +Subject: dt-bindings: crypto: qcom,ice: Fix missing power-domain and iface clk + +From: Harshal Dev + +[ Upstream commit e27264daac7d9ce892a2a5b4a864d6d9a3c9276a ] + +The DT bindings for inline-crypto engine do not specify the UFS_PHY_GDSC +power-domain and iface clock. Without enabling the iface clock and the +associated power-domain the ICE hardware cannot function correctly and +leads to unclocked hardware accesses being observed during probe. + +Extend and fix the DT bindings for inline-crypto engine by allowing +description of the iface clock and UFS_PHY_GDSC power-domain. + +This patch has been adapted from the mentioned upstream commit to drop +references to Eliza and Milos Qualcomm platforms which do not exist +on the stable tree. Thus, patch now fixes the original commit which +introduced the DT binding for Qualcomm inline-crypto engine. + +Fixes: f6ff91a47ac5 ("dt-bindings: crypto: Add Qualcomm Inline Crypto Engine") +Reviewed-by: Kuldeep Singh +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Harshal Dev +Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-1-5ccf5d7e2846@oss.qualcomm.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + .../crypto/qcom,inline-crypto-engine.yaml | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +index 08fe6a707a371..70aa5193800e5 100644 +--- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml ++++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +@@ -27,6 +27,16 @@ properties: + maxItems: 1 + + clocks: ++ minItems: 1 ++ maxItems: 2 ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: core ++ - const: iface ++ ++ power-domains: + maxItems: 1 + + required: +@@ -44,6 +54,10 @@ examples: + compatible = "qcom,sm8550-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x01d88000 0x8000>; +- clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; ++ clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, ++ <&gcc GCC_UFS_PHY_AHB_CLK>; ++ clock-names = "core", ++ "iface"; ++ power-domains = <&gcc UFS_PHY_GDSC>; + }; + ... +-- +2.53.0 + diff --git a/queue-6.18/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-6.18/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..0feb66964e --- /dev/null +++ b/queue-6.18/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,187 @@ +From 6b52c11862421d06405c7c805952b6f602f54bba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:43:28 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 85 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 58 insertions(+), 27 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index 9e7dea6fc0ccd..4f5d7d042f8e5 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -1028,8 +1028,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -1038,42 +1041,70 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: ++ * ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * In both cases the following conditions are met: ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, +- FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) { ++ futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, ++ FUTEX_BITSET_MATCH_ANY); ++ } + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-6.18/iommu-vt-d-gather-the-unmapped-range-before-freeing-.patch b/queue-6.18/iommu-vt-d-gather-the-unmapped-range-before-freeing-.patch new file mode 100644 index 0000000000..7c2602ba37 --- /dev/null +++ b/queue-6.18/iommu-vt-d-gather-the-unmapped-range-before-freeing-.patch @@ -0,0 +1,85 @@ +From 56ea04819b82fc62249435a90968dc9deae40bfb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 00:05:26 +0000 +Subject: iommu/vt-d: Gather the unmapped range before freeing its page tables + +From: Jose Fernandez (Anthropic) + +In the 6.12 and 6.18 stable trees, when an unmapped range covers a +whole page table, intel_iommu_unmap() can free that table before the +range has been invalidated. The freed table goes on gather->freelist +before the range is added to the gather. If +iommu_iotlb_gather_add_page() syncs before adding it, that sync +flushes only the earlier ranges but frees the whole freelist, that +table included. The range itself is flushed later with an empty +freelist, which means the flush is sent with the invalidation hint set +and the IOMMU may keep its paging-structure cache entry for the freed +table. DMA to the next mapping at that IOVA is then translated through +whatever the freed page holds by then, which is usually a silent wrong +translation and sometimes a DMAR fault. + +Under a userspace driver that maps and unmaps DMA buffers through VFIO +type1 continuously, this shows up as wrong data in device reads and +writes. An occasional DMAR fault on a mapped IOVA is the only thing in +the logs. With an Intel DSA engine assigned through vfio-pci, remapping +a 16 MiB buffer at a fixed IOVA and reading it through the device +returned data from the wrong pages in 280 of 400 iterations. With a +fresh IOVA per iteration it never did. + +Add the range to the gather first and splice the freed tables into +gather->freelist afterwards, so that they are only freed by a sync that +also invalidates their range. + +Mainline removed this code in v6.19 with commit d373449d8e97 +("iommu/vt-d: Use the generic iommu page table") and is not affected. + +Fixes: 2a2b8eaa5b25 ("iommu: Handle freelists when using deferred flushing in iommu drivers") +Cc: stable@vger.kernel.org # 6.12.y, 6.18.y +Reported-by: Mohammed Almaroof +Reviewed-by: Ben Cressey +Assisted-by: Claude:unspecified +Signed-off-by: Jose Fernandez (Anthropic) +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/iommu.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index cee1851b69245..8b38c65f403b2 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -3620,6 +3620,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain, + unsigned long iova, size_t size, + struct iommu_iotlb_gather *gather) + { ++ struct iommu_pages_list freelist = IOMMU_PAGES_LIST_INIT(freelist); + struct dmar_domain *dmar_domain = to_dmar_domain(domain); + unsigned long start_pfn, last_pfn; + int level = 0; +@@ -3636,7 +3637,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain, + start_pfn = iova >> VTD_PAGE_SHIFT; + last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT; + +- domain_unmap(dmar_domain, start_pfn, last_pfn, &gather->freelist); ++ domain_unmap(dmar_domain, start_pfn, last_pfn, &freelist); + + if (dmar_domain->max_addr == iova + size) + dmar_domain->max_addr = iova; +@@ -3648,6 +3649,14 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain, + if (!iommu_iotlb_gather_queued(gather)) + iommu_iotlb_gather_add_page(domain, gather, iova, size); + ++ /* ++ * iommu_iotlb_gather_add_page() may have synced, which frees ++ * gather->freelist. Hand this range's page tables over only after ++ * that call. A queued gather frees them from the flush queue ++ * instead. ++ */ ++ iommu_pages_list_splice(&freelist, &gather->freelist); ++ + return size; + } + +-- +2.53.0 + diff --git a/queue-6.18/kvm-s390-pci-fix-aisb-calculation.patch b/queue-6.18/kvm-s390-pci-fix-aisb-calculation.patch new file mode 100644 index 0000000000..dff147ced3 --- /dev/null +++ b/queue-6.18/kvm-s390-pci-fix-aisb-calculation.patch @@ -0,0 +1,46 @@ +From 23abc656c5ff95b7cdcfcdca6c1a123b4ea47a1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 13:37:29 -0700 +Subject: KVM: s390: pci: Fix aisb calculation + +From: Matthew Rosato + +[ Upstream commit 0cfe660559e857d7c00ab86c73e4510ce069086f ] + +The current implementation of aisb calculation will erroneously index +via an unsigned long * as well as multiply by 8B for every 64-bits in +the offset; only one or the other is required. This throws off aisb +calculations once the number of devices exceeds 64, and can result +in out-of-bounds access as well as failure to indicate summary bits +associated with those devices in guests. + +Fix this by converting to a physical address before applying the +offset, as is already done in arch/s390/pci/pci_irq.c. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Signed-off-by: Matthew Rosato +Reviewed-by: Niklas Schnelle +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolved merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index b729457d30167..2ac7e13640931 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -167,7 +167,7 @@ static int kvm_zpci_set_airq(struct zpci_dev *zdev) + fib.fmt0.noi = airq_iv_end(zdev->aibv); + fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); + fib.fmt0.aibvo = 0; +- fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); ++ fib.fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8; + fib.fmt0.aisbo = zdev->aisb & 63; + fib.gd = zdev->gisa; + +-- +2.53.0 + diff --git a/queue-6.18/netfilter-nf_tables-avoid-softlockup-warnings-in-nft.patch b/queue-6.18/netfilter-nf_tables-avoid-softlockup-warnings-in-nft.patch new file mode 100644 index 0000000000..bbad805d7d --- /dev/null +++ b/queue-6.18/netfilter-nf_tables-avoid-softlockup-warnings-in-nft.patch @@ -0,0 +1,46 @@ +From a93dfd5081ca5bcd6adf3c41ad93af2b98b34bfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 12:55:19 +0100 +Subject: netfilter: nf_tables: avoid softlockup warnings in nft_chain_validate + +From: Florian Westphal + +[ Upstream commit 7e7a817f2dfd79098a706ee5581ea9518b2de878 ] + +This reverts commit +314c82841602 ("netfilter: nf_tables: can't schedule in nft_chain_validate"): +Since commit a60a5abe19d6 ("netfilter: nf_tables: allow iter callbacks to sleep") +the iterator callback is invoked without rcu read lock held, so this +cond_resched() is now valid. + +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index ca6d2041eee66..db939e1988009 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4080,6 +4080,8 @@ int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain) + if (err < 0) + return err; + } ++ ++ cond_resched(); + } + + nft_chain_vstate_update(ctx, chain); +@@ -4104,8 +4106,6 @@ static int nft_table_validate(struct net *net, const struct nft_table *table) + err = nft_chain_validate(&ctx, chain); + if (err < 0) + goto err; +- +- cond_resched(); + } + + err: +-- +2.53.0 + diff --git a/queue-6.18/revert-drm-amd-display-fix-backlight-max_brightness-.patch b/queue-6.18/revert-drm-amd-display-fix-backlight-max_brightness-.patch new file mode 100644 index 0000000000..87c57638ca --- /dev/null +++ b/queue-6.18/revert-drm-amd-display-fix-backlight-max_brightness-.patch @@ -0,0 +1,48 @@ +From 0da8faaf841ae3b9338409e236e66a1bbf344bd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 10:49:01 -0400 +Subject: Revert "drm/amd/display: Fix backlight max_brightness to match + exported range" + +From: Alex Deucher + +This reverts commit 490ceacd2162de919a142bcb4eff363bb493b1de. + +This patch is apparently missing a dependency from 7.2 as users have not +reported any regressions with 7.2-rc, but there are regressions on 6.18. + +The regression manifests as inconsistent lower brightness at the top end +(e.g., around 98%). + +Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5562 +Signed-off-by: Alex Deucher +Cc: Thorsten Leemhuis +Cc: Sergio Callegari +Cc: Mario Limonciello +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 4f53297786623..fd5a6c6532a1e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5222,11 +5222,11 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) + caps = &dm->backlight_caps[aconnector->bl_idx]; + if (get_brightness_range(caps, &min, &max)) { + if (power_supply_is_system_supplied() > 0) +- props.brightness = DIV_ROUND_CLOSEST(max * caps->ac_level, 100); ++ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100); + else +- props.brightness = DIV_ROUND_CLOSEST(max * caps->dc_level, 100); ++ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100); + /* min is zero, so max needs to be adjusted */ +- props.max_brightness = max; ++ props.max_brightness = max - min; + drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max, + caps->ac_level, caps->dc_level); + } else +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index a2fe9fd6cc..c47cecae67 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -125,3 +125,13 @@ vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch mm-vmalloc-acquire-init_mm-lock-on-huge-vmap-to-avoid-ptdump-uaf.patch ima-fix-out-of-bounds-read-in-xattr_verify.patch +revert-drm-amd-display-fix-backlight-max_brightness-.patch +blk-mq-pop-cached-request-if-it-is-usable.patch +blk-mq-reinsert-cached-request-to-the-list.patch +kvm-s390-pci-fix-aisb-calculation.patch +dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch +iommu-vt-d-gather-the-unmapped-range-before-freeing-.patch +futex-prevent-robust-futex-exit-race-some-more.patch +netfilter-nf_tables-avoid-softlockup-warnings-in-nft.patch +bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch +bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch diff --git a/queue-6.6/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch b/queue-6.6/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch new file mode 100644 index 0000000000..fc26361b5d --- /dev/null +++ b/queue-6.6/dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch @@ -0,0 +1,69 @@ +From 9dc0c7a767276bcd0d4d20af78ccc636aaa2cbe9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 19:18:10 +0530 +Subject: dt-bindings: crypto: qcom,ice: Fix missing power-domain and iface clk + +From: Harshal Dev + +[ Upstream commit e27264daac7d9ce892a2a5b4a864d6d9a3c9276a ] + +The DT bindings for inline-crypto engine do not specify the UFS_PHY_GDSC +power-domain and iface clock. Without enabling the iface clock and the +associated power-domain the ICE hardware cannot function correctly and +leads to unclocked hardware accesses being observed during probe. + +Extend and fix the DT bindings for inline-crypto engine by allowing +description of the iface clock and UFS_PHY_GDSC power-domain. + +This patch has been adapted from the mentioned upstream commit to drop +references to Eliza and Milos Qualcomm platforms which do not exist +on the stable tree. Thus, patch now fixes the original commit which +introduced the DT binding for Qualcomm inline-crypto engine. + +Fixes: f6ff91a47ac5 ("dt-bindings: crypto: Add Qualcomm Inline Crypto Engine") +Reviewed-by: Kuldeep Singh +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Harshal Dev +Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-1-5ccf5d7e2846@oss.qualcomm.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + .../crypto/qcom,inline-crypto-engine.yaml | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +index 7da9aa82d8374..69731ff62c653 100644 +--- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml ++++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +@@ -21,6 +21,16 @@ properties: + maxItems: 1 + + clocks: ++ minItems: 1 ++ maxItems: 2 ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: core ++ - const: iface ++ ++ power-domains: + maxItems: 1 + + required: +@@ -38,6 +48,10 @@ examples: + compatible = "qcom,sm8550-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x01d88000 0x8000>; +- clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; ++ clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, ++ <&gcc GCC_UFS_PHY_AHB_CLK>; ++ clock-names = "core", ++ "iface"; ++ power-domains = <&gcc UFS_PHY_GDSC>; + }; + ... +-- +2.53.0 + diff --git a/queue-6.6/fortify-disable-wstringop-overread-in-tests.patch b/queue-6.6/fortify-disable-wstringop-overread-in-tests.patch new file mode 100644 index 0000000000..c3c321b18f --- /dev/null +++ b/queue-6.6/fortify-disable-wstringop-overread-in-tests.patch @@ -0,0 +1,61 @@ +From 80b851381e0ddec07a75eb8faee4a02af466cfe5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 13:23:46 -0700 +Subject: fortify: Disable -Wstringop-overread in tests + +From: Nathan Chancellor + +commit c1f3e770eec26d6f96dd6d2ea30555ba7c09a244 upstream. + +clang recently added support for -Wstringop-overread [1], which is on by +default like -Wfortify-source. This breaks the usage of -Werror in the +fortify tests, resulting in the following false positive warnings in the +kernel build: + + warning: unsafe memcmp() usage lacked '__read_overflow2' warning in lib/test_fortify/read_overflow2-memcmp.c + warning: unsafe memcmp() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memcmp.c + warning: unsafe memchr() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memchr.c + +Examining the fortify test logs shows a warning like the following in +each of the failed logs: + + In file included from lib/test_fortify/read_overflow2-memcmp.c:5: + lib/test_fortify/test_fortify.h:34:2: error: 'memcmp' reading 17 bytes from a region of size 16 [-Werror,-Wstringop-overread] + 34 | TEST; + | ^ + lib/test_fortify/read_overflow2-memcmp.c:3:2: note: expanded from macro 'TEST' + 3 | memcmp(large, small, sizeof(small) + 1) + | ^ + 1 error generated. + +Disable -Wstringop-overread for the fortify tests, as it defeats the +purpose of testing the Linux specific implementation of fortify, like +-Wfortify-source. + +Cc: stable@vger.kernel.org +Closes: https://github.com/ClangBuiltLinux/linux/issues/2168 +Link: https://github.com/llvm/llvm-project/commit/86f2e71cb8d165b59ad31a442b2391e23826133e [1] +Signed-off-by: Nathan Chancellor +Link: https://patch.msgid.link/20260623-fix-test_fortify-for-clang-stringop-overread-v1-1-15ee8342a953@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/test_fortify/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/test_fortify/Makefile b/lib/test_fortify/Makefile +index 7887e6126e79c..eba2ba0faeb6a 100644 +--- a/lib/test_fortify/Makefile ++++ b/lib/test_fortify/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + + ccflags-y := $(call cc-disable-warning,fortify-source) ++ccflags-y += $(call cc-disable-warning,stringop-overread) + + quiet_cmd_test_fortify = TEST $@ + cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ +-- +2.53.0 + diff --git a/queue-6.6/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch b/queue-6.6/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch new file mode 100644 index 0000000000..276eca1e39 --- /dev/null +++ b/queue-6.6/fortify-refactor-test_fortify-makefile-to-fix-some-b.patch @@ -0,0 +1,175 @@ +From 31788c44cf17ecde22381cd9b8c6df8e09969811 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Jul 2024 00:02:36 +0900 +Subject: fortify: refactor test_fortify Makefile to fix some build problems + +From: Masahiro Yamada + +commit 4e9903b0861c9df3464b82db4a7025863bac1897 upstream. + +There are some issues in the test_fortify Makefile code. + +Problem 1: cc-disable-warning invokes compiler dozens of times + +To see how many times the cc-disable-warning is evaluated, change +this code: + + $(call cc-disable-warning,fortify-source) + +to: + + $(call cc-disable-warning,$(shell touch /tmp/fortify-$$$$)fortify-source) + +Then, build the kernel with CONFIG_FORTIFY_SOURCE=y. You will see a +large number of '/tmp/fortify-' files created: + + $ ls -1 /tmp/fortify-* | wc + 80 80 1600 + +This means the compiler was invoked 80 times just for checking the +-Wno-fortify-source flag support. + +$(call cc-disable-warning,fortify-source) should be added to a simple +variable instead of a recursive variable. + +Problem 2: do not recompile string.o when the test code is updated + +The test cases are independent of the kernel. However, when the test +code is updated, $(obj)/string.o is rebuilt and vmlinux is relinked +due to this dependency: + + $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) + +always-y is suitable for building the log files. + +Problem 3: redundant code + + clean-files += $(addsuffix .o, $(TEST_FORTIFY_LOGS)) + +... is unneeded because the top Makefile globally cleans *.o files. + +This commit fixes these issues and makes the code readable. + +Signed-off-by: Masahiro Yamada +Link: https://lore.kernel.org/r/20240727150302.1823750-2-masahiroy@kernel.org +Signed-off-by: Kees Cook +[nathan: Fixed conflicts] +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + lib/.gitignore | 2 -- + lib/Makefile | 34 +--------------------------------- + lib/test_fortify/.gitignore | 2 ++ + lib/test_fortify/Makefile | 28 ++++++++++++++++++++++++++++ + scripts/remove-stale-files | 2 ++ + 5 files changed, 33 insertions(+), 35 deletions(-) + create mode 100644 lib/test_fortify/.gitignore + create mode 100644 lib/test_fortify/Makefile + +diff --git a/lib/.gitignore b/lib/.gitignore +index 54596b634ecbf..101a4aa92fb53 100644 +--- a/lib/.gitignore ++++ b/lib/.gitignore +@@ -5,5 +5,3 @@ + /gen_crc32table + /gen_crc64table + /oid_registry_data.c +-/test_fortify.log +-/test_fortify/*.log +diff --git a/lib/Makefile b/lib/Makefile +index b9d2577fbbe19..62737ad5aa74e 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -407,36 +407,4 @@ CFLAGS_longest_symbol_kunit.o += $(call cc-disable-warning, missing-prototypes) + + obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o + +-# FORTIFY_SOURCE compile-time behavior tests +-TEST_FORTIFY_SRCS = $(wildcard $(srctree)/$(src)/test_fortify/*-*.c) +-TEST_FORTIFY_LOGS = $(patsubst $(srctree)/$(src)/%.c, %.log, $(TEST_FORTIFY_SRCS)) +-TEST_FORTIFY_LOG = test_fortify.log +- +-quiet_cmd_test_fortify = TEST $@ +- cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ +- $< $@ "$(NM)" $(CC) $(c_flags) \ +- $(call cc-disable-warning,fortify-source) \ +- -DKBUILD_EXTRA_WARN1 +- +-targets += $(TEST_FORTIFY_LOGS) +-clean-files += $(TEST_FORTIFY_LOGS) +-clean-files += $(addsuffix .o, $(TEST_FORTIFY_LOGS)) +-$(obj)/test_fortify/%.log: $(src)/test_fortify/%.c \ +- $(src)/test_fortify/test_fortify.h \ +- $(srctree)/include/linux/fortify-string.h \ +- $(srctree)/scripts/test_fortify.sh \ +- FORCE +- $(call if_changed,test_fortify) +- +-quiet_cmd_gen_fortify_log = GEN $@ +- cmd_gen_fortify_log = cat /dev/null > $@ || true +- +-targets += $(TEST_FORTIFY_LOG) +-clean-files += $(TEST_FORTIFY_LOG) +-$(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE +- $(call if_changed,gen_fortify_log) +- +-# Fake dependency to trigger the fortify tests. +-ifeq ($(CONFIG_FORTIFY_SOURCE),y) +-$(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) +-endif ++subdir-$(CONFIG_FORTIFY_SOURCE) += test_fortify +diff --git a/lib/test_fortify/.gitignore b/lib/test_fortify/.gitignore +new file mode 100644 +index 0000000000000..c1ba37d14b50e +--- /dev/null ++++ b/lib/test_fortify/.gitignore +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++/*.log +diff --git a/lib/test_fortify/Makefile b/lib/test_fortify/Makefile +new file mode 100644 +index 0000000000000..7887e6126e79c +--- /dev/null ++++ b/lib/test_fortify/Makefile +@@ -0,0 +1,28 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++ccflags-y := $(call cc-disable-warning,fortify-source) ++ ++quiet_cmd_test_fortify = TEST $@ ++ cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \ ++ $< $@ "$(NM)" $(CC) $(c_flags) -DKBUILD_EXTRA_WARN1 ++ ++$(obj)/%.log: $(src)/%.c $(srctree)/scripts/test_fortify.sh \ ++ $(src)/test_fortify.h \ ++ $(srctree)/include/linux/fortify-string.h \ ++ FORCE ++ $(call if_changed,test_fortify) ++ ++logs = $(patsubst $(srctree)/$(src)/%.c, %.log, $(wildcard $(srctree)/$(src)/*-*.c)) ++targets += $(logs) ++ ++quiet_cmd_gen_fortify_log = CAT $@ ++ cmd_gen_fortify_log = cat $(or $(real-prereqs),/dev/null) > $@ ++ ++$(obj)/test_fortify.log: $(addprefix $(obj)/, $(logs)) FORCE ++ $(call if_changed,gen_fortify_log) ++ ++always-y += test_fortify.log ++ ++# Some architectures define __NO_FORTIFY if __SANITIZE_ADDRESS__ is undefined. ++# Pass CFLAGS_KASAN to avoid warnings. ++KASAN_SANITIZE := y +diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files +index 8b1a636f85434..38eb84eb605b6 100755 +--- a/scripts/remove-stale-files ++++ b/scripts/remove-stale-files +@@ -39,3 +39,5 @@ rm -rf include/ksym + find . -name '*.usyms' | xargs rm -f + + rm -f binkernel.spec ++ ++rm -f lib/test_fortify.log +-- +2.53.0 + diff --git a/queue-6.6/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-6.6/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..56a19bb167 --- /dev/null +++ b/queue-6.6/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,184 @@ +From c0a5ce57e6a8add71adde4086ef229ee06be7102 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:44:30 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 82 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 56 insertions(+), 26 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index f30a93e50f65e..660d7061740b8 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -660,8 +660,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -670,41 +673,68 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the following conditions are met: ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. ++ * ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) ++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-6.6/kvm-s390-pci-fix-aisb-calculation.patch b/queue-6.6/kvm-s390-pci-fix-aisb-calculation.patch new file mode 100644 index 0000000000..a59137f31d --- /dev/null +++ b/queue-6.6/kvm-s390-pci-fix-aisb-calculation.patch @@ -0,0 +1,46 @@ +From 048c84cdfaecbb9a185ad1b37a598a501f49f743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 14:24:03 -0700 +Subject: KVM: s390: pci: Fix aisb calculation + +From: Matthew Rosato + +[ Upstream commit 0cfe660559e857d7c00ab86c73e4510ce069086f ] + +The current implementation of aisb calculation will erroneously index +via an unsigned long * as well as multiply by 8B for every 64-bits in +the offset; only one or the other is required. This throws off aisb +calculations once the number of devices exceeds 64, and can result +in out-of-bounds access as well as failure to indicate summary bits +associated with those devices in guests. + +Fix this by converting to a physical address before applying the +offset, as is already done in arch/s390/pci/pci_irq.c. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Signed-off-by: Matthew Rosato +Reviewed-by: Niklas Schnelle +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolved merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index 61489016e4252..d9fcbf41025e0 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -167,7 +167,7 @@ static int kvm_zpci_set_airq(struct zpci_dev *zdev) + fib.fmt0.noi = airq_iv_end(zdev->aibv); + fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); + fib.fmt0.aibvo = 0; +- fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); ++ fib.fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8; + fib.fmt0.aisbo = zdev->aisb & 63; + fib.gd = zdev->gisa; + +-- +2.53.0 + diff --git a/queue-6.6/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch b/queue-6.6/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch new file mode 100644 index 0000000000..025721f8ae --- /dev/null +++ b/queue-6.6/kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch @@ -0,0 +1,141 @@ +From 24654c3c190b52636e4b7f26e601444e24a2641f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 14:24:00 -0700 +Subject: KVM: s390: pci: Fix memory accounting for pinned/unpinned pages + +From: Farhan Ali + +[ Upstream commit 36f6999ecde3976731a8bfc0b8e667da6f593069 ] + +The account_mem() and unaccount_mem() functions call get_uid() which +increments the reference count of struct user_struct on every invocation. +But we don't decrement the count by calling free_uid(). It also +accounted/unaccounted the pages against the current->mm. But its possible +the unaccount_mem() can be called from a different process context than the +one that originally pinned the pages. + +Let's fix this by storing the pinning process user_struct and mm_struct +when accounting for pinned pages, and subsequently free these resources +when the pages are unpinned. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Christian Borntraeger +Reviewed-by: Matthew Rosato +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +[borntraeger@linux.ibm.com: Fixed whitespace] +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolve merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 48 ++++++++++++++++++++++++++++++++------------- + arch/s390/kvm/pci.h | 2 ++ + 2 files changed, 36 insertions(+), 14 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index 17fedfc7bb990..f887e11b0f1ef 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -191,34 +191,54 @@ static int kvm_zpci_clear_airq(struct zpci_dev *zdev) + return cc ? -EIO : 0; + } + +-static inline void unaccount_mem(unsigned long nr_pages) ++static inline void unaccount_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) + { +- struct user_struct *user = get_uid(current_user()); ++ struct user_struct *user = kzdev->user_account; ++ struct mm_struct *mm_account = kzdev->mm_account; + +- if (user) ++ if (user) { + atomic_long_sub(nr_pages, &user->locked_vm); +- if (current->mm) +- atomic64_sub(nr_pages, ¤t->mm->pinned_vm); ++ free_uid(user); ++ kzdev->user_account = NULL; ++ } ++ ++ if (mm_account) { ++ atomic64_sub(nr_pages, &mm_account->pinned_vm); ++ mmdrop(mm_account); ++ kzdev->mm_account = NULL; ++ } + } + +-static inline int account_mem(unsigned long nr_pages) ++static inline int account_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) + { + struct user_struct *user = get_uid(current_user()); + unsigned long page_limit, cur_pages, new_pages; ++ int rc = 0; + + page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + ++ cur_pages = atomic_long_read(&user->locked_vm); + do { +- cur_pages = atomic_long_read(&user->locked_vm); + new_pages = cur_pages + nr_pages; +- if (new_pages > page_limit) +- return -ENOMEM; +- } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, +- new_pages) != cur_pages); ++ if (new_pages > page_limit) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages)); ++ ++ if (current->mm) { ++ mmgrab(current->mm); ++ atomic64_add(nr_pages, ¤t->mm->pinned_vm); ++ } + +- atomic64_add(nr_pages, ¤t->mm->pinned_vm); ++ kzdev->user_account = user; ++ kzdev->mm_account = current->mm; + + return 0; ++ ++out: ++ free_uid(user); ++ return rc; + } + + static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, +@@ -295,7 +315,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + } + + /* Account for pinned pages, roll back on failure */ +- if (account_mem(pcount)) ++ if (account_mem(zdev->kzdev, pcount)) + goto unpin2; + + /* AISB must be allocated before we can fill in GAITE */ +@@ -424,7 +444,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) + pcount++; + } + if (pcount > 0) +- unaccount_mem(pcount); ++ unaccount_mem(kzdev, pcount); + out: + mutex_unlock(&aift->aift_lock); + +diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h +index ff0972dd5e71d..fdf8c7bf4ed08 100644 +--- a/arch/s390/kvm/pci.h ++++ b/arch/s390/kvm/pci.h +@@ -22,6 +22,8 @@ struct kvm_zdev { + struct kvm *kvm; + struct zpci_fib fib; + struct list_head entry; ++ struct user_struct *user_account; ++ struct mm_struct *mm_account; + }; + + struct zpci_gaite { +-- +2.53.0 + diff --git a/queue-6.6/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch b/queue-6.6/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch new file mode 100644 index 0000000000..675e3e9b81 --- /dev/null +++ b/queue-6.6/kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch @@ -0,0 +1,64 @@ +From 349cb7510e20676cdf6cd79ee3634d209597a709 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 14:24:01 -0700 +Subject: KVM: s390: pci: Fix missing error codes and memory unaccounting + +From: Farhan Ali + +[ Upstream commit f86842e4d6c482300f4567f492d512c9ccf5bc4f ] + +In kvm_s390_pci_aif_enable() two error paths failed to set an error code, +causing the function to return 0 on failure. It also failed to rollback +memory accounting on failure. Fix both by propagating an error code on +failure and calling unaccount_mem() in the cleanup path. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Christian Borntraeger +Reviewed-by: Matthew Rosato +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolve merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index f887e11b0f1ef..a20fa27fa0301 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -315,14 +315,17 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + } + + /* Account for pinned pages, roll back on failure */ +- if (account_mem(zdev->kzdev, pcount)) ++ rc = account_mem(zdev->kzdev, pcount); ++ if (rc) + goto unpin2; + + /* AISB must be allocated before we can fill in GAITE */ + mutex_lock(&aift->aift_lock); + bit = airq_iv_alloc_bit(aift->sbv); +- if (bit == -1UL) ++ if (bit == -1UL) { ++ rc = -ENOMEM; + goto unlock; ++ } + zdev->aisb = bit; /* store the summary bit number */ + zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | + AIRQ_IV_BITLOCK | +@@ -374,6 +377,8 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + airq_iv_free_bit(aift->sbv, zdev->aisb); + zdev->aisb = 0; + unlock: ++ if (pcount > 0) ++ unaccount_mem(zdev->kzdev, pcount); + mutex_unlock(&aift->aift_lock); + unpin2: + if (fib->fmt0.sum == 1) +-- +2.53.0 + diff --git a/queue-6.6/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch b/queue-6.6/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch new file mode 100644 index 0000000000..7dcb9449ef --- /dev/null +++ b/queue-6.6/kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch @@ -0,0 +1,82 @@ +From 80db3265c3b10432eb1f921390a5cc27320ee91d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 14:24:02 -0700 +Subject: KVM: s390: pci: Fix resource leak on IRQ registration failure + +From: Farhan Ali + +[ Upstream commit 5580c9858f1e00f60191eb09c3add359836d60b6 ] + +Currently if kvm_zpci_set_airq() fails, kvm_s390_pci_aif_enable() returns +the error code but doesn't do any resource cleanup thus leaking resources. +Fix this by cleaning up all the resources such as the GAITE, AIBV, AISB and +unpinning any pinned pages. While at it, remove dead code that stored FIB +values that were never referenced. + +As part of the cleanup, we are also holding the aift_lock a bit longer, as +we hold the lock while executing the MPCIFC instruction. Though this is not +strictly necessary, it means we don't have to drop and re-acquire in the +error case. + +Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") +Cc: stable@vger.kernel.org +Reviewed-by: Matthew Rosato +Reviewed-by: Christian Borntraeger +Signed-off-by: Farhan Ali +Tested-by: Matthew Rosato +Signed-off-by: Christian Borntraeger +[alifm@linux.ibm.com: Resolved merge conflict] +Signed-off-by: Farhan Ali +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/pci.c | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c +index a20fa27fa0301..61489016e4252 100644 +--- a/arch/s390/kvm/pci.c ++++ b/arch/s390/kvm/pci.c +@@ -359,19 +359,32 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, + aift->kzdev[zdev->aisb] = zdev->kzdev; + spin_unlock_irq(&aift->gait_lock); + +- /* Update guest FIB for re-issue */ +- fib->fmt0.aisbo = zdev->aisb & 63; +- fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); +- fib->fmt0.isc = gisc; +- + /* Save some guest fib values in the host for later use */ +- zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc; ++ zdev->kzdev->fib.fmt0.isc = gisc; + zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv; +- mutex_unlock(&aift->aift_lock); + + /* Issue the clp to setup the irq now */ + rc = kvm_zpci_set_airq(zdev); +- return rc; ++ if (!rc) { ++ mutex_unlock(&aift->aift_lock); ++ return rc; ++ } ++ ++ /* Start cleanup */ ++ zdev->kzdev->fib.fmt0.isc = 0; ++ zdev->kzdev->fib.fmt0.aibv = 0; ++ ++ spin_lock_irq(&aift->gait_lock); ++ gaite->count--; ++ gaite->aisb = 0; ++ gaite->gisc = 0; ++ gaite->aisbo = 0; ++ gaite->gisa = 0; ++ aift->kzdev[zdev->aisb] = NULL; ++ spin_unlock_irq(&aift->gait_lock); ++ ++ airq_iv_release(zdev->aibv); ++ zdev->aibv = NULL; + + free_aisb: + airq_iv_free_bit(aift->sbv, zdev->aisb); +-- +2.53.0 + diff --git a/queue-6.6/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch b/queue-6.6/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch new file mode 100644 index 0000000000..158b87f80a --- /dev/null +++ b/queue-6.6/pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch @@ -0,0 +1,64 @@ +From 128fc6dd1a7d8b208bb27d6140c7b3342655e9a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 17:35:53 +0300 +Subject: pinctrl: renesas: rzg2l: Use -ENOTSUPP instead of -EOPNOTSUPP + +From: Claudiu Beznea + +commit c1492da3939c89372929e062d731f328f7693f1e upstream. + +The pinctrl and GPIO core code make exceptions for the -ENOTSUPP error +code. One such example is gpio_set_config_with_argument_optional(), +which returns success when gpio_set_config_with_argument() returns +-ENOTSUPP, but reports failure for all other error codes. + +Returning -EOPNOTSUPP from the pinctrl driver on the unsupported pinctrl +operation may lead to boot failures when pinctrl drivers implements +struct gpio_chip::set_config, the system uses GPIO hogs, and the +struct gpio_chip::set_config implementation returns -EOPNOTSUPP for the +unsupported operations. + +Return -ENOTSUPP for the unsupported pinctrl operation. + +Fixes: 560c633d378a ("pinctrl: renesas: rzg2l: Drop oen_read and oen_write callbacks") +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Cc: stable@vger.kernel.org +Signed-off-by: Claudiu Beznea +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Geert Uytterhoeven +Tested-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260515124008.2947838-2-claudiu.beznea@kernel.org +Signed-off-by: Geert Uytterhoeven +[claudiu.beznea: fixed conflict by dropping the code not present in + v6.6 stable] +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index ac629c72d5927..b713cc8e0fde8 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -710,7 +710,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, + } + + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + } + +@@ -759,7 +759,7 @@ static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, + + /* Check config matching between to pin */ + if (i && prev_config != *config) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + prev_config = *config; + } +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index 335c133095..74a5d66d85 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -72,3 +72,12 @@ vt-add-permission-check-for-kdskbmeta-ioctl.patch vt-stabilize-tty-reference-in-kbd_keycode-with-tty_port_tty_get.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch ima-fix-out-of-bounds-read-in-xattr_verify.patch +kvm-s390-pci-fix-memory-accounting-for-pinned-unpinn.patch +kvm-s390-pci-fix-missing-error-codes-and-memory-unac.patch +kvm-s390-pci-fix-resource-leak-on-irq-registration-f.patch +kvm-s390-pci-fix-aisb-calculation.patch +dt-bindings-crypto-qcom-ice-fix-missing-power-domain.patch +futex-prevent-robust-futex-exit-race-some-more.patch +fortify-refactor-test_fortify-makefile-to-fix-some-b.patch +fortify-disable-wstringop-overread-in-tests.patch +pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch diff --git a/queue-7.1/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch b/queue-7.1/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch new file mode 100644 index 0000000000..d6c73e0802 --- /dev/null +++ b/queue-7.1/bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch @@ -0,0 +1,55 @@ +From 63c6ce08c0ef6643b1b0dac409807840870d52dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Apr 2026 17:13:43 +0200 +Subject: Bluetooth: btrtl: fix RTL8761B/BU broken LE extended scan + +From: Alexej Sidorenko + +[ Upstream commit 5ead2063611ae56809b1b113ac44cef9547c81d7 ] + +RTL8761B and RTL8761BU devices report HCI version 5.1 but do not +support the LE Extended Scan commands. This causes repeated failures +with Opcode 0x2042 (LE Set Extended Scan Parameters) returning -EBUSY +when BlueZ attempts extended scanning while a connection is active. + +Set HCI_QUIRK_BROKEN_EXT_SCAN for CHIP_ID_8761B to make BlueZ fall +back to legacy LE scan commands which the firmware supports correctly. + +Tested with RTL8761BU (USB ID 0bda:a728) where the issue manifested +as continuous 'Opcode 0x2042 failed: -16' errors in dmesg whenever +a BLE connection was active. + +Signed-off-by: Alexej Sidorenko +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btrtl.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c +index 03fa9409e3ee4..7f54d2d2d13a0 100644 +--- a/drivers/bluetooth/btrtl.c ++++ b/drivers/bluetooth/btrtl.c +@@ -1343,6 +1343,19 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) + if (!btrtl_dev->ic_info) + return; + ++ switch (btrtl_dev->project_id) { ++ case CHIP_ID_8761B: ++ /* RTL8761B/BU reports HCI version 5.1 but does not support ++ * the LE Extended Scan commands (Opcode 0x2042), causing ++ * repeated -EBUSY failures when BlueZ attempts extended ++ * scanning while a connection is active. ++ */ ++ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); ++ break; ++ default: ++ break; ++ } ++ + switch (btrtl_dev->ic_info->lmp_subver) { + case RTL_ROM_LMP_8703B: + /* 8723CS reports two pages for local ext features, +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch b/queue-7.1/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch new file mode 100644 index 0000000000..036b2b522b --- /dev/null +++ b/queue-7.1/bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch @@ -0,0 +1,68 @@ +From 8bc845256754dec78b9910a62551b27f5a459583 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 14:39:34 +0200 +Subject: Bluetooth: btusb: Add TP-Link UB600 for Realtek 8761BUV + +From: Nils Helmig + +[ Upstream commit bc597f0cc44f0b173c50ee986a047219cd559ee9 ] + +Add the vendor/product ID (0x37ad, 0x0600) to usb_device_id table +for Realtek 8761BUV. + +The device info from /sys/kernel/debug/usb/devices as below. + +T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=37ad ProdID=0600 Rev= 2.00 +S: Manufacturer= +S: Product=TP-Link Bluetooth USB Adapter +S: SerialNumber=ACA7F14FD2A5 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Nils Helmig +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a072e6f57f31b..4a356f720e1fe 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -832,6 +832,8 @@ static const struct usb_device_id quirks_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2b89, 0x6275), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x37ad, 0x0600), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Additional Realtek 8821AE Bluetooth devices */ + { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, +-- +2.53.0 + diff --git a/queue-7.1/futex-prevent-robust-futex-exit-race-some-more.patch b/queue-7.1/futex-prevent-robust-futex-exit-race-some-more.patch new file mode 100644 index 0000000000..e9687716b5 --- /dev/null +++ b/queue-7.1/futex-prevent-robust-futex-exit-race-some-more.patch @@ -0,0 +1,187 @@ +From 41fa7fa78e4055749f5bc1ce02016a583d4a384c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Aug 2026 14:43:28 +0200 +Subject: futex: Prevent robust futex exit race some more + +From: Keno Fischer + +commit 6d4514ca9cdf61fec4ec634cf50386f6f7e69748 upstream. + +A robust futex unlock stores 0 over the whole futex value - wiping +FUTEX_WAITERS - and wakes a single waiter. That wakeup is a one-shot +notification: the protocol relies on its recipient to either acquire the +futex (and eventually unlock while aware of the remaining contention) or +re-arm FUTEX_WAITERS before sleeping again. If the woken waiter is killed +before it can do either, the kernel must jump in and wake the next task +down the line. + +This is a known complication of the futex protocol with a previous +partial fix in commit ca16d5bee598 ("futex: Prevent robust futex exit +race"). Unfortunately, that fix is insufficient. + +If a third task re-acquired the futex through the uncontended fast +path in the meantime, the notification is lost: robust exit processing +sees that it is owned by another task and does nothing, while the new +owner sees no FUTEX_WAITERS when it unlocks and wakes nobody. +The remaining waiters sleep forever behind a free futex: + + A owns the futex, B and C sleep in FUTEX_WAIT + uval == A | FUTEX_WAITERS + A robust unlock: store 0, FUTEX_WAKE(1) wakes B + uval == 0 + D fast path acquire: cmpxchg(0 -> D) + uval == D, no FUTEX_WAITERS + B killed before acting on the wakeup + B exit walk, pending op: owner D != B -> no action + D unlock: no FUTEX_WAITERS -> no wake + C sleeps forever + +This is clearly a shortcoming in the implementation, which fails to keep +the FUTEX_WAITERS bit consistent. + +Work around this by augmenting the robust list exit processing to also +perform the extra wakeup if the futex word is owned by another thread but +FUTEX_WAITERS is not set. + +This does not fix the problem of a non-contended take over/release and free +sequence, which has been discussed for years and has been addressed by +commit 3ca9595d9fb6 ("futex: Add support for unlocking robust futexes") and +subsequent changes, but failed to take the problem described above into +account. + +A more complete solution which is based on the in kernel unlock of +contended robust futexes has been discussed in the context of this change +and should show up in mainline sooner than later. + +[ tglx: Amend change log slightly and fixup coding style ] + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Keno Fischer +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Signed-off-by: Thomas Gleixner +Assisted-by: ClaudeCode:claude-fable-5 tla+ +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260730194705.38981-1-keno@juliacomputing.com +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 85 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 58 insertions(+), 27 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index ff2a4fb2993f0..6b3121c734bb5 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -1027,8 +1027,11 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + return -1; + + /* +- * Special case for regular (non PI) futexes. The unlock path in +- * user space has two race scenarios: ++ * Special case for regular (non PI) futexes. Ordinarily, we do ++ * not perform any processing here unless the current thread was ++ * the owner of the futex (by the TID check below). ++ * ++ * However, the unlock path has three race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up +@@ -1037,42 +1040,70 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * +- * In the second case, the wake up notification could be generated +- * by the unlock path in user space after setting the futex value +- * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * 3. A woken up waiter is killed in user space after another ++ * thread has acquired the futex, but before it can set ++ * FUTEX_WAITERS. ++ * ++ * Note that, if userspace uses the FUTEX_ROBUST_UNLOCK flag, we ++ * will not see case 1 here. ++ * ++ * In the second and third case, the wake up notification could ++ * be generated from any of: ++ * ++ * i. An ordinary futex wakeup after unlock (with or ++ * without FUTEX_ROBUST_UNLOCK) ++ * ii. A robust wakeup from another thread's death ++ * iii. A previous round through this special case ++ * ++ * As a result, the futex world will be in one of four states: ++ * ++ * A. The futex word is 0 (unlocked) ++ * B. The futex word is owned by another thread ++ * (FUTEX_WAITERS is not set) ++ * C. The futex word is owned by another thread ++ * (FUTEX_WAITERS set) ++ * D. The futex's owner died and OWNER_DIED is set ++ * (the owner part of the word is 0) + * +- * In both cases the TID validation below prevents a wakeup of +- * potential waiters which can cause these waiters to block +- * forever. ++ * The key issue is that the kernel usually (at least from ++ * sources ii. and iii. or when so requested by userspace from ++ * source i.) only ever wakes *one* waiter at a time. If this ++ * waiter dies before acquiring the futex (or setting the ++ * FUTEX_WAITERS bit), the kernel *must* still wake the next ++ * waiter down the line to uphold the futex invariants and ++ * avoid lost wakeups. Note we do not need to handle state C, ++ * as it does not matter to us whether *we* successfully set ++ * the bit or a third thread did so in the meantime. + * +- * In both cases the following conditions are met: ++ * Therefore, in these cases we must issue an additional ++ * futex_wake(). Note however that we *must not* set OWNER_DIED ++ * here. Our thread is *not* the owner of the futex. + * +- * 1) task->robust_list->list_op_pending != NULL +- * @pending_op == true +- * 2) The owner part of user space futex value == 0 ++ * Thus to summarize, the conditions for needing the additional ++ * futex_wake() are: ++ * ++ * 1) @pending_op == true (the thread has not finished the ++ * mutex operation) ++ * 2) The futex word is in one of the states A, B or D + * 3) Regular futex: @pi == false + * +- * If these conditions are met, it is safe to attempt waking up a +- * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. If the futex value is zero, +- * the rest of the user space mutex state is consistent, so a woken +- * waiter will just take over the uncontended futex. Setting the +- * OWNER_DIED bit would create inconsistent state and malfunction +- * of the user space owner died handling. Otherwise, the OWNER_DIED +- * bit is already set, and the woken waiter is expected to deal with +- * this. ++ * Note in particular that in all of the states A-D the owner ++ * portion of the futex word differs from our thread's TID ++ * (unless the actual owner has the same TID in another PID ++ * namespace, but we cannot currently distinguish that ++ * scenario), so this can be a special-case wakeup in the bail ++ * path of the ordinary TID check. + */ + owner = uval & FUTEX_TID_MASK; + +- if (pending_op && !pi && !owner) { +- futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, +- FUTEX_BITSET_MATCH_ANY); ++ if (owner != task_pid_vnr(curr)) { ++ if (pending_op && !pi && (!owner || !(uval & FUTEX_WAITERS))) { ++ futex_wake(uaddr, FLAGS_SIZE_32 | FLAGS_SHARED, 1, ++ FUTEX_BITSET_MATCH_ANY); ++ } + return 0; + } + +- if (owner != task_pid_vnr(curr)) +- return 0; +- + /* + * Ok, this dying thread is truly holding a futex + * of interest. Set the OWNER_DIED bit atomically +-- +2.53.0 + diff --git a/queue-7.1/revert-drm-amd-display-fix-backlight-max_brightness-.patch b/queue-7.1/revert-drm-amd-display-fix-backlight-max_brightness-.patch new file mode 100644 index 0000000000..58d4fc7c8b --- /dev/null +++ b/queue-7.1/revert-drm-amd-display-fix-backlight-max_brightness-.patch @@ -0,0 +1,48 @@ +From d910b7c81fcd8c6ffeaa1a4421f66a3e3d842ac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Aug 2026 10:49:01 -0400 +Subject: Revert "drm/amd/display: Fix backlight max_brightness to match + exported range" + +From: Alex Deucher + +This reverts commit 1191285ecb4233e5bf907da7e9394d7999055566. + +This patch is apparently missing a dependency from 7.2 as users have not +reported any regressions with 7.2-rc, but there are regressions on 7.1. + +The regression manifests as inconsistent lower brightness at the top end +(e.g., around 98%). + +Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5562 +Signed-off-by: Alex Deucher +Cc: Thorsten Leemhuis +Cc: Sergio Callegari +Cc: Mario Limonciello +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 40d82a3eeec05..6f9d4bea33795 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5401,11 +5401,11 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) + caps = &dm->backlight_caps[aconnector->bl_idx]; + if (get_brightness_range(caps, &min, &max)) { + if (power_supply_is_system_supplied() > 0) +- props.brightness = DIV_ROUND_CLOSEST(max * caps->ac_level, 100); ++ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100); + else +- props.brightness = DIV_ROUND_CLOSEST(max * caps->dc_level, 100); ++ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100); + /* min is zero, so max needs to be adjusted */ +- props.max_brightness = max; ++ props.max_brightness = max - min; + drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max, + caps->ac_level, caps->dc_level); + } else +-- +2.53.0 + diff --git a/queue-7.1/selftests-xsk-account-reclaimed-invalid-tx-descripto.patch b/queue-7.1/selftests-xsk-account-reclaimed-invalid-tx-descripto.patch new file mode 100644 index 0000000000..9869b8b98d --- /dev/null +++ b/queue-7.1/selftests-xsk-account-reclaimed-invalid-tx-descripto.patch @@ -0,0 +1,133 @@ +From d669da60a3510c5f2a2f147565f4fd24a692062d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 19:00:03 -0300 +Subject: selftests/xsk: account reclaimed invalid Tx descriptors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Fijalkowski + +[ Upstream commit f49d99eaee7c32badc7ddfaecbb01ce4d037d695 ] + +Invalid Tx descriptors are now returned through the completion ring, +regardless of whether they form a standalone packet or belong to an +invalid multi-buffer packet. + +The selftests previously counted only descriptors belonging to valid +packets, with a special exception for some invalid multi-buffer packets +in verbatim streams. This undercounts completion entries when a +standalone invalid descriptor or another invalid packet is reclaimed by +the kernel. + +Keep valid_pkts as the number of packets expected on the Rx side, but +count every descriptor submitted to the Tx ring in valid_frags, as every +such descriptor is now expected to be returned through the completion +ring. + +Make fragment counting in verbatim mode follow the packet boundary +instead of stopping at the first invalid fragment. Update custom stream +generation so an invalid middle fragment terminates the generated Rx +packet while Tx completion accounting still covers the complete invalid +packet. + +Also add explicit end fragments after invalid middle descriptors. This +exercises the kernel drain logic and verifies that subsequent valid +packets are not interpreted as continuations of the invalid packet. + +[ rbm: in testapp_invalid_desc_mb() hunk, use umem_size instead of umem_sz +] + +Reviewed-by: Jason Xing +Signed-off-by: Maciej Fijalkowski +Acked-by: Stanislav Fomichev +Link: https://patch.msgid.link/20260719135609.147823-7-maciej.fijalkowski@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Ricardo B. Marlière (SUSE) +Signed-off-by: Sasha Levin +--- + .../selftests/bpf/prog_tests/test_xsk.c | 26 ++++++++++--------- + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c +index 1c48a3b5ee736..31bf8a3fcd666 100644 +--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c ++++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c +@@ -414,14 +414,14 @@ static u32 pkt_nb_frags(u32 frame_size, struct pkt_stream *pkt_stream, struct pk + } + + /* Search for the end of the packet in verbatim mode */ +- if (!pkt_continues(pkt->options) || !pkt->valid) ++ if (!pkt_continues(pkt->options)) + return nb_frags; + + next_frag = pkt_stream->current_pkt_nb; + pkt++; + while (next_frag++ < pkt_stream->nb_pkts) { + nb_frags++; +- if (!pkt_continues(pkt->options) || !pkt->valid) ++ if (!pkt_continues(pkt->options)) + break; + pkt++; + } +@@ -652,11 +652,11 @@ static struct pkt_stream *__pkt_stream_generate_custom(struct ifobject *ifobj, s + if (!frame->valid || !pkt_continues(frame->options)) + payload++; + } else { +- if (frame->valid) ++ if (frame->valid) { + len += frame->len; +- if (frame->valid && pkt_continues(frame->options)) +- continue; +- ++ if (pkt_continues(frame->options)) ++ continue; ++ } + pkt->pkt_nb = pkt_nb; + pkt->len = len; + pkt->valid = frame->valid; +@@ -1236,10 +1236,9 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b + } + } + +- if (pkt && pkt->valid) { ++ if (pkt && pkt->valid) + valid_pkts++; +- valid_frags += nb_frags; +- } ++ valid_frags += nb_frags; + } + + pthread_mutex_lock(&pacing_mutex); +@@ -2075,13 +2074,16 @@ int testapp_invalid_desc_mb(struct test_spec *test) + {0, 0, 0, false, 0}, + /* Invalid address in the second frame */ + {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, +- {umem_size, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, ++ {umem_size * 2, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, ++ {0, MIN_PKT_SIZE, 0, false, 0}, + /* Invalid len in the middle */ + {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, + {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, ++ {0, MIN_PKT_SIZE, 0, false, 0}, + /* Invalid options in the middle */ + {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, + {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XSK_DESC__INVALID_OPTION}, ++ {0, MIN_PKT_SIZE, 0, false, 0}, + /* Transmit 2 frags, receive 3 */ + {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, XDP_PKT_CONTD}, + {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, 0}, +@@ -2093,8 +2095,8 @@ int testapp_invalid_desc_mb(struct test_spec *test) + + if (umem->unaligned_mode) { + /* Crossing a chunk boundary allowed */ +- pkts[12].valid = true; +- pkts[13].valid = true; ++ pkts[15].valid = true; ++ pkts[16].valid = true; + } + + test->mtu = MAX_ETH_JUMBO_SIZE; +-- +2.53.0 + diff --git a/queue-7.1/selftests-xsk-fix-too-many-frags-multi-buffer-tx-tes.patch b/queue-7.1/selftests-xsk-fix-too-many-frags-multi-buffer-tx-tes.patch new file mode 100644 index 0000000000..a27746fbed --- /dev/null +++ b/queue-7.1/selftests-xsk-fix-too-many-frags-multi-buffer-tx-tes.patch @@ -0,0 +1,91 @@ +From ddf59cf05d0779f6067eb14087662bddf162f399 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Aug 2026 19:00:02 -0300 +Subject: selftests/xsk: fix too-many-frags multi-buffer Tx test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Fijalkowski + +[ Upstream commit c5b1ca6a02886f00170ed91b757e244f23259e91 ] + +The too-many-frags test describes a packet that is valid from the Tx +ring ownership point of view, but invalid for transmission because it +exceeds the supported number of fragments. + +Keep the generated Tx descriptors valid so that __send_pkts() accounts +them as outstanding descriptors that must be reclaimed through the CQ. +Then mark the corresponding Rx packet invalid so the test still does +not expect the oversized packet to appear on the receive side. + +Add a valid synchronization packet after the oversized packet so the +test can verify that the Tx path drains the bad packet and resumes at +the next packet boundary. + +Reviewed-by: Jason Xing +Signed-off-by: Maciej Fijalkowski +Acked-by: Stanislav Fomichev +Link: https://patch.msgid.link/20260719135609.147823-6-maciej.fijalkowski@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Ricardo B. Marlière (SUSE) +Signed-off-by: Sasha Levin +--- + .../selftests/bpf/prog_tests/test_xsk.c | 24 ++++++++++++------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c +index 7950c504ed289..1c48a3b5ee736 100644 +--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c ++++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c +@@ -2229,7 +2229,7 @@ int testapp_too_many_frags(struct test_spec *test) + max_frags += 1; + } + +- pkts = calloc(2 * max_frags + 2, sizeof(struct pkt)); ++ pkts = calloc(2 * max_frags + 3, sizeof(struct pkt)); + if (!pkts) + return TEST_FAILURE; + +@@ -2247,24 +2247,30 @@ int testapp_too_many_frags(struct test_spec *test) + } + pkts[max_frags].options = 0; + +- /* An invalid packet with the max amount of frags but signals packet +- * continues on the last frag +- */ +- for (i = max_frags + 1; i < 2 * max_frags + 1; i++) { ++ /* An invalid packet with the max + 1 amount of frags */ ++ for (i = max_frags + 1; i < 2 * max_frags + 2; i++) { + pkts[i].len = MIN_PKT_SIZE; + pkts[i].options = XDP_PKT_CONTD; +- pkts[i].valid = false; ++ pkts[i].valid = true; + } ++ pkts[2 * max_frags + 1].options = 0; + + /* Valid packet for synch */ +- pkts[2 * max_frags + 1].len = MIN_PKT_SIZE; +- pkts[2 * max_frags + 1].valid = true; ++ pkts[2 * max_frags + 2].len = MIN_PKT_SIZE; ++ pkts[2 * max_frags + 2].valid = true; + +- if (pkt_stream_generate_custom(test, pkts, 2 * max_frags + 2)) { ++ if (pkt_stream_generate_custom(test, pkts, 2 * max_frags + 3)) { + free(pkts); + return TEST_FAILURE; + } + ++ /* The generated Tx stream must keep the too-big packet valid so that ++ * __send_pkts() accounts its descriptors in outstanding_tx. The Rx ++ * stream, however, must not expect this packet on the wire. ++ */ ++ test->ifobj_rx->xsk->pkt_stream->pkts[2].valid = false; ++ test->ifobj_rx->xsk->pkt_stream->nb_valid_entries--; ++ + ret = testapp_validate_traffic(test); + free(pkts); + return ret; +-- +2.53.0 + diff --git a/queue-7.1/series b/queue-7.1/series index f4f5939851..2fba1cc0c6 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -141,3 +141,9 @@ mm-fix-incorrect-flush-address-in-direct-page-table-reclaim.patch input-evdev-fix-information-leak-in-evdev_pass_values.patch mm-vmalloc-acquire-init_mm-lock-on-huge-vmap-to-avoid-ptdump-uaf.patch ima-fix-out-of-bounds-read-in-xattr_verify.patch +revert-drm-amd-display-fix-backlight-max_brightness-.patch +futex-prevent-robust-futex-exit-race-some-more.patch +selftests-xsk-fix-too-many-frags-multi-buffer-tx-tes.patch +selftests-xsk-account-reclaimed-invalid-tx-descripto.patch +bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch +bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch