]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Fri, 24 Jul 2026 10:59:05 +0000 (06:59 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 24 Jul 2026 11:22:25 +0000 (07:22 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
33 files changed:
staging-5.10/cpu-hotplug-bound-hotplug-states-sysfs-output.patch [new file with mode: 0644]
staging-5.10/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch [new file with mode: 0644]
staging-5.10/series
staging-5.15/futex-prevent-lockup-in-requeue-pi-during-signal-tim.patch [new file with mode: 0644]
staging-5.15/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch [new file with mode: 0644]
staging-5.15/series
staging-6.1/af_unix-set-gc_in_progress-to-true-in-unix_gc.patch [new file with mode: 0644]
staging-6.1/perf-x86-amd-brs-fix-kernel-address-leakage.patch [new file with mode: 0644]
staging-6.1/series
staging-6.12/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
staging-6.12/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch [new file with mode: 0644]
staging-6.12/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch [new file with mode: 0644]
staging-6.12/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch [new file with mode: 0644]
staging-6.12/netfilter-nft_counter-serialize-reset-with-spinlock.patch [new file with mode: 0644]
staging-6.12/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch [new file with mode: 0644]
staging-6.12/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch [new file with mode: 0644]
staging-6.12/series
staging-6.18/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
staging-6.18/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch [new file with mode: 0644]
staging-6.18/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch [new file with mode: 0644]
staging-6.18/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch [new file with mode: 0644]
staging-6.18/netfilter-nft_counter-serialize-reset-with-spinlock.patch [new file with mode: 0644]
staging-6.18/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch [new file with mode: 0644]
staging-6.18/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch [new file with mode: 0644]
staging-6.18/series
staging-6.6/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
staging-6.6/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch [new file with mode: 0644]
staging-6.6/platform-x86-amd-pmc-avoid-logging-null-for-dmi-valu.patch [new file with mode: 0644]
staging-6.6/platform-x86-amd-pmc-don-t-log-during-intermediate-w.patch [new file with mode: 0644]
staging-6.6/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch [new file with mode: 0644]
staging-6.6/series
staging-7.1/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch [new file with mode: 0644]
staging-7.1/series

diff --git a/staging-5.10/cpu-hotplug-bound-hotplug-states-sysfs-output.patch b/staging-5.10/cpu-hotplug-bound-hotplug-states-sysfs-output.patch
new file mode 100644 (file)
index 0000000..4e8b253
--- /dev/null
@@ -0,0 +1,54 @@
+From 4a5de2475370434b4d74c680145d3071f4621b5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 20:38:51 +0200
+Subject: cpu: hotplug: Bound hotplug states sysfs output
+
+From: Bradley Morgan <include@grrlz.net>
+
+commit 86f436567f2516a0083b210bedc933544826a2c3 upstream.
+
+states_show() adds CPU hotplug state names into a single sysfs buffer
+using sprintf(). With enough registered states, this can write past the
+end of the PAGE_SIZE buffer.
+
+Use sysfs_emit_at() so output is bounded.
+
+Fixes: 98f8cdce1db5 ("cpu/hotplug: Add sysfs state interface")
+Signed-off-by: Bradley Morgan <include@grrlz.net>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260619163719.12103-2-include@grrlz.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/cpu.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 08c2b2e30f23f1..69c7be3706f15b 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -2319,18 +2319,15 @@ static const struct attribute_group cpuhp_cpu_attr_group = {
+ static ssize_t show_cpuhp_states(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+ {
+-      ssize_t cur, res = 0;
++      ssize_t res = 0;
+       int i;
+       mutex_lock(&cpuhp_state_mutex);
+       for (i = CPUHP_OFFLINE; i <= CPUHP_ONLINE; i++) {
+               struct cpuhp_step *sp = cpuhp_get_step(i);
+-              if (sp->name) {
+-                      cur = sprintf(buf, "%3d: %s\n", i, sp->name);
+-                      buf += cur;
+-                      res += cur;
+-              }
++              if (sp->name)
++                      res += sysfs_emit_at(buf, res, "%3d: %s\n", i, sp->name);
+       }
+       mutex_unlock(&cpuhp_state_mutex);
+       return res;
+-- 
+2.53.0
+
diff --git a/staging-5.10/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch b/staging-5.10/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch
new file mode 100644 (file)
index 0000000..718a9e4
--- /dev/null
@@ -0,0 +1,53 @@
+From 2d0256ad2a9abc32a8d058158523e32fce9b3653 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 08:41:53 +0900
+Subject: macsec: don't read an unset MAC header in macsec_encrypt()
+
+From: Daehyeon Ko <4ncienth@gmail.com>
+
+commit f5089008f90c0a7c5520dff3934e0af00adf322d upstream.
+
+macsec_encrypt() reads the Ethernet header via eth_hdr(skb)
+(skb->head + skb->mac_header) to memmove() the 12 source/destination MAC
+bytes forward and make room for the SecTAG.
+
+On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
+reaches the macsec ndo_start_xmit() with the MAC header unset, so
+eth_hdr(skb) resolves to skb->head + (u16)~0 and the read is out of
+bounds: a 12-byte heap over-read that is also emitted on the wire as the
+frame's outer source/destination MAC. KASAN reports a slab-out-of-bounds
+read in macsec_start_xmit() on 6.0; on current mainline a CONFIG_DEBUG_NET
+build flags it as an unset mac header in skb_mac_header().
+
+On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), added
+by commit 96cc4b69581d ("macvlan: do not assume mac_header is set in
+macvlan_broadcast()") for exactly this purpose.
+
+Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://patch.msgid.link/20260703083634.2035145-1-4ncienth@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/macsec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index d19b5b1c1aca11..d07dba76940a9d 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -666,7 +666,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
+       }
+       unprotected_len = skb->len;
+-      eth = eth_hdr(skb);
++      eth = skb_eth_hdr(skb);
+       sci_present = send_sci(secy);
+       hh = skb_push(skb, macsec_extra_len(sci_present));
+       memmove(hh, eth, 2 * ETH_ALEN);
+-- 
+2.53.0
+
index 632f68e799e44c8125e683fbc999ba6322df16e3..5e01f56936d25714b883a1ad1380c346dfd8cae5 100644 (file)
@@ -1 +1,3 @@
 nvmet-tcp-fix-potential-uaf-when-ddgst-mismatch.patch
+cpu-hotplug-bound-hotplug-states-sysfs-output.patch
+macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch
diff --git a/staging-5.15/futex-prevent-lockup-in-requeue-pi-during-signal-tim.patch b/staging-5.15/futex-prevent-lockup-in-requeue-pi-during-signal-tim.patch
new file mode 100644 (file)
index 0000000..3b7ac45
--- /dev/null
@@ -0,0 +1,103 @@
+From d8061ac076105b4a44a8c8e8327752017d8309e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 20:47:48 +0000
+Subject: futex: Prevent lockup in requeue-PI during signal/ timeout wakeup
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit bc7304f3ae20972d11db6e0b1b541c63feda5f05 ]
+
+During wait-requeue-pi (task A) and requeue-PI (task B) the following
+race can happen:
+
+     Task A                             Task B
+  futex_wait_requeue_pi()
+    futex_setup_timer()
+    futex_do_wait()
+                                   futex_requeue()
+                                        CLASS(hb, hb1)(&key1);
+                                        CLASS(hb, hb2)(&key2);
+        *timeout*
+    futex_requeue_pi_wakeup_sync()
+        requeue_state = Q_REQUEUE_PI_IGNORE
+
+    *blocks on hb->lock*
+
+                                        futex_proxy_trylock_atomic()
+                                          futex_requeue_pi_prepare()
+                                            Q_REQUEUE_PI_IGNORE => -EAGAIN
+                                        double_unlock_hb(hb1, hb2)
+                                         *retry*
+
+Task B acquires both hb locks and attempts to acquire the PI-lock of the
+top most waiter (task B). Task A is leaving early due to a signal/
+timeout and started removing itself from the queue. It updates its
+requeue_state but can not remove it from the list because this requires
+the hb lock which is owned by task B.
+
+Usually task A is able to swoop the lock after task B unlocked it.
+However if task B is of higher priority then task A may not be able to
+wake up in time and acquire the lock before task B gets it again.
+Especially on a UP system where A is never scheduled.
+
+As a result task A blocks on the lock and task B busy loops, trying to
+make progress but live locks the system instead. Tragic.
+
+This can be fixed by removing the top most waiter from the list in this
+case. This allows task B to grab the next top waiter (if any) in the
+next iteration and make progress.
+
+Remove the top most waiter if futex_requeue_pi_prepare() fails.
+Let the waiter conditionally remove itself from the list in
+handle_early_requeue_pi_wakeup().
+
+Fixes: 07d91ef510fb1 ("futex: Prevent requeue_pi() lock nesting issue on RT")
+Reported-by: Moritz Klammler <Moritz.Klammler@ferchau.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Link: https://patch.msgid.link/20260428103425.dywXyPd3@linutronix.de
+Closes: https://lore.kernel.org/all/VE1PR06MB6894BE61C173D802365BE19DFF4CA@VE1PR06MB6894.eurprd06.prod.outlook.com
+[cmllamas: adapt to 5.15, apply hunk to kernel/futex/core.c prior to the
+ requeue code split and use hb_waiters_dec() before the helper rename]
+Signed-off-by: Carlos Llamas <cmllamas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/futex/core.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/futex/core.c b/kernel/futex/core.c
+index 42cd8f2b6da813..8b4af13b8d262a 100644
+--- a/kernel/futex/core.c
++++ b/kernel/futex/core.c
+@@ -2078,8 +2078,11 @@ futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1,
+               return -EINVAL;
+       /* Ensure that this does not race against an early wakeup */
+-      if (!futex_requeue_pi_prepare(top_waiter, NULL))
++      if (!futex_requeue_pi_prepare(top_waiter, NULL)) {
++              plist_del(&top_waiter->list, &hb1->chain);
++              hb_waiters_dec(hb1);
+               return -EAGAIN;
++      }
+       /*
+        * Try to take the lock for top_waiter and set the FUTEX_WAITERS bit
+@@ -3360,10 +3363,12 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
+       /*
+        * We were woken prior to requeue by a timeout or a signal.
+-       * Unqueue the futex_q and determine which it was.
++       * Conditionally unqueue the futex_q and determine which it was.
+        */
+-      plist_del(&q->list, &hb->chain);
+-      hb_waiters_dec(hb);
++      if (!plist_node_empty(&q->list)) {
++              plist_del(&q->list, &hb->chain);
++              hb_waiters_dec(hb);
++      }
+       /* Handle spurious wakeups gracefully */
+       ret = -EWOULDBLOCK;
+-- 
+2.53.0
+
diff --git a/staging-5.15/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch b/staging-5.15/macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch
new file mode 100644 (file)
index 0000000..f83f485
--- /dev/null
@@ -0,0 +1,53 @@
+From e1c95a05572050f1ffdcd33881131a04a3809995 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 08:40:44 +0900
+Subject: macsec: don't read an unset MAC header in macsec_encrypt()
+
+From: Daehyeon Ko <4ncienth@gmail.com>
+
+commit f5089008f90c0a7c5520dff3934e0af00adf322d upstream.
+
+macsec_encrypt() reads the Ethernet header via eth_hdr(skb)
+(skb->head + skb->mac_header) to memmove() the 12 source/destination MAC
+bytes forward and make room for the SecTAG.
+
+On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
+reaches the macsec ndo_start_xmit() with the MAC header unset, so
+eth_hdr(skb) resolves to skb->head + (u16)~0 and the read is out of
+bounds: a 12-byte heap over-read that is also emitted on the wire as the
+frame's outer source/destination MAC. KASAN reports a slab-out-of-bounds
+read in macsec_start_xmit() on 6.0; on current mainline a CONFIG_DEBUG_NET
+build flags it as an unset mac header in skb_mac_header().
+
+On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), added
+by commit 96cc4b69581d ("macvlan: do not assume mac_header is set in
+macvlan_broadcast()") for exactly this purpose.
+
+Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://patch.msgid.link/20260703083634.2035145-1-4ncienth@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/macsec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 9b0cb78507384b..5de940761ebf1e 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -662,7 +662,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
+       }
+       unprotected_len = skb->len;
+-      eth = eth_hdr(skb);
++      eth = skb_eth_hdr(skb);
+       sci_present = send_sci(secy);
+       hh = skb_push(skb, macsec_extra_len(sci_present));
+       memmove(hh, eth, 2 * ETH_ALEN);
+-- 
+2.53.0
+
index 632f68e799e44c8125e683fbc999ba6322df16e3..754bba0d5598defa536645cdbb910cdeddd0820d 100644 (file)
@@ -1 +1,3 @@
 nvmet-tcp-fix-potential-uaf-when-ddgst-mismatch.patch
+futex-prevent-lockup-in-requeue-pi-during-signal-tim.patch
+macsec-don-t-read-an-unset-mac-header-in-macsec_encr.patch
diff --git a/staging-6.1/af_unix-set-gc_in_progress-to-true-in-unix_gc.patch b/staging-6.1/af_unix-set-gc_in_progress-to-true-in-unix_gc.patch
new file mode 100644 (file)
index 0000000..3757306
--- /dev/null
@@ -0,0 +1,66 @@
+From 72289fce6d99033c398b3f0fb634511a5c80b39b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 00:27:09 +0000
+Subject: af_unix: Set gc_in_progress to true in unix_gc().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit d82ba05263c69fa2437fe93e4e561cc40f4c03af ]
+
+Igor Ushakov reported that unix_gc() could run with gc_in_progress
+being false if the work is scheduled while running:
+
+  Thread 1         Thread 2                     Thread 3
+  --------         --------                     --------
+                   unix_schedule_gc()           unix_schedule_gc()
+                   `- if (!gc_in_progress)      `- if (!gc_in_progress)
+                      |- gc_in_progress = true     |
+                      `- queue_work()              |
+  unix_gc() <----------------/                     |
+  |                                                |- gc_in_progress = true
+  ...                                              `- queue_work()
+  |                                                       |
+  `- gc_in_progress = false                               |
+                                                          |
+  unix_gc() <---------------------------------------------'
+  |
+  ... /* gc_in_progress == false */
+  |
+  `- gc_in_progress = false
+
+unix_peek_fpl() relies on gc_in_progress not to confuse GC
+by MSG_PEEK.
+
+Let's set gc_in_progress to true in unix_gc().
+
+Fixes: 8b90a9f819dc ("af_unix: Run GC on only one CPU.")
+Reported-by: Igor Ushakov <sysroot314@gmail.com>
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260501073945.1884564-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Add setting gc_in_progress in __unix_gc(). Keep the existing
+  set in unix_gc() for wait_for_unix_gc() over-limit throttling. ]
+Signed-off-by: Igor Ushakov <sysroot314@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Jay Wang <wanjay@amazon.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/garbage.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 66fd606c43f45d..38c8cae1316716 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -560,6 +560,8 @@ static void __unix_gc(struct work_struct *work)
+       struct sk_buff_head hitlist;
+       struct sk_buff *skb;
++      WRITE_ONCE(gc_in_progress, true);
++
+       spin_lock(&unix_gc_lock);
+       if (!unix_graph_maybe_cyclic) {
+-- 
+2.53.0
+
diff --git a/staging-6.1/perf-x86-amd-brs-fix-kernel-address-leakage.patch b/staging-6.1/perf-x86-amd-brs-fix-kernel-address-leakage.patch
new file mode 100644 (file)
index 0000000..cb9691a
--- /dev/null
@@ -0,0 +1,92 @@
+From 54d42f00be1a39f947e46af6b913e28e17756e10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 15:39:00 +0530
+Subject: perf/x86/amd/brs: Fix kernel address leakage
+
+From: Sandipan Das <sandipan.das@amd.com>
+
+commit 47915e855fb38b42133e31ba917d99565f862154 upstream.
+
+A user-only branch stack can contain branches that originate from
+the kernel. As a result, kernel addresses are exposed to user space
+even when PERF_SAMPLE_BRANCH_USER is requested. On AMD processors
+supporting X86_FEATURE_BRS (Zen 3 only), perf can still report entries
+such as SYSRET/interrupt returns for which the branch-from addresses
+are in the kernel.
+
+E.g.
+
+  $ perf record -j any,u -c 4000 -e branch-brs -o - -- \
+        perf bench syscall basic --loop 1000 | \
+        perf script -i - -F brstack|tr ' ' '\n'| \
+        grep -E '0x[89a-f][0-9a-f]{15}'
+
+  ...
+  0xffffffff810001c4/0x72e2e32955eb/-/-/-/0//-
+  0xffffffff810001c4/0x72e2d94a9821/-/-/-/0//-
+  0xffffffff810001c4/0x72e2d94ffa1b/-/-/-/0//-
+  ...
+
+BRS provides no hardware branch filtering, so privilege level
+filtering is performed entirely in software. However, amd_brs_match_plm()
+only validates the branch-to address against the requested privilege
+levels. For branches from the kernel to user space, the branch-from
+address is left unchecked and is leaked. Extend the software filter to
+also validate the branch-from address, so that any branch record whose
+branch-from address is in the kernel is dropped when
+PERF_SAMPLE_BRANCH_USER is requested.
+
+Fixes: 8910075d61a3 ("perf/x86/amd: Enable branch sampling priv level filtering")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Sandipan Das <sandipan.das@amd.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: stable@vger.kernel.org
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Stephane Eranian <eranian@google.com>
+Link: https://patch.msgid.link/f05931c4f89a146c364bd5dc6b8170b1ac611c65.1783701239.git.sandipan.das@amd.com
+Closes: https://lore.kernel.org/all/20260710110235.F3FD81F000E9@smtp.kernel.org/
+[sandipan: backport to linux-6.1.y]
+Signed-off-by: Sandipan Das <sandipan.das@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/brs.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/events/amd/brs.c b/arch/x86/events/amd/brs.c
+index f1bff153d94578..fd46e73cb8e716 100644
+--- a/arch/x86/events/amd/brs.c
++++ b/arch/x86/events/amd/brs.c
+@@ -262,13 +262,13 @@ void amd_brs_disable_all(void)
+               amd_brs_disable();
+ }
+-static bool amd_brs_match_plm(struct perf_event *event, u64 to)
++static bool amd_brs_match_plm(struct perf_event *event, u64 from, u64 to)
+ {
+       int type = event->attr.branch_sample_type;
+       int plm_k = PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV;
+       int plm_u = PERF_SAMPLE_BRANCH_USER;
+-      if (!(type & plm_k) && kernel_ip(to))
++      if (!(type & plm_k) && (kernel_ip(to) || kernel_ip(from)))
+               return 0;
+       if (!(type & plm_u) && !kernel_ip(to))
+@@ -341,11 +341,11 @@ void amd_brs_drain(void)
+                */
+               to = (u64)(((s64)to << shift) >> shift);
+-              if (!amd_brs_match_plm(event, to))
+-                      continue;
+-
+               rdmsrl(brs_from(brs_idx), from);
++              if (!amd_brs_match_plm(event, from, to))
++                      continue;
++
+               perf_clear_branch_entry_bitfields(br+nr);
+               br[nr].from = from;
+-- 
+2.53.0
+
index 07ddd9b506ed0ac44c97ea36d22b3520688287f2..8dd80c6d818a5a8f05736f756ad371afbad67e9e 100644 (file)
@@ -1 +1,3 @@
 platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
+af_unix-set-gc_in_progress-to-true-in-unix_gc.patch
+perf-x86-amd-brs-fix-kernel-address-leakage.patch
diff --git a/staging-6.12/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/staging-6.12/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..c7e8175
--- /dev/null
@@ -0,0 +1,71 @@
+From f485839978a7381a4d7cbc551f827fdd7f32698d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:07 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 7f1144486a8c4a..8c3c4ab989a053 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -16100,6 +16100,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              mark_reg_scratched(env, BPF_REG_0);
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.12/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch b/staging-6.12/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
new file mode 100644 (file)
index 0000000..cc1cc9b
--- /dev/null
@@ -0,0 +1,82 @@
+From f6e03317c14058ea9a9ea6805191794eb40df13d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 22:01:00 +0900
+Subject: drm/virtio: fix deadlock in display_info_cb by removing hotplug from
+ dequeue worker
+
+From: Ryosuke Yasuoka <ryasuoka@redhat.com>
+
+[ Upstream commit d1b894c5bbb3fee0012bd14356286dc2384e8213 ]
+
+A probe-time deadlock can occur between the dequeue worker and
+drm_client_register(). During probe, drm_client_register() holds
+clientlist_mutex and calls the fbdev hotplug callback, which triggers an
+atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
+waiting for virtqueue space. The dequeue worker that would free that
+space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
+drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
+to acquire the same clientlist_mutex. Since wake_up() is only called
+after the resp_cb loop, the probe thread is never woken and both threads
+deadlock.
+
+Fix this by removing the hotplug notification from
+virtio_gpu_cmd_get_display_info_cb(). The display data (outputs[i].info)
+is still updated synchronously in the callback.
+
+For the init path, drm_client_register() already fires an initial
+hotplug when the client is registered, which picks up the connector
+state updated by display_info_cb.
+
+For the runtime config_changed path, add a wait_event_timeout() in
+config_changed_work_func() so that display_info_cb updates the connector
+data before the hotplug notification is sent. Also replace
+drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event() since
+virtio-gpu never calls drm_kms_helper_poll_init() and thus
+drm_helper_hpd_irq_event() always returns false without doing anything.
+
+Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
+Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
+Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
+Suggested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
+Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Link: https://patch.msgid.link/20260713-virtiogpu_syzbot-v2-1-2958fa37d46d@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/virtio/virtgpu_kms.c | 5 ++++-
+ drivers/gpu/drm/virtio/virtgpu_vq.c  | 3 ---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
+index 7dfb2006c561ca..ec31a41d33d678 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
++++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
+@@ -48,7 +48,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
+                               virtio_gpu_cmd_get_edids(vgdev);
+                       virtio_gpu_cmd_get_display_info(vgdev);
+                       virtio_gpu_notify(vgdev);
+-                      drm_helper_hpd_irq_event(vgdev->ddev);
++                      wait_event_timeout(vgdev->resp_wq,
++                                         !vgdev->display_info_pending,
++                                         5 * HZ);
++                      drm_kms_helper_hotplug_event(vgdev->ddev);
+               }
+               events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
+       }
+diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
+index 0d3d0d09f39b9f..bcc070b478d30e 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
+@@ -669,9 +669,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
+       vgdev->display_info_pending = false;
+       spin_unlock(&vgdev->display_info_lock);
+       wake_up(&vgdev->resp_wq);
+-
+-      if (!drm_helper_hpd_irq_event(vgdev->ddev))
+-              drm_kms_helper_hotplug_event(vgdev->ddev);
+ }
+ static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+-- 
+2.53.0
+
diff --git a/staging-6.12/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch b/staging-6.12/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch
new file mode 100644 (file)
index 0000000..7976d34
--- /dev/null
@@ -0,0 +1,124 @@
+From c40153ad06ebf9c980f59259f025b8bbdb5c0981 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 12:01:20 +0100
+Subject: fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race
+
+From: Kiryl Shutsemau <kas@kernel.org>
+
+commit 04718f7c9290f95385f0dd328758753dc1c36dec upstream.
+
+Patch series "userfaultfd/pagemap: pre-existing fixes".
+
+These are pre-existing bug fixes that were carried at the front of the
+userfaultfd RWP working-set-tracking series up to v5 [1].  Per review
+feedback that fixes should not sit in the middle of a feature series, they
+are split out and sent on their own; the RWP series is reposted rebased on
+top of this.
+
+All six were flagged by the Sashiko AI review of the RWP series and carry
+Reported-by: Sashiko AI review <sashiko-bot@kernel.org>.  They are
+independent of RWP, apply to mm-new directly, and carry Cc: stable@.
+
+  1: fs/proc/task_mmu: a missing huge_ptep_modify_prot_start() in
+     make_uffd_wp_huge_pte() can lose hardware Dirty/Accessed updates
+     when PAGEMAP_SCAN write-protects a hugetlb PTE.
+
+  2: fs/proc/task_mmu: pagemap_scan_hugetlb_entry() compares the range
+     against HPAGE_SIZE rather than the hstate page size, so it never
+     write-protects gigantic hugetlb pages.
+
+  3: fs/proc/task_mmu: PAGEMAP_SCAN with PM_SCAN_WP_MATCHING over an
+     unpopulated hugetlb range self-deadlocks -- pagemap_scan_pte_hole()
+     calls uffd_wp_range() while walk_hugetlb_range() holds the hugetlb
+     vma lock for read, and hugetlb_change_protection() then takes it
+     for write. Install the marker inline instead.
+
+  4: mm/huge_memory: change_non_present_huge_pmd() drops pmd_swp_uffd_wp
+     on a device-private PMD permission downgrade, silently losing the
+     uffd-wp marker.
+
+  5: userfaultfd: must_wait() applies pte_write() to a locklessly read
+     PTE without checking pte_present(), so swap/migration entries
+     decode random offset bits and a thread can stay parked on a stale
+     fault.
+
+  6: userfaultfd: __VMA_UFFD_FLAGS feeds VMA_UFFD_MINOR_BIT (41) to
+     mk_vma_flags() unconditionally, an out-of-bounds write into the
+     single-word vma_flags_t on 32-bit. Build the mask from config-gated
+     per-mode masks so an unavailable bit is never materialised.
+
+This patch (of 6):
+
+make_uffd_wp_huge_pte() arms the UFFD_WP bit on a present HugeTLB PTE by
+calling huge_ptep_modify_prot_commit() with a ptent snapshot that was
+fetched without the corresponding huge_ptep_modify_prot_start().  The
+start helper is what atomically clears the entry so the kernel-owned
+snapshot stays consistent until the commit; without it, the hardware may
+set Dirty or Accessed in the live PTE between the original read and the
+commit, and huge_ptep_modify_prot_commit() (whose generic implementation
+just calls set_huge_pte_at()) then writes the stale snapshot back over the
+live hardware bits, losing the update.
+
+The non-hugetlb sibling make_uffd_wp_pte() does this correctly via
+ptep_modify_prot_start() / ptep_modify_prot_commit().  Mirror that pattern
+for the present-PTE branch.  The migration case stays as-is -- migration
+entries are non-present, so there's no hardware update to race against.
+
+Link: https://lore.kernel.org/20260529172331.356655-1-kas@kernel.org
+Link: https://lore.kernel.org/20260529172331.356655-2-kas@kernel.org
+Link: https://lore.kernel.org/all/20260526130509.2748441-1-kirill@shutemov.name/ [1]
+Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
+Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
+Reported-by: Sashiko AI review <sashiko-bot@kernel.org>
+Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
+Reviewed-by: Dev Jain <dev.jain@arm.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Balbir Singh <balbirs@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ kas: adapt to the pre-softleaf idiom; apply the
+  huge_ptep_modify_prot_start()/commit() fix to the present-PTE
+  (!huge_pte_none()) branch ]
+Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/task_mmu.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 673b7d0fcfd8fa..bc127f1ad4bb28 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -2254,15 +2254,19 @@ static void make_uffd_wp_huge_pte(struct vm_area_struct *vma,
+       psize = huge_page_size(hstate_vma(vma));
+-      if (is_hugetlb_entry_migration(ptent))
++      if (is_hugetlb_entry_migration(ptent)) {
+               set_huge_pte_at(vma->vm_mm, addr, ptep,
+                               pte_swp_mkuffd_wp(ptent), psize);
+-      else if (!huge_pte_none(ptent))
+-              huge_ptep_modify_prot_commit(vma, addr, ptep, ptent,
+-                                           huge_pte_mkuffd_wp(ptent));
+-      else
++      } else if (!huge_pte_none(ptent)) {
++              pte_t old_pte, new_pte;
++
++              old_pte = huge_ptep_modify_prot_start(vma, addr, ptep);
++              new_pte = huge_pte_mkuffd_wp(old_pte);
++              huge_ptep_modify_prot_commit(vma, addr, ptep, old_pte, new_pte);
++      } else {
+               set_huge_pte_at(vma->vm_mm, addr, ptep,
+                               make_pte_marker(PTE_MARKER_UFFD_WP), psize);
++      }
+ }
+ #endif /* CONFIG_HUGETLB_PAGE */
+-- 
+2.53.0
+
diff --git a/staging-6.12/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch b/staging-6.12/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch
new file mode 100644 (file)
index 0000000..0fc138d
--- /dev/null
@@ -0,0 +1,424 @@
+From c521ebd5e8627de5d903243604cca0f039c1f967 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:36 -0600
+Subject: netfilter: nf_tables: revert commit_mutex usage in reset path
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 7f261bb906bf527c4a6e2a646e2d5f3679f2a8bc ]
+
+It causes circular lock dependency between commit_mutex, nfnl_subsys_ipset
+and nlk_cb_mutex when nft reset, ipset list, and iptables-nft with '-m set'
+rule run at the same time.
+
+Previous patches made it safe to run individual reset handlers concurrently
+so commit_mutex is no longer required to prevent this.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Link: https://lore.kernel.org/all/aUh_3mVRV8OrGsVo@strlen.de/
+Reported-by: <syzbot+ff16b505ec9152e5f448@syzkaller.appspotmail.com>
+Closes: https://syzkaller.appspot.com/bug?extid=ff16b505ec9152e5f448
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 248 ++++++----------------------------
+ 1 file changed, 42 insertions(+), 206 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 838c9f49e4e01a..09969379c43a73 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -3719,23 +3719,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
+       return skb->len;
+ }
+-static int nf_tables_dumpreset_rules(struct sk_buff *skb,
+-                                   struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      int ret;
+-
+-      /* Mutex is held is to prevent that two concurrent dump-and-reset calls
+-       * do not underrun counters and quotas. The commit_mutex is used for
+-       * the lack a better lock, this is not transaction path.
+-       */
+-      mutex_lock(&nft_net->commit_mutex);
+-      ret = nf_tables_dump_rules(skb, cb);
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
+ {
+       struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
+@@ -3755,16 +3738,10 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
+                       return -ENOMEM;
+               }
+       }
+-      return 0;
+-}
+-
+-static int nf_tables_dumpreset_rules_start(struct netlink_callback *cb)
+-{
+-      struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
+-
+-      ctx->reset = true;
++      if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
++              ctx->reset = true;
+-      return nf_tables_dump_rules_start(cb);
++      return 0;
+ }
+ static int nf_tables_dump_rules_done(struct netlink_callback *cb)
+@@ -3830,6 +3807,8 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
+       u32 portid = NETLINK_CB(skb).portid;
+       struct net *net = info->net;
+       struct sk_buff *skb2;
++      bool reset = false;
++      char *buf;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+@@ -3843,47 +3822,16 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+       }
+-      skb2 = nf_tables_getrule_single(portid, info, nla, false);
+-      if (IS_ERR(skb2))
+-              return PTR_ERR(skb2);
+-
+-      return nfnetlink_unicast(skb2, net, portid);
+-}
+-
+-static int nf_tables_getrule_reset(struct sk_buff *skb,
+-                                 const struct nfnl_info *info,
+-                                 const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+-      u32 portid = NETLINK_CB(skb).portid;
+-      struct net *net = info->net;
+-      struct sk_buff *skb2;
+-      char *buf;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start= nf_tables_dumpreset_rules_start,
+-                      .dump = nf_tables_dumpreset_rules,
+-                      .done = nf_tables_dump_rules_done,
+-                      .module = THIS_MODULE,
+-                      .data = (void *)nla,
+-              };
+-
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      skb2 = nf_tables_getrule_single(portid, info, nla, true);
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
++              reset = true;
++      skb2 = nf_tables_getrule_single(portid, info, nla, reset);
+       if (IS_ERR(skb2))
+               return PTR_ERR(skb2);
++      if (!reset)
++              return nfnetlink_unicast(skb2, net, portid);
++
+       buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
+                       nla_len(nla[NFTA_RULE_TABLE]),
+                       (char *)nla_data(nla[NFTA_RULE_TABLE]),
+@@ -6107,6 +6055,10 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
+       nla_nest_end(skb, nest);
+       nlmsg_end(skb, nlh);
++      if (dump_ctx->reset && args.iter.count > args.iter.skip)
++              audit_log_nft_set_reset(table, cb->seq,
++                                      args.iter.count - args.iter.skip);
++
+       rcu_read_unlock();
+       if (args.iter.err && args.iter.err != -EMSGSIZE)
+@@ -6122,26 +6074,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
+       return -ENOSPC;
+ }
+-static int nf_tables_dumpreset_set(struct sk_buff *skb,
+-                                 struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      struct nft_set_dump_ctx *dump_ctx = cb->data;
+-      int ret, skip = cb->args[0];
+-
+-      mutex_lock(&nft_net->commit_mutex);
+-
+-      ret = nf_tables_dump_set(skb, cb);
+-
+-      if (cb->args[0] > skip)
+-              audit_log_nft_set_reset(dump_ctx->ctx.table, cb->seq,
+-                                      cb->args[0] - skip);
+-
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_set_start(struct netlink_callback *cb)
+ {
+       struct nft_set_dump_ctx *dump_ctx = cb->data;
+@@ -6385,8 +6317,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+ {
+       struct netlink_ext_ack *extack = info->extack;
+       struct nft_set_dump_ctx dump_ctx;
++      int rem, err = 0, nelems = 0;
++      struct net *net = info->net;
+       struct nlattr *attr;
+-      int rem, err = 0;
++      bool reset = false;
++
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
++              reset = true;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+@@ -6396,7 +6333,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+                       .module = THIS_MODULE,
+               };
+-              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
++              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
+               if (err)
+                       return err;
+@@ -6407,75 +6344,21 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+       if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
+               return -EINVAL;
+-      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
++      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
+       if (err)
+               return err;
+       nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+-              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, false);
+-              if (err < 0) {
+-                      NL_SET_BAD_ATTR(extack, attr);
+-                      break;
+-              }
+-      }
+-
+-      return err;
+-}
+-
+-static int nf_tables_getsetelem_reset(struct sk_buff *skb,
+-                                    const struct nfnl_info *info,
+-                                    const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+-      struct netlink_ext_ack *extack = info->extack;
+-      struct nft_set_dump_ctx dump_ctx;
+-      int rem, err = 0, nelems = 0;
+-      struct nlattr *attr;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start = nf_tables_dump_set_start,
+-                      .dump = nf_tables_dumpreset_set,
+-                      .done = nf_tables_dump_set_done,
+-                      .module = THIS_MODULE,
+-              };
+-
+-              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
+-              if (err)
+-                      return err;
+-
+-              c.data = &dump_ctx;
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
+-              return -EINVAL;
+-
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-
+-      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
+-      if (err)
+-              goto out_unlock;
+-
+-      nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+-              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, true);
++              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, reset);
+               if (err < 0) {
+                       NL_SET_BAD_ATTR(extack, attr);
+                       break;
+               }
+               nelems++;
+       }
+-      audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems);
+-
+-out_unlock:
+-      rcu_read_unlock();
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (reset)
++              audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(net),
++                                      nelems);
+       return err;
+ }
+@@ -8182,19 +8065,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
+       return skb->len;
+ }
+-static int nf_tables_dumpreset_obj(struct sk_buff *skb,
+-                                 struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      int ret;
+-
+-      mutex_lock(&nft_net->commit_mutex);
+-      ret = nf_tables_dump_obj(skb, cb);
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
+ {
+       struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
+@@ -8211,16 +8081,10 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
+       if (nla[NFTA_OBJ_TYPE])
+               ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+-      return 0;
+-}
+-
+-static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb)
+-{
+-      struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
+-
+-      ctx->reset = true;
++      if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
++              ctx->reset = true;
+-      return nf_tables_dump_obj_start(cb);
++      return 0;
+ }
+ static int nf_tables_dump_obj_done(struct netlink_callback *cb)
+@@ -8282,42 +8146,16 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
+ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
+ {
+-      u32 portid = NETLINK_CB(skb).portid;
+-      struct sk_buff *skb2;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start = nf_tables_dump_obj_start,
+-                      .dump = nf_tables_dump_obj,
+-                      .done = nf_tables_dump_obj_done,
+-                      .module = THIS_MODULE,
+-                      .data = (void *)nla,
+-              };
+-
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      skb2 = nf_tables_getobj_single(portid, info, nla, false);
+-      if (IS_ERR(skb2))
+-              return PTR_ERR(skb2);
+-
+-      return nfnetlink_unicast(skb2, info->net, portid);
+-}
+-
+-static int nf_tables_getobj_reset(struct sk_buff *skb,
+-                                const struct nfnl_info *info,
+-                                const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+       u32 portid = NETLINK_CB(skb).portid;
+       struct net *net = info->net;
+       struct sk_buff *skb2;
++      bool reset = false;
+       char *buf;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+-                      .start = nf_tables_dumpreset_obj_start,
+-                      .dump = nf_tables_dumpreset_obj,
++                      .start = nf_tables_dump_obj_start,
++                      .dump = nf_tables_dump_obj,
+                       .done = nf_tables_dump_obj_done,
+                       .module = THIS_MODULE,
+                       .data = (void *)nla,
+@@ -8326,18 +8164,16 @@ static int nf_tables_getobj_reset(struct sk_buff *skb,
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+       }
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      skb2 = nf_tables_getobj_single(portid, info, nla, true);
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
++              reset = true;
++      skb2 = nf_tables_getobj_single(portid, info, nla, reset);
+       if (IS_ERR(skb2))
+               return PTR_ERR(skb2);
++      if (!reset)
++              return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
++
+       buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
+                       nla_len(nla[NFTA_OBJ_TABLE]),
+                       (char *)nla_data(nla[NFTA_OBJ_TABLE]),
+@@ -9540,7 +9376,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_rule_policy,
+       },
+       [NFT_MSG_GETRULE_RESET] = {
+-              .call           = nf_tables_getrule_reset,
++              .call           = nf_tables_getrule,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_RULE_MAX,
+               .policy         = nft_rule_policy,
+@@ -9594,7 +9430,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_set_elem_list_policy,
+       },
+       [NFT_MSG_GETSETELEM_RESET] = {
+-              .call           = nf_tables_getsetelem_reset,
++              .call           = nf_tables_getsetelem,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_SET_ELEM_LIST_MAX,
+               .policy         = nft_set_elem_list_policy,
+@@ -9640,7 +9476,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_obj_policy,
+       },
+       [NFT_MSG_GETOBJ_RESET] = {
+-              .call           = nf_tables_getobj_reset,
++              .call           = nf_tables_getobj,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_OBJ_MAX,
+               .policy         = nft_obj_policy,
+-- 
+2.53.0
+
diff --git a/staging-6.12/netfilter-nft_counter-serialize-reset-with-spinlock.patch b/staging-6.12/netfilter-nft_counter-serialize-reset-with-spinlock.patch
new file mode 100644 (file)
index 0000000..9160a8f
--- /dev/null
@@ -0,0 +1,86 @@
+From 47bbfcce532ae34c10759d24a321b19bb7571299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:37 -0600
+Subject: netfilter: nft_counter: serialize reset with spinlock
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 779c60a5190c42689534172f4b49e927c9959e4e ]
+
+Add a global static spinlock to serialize counter fetch+reset
+operations, preventing concurrent dump-and-reset from underrunning
+values.
+
+The lock is taken before fetching the total so that two parallel
+resets cannot both read the same counter values and then both
+subtract them.
+
+A global lock is used for simplicity since resets are infrequent.
+If this becomes a bottleneck, it can be replaced with a per-net
+lock later.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_counter.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c
+index 0d70325280cc57..169ae93688bcc5 100644
+--- a/net/netfilter/nft_counter.c
++++ b/net/netfilter/nft_counter.c
+@@ -32,6 +32,9 @@ struct nft_counter_percpu_priv {
+ static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);
++/* control plane only: sync fetch+reset */
++static DEFINE_SPINLOCK(nft_counter_lock);
++
+ static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
+                                      struct nft_regs *regs,
+                                      const struct nft_pktinfo *pkt)
+@@ -148,13 +151,25 @@ static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
+       }
+ }
++static void nft_counter_fetch_and_reset(struct nft_counter_percpu_priv *priv,
++                                      struct nft_counter_tot *total)
++{
++      spin_lock(&nft_counter_lock);
++      nft_counter_fetch(priv, total);
++      nft_counter_reset(priv, total);
++      spin_unlock(&nft_counter_lock);
++}
++
+ static int nft_counter_do_dump(struct sk_buff *skb,
+                              struct nft_counter_percpu_priv *priv,
+                              bool reset)
+ {
+       struct nft_counter_tot total;
+-      nft_counter_fetch(priv, &total);
++      if (unlikely(reset))
++              nft_counter_fetch_and_reset(priv, &total);
++      else
++              nft_counter_fetch(priv, &total);
+       if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
+                        NFTA_COUNTER_PAD) ||
+@@ -162,9 +177,6 @@ static int nft_counter_do_dump(struct sk_buff *skb,
+                        NFTA_COUNTER_PAD))
+               goto nla_put_failure;
+-      if (reset)
+-              nft_counter_reset(priv, &total);
+-
+       return 0;
+ nla_put_failure:
+-- 
+2.53.0
+
diff --git a/staging-6.12/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch b/staging-6.12/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch
new file mode 100644 (file)
index 0000000..97f3dc6
--- /dev/null
@@ -0,0 +1,61 @@
+From 07749809d6857f884e1b16aa556cef9b83f13efe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:38 -0600
+Subject: netfilter: nft_quota: use atomic64_xchg for reset
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 30c4d7fb59ac4c8d7fa7937df11eed10b368fa11 ]
+
+Use atomic64_xchg() to atomically read and zero the consumed value
+on reset, which is simpler than the previous read+sub pattern and
+doesn't require lock serialization.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_quota.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
+index df0798da2329b9..cb6c0e04ff6755 100644
+--- a/net/netfilter/nft_quota.c
++++ b/net/netfilter/nft_quota.c
+@@ -140,11 +140,16 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
+       u64 consumed, consumed_cap, quota;
+       u32 flags = priv->flags;
+-      /* Since we inconditionally increment consumed quota for each packet
++      /* Since we unconditionally increment consumed quota for each packet
+        * that we see, don't go over the quota boundary in what we send to
+        * userspace.
+        */
+-      consumed = atomic64_read(priv->consumed);
++      if (reset) {
++              consumed = atomic64_xchg(priv->consumed, 0);
++              clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
++      } else {
++              consumed = atomic64_read(priv->consumed);
++      }
+       quota = atomic64_read(&priv->quota);
+       if (consumed >= quota) {
+               consumed_cap = quota;
+@@ -160,10 +165,6 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
+           nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
+               goto nla_put_failure;
+-      if (reset) {
+-              atomic64_sub(consumed, priv->consumed);
+-              clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
+-      }
+       return 0;
+ nla_put_failure:
+-- 
+2.53.0
+
diff --git a/staging-6.12/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch b/staging-6.12/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
new file mode 100644 (file)
index 0000000..7571078
--- /dev/null
@@ -0,0 +1,200 @@
+From 49c4710cc0804c5d854b37a3a6e18297ca4a17bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:08 +0800
+Subject: selftests/bpf: Add tests for ld_{abs,ind} failure path in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit e0fcb42bc6f41bab2895757d6610616b3820eff7 upstream.
+
+Extend the verifier_ld_ind BPF selftests with subprogs containing
+ld_{abs,ind} and craft the test in a way where the invalid register
+read is rejected in the fixed case. Also add a success case each,
+and add additional coverage related to the BTF return type enforcement.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_ld_ind
+  [...]
+  #611/1   verifier_ld_ind/ld_ind: check calling conv, r1:OK
+  #611/2   verifier_ld_ind/ld_ind: check calling conv, r1 @unpriv:OK
+  #611/3   verifier_ld_ind/ld_ind: check calling conv, r2:OK
+  #611/4   verifier_ld_ind/ld_ind: check calling conv, r2 @unpriv:OK
+  #611/5   verifier_ld_ind/ld_ind: check calling conv, r3:OK
+  #611/6   verifier_ld_ind/ld_ind: check calling conv, r3 @unpriv:OK
+  #611/7   verifier_ld_ind/ld_ind: check calling conv, r4:OK
+  #611/8   verifier_ld_ind/ld_ind: check calling conv, r4 @unpriv:OK
+  #611/9   verifier_ld_ind/ld_ind: check calling conv, r5:OK
+  #611/10  verifier_ld_ind/ld_ind: check calling conv, r5 @unpriv:OK
+  #611/11  verifier_ld_ind/ld_ind: check calling conv, r7:OK
+  #611/12  verifier_ld_ind/ld_ind: check calling conv, r7 @unpriv:OK
+  #611/13  verifier_ld_ind/ld_abs: subprog early exit on ld_abs failure:OK
+  #611/14  verifier_ld_ind/ld_ind: subprog early exit on ld_ind failure:OK
+  #611/15  verifier_ld_ind/ld_abs: subprog with both paths safe:OK
+  #611/16  verifier_ld_ind/ld_ind: subprog with both paths safe:OK
+  #611/17  verifier_ld_ind/ld_abs: reject void return subprog:OK
+  #611/18  verifier_ld_ind/ld_ind: reject void return subprog:OK
+  #611     verifier_ld_ind:OK
+  Summary: 1/18 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-4-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_ld_ind.c     | 142 ++++++++++++++++++
+ 1 file changed, 142 insertions(+)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+index c925ba9a2e74c2..09e81b99eecb4e 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
++++ b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+@@ -107,4 +107,146 @@ __naked void ind_check_calling_conv_r7(void)
+       : __clobber_all);
+ }
++/*
++ * ld_{abs,ind} subprog that always sets r0=1 on the success path.
++ * bpf_gen_ld_abs() emits a hidden exit with r0=0 when the load helper
++ * fails. The verifier must model this failure return so that callers
++ * account for r0=0 as a possible return value.
++ */
++__naked __noinline __used
++static int ldabs_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++__naked __noinline __used
++static int ldind_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog early exit on ld_abs failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_abs_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog early exit on ld_ind failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_ind_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog with both paths safe")
++__success
++__naked void ld_abs_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog with both paths safe")
++__success
++__naked void ld_ind_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++/*
++ * ld_{abs,ind} in subprogs require scalar (int) return type in BTF.
++ * A test with void return must be rejected.
++ */
++__naked __noinline __used
++static void ldabs_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_abs_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldabs_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++__naked __noinline __used
++static void ldind_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_ind_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldind_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
+ char _license[] SEC("license") = "GPL";
+-- 
+2.53.0
+
index e3628cf8d9f065e8bb65be2975cfff57ed06914a..03317ced8ea23f5689cc02eab9bf71de4be8ae9f 100644 (file)
@@ -1,3 +1,10 @@
 platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
 net-airoha-move-airoha_eth-driver-in-a-dedicated-fol.patch
 net-airoha-fix-skb-priority-underflow-in-airoha_dev_.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
+netfilter-nft_counter-serialize-reset-with-spinlock.patch
+netfilter-nft_quota-use-atomic64_xchg-for-reset.patch
+netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch
+drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
+fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch
diff --git a/staging-6.18/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/staging-6.18/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..f538b39
--- /dev/null
@@ -0,0 +1,71 @@
+From 8b3a33ebf9bf89cca304a2e10fef5916d1203c34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:07 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index d1c51d812f3b66..463455180a8e35 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -17402,6 +17402,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              mark_reg_scratched(env, BPF_REG_0);
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.18/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch b/staging-6.18/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
new file mode 100644 (file)
index 0000000..0ad65b6
--- /dev/null
@@ -0,0 +1,82 @@
+From 60c0c4cffc2072c69dfde68e5c6e40b82d9c9b0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 22:01:00 +0900
+Subject: drm/virtio: fix deadlock in display_info_cb by removing hotplug from
+ dequeue worker
+
+From: Ryosuke Yasuoka <ryasuoka@redhat.com>
+
+[ Upstream commit d1b894c5bbb3fee0012bd14356286dc2384e8213 ]
+
+A probe-time deadlock can occur between the dequeue worker and
+drm_client_register(). During probe, drm_client_register() holds
+clientlist_mutex and calls the fbdev hotplug callback, which triggers an
+atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
+waiting for virtqueue space. The dequeue worker that would free that
+space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
+drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
+to acquire the same clientlist_mutex. Since wake_up() is only called
+after the resp_cb loop, the probe thread is never woken and both threads
+deadlock.
+
+Fix this by removing the hotplug notification from
+virtio_gpu_cmd_get_display_info_cb(). The display data (outputs[i].info)
+is still updated synchronously in the callback.
+
+For the init path, drm_client_register() already fires an initial
+hotplug when the client is registered, which picks up the connector
+state updated by display_info_cb.
+
+For the runtime config_changed path, add a wait_event_timeout() in
+config_changed_work_func() so that display_info_cb updates the connector
+data before the hotplug notification is sent. Also replace
+drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event() since
+virtio-gpu never calls drm_kms_helper_poll_init() and thus
+drm_helper_hpd_irq_event() always returns false without doing anything.
+
+Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
+Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
+Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
+Suggested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
+Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Link: https://patch.msgid.link/20260713-virtiogpu_syzbot-v2-1-2958fa37d46d@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/virtio/virtgpu_kms.c | 5 ++++-
+ drivers/gpu/drm/virtio/virtgpu_vq.c  | 3 ---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
+index 1c15cbf326b78c..4a25347734fda4 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
++++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
+@@ -48,7 +48,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
+                               virtio_gpu_cmd_get_edids(vgdev);
+                       virtio_gpu_cmd_get_display_info(vgdev);
+                       virtio_gpu_notify(vgdev);
+-                      drm_helper_hpd_irq_event(vgdev->ddev);
++                      wait_event_timeout(vgdev->resp_wq,
++                                         !vgdev->display_info_pending,
++                                         5 * HZ);
++                      drm_kms_helper_hotplug_event(vgdev->ddev);
+               }
+               events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
+       }
+diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
+index 8181b22b9b46a1..412384e16daea4 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
+@@ -839,9 +839,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
+       vgdev->display_info_pending = false;
+       spin_unlock(&vgdev->display_info_lock);
+       wake_up(&vgdev->resp_wq);
+-
+-      if (!drm_helper_hpd_irq_event(vgdev->ddev))
+-              drm_kms_helper_hotplug_event(vgdev->ddev);
+ }
+ static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+-- 
+2.53.0
+
diff --git a/staging-6.18/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch b/staging-6.18/fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch
new file mode 100644 (file)
index 0000000..a86e2be
--- /dev/null
@@ -0,0 +1,124 @@
+From 1fb7b87252e9b6ba3e250edddcba62956e2226fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 12:01:23 +0100
+Subject: fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race
+
+From: Kiryl Shutsemau <kas@kernel.org>
+
+commit 04718f7c9290f95385f0dd328758753dc1c36dec upstream.
+
+Patch series "userfaultfd/pagemap: pre-existing fixes".
+
+These are pre-existing bug fixes that were carried at the front of the
+userfaultfd RWP working-set-tracking series up to v5 [1].  Per review
+feedback that fixes should not sit in the middle of a feature series, they
+are split out and sent on their own; the RWP series is reposted rebased on
+top of this.
+
+All six were flagged by the Sashiko AI review of the RWP series and carry
+Reported-by: Sashiko AI review <sashiko-bot@kernel.org>.  They are
+independent of RWP, apply to mm-new directly, and carry Cc: stable@.
+
+  1: fs/proc/task_mmu: a missing huge_ptep_modify_prot_start() in
+     make_uffd_wp_huge_pte() can lose hardware Dirty/Accessed updates
+     when PAGEMAP_SCAN write-protects a hugetlb PTE.
+
+  2: fs/proc/task_mmu: pagemap_scan_hugetlb_entry() compares the range
+     against HPAGE_SIZE rather than the hstate page size, so it never
+     write-protects gigantic hugetlb pages.
+
+  3: fs/proc/task_mmu: PAGEMAP_SCAN with PM_SCAN_WP_MATCHING over an
+     unpopulated hugetlb range self-deadlocks -- pagemap_scan_pte_hole()
+     calls uffd_wp_range() while walk_hugetlb_range() holds the hugetlb
+     vma lock for read, and hugetlb_change_protection() then takes it
+     for write. Install the marker inline instead.
+
+  4: mm/huge_memory: change_non_present_huge_pmd() drops pmd_swp_uffd_wp
+     on a device-private PMD permission downgrade, silently losing the
+     uffd-wp marker.
+
+  5: userfaultfd: must_wait() applies pte_write() to a locklessly read
+     PTE without checking pte_present(), so swap/migration entries
+     decode random offset bits and a thread can stay parked on a stale
+     fault.
+
+  6: userfaultfd: __VMA_UFFD_FLAGS feeds VMA_UFFD_MINOR_BIT (41) to
+     mk_vma_flags() unconditionally, an out-of-bounds write into the
+     single-word vma_flags_t on 32-bit. Build the mask from config-gated
+     per-mode masks so an unavailable bit is never materialised.
+
+This patch (of 6):
+
+make_uffd_wp_huge_pte() arms the UFFD_WP bit on a present HugeTLB PTE by
+calling huge_ptep_modify_prot_commit() with a ptent snapshot that was
+fetched without the corresponding huge_ptep_modify_prot_start().  The
+start helper is what atomically clears the entry so the kernel-owned
+snapshot stays consistent until the commit; without it, the hardware may
+set Dirty or Accessed in the live PTE between the original read and the
+commit, and huge_ptep_modify_prot_commit() (whose generic implementation
+just calls set_huge_pte_at()) then writes the stale snapshot back over the
+live hardware bits, losing the update.
+
+The non-hugetlb sibling make_uffd_wp_pte() does this correctly via
+ptep_modify_prot_start() / ptep_modify_prot_commit().  Mirror that pattern
+for the present-PTE branch.  The migration case stays as-is -- migration
+entries are non-present, so there's no hardware update to race against.
+
+Link: https://lore.kernel.org/20260529172331.356655-1-kas@kernel.org
+Link: https://lore.kernel.org/20260529172331.356655-2-kas@kernel.org
+Link: https://lore.kernel.org/all/20260526130509.2748441-1-kirill@shutemov.name/ [1]
+Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
+Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
+Reported-by: Sashiko AI review <sashiko-bot@kernel.org>
+Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
+Reviewed-by: Dev Jain <dev.jain@arm.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Balbir Singh <balbirs@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ kas: adapt to the pre-softleaf idiom; apply the
+  huge_ptep_modify_prot_start()/commit() fix to the present-PTE
+  (!huge_pte_none()) branch ]
+Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/task_mmu.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 38b9d47426ca99..858b11009c269e 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -2485,15 +2485,19 @@ static void make_uffd_wp_huge_pte(struct vm_area_struct *vma,
+       psize = huge_page_size(hstate_vma(vma));
+-      if (is_hugetlb_entry_migration(ptent))
++      if (is_hugetlb_entry_migration(ptent)) {
+               set_huge_pte_at(vma->vm_mm, addr, ptep,
+                               pte_swp_mkuffd_wp(ptent), psize);
+-      else if (!huge_pte_none(ptent))
+-              huge_ptep_modify_prot_commit(vma, addr, ptep, ptent,
+-                                           huge_pte_mkuffd_wp(ptent));
+-      else
++      } else if (!huge_pte_none(ptent)) {
++              pte_t old_pte, new_pte;
++
++              old_pte = huge_ptep_modify_prot_start(vma, addr, ptep);
++              new_pte = huge_pte_mkuffd_wp(old_pte);
++              huge_ptep_modify_prot_commit(vma, addr, ptep, old_pte, new_pte);
++      } else {
+               set_huge_pte_at(vma->vm_mm, addr, ptep,
+                               make_pte_marker(PTE_MARKER_UFFD_WP), psize);
++      }
+ }
+ #endif /* CONFIG_HUGETLB_PAGE */
+-- 
+2.53.0
+
diff --git a/staging-6.18/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch b/staging-6.18/netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch
new file mode 100644 (file)
index 0000000..95481ac
--- /dev/null
@@ -0,0 +1,424 @@
+From 6b1304757f523ace8898896505d3108bbcc89a70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:36 -0600
+Subject: netfilter: nf_tables: revert commit_mutex usage in reset path
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 7f261bb906bf527c4a6e2a646e2d5f3679f2a8bc ]
+
+It causes circular lock dependency between commit_mutex, nfnl_subsys_ipset
+and nlk_cb_mutex when nft reset, ipset list, and iptables-nft with '-m set'
+rule run at the same time.
+
+Previous patches made it safe to run individual reset handlers concurrently
+so commit_mutex is no longer required to prevent this.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Link: https://lore.kernel.org/all/aUh_3mVRV8OrGsVo@strlen.de/
+Reported-by: <syzbot+ff16b505ec9152e5f448@syzkaller.appspotmail.com>
+Closes: https://syzkaller.appspot.com/bug?extid=ff16b505ec9152e5f448
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 248 ++++++----------------------------
+ 1 file changed, 42 insertions(+), 206 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 0842916c19f503..c82c16bd4257e4 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -3908,23 +3908,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
+       return skb->len;
+ }
+-static int nf_tables_dumpreset_rules(struct sk_buff *skb,
+-                                   struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      int ret;
+-
+-      /* Mutex is held is to prevent that two concurrent dump-and-reset calls
+-       * do not underrun counters and quotas. The commit_mutex is used for
+-       * the lack a better lock, this is not transaction path.
+-       */
+-      mutex_lock(&nft_net->commit_mutex);
+-      ret = nf_tables_dump_rules(skb, cb);
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
+ {
+       struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
+@@ -3944,16 +3927,10 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
+                       return -ENOMEM;
+               }
+       }
+-      return 0;
+-}
+-
+-static int nf_tables_dumpreset_rules_start(struct netlink_callback *cb)
+-{
+-      struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
+-
+-      ctx->reset = true;
++      if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
++              ctx->reset = true;
+-      return nf_tables_dump_rules_start(cb);
++      return 0;
+ }
+ static int nf_tables_dump_rules_done(struct netlink_callback *cb)
+@@ -4019,6 +3996,8 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
+       u32 portid = NETLINK_CB(skb).portid;
+       struct net *net = info->net;
+       struct sk_buff *skb2;
++      bool reset = false;
++      char *buf;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+@@ -4032,47 +4011,16 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+       }
+-      skb2 = nf_tables_getrule_single(portid, info, nla, false);
+-      if (IS_ERR(skb2))
+-              return PTR_ERR(skb2);
+-
+-      return nfnetlink_unicast(skb2, net, portid);
+-}
+-
+-static int nf_tables_getrule_reset(struct sk_buff *skb,
+-                                 const struct nfnl_info *info,
+-                                 const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+-      u32 portid = NETLINK_CB(skb).portid;
+-      struct net *net = info->net;
+-      struct sk_buff *skb2;
+-      char *buf;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start= nf_tables_dumpreset_rules_start,
+-                      .dump = nf_tables_dumpreset_rules,
+-                      .done = nf_tables_dump_rules_done,
+-                      .module = THIS_MODULE,
+-                      .data = (void *)nla,
+-              };
+-
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      skb2 = nf_tables_getrule_single(portid, info, nla, true);
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
++              reset = true;
++      skb2 = nf_tables_getrule_single(portid, info, nla, reset);
+       if (IS_ERR(skb2))
+               return PTR_ERR(skb2);
++      if (!reset)
++              return nfnetlink_unicast(skb2, net, portid);
++
+       buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
+                       nla_len(nla[NFTA_RULE_TABLE]),
+                       (char *)nla_data(nla[NFTA_RULE_TABLE]),
+@@ -6332,6 +6280,10 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
+       nla_nest_end(skb, nest);
+       nlmsg_end(skb, nlh);
++      if (dump_ctx->reset && args.iter.count > args.iter.skip)
++              audit_log_nft_set_reset(table, cb->seq,
++                                      args.iter.count - args.iter.skip);
++
+       rcu_read_unlock();
+       if (args.iter.err && args.iter.err != -EMSGSIZE)
+@@ -6347,26 +6299,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
+       return -ENOSPC;
+ }
+-static int nf_tables_dumpreset_set(struct sk_buff *skb,
+-                                 struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      struct nft_set_dump_ctx *dump_ctx = cb->data;
+-      int ret, skip = cb->args[0];
+-
+-      mutex_lock(&nft_net->commit_mutex);
+-
+-      ret = nf_tables_dump_set(skb, cb);
+-
+-      if (cb->args[0] > skip)
+-              audit_log_nft_set_reset(dump_ctx->ctx.table, cb->seq,
+-                                      cb->args[0] - skip);
+-
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_set_start(struct netlink_callback *cb)
+ {
+       struct nft_set_dump_ctx *dump_ctx = cb->data;
+@@ -6613,8 +6545,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+ {
+       struct netlink_ext_ack *extack = info->extack;
+       struct nft_set_dump_ctx dump_ctx;
++      int rem, err = 0, nelems = 0;
++      struct net *net = info->net;
+       struct nlattr *attr;
+-      int rem, err = 0;
++      bool reset = false;
++
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
++              reset = true;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+@@ -6624,7 +6561,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+                       .module = THIS_MODULE,
+               };
+-              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
++              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
+               if (err)
+                       return err;
+@@ -6635,75 +6572,21 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
+       if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
+               return -EINVAL;
+-      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
++      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
+       if (err)
+               return err;
+       nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+-              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, false);
+-              if (err < 0) {
+-                      NL_SET_BAD_ATTR(extack, attr);
+-                      break;
+-              }
+-      }
+-
+-      return err;
+-}
+-
+-static int nf_tables_getsetelem_reset(struct sk_buff *skb,
+-                                    const struct nfnl_info *info,
+-                                    const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+-      struct netlink_ext_ack *extack = info->extack;
+-      struct nft_set_dump_ctx dump_ctx;
+-      int rem, err = 0, nelems = 0;
+-      struct nlattr *attr;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start = nf_tables_dump_set_start,
+-                      .dump = nf_tables_dumpreset_set,
+-                      .done = nf_tables_dump_set_done,
+-                      .module = THIS_MODULE,
+-              };
+-
+-              err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
+-              if (err)
+-                      return err;
+-
+-              c.data = &dump_ctx;
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
+-              return -EINVAL;
+-
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-
+-      err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
+-      if (err)
+-              goto out_unlock;
+-
+-      nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+-              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, true);
++              err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, reset);
+               if (err < 0) {
+                       NL_SET_BAD_ATTR(extack, attr);
+                       break;
+               }
+               nelems++;
+       }
+-      audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems);
+-
+-out_unlock:
+-      rcu_read_unlock();
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (reset)
++              audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(net),
++                                      nelems);
+       return err;
+ }
+@@ -8567,19 +8450,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
+       return skb->len;
+ }
+-static int nf_tables_dumpreset_obj(struct sk_buff *skb,
+-                                 struct netlink_callback *cb)
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+-      int ret;
+-
+-      mutex_lock(&nft_net->commit_mutex);
+-      ret = nf_tables_dump_obj(skb, cb);
+-      mutex_unlock(&nft_net->commit_mutex);
+-
+-      return ret;
+-}
+-
+ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
+ {
+       struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
+@@ -8596,16 +8466,10 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
+       if (nla[NFTA_OBJ_TYPE])
+               ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+-      return 0;
+-}
+-
+-static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb)
+-{
+-      struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
+-
+-      ctx->reset = true;
++      if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
++              ctx->reset = true;
+-      return nf_tables_dump_obj_start(cb);
++      return 0;
+ }
+ static int nf_tables_dump_obj_done(struct netlink_callback *cb)
+@@ -8667,42 +8531,16 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
+ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
+ {
+-      u32 portid = NETLINK_CB(skb).portid;
+-      struct sk_buff *skb2;
+-
+-      if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+-              struct netlink_dump_control c = {
+-                      .start = nf_tables_dump_obj_start,
+-                      .dump = nf_tables_dump_obj,
+-                      .done = nf_tables_dump_obj_done,
+-                      .module = THIS_MODULE,
+-                      .data = (void *)nla,
+-              };
+-
+-              return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+-      }
+-
+-      skb2 = nf_tables_getobj_single(portid, info, nla, false);
+-      if (IS_ERR(skb2))
+-              return PTR_ERR(skb2);
+-
+-      return nfnetlink_unicast(skb2, info->net, portid);
+-}
+-
+-static int nf_tables_getobj_reset(struct sk_buff *skb,
+-                                const struct nfnl_info *info,
+-                                const struct nlattr * const nla[])
+-{
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+       u32 portid = NETLINK_CB(skb).portid;
+       struct net *net = info->net;
+       struct sk_buff *skb2;
++      bool reset = false;
+       char *buf;
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+-                      .start = nf_tables_dumpreset_obj_start,
+-                      .dump = nf_tables_dumpreset_obj,
++                      .start = nf_tables_dump_obj_start,
++                      .dump = nf_tables_dump_obj,
+                       .done = nf_tables_dump_obj_done,
+                       .module = THIS_MODULE,
+                       .data = (void *)nla,
+@@ -8711,18 +8549,16 @@ static int nf_tables_getobj_reset(struct sk_buff *skb,
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+       }
+-      if (!try_module_get(THIS_MODULE))
+-              return -EINVAL;
+-      rcu_read_unlock();
+-      mutex_lock(&nft_net->commit_mutex);
+-      skb2 = nf_tables_getobj_single(portid, info, nla, true);
+-      mutex_unlock(&nft_net->commit_mutex);
+-      rcu_read_lock();
+-      module_put(THIS_MODULE);
++      if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
++              reset = true;
++      skb2 = nf_tables_getobj_single(portid, info, nla, reset);
+       if (IS_ERR(skb2))
+               return PTR_ERR(skb2);
++      if (!reset)
++              return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
++
+       buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
+                       nla_len(nla[NFTA_OBJ_TABLE]),
+                       (char *)nla_data(nla[NFTA_OBJ_TABLE]),
+@@ -10030,7 +9866,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_rule_policy,
+       },
+       [NFT_MSG_GETRULE_RESET] = {
+-              .call           = nf_tables_getrule_reset,
++              .call           = nf_tables_getrule,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_RULE_MAX,
+               .policy         = nft_rule_policy,
+@@ -10084,7 +9920,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_set_elem_list_policy,
+       },
+       [NFT_MSG_GETSETELEM_RESET] = {
+-              .call           = nf_tables_getsetelem_reset,
++              .call           = nf_tables_getsetelem,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_SET_ELEM_LIST_MAX,
+               .policy         = nft_set_elem_list_policy,
+@@ -10130,7 +9966,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
+               .policy         = nft_obj_policy,
+       },
+       [NFT_MSG_GETOBJ_RESET] = {
+-              .call           = nf_tables_getobj_reset,
++              .call           = nf_tables_getobj,
+               .type           = NFNL_CB_RCU,
+               .attr_count     = NFTA_OBJ_MAX,
+               .policy         = nft_obj_policy,
+-- 
+2.53.0
+
diff --git a/staging-6.18/netfilter-nft_counter-serialize-reset-with-spinlock.patch b/staging-6.18/netfilter-nft_counter-serialize-reset-with-spinlock.patch
new file mode 100644 (file)
index 0000000..e2846bb
--- /dev/null
@@ -0,0 +1,86 @@
+From 4a9110c30d5e1af7349390950df0bc7e9b4a14cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:37 -0600
+Subject: netfilter: nft_counter: serialize reset with spinlock
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 779c60a5190c42689534172f4b49e927c9959e4e ]
+
+Add a global static spinlock to serialize counter fetch+reset
+operations, preventing concurrent dump-and-reset from underrunning
+values.
+
+The lock is taken before fetching the total so that two parallel
+resets cannot both read the same counter values and then both
+subtract them.
+
+A global lock is used for simplicity since resets are infrequent.
+If this becomes a bottleneck, it can be replaced with a per-net
+lock later.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_counter.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c
+index 0d70325280cc57..169ae93688bcc5 100644
+--- a/net/netfilter/nft_counter.c
++++ b/net/netfilter/nft_counter.c
+@@ -32,6 +32,9 @@ struct nft_counter_percpu_priv {
+ static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);
++/* control plane only: sync fetch+reset */
++static DEFINE_SPINLOCK(nft_counter_lock);
++
+ static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
+                                      struct nft_regs *regs,
+                                      const struct nft_pktinfo *pkt)
+@@ -148,13 +151,25 @@ static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
+       }
+ }
++static void nft_counter_fetch_and_reset(struct nft_counter_percpu_priv *priv,
++                                      struct nft_counter_tot *total)
++{
++      spin_lock(&nft_counter_lock);
++      nft_counter_fetch(priv, total);
++      nft_counter_reset(priv, total);
++      spin_unlock(&nft_counter_lock);
++}
++
+ static int nft_counter_do_dump(struct sk_buff *skb,
+                              struct nft_counter_percpu_priv *priv,
+                              bool reset)
+ {
+       struct nft_counter_tot total;
+-      nft_counter_fetch(priv, &total);
++      if (unlikely(reset))
++              nft_counter_fetch_and_reset(priv, &total);
++      else
++              nft_counter_fetch(priv, &total);
+       if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
+                        NFTA_COUNTER_PAD) ||
+@@ -162,9 +177,6 @@ static int nft_counter_do_dump(struct sk_buff *skb,
+                        NFTA_COUNTER_PAD))
+               goto nla_put_failure;
+-      if (reset)
+-              nft_counter_reset(priv, &total);
+-
+       return 0;
+ nla_put_failure:
+-- 
+2.53.0
+
diff --git a/staging-6.18/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch b/staging-6.18/netfilter-nft_quota-use-atomic64_xchg-for-reset.patch
new file mode 100644 (file)
index 0000000..46f8477
--- /dev/null
@@ -0,0 +1,61 @@
+From a3ef9fe7d75aac0a74fabd11231e810069a54360 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Feb 2026 14:26:38 -0600
+Subject: netfilter: nft_quota: use atomic64_xchg for reset
+
+From: Brian Witte <brianwitte@mailfence.com>
+
+[ Upstream commit 30c4d7fb59ac4c8d7fa7937df11eed10b368fa11 ]
+
+Use atomic64_xchg() to atomically read and zero the consumed value
+on reset, which is simpler than the previous read+sub pattern and
+doesn't require lock serialization.
+
+Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
+Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
+Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
+Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Brian Witte <brianwitte@mailfence.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_quota.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
+index df0798da2329b9..cb6c0e04ff6755 100644
+--- a/net/netfilter/nft_quota.c
++++ b/net/netfilter/nft_quota.c
+@@ -140,11 +140,16 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
+       u64 consumed, consumed_cap, quota;
+       u32 flags = priv->flags;
+-      /* Since we inconditionally increment consumed quota for each packet
++      /* Since we unconditionally increment consumed quota for each packet
+        * that we see, don't go over the quota boundary in what we send to
+        * userspace.
+        */
+-      consumed = atomic64_read(priv->consumed);
++      if (reset) {
++              consumed = atomic64_xchg(priv->consumed, 0);
++              clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
++      } else {
++              consumed = atomic64_read(priv->consumed);
++      }
+       quota = atomic64_read(&priv->quota);
+       if (consumed >= quota) {
+               consumed_cap = quota;
+@@ -160,10 +165,6 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
+           nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
+               goto nla_put_failure;
+-      if (reset) {
+-              atomic64_sub(consumed, priv->consumed);
+-              clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
+-      }
+       return 0;
+ nla_put_failure:
+-- 
+2.53.0
+
diff --git a/staging-6.18/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch b/staging-6.18/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
new file mode 100644 (file)
index 0000000..8d881a3
--- /dev/null
@@ -0,0 +1,200 @@
+From d3b6095a981698eb7d0e7c72ff6ade902bcdedff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:08 +0800
+Subject: selftests/bpf: Add tests for ld_{abs,ind} failure path in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit e0fcb42bc6f41bab2895757d6610616b3820eff7 upstream.
+
+Extend the verifier_ld_ind BPF selftests with subprogs containing
+ld_{abs,ind} and craft the test in a way where the invalid register
+read is rejected in the fixed case. Also add a success case each,
+and add additional coverage related to the BTF return type enforcement.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_ld_ind
+  [...]
+  #611/1   verifier_ld_ind/ld_ind: check calling conv, r1:OK
+  #611/2   verifier_ld_ind/ld_ind: check calling conv, r1 @unpriv:OK
+  #611/3   verifier_ld_ind/ld_ind: check calling conv, r2:OK
+  #611/4   verifier_ld_ind/ld_ind: check calling conv, r2 @unpriv:OK
+  #611/5   verifier_ld_ind/ld_ind: check calling conv, r3:OK
+  #611/6   verifier_ld_ind/ld_ind: check calling conv, r3 @unpriv:OK
+  #611/7   verifier_ld_ind/ld_ind: check calling conv, r4:OK
+  #611/8   verifier_ld_ind/ld_ind: check calling conv, r4 @unpriv:OK
+  #611/9   verifier_ld_ind/ld_ind: check calling conv, r5:OK
+  #611/10  verifier_ld_ind/ld_ind: check calling conv, r5 @unpriv:OK
+  #611/11  verifier_ld_ind/ld_ind: check calling conv, r7:OK
+  #611/12  verifier_ld_ind/ld_ind: check calling conv, r7 @unpriv:OK
+  #611/13  verifier_ld_ind/ld_abs: subprog early exit on ld_abs failure:OK
+  #611/14  verifier_ld_ind/ld_ind: subprog early exit on ld_ind failure:OK
+  #611/15  verifier_ld_ind/ld_abs: subprog with both paths safe:OK
+  #611/16  verifier_ld_ind/ld_ind: subprog with both paths safe:OK
+  #611/17  verifier_ld_ind/ld_abs: reject void return subprog:OK
+  #611/18  verifier_ld_ind/ld_ind: reject void return subprog:OK
+  #611     verifier_ld_ind:OK
+  Summary: 1/18 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-4-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_ld_ind.c     | 142 ++++++++++++++++++
+ 1 file changed, 142 insertions(+)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+index c925ba9a2e74c2..09e81b99eecb4e 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
++++ b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+@@ -107,4 +107,146 @@ __naked void ind_check_calling_conv_r7(void)
+       : __clobber_all);
+ }
++/*
++ * ld_{abs,ind} subprog that always sets r0=1 on the success path.
++ * bpf_gen_ld_abs() emits a hidden exit with r0=0 when the load helper
++ * fails. The verifier must model this failure return so that callers
++ * account for r0=0 as a possible return value.
++ */
++__naked __noinline __used
++static int ldabs_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++__naked __noinline __used
++static int ldind_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog early exit on ld_abs failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_abs_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog early exit on ld_ind failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_ind_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog with both paths safe")
++__success
++__naked void ld_abs_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog with both paths safe")
++__success
++__naked void ld_ind_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++/*
++ * ld_{abs,ind} in subprogs require scalar (int) return type in BTF.
++ * A test with void return must be rejected.
++ */
++__naked __noinline __used
++static void ldabs_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_abs_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldabs_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++__naked __noinline __used
++static void ldind_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_ind_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldind_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
+ char _license[] SEC("license") = "GPL";
+-- 
+2.53.0
+
index a69a51ccf5087a65f0b69157f284d4c9747125ae..b0d818b02e54f1cf3f4e85e150802dfeccb74a31 100644 (file)
@@ -1,3 +1,10 @@
 posix-timers-expand-timer_-re-arm-callbacks-with-a-b.patch
 posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
 platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
+netfilter-nft_counter-serialize-reset-with-spinlock.patch
+netfilter-nft_quota-use-atomic64_xchg-for-reset.patch
+netfilter-nf_tables-revert-commit_mutex-usage-in-res.patch
+drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
+fs-proc-task_mmu-fix-make_uffd_wp_huge_pte-prot-upda.patch
diff --git a/staging-6.6/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/staging-6.6/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..d82aa92
--- /dev/null
@@ -0,0 +1,71 @@
+From 477e3f08c9d4e470f508dc8f21a8699830f01176 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:07 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 1da0092122c1db..5e094c12fc94c5 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -15120,6 +15120,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              mark_reg_scratched(env, BPF_REG_0);
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.6/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch b/staging-6.6/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
new file mode 100644 (file)
index 0000000..44755d1
--- /dev/null
@@ -0,0 +1,82 @@
+From 09ef4b7a3b15ae1f5471cf07728820c038354e3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 22:01:00 +0900
+Subject: drm/virtio: fix deadlock in display_info_cb by removing hotplug from
+ dequeue worker
+
+From: Ryosuke Yasuoka <ryasuoka@redhat.com>
+
+[ Upstream commit d1b894c5bbb3fee0012bd14356286dc2384e8213 ]
+
+A probe-time deadlock can occur between the dequeue worker and
+drm_client_register(). During probe, drm_client_register() holds
+clientlist_mutex and calls the fbdev hotplug callback, which triggers an
+atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
+waiting for virtqueue space. The dequeue worker that would free that
+space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
+drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
+to acquire the same clientlist_mutex. Since wake_up() is only called
+after the resp_cb loop, the probe thread is never woken and both threads
+deadlock.
+
+Fix this by removing the hotplug notification from
+virtio_gpu_cmd_get_display_info_cb(). The display data (outputs[i].info)
+is still updated synchronously in the callback.
+
+For the init path, drm_client_register() already fires an initial
+hotplug when the client is registered, which picks up the connector
+state updated by display_info_cb.
+
+For the runtime config_changed path, add a wait_event_timeout() in
+config_changed_work_func() so that display_info_cb updates the connector
+data before the hotplug notification is sent. Also replace
+drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event() since
+virtio-gpu never calls drm_kms_helper_poll_init() and thus
+drm_helper_hpd_irq_event() always returns false without doing anything.
+
+Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
+Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
+Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
+Suggested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
+Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Link: https://patch.msgid.link/20260713-virtiogpu_syzbot-v2-1-2958fa37d46d@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/virtio/virtgpu_kms.c | 5 ++++-
+ drivers/gpu/drm/virtio/virtgpu_vq.c  | 3 ---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
+index 5a3b5aaed1f361..c88456bc9fcc00 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
++++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
+@@ -48,7 +48,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
+                               virtio_gpu_cmd_get_edids(vgdev);
+                       virtio_gpu_cmd_get_display_info(vgdev);
+                       virtio_gpu_notify(vgdev);
+-                      drm_helper_hpd_irq_event(vgdev->ddev);
++                      wait_event_timeout(vgdev->resp_wq,
++                                         !vgdev->display_info_pending,
++                                         5 * HZ);
++                      drm_kms_helper_hotplug_event(vgdev->ddev);
+               }
+               events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
+       }
+diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
+index b1a00c0c25a70b..fbafa44a726453 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
+@@ -669,9 +669,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
+       vgdev->display_info_pending = false;
+       spin_unlock(&vgdev->display_info_lock);
+       wake_up(&vgdev->resp_wq);
+-
+-      if (!drm_helper_hpd_irq_event(vgdev->ddev))
+-              drm_kms_helper_hotplug_event(vgdev->ddev);
+ }
+ static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+-- 
+2.53.0
+
diff --git a/staging-6.6/platform-x86-amd-pmc-avoid-logging-null-for-dmi-valu.patch b/staging-6.6/platform-x86-amd-pmc-avoid-logging-null-for-dmi-valu.patch
new file mode 100644 (file)
index 0000000..c65d083
--- /dev/null
@@ -0,0 +1,56 @@
+From 295d1cf7e341d3d27dccefd8775ad6d71ad0ac93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 18:54:02 +0200
+Subject: platform/x86/amd/pmc: Avoid logging "(null)" for DMI values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Daniel Gibson <daniel@gibson.sh>
+
+commit a0738abd042f7406edd2175a819cf2e66388ed97 upstream.
+
+dmi_get_system_info(...) can return NULL. Using that as %s arguments
+of dev_info() would log "(null)" (as part of a message like
+'... System Vendor: "(null)", Product Name: "(null)" ...'), which may
+be confusing for users.
+
+Use Elvis operator to print "(Unknown)" instead.
+
+Fixes: 428b9fd2dce5 ("platform/x86/amd/pmc: Add delay_suspend module parameter")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202606251540.Nr2BtaNu-lkp@intel.com/
+Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Daniel Gibson <daniel@gibson.sh>
+Link: https://patch.msgid.link/20260626220210.1761783-2-daniel@gibson.sh
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/amd/pmc/pmc.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
+index b0951236887797..bf6c7ca247e243 100644
+--- a/drivers/platform/x86/amd/pmc/pmc.c
++++ b/drivers/platform/x86/amd/pmc/pmc.c
+@@ -852,11 +852,11 @@ static bool amd_pmc_want_suspend_delay(struct amd_pmc_dev *pdev)
+       } else if (delay_suspend == 1) {
+               if (!intermediate_wakeup)
+                       dev_info(pdev->dev, "Delaying suspend by 2.5s because delay_suspend=1. If this solves problems on your machine, please report this whole line to: platform-driver-x86@vger.kernel.org so it can be automatically detected as affected in the future. System Vendor: \"%s\" Product Name: \"%s\" Product Family: \"%s\" Board Vendor: \"%s\" Board Name: \"%s\"\n",
+-                               dmi_get_system_info(DMI_SYS_VENDOR),
+-                               dmi_get_system_info(DMI_PRODUCT_NAME),
+-                               dmi_get_system_info(DMI_PRODUCT_FAMILY),
+-                               dmi_get_system_info(DMI_BOARD_VENDOR),
+-                               dmi_get_system_info(DMI_BOARD_NAME));
++                               dmi_get_system_info(DMI_SYS_VENDOR) ?: "(Unknown)",
++                               dmi_get_system_info(DMI_PRODUCT_NAME) ?: "(Unknown)",
++                               dmi_get_system_info(DMI_PRODUCT_FAMILY) ?: "(Unknown)",
++                               dmi_get_system_info(DMI_BOARD_VENDOR) ?: "(Unknown)",
++                               dmi_get_system_info(DMI_BOARD_NAME) ?: "(Unknown)");
+               return true;
+       }
+       return false;
+-- 
+2.53.0
+
diff --git a/staging-6.6/platform-x86-amd-pmc-don-t-log-during-intermediate-w.patch b/staging-6.6/platform-x86-amd-pmc-don-t-log-during-intermediate-w.patch
new file mode 100644 (file)
index 0000000..21aaac0
--- /dev/null
@@ -0,0 +1,124 @@
+From c5e4d6584db2775f800e78be3e2b442957eb7c40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 18:54:01 +0200
+Subject: platform/x86/amd/pmc: Don't log during intermediate wakeups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Daniel Gibson <daniel@gibson.sh>
+
+commit 037f0b03c663a247366673a807834389107995b7 upstream.
+
+The ECs in the IdeaPads that need the delay_suspend quirk send lots
+of messages when charging, which not only causes intermediate wakeups
+when suspended, but also prevents the device from reaching the deepest
+suspend state.
+
+Because of this amd_pmc_intermediate_wakeup_need_delay() returns false
+during intermediate wakeups and amd_pmc_want_suspend_delay() is called.
+So far it always logged its "Delaying suspend by 2.5s ..." messages
+then, which spams dmesg. This commit makes sure that those messages are
+only logged once per suspend.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=221383
+Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Daniel Gibson <daniel@gibson.sh>
+Link: https://patch.msgid.link/20260611150426.3683372-5-daniel@gibson.sh
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/amd/pmc/pmc.c | 39 ++++++++++++++++++++++++------
+ drivers/platform/x86/amd/pmc/pmc.h |  1 +
+ 2 files changed, 32 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
+index d5b543f74a22db..b0951236887797 100644
+--- a/drivers/platform/x86/amd/pmc/pmc.c
++++ b/drivers/platform/x86/amd/pmc/pmc.c
+@@ -811,6 +811,20 @@ static bool amd_pmc_intermediate_wakeup_need_delay(struct amd_pmc_dev *pdev)
+ static bool amd_pmc_want_suspend_delay(struct amd_pmc_dev *pdev)
+ {
++      /*
++       * intermediate_wakeup implies that the machine didn't get to deepest sleep
++       * state before - otherwise this function isn't called in amd_pmc_s2idle_check()
++       * because amd_pmc_intermediate_wakeup_need_delay() returns true first.
++       * On some IdeaPads that happens when charging, because the EC seems
++       * to send lots of messages then that wake the machine.
++       *
++       * But even in that case, the sleep here is necessary (on those IdeaPads),
++       * otherwise they wake up completely (resume) after a few seconds.
++       * So this variable is only used to avoid spamming dmesg on each
++       * intermediate wakeup.
++       */
++      bool intermediate_wakeup = !pdev->is_first_check_after_suspend;
++
+       /*
+        * Some Lenovo Laptops (like different IdeaPad 3 Slims) need some
+        * me-time before sleeping or they get uncooperative after waking
+@@ -829,17 +843,20 @@ static bool amd_pmc_want_suspend_delay(struct amd_pmc_dev *pdev)
+                * disabled with disable_workarounds or delay_suspend=0
+                */
+               if (delay_suspend == 1 || (delay_suspend == -1 && !disable_workarounds)) {
+-                      dev_info(pdev->dev, "Delaying suspend by 2.5s to avoid platform bug\n");
++                      if (!intermediate_wakeup)
++                              dev_info(pdev->dev, "Delaying suspend by 2.5s to avoid platform bug\n");
+                       return true;
+               }
+-              dev_info(pdev->dev, "Not delaying suspend because of module parameter, even though your device is assumed to need it!\n");
++              if (!intermediate_wakeup)
++                      dev_info(pdev->dev, "Not delaying suspend because of module parameter, even though your device is assumed to need it!\n");
+       } else if (delay_suspend == 1) {
+-              dev_info(pdev->dev, "Delaying suspend by 2.5s because delay_suspend=1. If this solves problems on your machine, please report this whole line to: platform-driver-x86@vger.kernel.org so it can be automatically detected as affected in the future. System Vendor: \"%s\" Product Name: \"%s\" Product Family: \"%s\" Board Vendor: \"%s\" Board Name: \"%s\"\n",
+-                       dmi_get_system_info(DMI_SYS_VENDOR),
+-                       dmi_get_system_info(DMI_PRODUCT_NAME),
+-                       dmi_get_system_info(DMI_PRODUCT_FAMILY),
+-                       dmi_get_system_info(DMI_BOARD_VENDOR),
+-                       dmi_get_system_info(DMI_BOARD_NAME));
++              if (!intermediate_wakeup)
++                      dev_info(pdev->dev, "Delaying suspend by 2.5s because delay_suspend=1. If this solves problems on your machine, please report this whole line to: platform-driver-x86@vger.kernel.org so it can be automatically detected as affected in the future. System Vendor: \"%s\" Product Name: \"%s\" Product Family: \"%s\" Board Vendor: \"%s\" Board Name: \"%s\"\n",
++                               dmi_get_system_info(DMI_SYS_VENDOR),
++                               dmi_get_system_info(DMI_PRODUCT_NAME),
++                               dmi_get_system_info(DMI_PRODUCT_FAMILY),
++                               dmi_get_system_info(DMI_BOARD_VENDOR),
++                               dmi_get_system_info(DMI_BOARD_NAME));
+               return true;
+       }
+       return false;
+@@ -852,6 +869,9 @@ static void amd_pmc_s2idle_prepare(void)
+       u8 msg;
+       u32 arg = 1;
++      /* Reset this variable because this is a fresh suspend */
++      pdev->is_first_check_after_suspend = true;
++
+       /* Reset and Start SMU logging - to monitor the s0i3 stats */
+       amd_pmc_setup_smu_logging(pdev);
+@@ -891,6 +911,9 @@ static void amd_pmc_s2idle_check(void)
+       rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_S2IDLE_CHECK);
+       if (rc)
+               dev_err(pdev->dev, "error writing to STB: %d\n", rc);
++
++      /* remember that first check after suspend is done (until next prepare) */
++      pdev->is_first_check_after_suspend = false;
+ }
+ static int amd_pmc_dump_data(struct amd_pmc_dev *pdev)
+diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h
+index 5e7b8d5dc5d624..bea65810de5ab6 100644
+--- a/drivers/platform/x86/amd/pmc/pmc.h
++++ b/drivers/platform/x86/amd/pmc/pmc.h
+@@ -37,6 +37,7 @@ struct amd_pmc_dev {
+       struct dentry *dbgfs_dir;
+       struct quirk_entry *quirks;
+       bool disable_8042_wakeup;
++      bool is_first_check_after_suspend;
+ };
+ void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
+-- 
+2.53.0
+
diff --git a/staging-6.6/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch b/staging-6.6/selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
new file mode 100644 (file)
index 0000000..6b05514
--- /dev/null
@@ -0,0 +1,200 @@
+From 0ccd05109e62f37f8364fcfe1f962026cda29a77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jul 2026 15:39:08 +0800
+Subject: selftests/bpf: Add tests for ld_{abs,ind} failure path in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit e0fcb42bc6f41bab2895757d6610616b3820eff7 upstream.
+
+Extend the verifier_ld_ind BPF selftests with subprogs containing
+ld_{abs,ind} and craft the test in a way where the invalid register
+read is rejected in the fixed case. Also add a success case each,
+and add additional coverage related to the BTF return type enforcement.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_ld_ind
+  [...]
+  #611/1   verifier_ld_ind/ld_ind: check calling conv, r1:OK
+  #611/2   verifier_ld_ind/ld_ind: check calling conv, r1 @unpriv:OK
+  #611/3   verifier_ld_ind/ld_ind: check calling conv, r2:OK
+  #611/4   verifier_ld_ind/ld_ind: check calling conv, r2 @unpriv:OK
+  #611/5   verifier_ld_ind/ld_ind: check calling conv, r3:OK
+  #611/6   verifier_ld_ind/ld_ind: check calling conv, r3 @unpriv:OK
+  #611/7   verifier_ld_ind/ld_ind: check calling conv, r4:OK
+  #611/8   verifier_ld_ind/ld_ind: check calling conv, r4 @unpriv:OK
+  #611/9   verifier_ld_ind/ld_ind: check calling conv, r5:OK
+  #611/10  verifier_ld_ind/ld_ind: check calling conv, r5 @unpriv:OK
+  #611/11  verifier_ld_ind/ld_ind: check calling conv, r7:OK
+  #611/12  verifier_ld_ind/ld_ind: check calling conv, r7 @unpriv:OK
+  #611/13  verifier_ld_ind/ld_abs: subprog early exit on ld_abs failure:OK
+  #611/14  verifier_ld_ind/ld_ind: subprog early exit on ld_ind failure:OK
+  #611/15  verifier_ld_ind/ld_abs: subprog with both paths safe:OK
+  #611/16  verifier_ld_ind/ld_ind: subprog with both paths safe:OK
+  #611/17  verifier_ld_ind/ld_abs: reject void return subprog:OK
+  #611/18  verifier_ld_ind/ld_ind: reject void return subprog:OK
+  #611     verifier_ld_ind:OK
+  Summary: 1/18 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-4-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_ld_ind.c     | 142 ++++++++++++++++++
+ 1 file changed, 142 insertions(+)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+index c925ba9a2e74c2..09e81b99eecb4e 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
++++ b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+@@ -107,4 +107,146 @@ __naked void ind_check_calling_conv_r7(void)
+       : __clobber_all);
+ }
++/*
++ * ld_{abs,ind} subprog that always sets r0=1 on the success path.
++ * bpf_gen_ld_abs() emits a hidden exit with r0=0 when the load helper
++ * fails. The verifier must model this failure return so that callers
++ * account for r0=0 as a possible return value.
++ */
++__naked __noinline __used
++static int ldabs_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++__naked __noinline __used
++static int ldind_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog early exit on ld_abs failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_abs_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog early exit on ld_ind failure")
++__failure __msg("R9 !read_ok")
++__naked void ld_ind_subprog_early_exit(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "if r0 != 0 goto l_exit_%=;"
++      "r0 = r9;"
++      "l_exit_%=:"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: subprog with both paths safe")
++__success
++__naked void ld_abs_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldabs_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: subprog with both paths safe")
++__success
++__naked void ld_ind_subprog_both_paths_safe(void)
++{
++      asm volatile (
++      "call ldind_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++/*
++ * ld_{abs,ind} in subprogs require scalar (int) return type in BTF.
++ * A test with void return must be rejected.
++ */
++__naked __noinline __used
++static void ldabs_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      ".8byte %[ld_abs];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_abs: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_abs_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldabs_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
++__naked __noinline __used
++static void ldind_void_subprog(void)
++{
++      asm volatile (
++      "r6 = r1;"
++      "r7 = 0;"
++      ".8byte %[ld_ind];"
++      "r0 = 1;"
++      "exit;"
++      :
++      : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
++      : __clobber_all);
++}
++
++SEC("socket")
++__description("ld_ind: reject void return subprog")
++__failure __msg("LD_ABS is only allowed in functions that return 'int'")
++__naked void ld_ind_void_subprog_reject(void)
++{
++      asm volatile (
++      "call ldind_void_subprog;"
++      "r0 = 0;"
++      "exit;"
++      ::: __clobber_all);
++}
++
+ char _license[] SEC("license") = "GPL";
+-- 
+2.53.0
+
index 07ddd9b506ed0ac44c97ea36d22b3520688287f2..0f8f13d4f5eed51eaef4e3343919ba35f3410141 100644 (file)
@@ -1 +1,6 @@
 platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+selftests-bpf-add-tests-for-ld_-abs-ind-failure-path.patch
+drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
+platform-x86-amd-pmc-don-t-log-during-intermediate-w.patch
+platform-x86-amd-pmc-avoid-logging-null-for-dmi-valu.patch
diff --git a/staging-7.1/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch b/staging-7.1/drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch
new file mode 100644 (file)
index 0000000..269f69b
--- /dev/null
@@ -0,0 +1,82 @@
+From 29b70c650570e1fad7a5efe475d0376eadc4f1e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 22:01:00 +0900
+Subject: drm/virtio: fix deadlock in display_info_cb by removing hotplug from
+ dequeue worker
+
+From: Ryosuke Yasuoka <ryasuoka@redhat.com>
+
+[ Upstream commit d1b894c5bbb3fee0012bd14356286dc2384e8213 ]
+
+A probe-time deadlock can occur between the dequeue worker and
+drm_client_register(). During probe, drm_client_register() holds
+clientlist_mutex and calls the fbdev hotplug callback, which triggers an
+atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
+waiting for virtqueue space. The dequeue worker that would free that
+space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
+drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
+to acquire the same clientlist_mutex. Since wake_up() is only called
+after the resp_cb loop, the probe thread is never woken and both threads
+deadlock.
+
+Fix this by removing the hotplug notification from
+virtio_gpu_cmd_get_display_info_cb(). The display data (outputs[i].info)
+is still updated synchronously in the callback.
+
+For the init path, drm_client_register() already fires an initial
+hotplug when the client is registered, which picks up the connector
+state updated by display_info_cb.
+
+For the runtime config_changed path, add a wait_event_timeout() in
+config_changed_work_func() so that display_info_cb updates the connector
+data before the hotplug notification is sent. Also replace
+drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event() since
+virtio-gpu never calls drm_kms_helper_poll_init() and thus
+drm_helper_hpd_irq_event() always returns false without doing anything.
+
+Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
+Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
+Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
+Suggested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
+Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Link: https://patch.msgid.link/20260713-virtiogpu_syzbot-v2-1-2958fa37d46d@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/virtio/virtgpu_kms.c | 5 ++++-
+ drivers/gpu/drm/virtio/virtgpu_vq.c  | 3 ---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
+index 80ba69b4860bc5..b79fd8350b6a47 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
++++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
+@@ -49,7 +49,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
+                               virtio_gpu_cmd_get_edids(vgdev);
+                       virtio_gpu_cmd_get_display_info(vgdev);
+                       virtio_gpu_notify(vgdev);
+-                      drm_helper_hpd_irq_event(vgdev->ddev);
++                      wait_event_timeout(vgdev->resp_wq,
++                                         !vgdev->display_info_pending,
++                                         5 * HZ);
++                      drm_kms_helper_hotplug_event(vgdev->ddev);
+               }
+               events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
+       }
+diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
+index 67865810a2e708..337189b15ad01b 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
+@@ -840,9 +840,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
+       vgdev->display_info_pending = false;
+       spin_unlock(&vgdev->display_info_lock);
+       wake_up(&vgdev->resp_wq);
+-
+-      if (!drm_helper_hpd_irq_event(vgdev->ddev))
+-              drm_kms_helper_hotplug_event(vgdev->ddev);
+ }
+ static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+-- 
+2.53.0
+
index 1487d9b4e0263ea1a71dd67a8a41e7981e8d9b07..b81e4ac3cc4d3c81cfec9f31b25cd8e9048b9262 100644 (file)
@@ -1,2 +1,3 @@
 platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
 sched_ext-skip-ops.set_weight-for-disabled-tasks.patch
+drm-virtio-fix-deadlock-in-display_info_cb-by-removi.patch