--- /dev/null
+From 57b3197298bfd366a7fa63f1e114fa87e97dcb81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:16:48 +0000
+Subject: af_unix: Reject SIOCATMARK on non-stream sockets
+
+From: Jiexun Wang <wangjiexun2025@gmail.com>
+
+commit d119775f2bad827edc28071c061fdd4a91f889a5 upstream.
+
+SIOCATMARK reports whether the receive queue is at the urgent mark for
+MSG_OOB.
+
+In AF_UNIX, MSG_OOB is supported only for SOCK_STREAM sockets.
+SOCK_DGRAM and SOCK_SEQPACKET reject MSG_OOB in sendmsg() and recvmsg(),
+so they should not support SIOCATMARK either.
+
+Return -EOPNOTSUPP for non-stream sockets before checking the receive
+queue.
+
+Fixes: 314001f0bf92 ("af_unix: Add OOB support")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
+Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260506140825.2987635-1-n05ec@lzu.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 1676bffe7259dc..8e9a8499db5e66 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -3040,6 +3040,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ struct sk_buff *skb;
+ int answ = 0;
+
++ if (sk->sk_type != SOCK_STREAM)
++ return -EOPNOTSUPP;
++
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb && skb == READ_ONCE(unix_sk(sk)->oob_skb))
+ answ = 1;
+--
+2.53.0
+
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
+xhci-fix-memory-leak-regression-when-freeing-xhci-vd.patch
+af_unix-reject-siocatmark-on-non-stream-sockets.patch
--- /dev/null
+From 8974b559fc0e47c9a6413f0cc16c7aaa40d02b6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jun 2026 20:49:38 -0700
+Subject: xhci: fix memory leak regression when freeing xhci vdev devices depth
+ first
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit edcbe06453ddfde21f6aa763f7cab655f26133cc upstream
+
+Suspend-resume cycle test revealed a memory leak in 6.17-rc3
+
+Turns out the slot_id race fix changes accidentally ends up calling
+xhci_free_virt_device() with an incorrect vdev parameter.
+The vdev variable was reused for temporary purposes right before calling
+xhci_free_virt_device().
+
+Fix this by passing the correct vdev parameter.
+
+The slot_id race fix that caused this regression was targeted for stable,
+so this needs to be applied there as well.
+
+Fixes: 2eb03376151b ("usb: xhci: Fix slot_id resource race conflict")
+Reported-by: David Wang <00107082@163.com>
+Closes: https://lore.kernel.org/linux-usb/20250829181354.4450-1-00107082@163.com
+Suggested-by: Michal Pecio <michal.pecio@gmail.com>
+Suggested-by: David Wang <00107082@163.com>
+Cc: stable@vger.kernel.org
+Tested-by: David Wang <00107082@163.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20250902105306.877476-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Justin Chen <justin.chen@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-mem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index fb81e61a599d75..7f75298a09d6fc 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -961,7 +961,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
+ out:
+ /* we are now at a leaf device */
+ xhci_debugfs_remove_slot(xhci, slot_id);
+- xhci_free_virt_device(xhci, vdev, slot_id);
++ xhci_free_virt_device(xhci, xhci->devs[slot_id], slot_id);
+ }
+
+ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
+--
+2.53.0
+
--- /dev/null
+From da7af1d1f5d0dc4bed9d6f3dbabb98ccce99c383 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:16:48 +0000
+Subject: af_unix: Reject SIOCATMARK on non-stream sockets
+
+From: Jiexun Wang <wangjiexun2025@gmail.com>
+
+commit d119775f2bad827edc28071c061fdd4a91f889a5 upstream.
+
+SIOCATMARK reports whether the receive queue is at the urgent mark for
+MSG_OOB.
+
+In AF_UNIX, MSG_OOB is supported only for SOCK_STREAM sockets.
+SOCK_DGRAM and SOCK_SEQPACKET reject MSG_OOB in sendmsg() and recvmsg(),
+so they should not support SIOCATMARK either.
+
+Return -EOPNOTSUPP for non-stream sockets before checking the receive
+queue.
+
+Fixes: 314001f0bf92 ("af_unix: Add OOB support")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
+Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260506140825.2987635-1-n05ec@lzu.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index f5b215ca76d249..3e5dc698416f09 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -3181,6 +3181,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ struct sk_buff *skb;
+ int answ = 0;
+
++ if (sk->sk_type != SOCK_STREAM)
++ return -EOPNOTSUPP;
++
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb && skb == READ_ONCE(unix_sk(sk)->oob_skb))
+ answ = 1;
+--
+2.53.0
+
--- /dev/null
+From 3ad37d2d981625e9308858e6198c97fdefb0caf9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 12:23:22 +0000
+Subject: ring-buffer: Remove ring_buffer_read_prepare_sync()
+
+From: Bjoern Doebel <doebel@amazon.de>
+
+[ Upstream commit 119a5d573622ae90ba730d18acfae9bb75d77b9a ]
+
+When the ring buffer was first introduced, reading the non-consuming
+"trace" file required disabling the writing of the ring buffer. To make
+sure the writing was fully disabled before iterating the buffer with a
+non-consuming read, it would set the disable flag of the buffer and then
+call an RCU synchronization to make sure all the buffers were
+synchronized.
+
+The function ring_buffer_read_start() originally would initialize the
+iterator and call an RCU synchronization, but this was for each individual
+per CPU buffer where this would get called many times on a machine with
+many CPUs before the trace file could be read. The commit 72c9ddfd4c5bf
+("ring-buffer: Make non-consuming read less expensive with lots of cpus.")
+separated ring_buffer_read_start into ring_buffer_read_prepare(),
+ring_buffer_read_sync() and then ring_buffer_read_start() to allow each of
+the per CPU buffers to be prepared, call the read_buffer_read_sync() once,
+and then the ring_buffer_read_start() for each of the CPUs which made
+things much faster.
+
+The commit 1039221cc278 ("ring-buffer: Do not disable recording when there
+is an iterator") removed the requirement of disabling the recording of the
+ring buffer in order to iterate it, but it did not remove the
+synchronization that was happening that was required to wait for all the
+buffers to have no more writers. It's now OK for the buffers to have
+writers and no synchronization is needed.
+
+Remove the synchronization and put back the interface for the ring buffer
+iterator back before commit 72c9ddfd4c5bf was applied.
+
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Link: https://lore.kernel.org/20250630180440.3eabb514@batman.local.home
+Reported-by: David Howells <dhowells@redhat.com>
+Fixes: 1039221cc278 ("ring-buffer: Do not disable recording when there is an iterator")
+Tested-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Assisted-by: Kiro:claude-opus-4.8
+Signed-off-by: Bjoern Doebel <doebel@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/ring_buffer.h | 4 +--
+ kernel/trace/ring_buffer.c | 67 ++++++-------------------------------
+ kernel/trace/trace.c | 14 +++-----
+ kernel/trace/trace_kdb.c | 8 ++---
+ 4 files changed, 18 insertions(+), 75 deletions(-)
+
+diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
+index 3e7bfc0f65aee2..b53335ed2d0efc 100644
+--- a/include/linux/ring_buffer.h
++++ b/include/linux/ring_buffer.h
+@@ -130,9 +130,7 @@ ring_buffer_consume(struct trace_buffer *buffer, int cpu, u64 *ts,
+ unsigned long *lost_events);
+
+ struct ring_buffer_iter *
+-ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags);
+-void ring_buffer_read_prepare_sync(void);
+-void ring_buffer_read_start(struct ring_buffer_iter *iter);
++ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags);
+ void ring_buffer_read_finish(struct ring_buffer_iter *iter);
+
+ struct ring_buffer_event *
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index d3a31ba7c71044..5edc4126d0c6ba 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -5082,28 +5082,20 @@ ring_buffer_consume(struct trace_buffer *buffer, int cpu, u64 *ts,
+ EXPORT_SYMBOL_GPL(ring_buffer_consume);
+
+ /**
+- * ring_buffer_read_prepare - Prepare for a non consuming read of the buffer
++ * ring_buffer_read_start - start a non consuming read of the buffer
+ * @buffer: The ring buffer to read from
+ * @cpu: The cpu buffer to iterate over
+ * @flags: gfp flags to use for memory allocation
+ *
+- * This performs the initial preparations necessary to iterate
+- * through the buffer. Memory is allocated, buffer recording
+- * is disabled, and the iterator pointer is returned to the caller.
+- *
+- * Disabling buffer recording prevents the reading from being
+- * corrupted. This is not a consuming read, so a producer is not
+- * expected.
+- *
+- * After a sequence of ring_buffer_read_prepare calls, the user is
+- * expected to make at least one call to ring_buffer_read_prepare_sync.
+- * Afterwards, ring_buffer_read_start is invoked to get things going
+- * for real.
++ * This creates an iterator to allow non-consuming iteration through
++ * the buffer. If the buffer is disabled for writing, it will produce
++ * the same information each time, but if the buffer is still writing
++ * then the first hit of a write will cause the iteration to stop.
+ *
+- * This overall must be paired with ring_buffer_read_finish.
++ * Must be paired with ring_buffer_read_finish.
+ */
+ struct ring_buffer_iter *
+-ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags)
++ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags)
+ {
+ struct ring_buffer_per_cpu *cpu_buffer;
+ struct ring_buffer_iter *iter;
+@@ -5128,51 +5120,12 @@ ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags)
+
+ atomic_inc(&cpu_buffer->resize_disabled);
+
+- return iter;
+-}
+-EXPORT_SYMBOL_GPL(ring_buffer_read_prepare);
+-
+-/**
+- * ring_buffer_read_prepare_sync - Synchronize a set of prepare calls
+- *
+- * All previously invoked ring_buffer_read_prepare calls to prepare
+- * iterators will be synchronized. Afterwards, read_buffer_read_start
+- * calls on those iterators are allowed.
+- */
+-void
+-ring_buffer_read_prepare_sync(void)
+-{
+- synchronize_rcu();
+-}
+-EXPORT_SYMBOL_GPL(ring_buffer_read_prepare_sync);
+-
+-/**
+- * ring_buffer_read_start - start a non consuming read of the buffer
+- * @iter: The iterator returned by ring_buffer_read_prepare
+- *
+- * This finalizes the startup of an iteration through the buffer.
+- * The iterator comes from a call to ring_buffer_read_prepare and
+- * an intervening ring_buffer_read_prepare_sync must have been
+- * performed.
+- *
+- * Must be paired with ring_buffer_read_finish.
+- */
+-void
+-ring_buffer_read_start(struct ring_buffer_iter *iter)
+-{
+- struct ring_buffer_per_cpu *cpu_buffer;
+- unsigned long flags;
+-
+- if (!iter)
+- return;
+-
+- cpu_buffer = iter->cpu_buffer;
+-
+- raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
++ guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
+ arch_spin_lock(&cpu_buffer->lock);
+ rb_iter_reset(iter);
+ arch_spin_unlock(&cpu_buffer->lock);
+- raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
++
++ return iter;
+ }
+ EXPORT_SYMBOL_GPL(ring_buffer_read_start);
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 25f31d7718c64f..5ef1c79dc5c9e4 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -4819,21 +4819,15 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
+ if (iter->cpu_file == RING_BUFFER_ALL_CPUS) {
+ for_each_tracing_cpu(cpu) {
+ iter->buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter->array_buffer->buffer,
+- cpu, GFP_KERNEL);
+- }
+- ring_buffer_read_prepare_sync();
+- for_each_tracing_cpu(cpu) {
+- ring_buffer_read_start(iter->buffer_iter[cpu]);
++ ring_buffer_read_start(iter->array_buffer->buffer,
++ cpu, GFP_KERNEL);
+ tracing_iter_reset(iter, cpu);
+ }
+ } else {
+ cpu = iter->cpu_file;
+ iter->buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter->array_buffer->buffer,
+- cpu, GFP_KERNEL);
+- ring_buffer_read_prepare_sync();
+- ring_buffer_read_start(iter->buffer_iter[cpu]);
++ ring_buffer_read_start(iter->array_buffer->buffer,
++ cpu, GFP_KERNEL);
+ tracing_iter_reset(iter, cpu);
+ }
+
+diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
+index 59857a1ee44cdf..628c25693cef2f 100644
+--- a/kernel/trace/trace_kdb.c
++++ b/kernel/trace/trace_kdb.c
+@@ -43,17 +43,15 @@ static void ftrace_dump_buf(int skip_entries, long cpu_file)
+ if (cpu_file == RING_BUFFER_ALL_CPUS) {
+ for_each_tracing_cpu(cpu) {
+ iter.buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter.array_buffer->buffer,
+- cpu, GFP_ATOMIC);
+- ring_buffer_read_start(iter.buffer_iter[cpu]);
++ ring_buffer_read_start(iter.array_buffer->buffer,
++ cpu, GFP_ATOMIC);
+ tracing_iter_reset(&iter, cpu);
+ }
+ } else {
+ iter.cpu_file = cpu_file;
+ iter.buffer_iter[cpu_file] =
+- ring_buffer_read_prepare(iter.array_buffer->buffer,
++ ring_buffer_read_start(iter.array_buffer->buffer,
+ cpu_file, GFP_ATOMIC);
+- ring_buffer_read_start(iter.buffer_iter[cpu_file]);
+ tracing_iter_reset(&iter, cpu_file);
+ }
+
+--
+2.53.0
+
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
+af_unix-reject-siocatmark-on-non-stream-sockets.patch
+ring-buffer-remove-ring_buffer_read_prepare_sync.patch
--- /dev/null
+From 046411954db8bf65c5ede50306036047ca784ea6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 14:38:16 +0800
+Subject: ACPI: scan: Use async schedule function in acpi_scan_clear_dep_fn()
+
+From: Yicong Yang <yang.yicong@picoheart.com>
+
+[ Upstream commit 7cf28b3797a81b616bb7eb3e90cf131afc452919 ]
+
+The device object rescan in acpi_scan_clear_dep_fn() is scheduled on a
+system workqueue which is not guaranteed to be finished before entering
+userspace. This may cause some key devices to be missing when userspace
+init task tries to find them. Two issues observed on RISCV platforms:
+
+ - Kernel panic due to userspace init cannot have an opened
+ console.
+
+ The console device scanning is queued by acpi_scan_clear_dep_queue()
+ and not finished by the time userspace init process running, thus by
+ the time userspace init runs, no console is present.
+
+ - Entering rescue shell due to the lack of root devices (PCIe nvme in
+ our case).
+
+ Same reason as above, the PCIe host bridge scanning is queued on
+ a system workqueue and finished after init process runs.
+
+The reason is because both devices (console, PCIe host bridge) depend on
+riscv-aplic irqchip to serve their interrupts (console's wired interrupt
+and PCI's INTx interrupts). In order to keep the dependency, these
+devices are scanned and created after initializing riscv-aplic. The
+riscv-aplic is initialized in device_initcall() and a device scan work
+is queued via acpi_scan_clear_dep_queue(), which is close to the time
+userspace init process is run. Since system_dfl_wq is used in
+acpi_scan_clear_dep_queue() with no synchronization, the issues will
+happen if userspace init runs before these devices are ready.
+
+The solution is to wait for the queued work to complete before entering
+userspace init. One possible way would be to use a dedicated workqueue
+instead of system_dfl_wq, and explicitly flush it somewhere in the
+initcall stage before entering userspace. Another way is to use
+async_schedule_dev_nocall() for scanning these devices. It's designed
+for asynchronous initialization and will work in the same way as before
+because it's using a dedicated unbound workqueue as well, but the kernel
+init code calls async_synchronize_full() right before entering userspace
+init which will wait for the work to complete.
+
+Compared to a dedicated workqueue, the second approach is simpler
+because the async schedule framework takes care of all of the details.
+The ACPI code only needs to focus on its job. A dedicated workqueue for
+this could also be redundant because some platforms don't need
+acpi_scan_clear_dep_queue() for their device scanning.
+
+Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
+[ rjw: Subject adjustment, changelog edits ]
+Link: https://patch.msgid.link/20260128132848.93638-1-yang.yicong@picoheart.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+[ Vivian: Adjust system_dfl_wq -> system_unbound_wq in removed lines ]
+Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/scan.c | 41 +++++++++++++++--------------------------
+ 1 file changed, 15 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 0774cc6921100b..4b9c81fbdc3bb2 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -5,6 +5,7 @@
+
+ #define pr_fmt(fmt) "ACPI: " fmt
+
++#include <linux/async.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+@@ -2364,46 +2365,34 @@ static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *da
+ return 0;
+ }
+
+-struct acpi_scan_clear_dep_work {
+- struct work_struct work;
+- struct acpi_device *adev;
+-};
+-
+-static void acpi_scan_clear_dep_fn(struct work_struct *work)
++static void acpi_scan_clear_dep_fn(void *dev, async_cookie_t cookie)
+ {
+- struct acpi_scan_clear_dep_work *cdw;
+-
+- cdw = container_of(work, struct acpi_scan_clear_dep_work, work);
++ struct acpi_device *adev = to_acpi_device(dev);
+
+ acpi_scan_lock_acquire();
+- acpi_bus_attach(cdw->adev, (void *)true);
++ acpi_bus_attach(adev, (void *)true);
+ acpi_scan_lock_release();
+
+- acpi_dev_put(cdw->adev);
+- kfree(cdw);
++ acpi_dev_put(adev);
+ }
+
+ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
+ {
+- struct acpi_scan_clear_dep_work *cdw;
+-
+ if (adev->dep_unmet)
+ return false;
+
+- cdw = kmalloc(sizeof(*cdw), GFP_KERNEL);
+- if (!cdw)
+- return false;
+-
+- cdw->adev = adev;
+- INIT_WORK(&cdw->work, acpi_scan_clear_dep_fn);
+ /*
+- * Since the work function may block on the lock until the entire
+- * initial enumeration of devices is complete, put it into the unbound
+- * workqueue.
++ * Async schedule the deferred acpi_scan_clear_dep_fn() since:
++ * - acpi_bus_attach() needs to hold acpi_scan_lock which cannot
++ * be acquired under acpi_dep_list_lock (held here)
++ * - the deferred work at boot stage is ensured to be finished
++ * before userspace init task by the async_synchronize_full()
++ * barrier
++ *
++ * Use _nocall variant since it'll return on failure instead of
++ * run the function synchronously.
+ */
+- queue_work(system_unbound_wq, &cdw->work);
+-
+- return true;
++ return async_schedule_dev_nocall(acpi_scan_clear_dep_fn, &adev->dev);
+ }
+
+ static void acpi_scan_delete_dep_data(struct acpi_dep_data *dep)
+--
+2.53.0
+
--- /dev/null
+From 17d137d92bfbb072e6d40ebf18cd706fa389d55e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 14:22:31 +0800
+Subject: bpf: Reject sleepable kprobe_multi programs at attach time
+
+From: Varun R Mallya <varunrmallya@gmail.com>
+
+commit eb7024bfcc5f68ed11ed9dd4891a3073c15f04a8 upstream.
+
+kprobe.multi programs run in atomic/RCU context and cannot sleep.
+However, bpf_kprobe_multi_link_attach() did not validate whether the
+program being attached had the sleepable flag set, allowing sleepable
+helpers such as bpf_copy_from_user() to be invoked from a non-sleepable
+context.
+
+This causes a "sleeping function called from invalid context" splat:
+
+ BUG: sleeping function called from invalid context at ./include/linux/uaccess.h:169
+ in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1787, name: sudo
+ preempt_count: 1, expected: 0
+ RCU nest depth: 2, expected: 0
+
+Fix this by rejecting sleepable programs early in
+bpf_kprobe_multi_link_attach(), before any further processing.
+
+Fixes: 0dcac2725406 ("bpf: Add multi kprobe link")
+Signed-off-by: Varun R Mallya <varunrmallya@gmail.com>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Leon Hwang <leon.hwang@linux.dev>
+Acked-by: Jiri Olsa <jolsa@kernel.org>
+Link: https://lore.kernel.org/r/20260401191126.440683-1-varunrmallya@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/bpf_trace.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index 4a44451efbcc67..41c874fbd6fa79 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2943,6 +2943,10 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
+ if (!is_kprobe_multi(prog))
+ return -EINVAL;
+
++ /* kprobe_multi is not allowed to be sleepable. */
++ if (prog->sleepable)
++ return -EINVAL;
++
+ flags = attr->link_create.kprobe_multi.flags;
+ if (flags & ~BPF_F_KPROBE_MULTI_RETURN)
+ return -EINVAL;
+--
+2.53.0
+
--- /dev/null
+From 762331b2fb6b319a348e7121346a396339b1df07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 14:22:32 +0800
+Subject: selftests/bpf: Add test to ensure kprobe_multi is not sleepable
+
+From: Varun R Mallya <varunrmallya@gmail.com>
+
+commit c7cab53f9d5273f0cf2a26bdf178c4e074bdfb50 upstream.
+
+Add a selftest to ensure that kprobe_multi programs cannot be attached
+using the BPF_F_SLEEPABLE flag. This test succeeds when the kernel
+rejects attachment of kprobe_multi when the BPF_F_SLEEPABLE flag is set.
+
+Suggested-by: Leon Hwang <leon.hwang@linux.dev>
+Signed-off-by: Varun R Mallya <varunrmallya@gmail.com>
+Link: https://lore.kernel.org/r/20260408190137.101418-3-varunrmallya@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../bpf/prog_tests/kprobe_multi_test.c | 35 ++++++++++++++++++-
+ .../bpf/progs/kprobe_multi_sleepable.c | 25 +++++++++++++
+ 2 files changed, 59 insertions(+), 1 deletion(-)
+ create mode 100644 tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+index 960c9323d1e0f5..4183c2c057a304 100644
+--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+@@ -6,6 +6,7 @@
+ #include "kprobe_multi_override.skel.h"
+ #include "kprobe_multi_session.skel.h"
+ #include "kprobe_multi_session_cookie.skel.h"
++#include "kprobe_multi_sleepable.skel.h"
+ #include "bpf/libbpf_internal.h"
+ #include "bpf/hashmap.h"
+
+@@ -216,7 +217,9 @@ static void test_attach_api_syms(void)
+ static void test_attach_api_fails(void)
+ {
+ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
++ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ struct kprobe_multi *skel = NULL;
++ struct kprobe_multi_sleepable *sl_skel = NULL;
+ struct bpf_link *link = NULL;
+ unsigned long long addrs[2];
+ const char *syms[2] = {
+@@ -224,7 +227,7 @@ static void test_attach_api_fails(void)
+ "bpf_fentry_test2",
+ };
+ __u64 cookies[2];
+- int saved_error;
++ int saved_error, err;
+
+ addrs[0] = ksym_get_addr("bpf_fentry_test1");
+ addrs[1] = ksym_get_addr("bpf_fentry_test2");
+@@ -323,9 +326,39 @@ static void test_attach_api_fails(void)
+ if (!ASSERT_EQ(saved_error, -E2BIG, "fail_6_error"))
+ goto cleanup;
+
++ /* fail_9 - sleepable kprobe multi should not attach */
++ sl_skel = kprobe_multi_sleepable__open();
++ if (!ASSERT_OK_PTR(sl_skel, "sleep_skel_open"))
++ goto cleanup;
++
++ sl_skel->bss->user_ptr = sl_skel;
++
++ err = bpf_program__set_flags(sl_skel->progs.handle_kprobe_multi_sleepable,
++ BPF_F_SLEEPABLE);
++ if (!ASSERT_OK(err, "sleep_skel_set_flags"))
++ goto cleanup;
++
++ err = kprobe_multi_sleepable__load(sl_skel);
++ if (!ASSERT_OK(err, "sleep_skel_load"))
++ goto cleanup;
++
++ link = bpf_program__attach_kprobe_multi_opts(sl_skel->progs.handle_kprobe_multi_sleepable,
++ "bpf_fentry_test1", NULL);
++ saved_error = -errno;
++
++ if (!ASSERT_ERR_PTR(link, "fail_9"))
++ goto cleanup;
++
++ if (!ASSERT_EQ(saved_error, -EINVAL, "fail_9_error"))
++ goto cleanup;
++
++ err = bpf_prog_test_run_opts(bpf_program__fd(sl_skel->progs.fentry), &topts);
++ ASSERT_OK(err, "bpf_prog_test_run_opts");
++
+ cleanup:
+ bpf_link__destroy(link);
+ kprobe_multi__destroy(skel);
++ kprobe_multi_sleepable__destroy(sl_skel);
+ }
+
+ static void test_session_skel_api(void)
+diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c b/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+new file mode 100644
+index 00000000000000..932e1d9c72e2d0
+--- /dev/null
++++ b/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+@@ -0,0 +1,25 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include "vmlinux.h"
++#include <bpf/bpf_helpers.h>
++#include <bpf/bpf_tracing.h>
++
++void *user_ptr = 0;
++
++SEC("kprobe.multi")
++int handle_kprobe_multi_sleepable(struct pt_regs *ctx)
++{
++ int a, err;
++
++ err = bpf_copy_from_user(&a, sizeof(a), user_ptr);
++ barrier_var(a);
++ return err;
++}
++
++SEC("fentry/bpf_fentry_test1")
++int BPF_PROG(fentry)
++{
++ return 0;
++}
++
++char _license[] SEC("license") = "GPL";
+--
+2.53.0
+
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
+bpf-reject-sleepable-kprobe_multi-programs-at-attach.patch
+selftests-bpf-add-test-to-ensure-kprobe_multi-is-not.patch
+acpi-scan-use-async-schedule-function-in-acpi_scan_c.patch
--- /dev/null
+From d5d924be016df0e9f700868cb35231dbb02ae5a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 14:38:16 +0800
+Subject: ACPI: scan: Use async schedule function in acpi_scan_clear_dep_fn()
+
+From: Yicong Yang <yang.yicong@picoheart.com>
+
+[ Upstream commit 7cf28b3797a81b616bb7eb3e90cf131afc452919 ]
+
+The device object rescan in acpi_scan_clear_dep_fn() is scheduled on a
+system workqueue which is not guaranteed to be finished before entering
+userspace. This may cause some key devices to be missing when userspace
+init task tries to find them. Two issues observed on RISCV platforms:
+
+ - Kernel panic due to userspace init cannot have an opened
+ console.
+
+ The console device scanning is queued by acpi_scan_clear_dep_queue()
+ and not finished by the time userspace init process running, thus by
+ the time userspace init runs, no console is present.
+
+ - Entering rescue shell due to the lack of root devices (PCIe nvme in
+ our case).
+
+ Same reason as above, the PCIe host bridge scanning is queued on
+ a system workqueue and finished after init process runs.
+
+The reason is because both devices (console, PCIe host bridge) depend on
+riscv-aplic irqchip to serve their interrupts (console's wired interrupt
+and PCI's INTx interrupts). In order to keep the dependency, these
+devices are scanned and created after initializing riscv-aplic. The
+riscv-aplic is initialized in device_initcall() and a device scan work
+is queued via acpi_scan_clear_dep_queue(), which is close to the time
+userspace init process is run. Since system_dfl_wq is used in
+acpi_scan_clear_dep_queue() with no synchronization, the issues will
+happen if userspace init runs before these devices are ready.
+
+The solution is to wait for the queued work to complete before entering
+userspace init. One possible way would be to use a dedicated workqueue
+instead of system_dfl_wq, and explicitly flush it somewhere in the
+initcall stage before entering userspace. Another way is to use
+async_schedule_dev_nocall() for scanning these devices. It's designed
+for asynchronous initialization and will work in the same way as before
+because it's using a dedicated unbound workqueue as well, but the kernel
+init code calls async_synchronize_full() right before entering userspace
+init which will wait for the work to complete.
+
+Compared to a dedicated workqueue, the second approach is simpler
+because the async schedule framework takes care of all of the details.
+The ACPI code only needs to focus on its job. A dedicated workqueue for
+this could also be redundant because some platforms don't need
+acpi_scan_clear_dep_queue() for their device scanning.
+
+Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
+[ rjw: Subject adjustment, changelog edits ]
+Link: https://patch.msgid.link/20260128132848.93638-1-yang.yicong@picoheart.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+[ Vivian: Adjust system_dfl_wq -> system_unbound_wq in removed lines ]
+Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/scan.c | 41 +++++++++++++++--------------------------
+ 1 file changed, 15 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 50f60da6cf27fc..16704c2a730c04 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -5,6 +5,7 @@
+
+ #define pr_fmt(fmt) "ACPI: " fmt
+
++#include <linux/async.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+@@ -2360,46 +2361,34 @@ static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *da
+ return 0;
+ }
+
+-struct acpi_scan_clear_dep_work {
+- struct work_struct work;
+- struct acpi_device *adev;
+-};
+-
+-static void acpi_scan_clear_dep_fn(struct work_struct *work)
++static void acpi_scan_clear_dep_fn(void *dev, async_cookie_t cookie)
+ {
+- struct acpi_scan_clear_dep_work *cdw;
+-
+- cdw = container_of(work, struct acpi_scan_clear_dep_work, work);
++ struct acpi_device *adev = to_acpi_device(dev);
+
+ acpi_scan_lock_acquire();
+- acpi_bus_attach(cdw->adev, (void *)true);
++ acpi_bus_attach(adev, (void *)true);
+ acpi_scan_lock_release();
+
+- acpi_dev_put(cdw->adev);
+- kfree(cdw);
++ acpi_dev_put(adev);
+ }
+
+ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
+ {
+- struct acpi_scan_clear_dep_work *cdw;
+-
+ if (adev->dep_unmet)
+ return false;
+
+- cdw = kmalloc(sizeof(*cdw), GFP_KERNEL);
+- if (!cdw)
+- return false;
+-
+- cdw->adev = adev;
+- INIT_WORK(&cdw->work, acpi_scan_clear_dep_fn);
+ /*
+- * Since the work function may block on the lock until the entire
+- * initial enumeration of devices is complete, put it into the unbound
+- * workqueue.
++ * Async schedule the deferred acpi_scan_clear_dep_fn() since:
++ * - acpi_bus_attach() needs to hold acpi_scan_lock which cannot
++ * be acquired under acpi_dep_list_lock (held here)
++ * - the deferred work at boot stage is ensured to be finished
++ * before userspace init task by the async_synchronize_full()
++ * barrier
++ *
++ * Use _nocall variant since it'll return on failure instead of
++ * run the function synchronously.
+ */
+- queue_work(system_unbound_wq, &cdw->work);
+-
+- return true;
++ return async_schedule_dev_nocall(acpi_scan_clear_dep_fn, &adev->dev);
+ }
+
+ static void acpi_scan_delete_dep_data(struct acpi_dep_data *dep)
+--
+2.53.0
+
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
+acpi-scan-use-async-schedule-function-in-acpi_scan_c.patch
--- /dev/null
+From 72223310fb78cc5edc8022d598ad1a83f05c2ccf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:16:48 +0000
+Subject: af_unix: Reject SIOCATMARK on non-stream sockets
+
+From: Jiexun Wang <wangjiexun2025@gmail.com>
+
+commit d119775f2bad827edc28071c061fdd4a91f889a5 upstream.
+
+SIOCATMARK reports whether the receive queue is at the urgent mark for
+MSG_OOB.
+
+In AF_UNIX, MSG_OOB is supported only for SOCK_STREAM sockets.
+SOCK_DGRAM and SOCK_SEQPACKET reject MSG_OOB in sendmsg() and recvmsg(),
+so they should not support SIOCATMARK either.
+
+Return -EOPNOTSUPP for non-stream sockets before checking the receive
+queue.
+
+Fixes: 314001f0bf92 ("af_unix: Add OOB support")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
+Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260506140825.2987635-1-n05ec@lzu.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 32892a40d139c2..8bd78cad69e7c5 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -3139,6 +3139,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ struct sk_buff *skb;
+ int answ = 0;
+
++ if (sk->sk_type != SOCK_STREAM)
++ return -EOPNOTSUPP;
++
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb && skb == READ_ONCE(unix_sk(sk)->oob_skb))
+ answ = 1;
+--
+2.53.0
+
--- /dev/null
+From 41d26894e1ec21c2773302e49caa5825d2d7caa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:28:59 +0800
+Subject: bpf: Reject sleepable kprobe_multi programs at attach time
+
+From: Varun R Mallya <varunrmallya@gmail.com>
+
+commit eb7024bfcc5f68ed11ed9dd4891a3073c15f04a8 upstream.
+
+kprobe.multi programs run in atomic/RCU context and cannot sleep.
+However, bpf_kprobe_multi_link_attach() did not validate whether the
+program being attached had the sleepable flag set, allowing sleepable
+helpers such as bpf_copy_from_user() to be invoked from a non-sleepable
+context.
+
+This causes a "sleeping function called from invalid context" splat:
+
+ BUG: sleeping function called from invalid context at ./include/linux/uaccess.h:169
+ in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1787, name: sudo
+ preempt_count: 1, expected: 0
+ RCU nest depth: 2, expected: 0
+
+Fix this by rejecting sleepable programs early in
+bpf_kprobe_multi_link_attach(), before any further processing.
+
+Fixes: 0dcac2725406 ("bpf: Add multi kprobe link")
+Signed-off-by: Varun R Mallya <varunrmallya@gmail.com>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Leon Hwang <leon.hwang@linux.dev>
+Acked-by: Jiri Olsa <jolsa@kernel.org>
+Link: https://lore.kernel.org/r/20260401191126.440683-1-varunrmallya@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[shung-hsi.yu: sleepable flag was in 'struct bpf_prog_aux' before commit
+66c8473135c6 "bpf: move sleepable flag from bpf_prog_aux to bpf_prog"]
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/bpf_trace.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index a896b80252ae11..87e7cc2dc5ccd8 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2905,6 +2905,10 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
+ if (prog->expected_attach_type != BPF_TRACE_KPROBE_MULTI)
+ return -EINVAL;
+
++ /* kprobe_multi is not allowed to be sleepable. */
++ if (prog->aux->sleepable)
++ return -EINVAL;
++
+ flags = attr->link_create.kprobe_multi.flags;
+ if (flags & ~BPF_F_KPROBE_MULTI_RETURN)
+ return -EINVAL;
+--
+2.53.0
+
--- /dev/null
+From fa38cff5bc2097256305c81974bcc34c278aebe9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jun 2026 01:27:33 +0800
+Subject: bpf: Remove mark_precise_scalar_ids()
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit 842edb5507a1038e009d27e69d13b94b6f085763 ]
+
+Function mark_precise_scalar_ids() is superseded by
+bt_sync_linked_regs() and equal scalars tracking in jump history.
+mark_precise_scalar_ids() propagates precision over registers sharing
+same ID on parent/child state boundaries, while jump history records
+allow bt_sync_linked_regs() to propagate same information with
+instruction level granularity, which is strictly more precise.
+
+This commit removes mark_precise_scalar_ids() and updates test cases
+in progs/verifier_scalar_ids to reflect new verifier behavior.
+
+The tests are updated in the following manner:
+- mark_precise_scalar_ids() propagated precision regardless of
+ presence of conditional jumps, while new jump history based logic
+ only kicks in when conditional jumps are present.
+ Hence test cases are augmented with conditional jumps to still
+ trigger precision propagation.
+- As equal scalars tracking no longer relies on parent/child state
+ boundaries some test cases are no longer interesting,
+ such test cases are removed, namely:
+ - precision_same_state and precision_cross_state are superseded by
+ linked_regs_bpf_k;
+ - precision_same_state_broken_link and equal_scalars_broken_link
+ are superseded by linked_regs_broken_link.
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20240718202357.1746514-3-eddyz87@gmail.com
+[ zhenzhong: backport to 6.6.y after adapting the first linked-regs
+ history commit to the older scalar-id verifier layout. ]
+Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 115 ------------
+ .../selftests/bpf/progs/verifier_scalar_ids.c | 171 ++++++------------
+ .../testing/selftests/bpf/verifier/precise.c | 2 +-
+ 3 files changed, 56 insertions(+), 232 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 2268f095203e21..f638b2d3a42fbc 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -4265,96 +4265,6 @@ static void mark_all_scalars_imprecise(struct bpf_verifier_env *env, struct bpf_
+ }
+ }
+
+-static bool idset_contains(struct bpf_idset *s, u32 id)
+-{
+- u32 i;
+-
+- for (i = 0; i < s->count; ++i)
+- if (s->ids[i] == id)
+- return true;
+-
+- return false;
+-}
+-
+-static int idset_push(struct bpf_idset *s, u32 id)
+-{
+- if (WARN_ON_ONCE(s->count >= ARRAY_SIZE(s->ids)))
+- return -EFAULT;
+- s->ids[s->count++] = id;
+- return 0;
+-}
+-
+-static void idset_reset(struct bpf_idset *s)
+-{
+- s->count = 0;
+-}
+-
+-/* Collect a set of IDs for all registers currently marked as precise in env->bt.
+- * Mark all registers with these IDs as precise.
+- */
+-static int mark_precise_scalar_ids(struct bpf_verifier_env *env, struct bpf_verifier_state *st)
+-{
+- struct bpf_idset *precise_ids = &env->idset_scratch;
+- struct backtrack_state *bt = &env->bt;
+- struct bpf_func_state *func;
+- struct bpf_reg_state *reg;
+- DECLARE_BITMAP(mask, 64);
+- int i, fr;
+-
+- idset_reset(precise_ids);
+-
+- for (fr = bt->frame; fr >= 0; fr--) {
+- func = st->frame[fr];
+-
+- bitmap_from_u64(mask, bt_frame_reg_mask(bt, fr));
+- for_each_set_bit(i, mask, 32) {
+- reg = &func->regs[i];
+- if (!reg->id || reg->type != SCALAR_VALUE)
+- continue;
+- if (idset_push(precise_ids, reg->id))
+- return -EFAULT;
+- }
+-
+- bitmap_from_u64(mask, bt_frame_stack_mask(bt, fr));
+- for_each_set_bit(i, mask, 64) {
+- if (i >= func->allocated_stack / BPF_REG_SIZE)
+- break;
+- if (!is_spilled_scalar_reg(&func->stack[i]))
+- continue;
+- reg = &func->stack[i].spilled_ptr;
+- if (!reg->id)
+- continue;
+- if (idset_push(precise_ids, reg->id))
+- return -EFAULT;
+- }
+- }
+-
+- for (fr = 0; fr <= st->curframe; ++fr) {
+- func = st->frame[fr];
+-
+- for (i = BPF_REG_0; i < BPF_REG_10; ++i) {
+- reg = &func->regs[i];
+- if (!reg->id)
+- continue;
+- if (!idset_contains(precise_ids, reg->id))
+- continue;
+- bt_set_frame_reg(bt, fr, i);
+- }
+- for (i = 0; i < func->allocated_stack / BPF_REG_SIZE; ++i) {
+- if (!is_spilled_scalar_reg(&func->stack[i]))
+- continue;
+- reg = &func->stack[i].spilled_ptr;
+- if (!reg->id)
+- continue;
+- if (!idset_contains(precise_ids, reg->id))
+- continue;
+- bt_set_frame_slot(bt, fr, i);
+- }
+- }
+-
+- return 0;
+-}
+-
+ /*
+ * __mark_chain_precision() backtracks BPF program instruction sequence and
+ * chain of verifier states making sure that register *regno* (if regno >= 0)
+@@ -4487,31 +4397,6 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
+ bt->frame, last_idx, first_idx, subseq_idx);
+ }
+
+- /* If some register with scalar ID is marked as precise,
+- * make sure that all registers sharing this ID are also precise.
+- * This is needed to estimate effect of sync_linked_regs().
+- * Do this at the last instruction of each state,
+- * bpf_reg_state::id fields are valid for these instructions.
+- *
+- * Allows to track precision in situation like below:
+- *
+- * r2 = unknown value
+- * ...
+- * --- state #0 ---
+- * ...
+- * r1 = r2 // r1 and r2 now share the same ID
+- * ...
+- * --- state #1 {r1.id = A, r2.id = A} ---
+- * ...
+- * if (r2 > 10) goto exit; // sync_linked_regs() assigns range to r1
+- * ...
+- * --- state #2 {r1.id = A, r2.id = A} ---
+- * r3 = r10
+- * r3 += r1 // need to mark both r1 and r2
+- */
+- if (mark_precise_scalar_ids(env, st))
+- return -EFAULT;
+-
+ if (last_idx < 0) {
+ /* we are at the entry into subprog, which
+ * is expected for global funcs, but only if
+diff --git a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
+index 22a6cf6e8255df..f70392bf696c62 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
++++ b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
+@@ -5,54 +5,27 @@
+ #include "bpf_misc.h"
+
+ /* Check that precision marks propagate through scalar IDs.
+- * Registers r{0,1,2} have the same scalar ID at the moment when r0 is
+- * marked to be precise, this mark is immediately propagated to r{1,2}.
++ * Registers r{0,1,2} have the same scalar ID.
++ * Range information is propagated for scalars sharing same ID.
++ * Check that precision mark for r0 causes precision marks for r{1,2}
++ * when range information is propagated for 'if <reg> <op> <const>' insn.
+ */
+ SEC("socket")
+ __success __log_level(2)
+-__msg("frame0: regs=r0,r1,r2 stack= before 4: (bf) r3 = r10")
+-__msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
+-__msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
+-__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
+-__msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
+-__flag(BPF_F_TEST_STATE_FREQ)
+-__naked void precision_same_state(void)
+-{
+- asm volatile (
+- /* r0 = random number up to 0xff */
+- "call %[bpf_ktime_get_ns];"
+- "r0 &= 0xff;"
+- /* tie r0.id == r1.id == r2.id */
+- "r1 = r0;"
+- "r2 = r0;"
+- /* force r0 to be precise, this immediately marks r1 and r2 as
+- * precise as well because of shared IDs
+- */
+- "r3 = r10;"
+- "r3 += r0;"
+- "r0 = 0;"
+- "exit;"
+- :
+- : __imm(bpf_ktime_get_ns)
+- : __clobber_all);
+-}
+-
+-/* Same as precision_same_state, but mark propagates through state /
+- * parent state boundary.
+- */
+-SEC("socket")
+-__success __log_level(2)
+-__msg("frame0: last_idx 6 first_idx 5 subseq_idx -1")
+-__msg("frame0: regs=r0,r1,r2 stack= before 5: (bf) r3 = r10")
++/* first 'if' branch */
++__msg("6: (0f) r3 += r0")
++__msg("frame0: regs=r0 stack= before 4: (25) if r1 > 0x7 goto pc+0")
+ __msg("frame0: parent state regs=r0,r1,r2 stack=:")
+-__msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
+ __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
+-__msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
+-__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
+-__msg("frame0: parent state regs=r0 stack=:")
+-__msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
++/* second 'if' branch */
++__msg("from 4 to 5: ")
++__msg("6: (0f) r3 += r0")
++__msg("frame0: regs=r0 stack= before 5: (bf) r3 = r10")
++__msg("frame0: regs=r0 stack= before 4: (25) if r1 > 0x7 goto pc+0")
++/* parent state already has r{0,1,2} as precise */
++__msg("frame0: parent state regs= stack=:")
+ __flag(BPF_F_TEST_STATE_FREQ)
+-__naked void precision_cross_state(void)
++__naked void linked_regs_bpf_k(void)
+ {
+ asm volatile (
+ /* r0 = random number up to 0xff */
+@@ -61,9 +34,8 @@ __naked void precision_cross_state(void)
+ /* tie r0.id == r1.id == r2.id */
+ "r1 = r0;"
+ "r2 = r0;"
+- /* force checkpoint */
+- "goto +0;"
+- /* force r0 to be precise, this immediately marks r1 and r2 as
++ "if r1 > 7 goto +0;"
++ /* force r0 to be precise, this eventually marks r1 and r2 as
+ * precise as well because of shared IDs
+ */
+ "r3 = r10;"
+@@ -75,59 +47,18 @@ __naked void precision_cross_state(void)
+ : __clobber_all);
+ }
+
+-/* Same as precision_same_state, but break one of the
++/* Same as linked_regs_bpf_k, but break one of the
+ * links, note that r1 is absent from regs=... in __msg below.
+ */
+ SEC("socket")
+ __success __log_level(2)
+-__msg("frame0: regs=r0,r2 stack= before 5: (bf) r3 = r10")
+-__msg("frame0: regs=r0,r2 stack= before 4: (b7) r1 = 0")
+-__msg("frame0: regs=r0,r2 stack= before 3: (bf) r2 = r0")
+-__msg("frame0: regs=r0 stack= before 2: (bf) r1 = r0")
+-__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
+-__msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
+-__flag(BPF_F_TEST_STATE_FREQ)
+-__naked void precision_same_state_broken_link(void)
+-{
+- asm volatile (
+- /* r0 = random number up to 0xff */
+- "call %[bpf_ktime_get_ns];"
+- "r0 &= 0xff;"
+- /* tie r0.id == r1.id == r2.id */
+- "r1 = r0;"
+- "r2 = r0;"
+- /* break link for r1, this is the only line that differs
+- * compared to the previous test
+- */
+- "r1 = 0;"
+- /* force r0 to be precise, this immediately marks r1 and r2 as
+- * precise as well because of shared IDs
+- */
+- "r3 = r10;"
+- "r3 += r0;"
+- "r0 = 0;"
+- "exit;"
+- :
+- : __imm(bpf_ktime_get_ns)
+- : __clobber_all);
+-}
+-
+-/* Same as precision_same_state_broken_link, but with state /
+- * parent state boundary.
+- */
+-SEC("socket")
+-__success __log_level(2)
+-__msg("frame0: regs=r0,r2 stack= before 6: (bf) r3 = r10")
+-__msg("frame0: regs=r0,r2 stack= before 5: (b7) r1 = 0")
+-__msg("frame0: parent state regs=r0,r2 stack=:")
+-__msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
+-__msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
+-__msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
+-__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
++__msg("7: (0f) r3 += r0")
++__msg("frame0: regs=r0 stack= before 6: (bf) r3 = r10")
+ __msg("frame0: parent state regs=r0 stack=:")
+-__msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
++__msg("frame0: regs=r0 stack= before 5: (25) if r0 > 0x7 goto pc+0")
++__msg("frame0: parent state regs=r0,r2 stack=:")
+ __flag(BPF_F_TEST_STATE_FREQ)
+-__naked void precision_cross_state_broken_link(void)
++__naked void linked_regs_broken_link(void)
+ {
+ asm volatile (
+ /* r0 = random number up to 0xff */
+@@ -136,18 +67,13 @@ __naked void precision_cross_state_broken_link(void)
+ /* tie r0.id == r1.id == r2.id */
+ "r1 = r0;"
+ "r2 = r0;"
+- /* force checkpoint, although link between r1 and r{0,2} is
+- * broken by the next statement current precision tracking
+- * algorithm can't react to it and propagates mark for r1 to
+- * the parent state.
+- */
+- "goto +0;"
+ /* break link for r1, this is the only line that differs
+- * compared to precision_cross_state()
++ * compared to the previous test
+ */
+ "r1 = 0;"
+- /* force r0 to be precise, this immediately marks r1 and r2 as
+- * precise as well because of shared IDs
++ "if r0 > 7 goto +0;"
++ /* force r0 to be precise,
++ * this eventually marks r2 as precise because of shared IDs
+ */
+ "r3 = r10;"
+ "r3 += r0;"
+@@ -164,10 +90,16 @@ __naked void precision_cross_state_broken_link(void)
+ */
+ SEC("socket")
+ __success __log_level(2)
+-__msg("11: (0f) r2 += r1")
++__msg("12: (0f) r2 += r1")
+ /* Current state */
+-__msg("frame2: last_idx 11 first_idx 10 subseq_idx -1")
+-__msg("frame2: regs=r1 stack= before 10: (bf) r2 = r10")
++__msg("frame2: last_idx 12 first_idx 11 subseq_idx -1 ")
++__msg("frame2: regs=r1 stack= before 11: (bf) r2 = r10")
++__msg("frame2: parent state regs=r1 stack=")
++__msg("frame1: parent state regs= stack=")
++__msg("frame0: parent state regs= stack=")
++/* Parent state */
++__msg("frame2: last_idx 10 first_idx 10 subseq_idx 11 ")
++__msg("frame2: regs=r1 stack= before 10: (25) if r1 > 0x7 goto pc+0")
+ __msg("frame2: parent state regs=r1 stack=")
+ /* frame1.r{6,7} are marked because mark_precise_scalar_ids()
+ * looks for all registers with frame2.r1.id in the current state
+@@ -192,7 +124,7 @@ __msg("frame1: regs=r1 stack= before 4: (85) call pc+1")
+ __msg("frame0: parent state regs=r1,r6 stack=")
+ /* Parent state */
+ __msg("frame0: last_idx 3 first_idx 1 subseq_idx 4")
+-__msg("frame0: regs=r0,r1,r6 stack= before 3: (bf) r6 = r0")
++__msg("frame0: regs=r1,r6 stack= before 3: (bf) r6 = r0")
+ __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
+ __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
+ __flag(BPF_F_TEST_STATE_FREQ)
+@@ -230,7 +162,8 @@ static __naked __noinline __used
+ void precision_many_frames__bar(void)
+ {
+ asm volatile (
+- /* force r1 to be precise, this immediately marks:
++ "if r1 > 7 goto +0;"
++ /* force r1 to be precise, this eventually marks:
+ * - bar frame r1
+ * - foo frame r{1,6,7}
+ * - main frame r{1,6}
+@@ -247,14 +180,16 @@ void precision_many_frames__bar(void)
+ */
+ SEC("socket")
+ __success __log_level(2)
++__msg("11: (0f) r2 += r1")
+ /* foo frame */
+-__msg("frame1: regs=r1 stack=-8,-16 before 9: (bf) r2 = r10")
++__msg("frame1: regs=r1 stack= before 10: (bf) r2 = r10")
++__msg("frame1: regs=r1 stack= before 9: (25) if r1 > 0x7 goto pc+0")
+ __msg("frame1: regs=r1 stack=-8,-16 before 8: (7b) *(u64 *)(r10 -16) = r1")
+ __msg("frame1: regs=r1 stack=-8 before 7: (7b) *(u64 *)(r10 -8) = r1")
+ __msg("frame1: regs=r1 stack= before 4: (85) call pc+2")
+ /* main frame */
+-__msg("frame0: regs=r0,r1 stack=-8 before 3: (7b) *(u64 *)(r10 -8) = r1")
+-__msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
++__msg("frame0: regs=r1 stack=-8 before 3: (7b) *(u64 *)(r10 -8) = r1")
++__msg("frame0: regs=r1 stack= before 2: (bf) r1 = r0")
+ __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
+ __flag(BPF_F_TEST_STATE_FREQ)
+ __naked void precision_stack(void)
+@@ -283,7 +218,8 @@ void precision_stack__foo(void)
+ */
+ "*(u64*)(r10 - 8) = r1;"
+ "*(u64*)(r10 - 16) = r1;"
+- /* force r1 to be precise, this immediately marks:
++ "if r1 > 7 goto +0;"
++ /* force r1 to be precise, this eventually marks:
+ * - foo frame r1,fp{-8,-16}
+ * - main frame r1,fp{-8}
+ */
+@@ -299,15 +235,17 @@ void precision_stack__foo(void)
+ SEC("socket")
+ __success __log_level(2)
+ /* r{6,7} */
+-__msg("11: (0f) r3 += r7")
+-__msg("frame0: regs=r6,r7 stack= before 10: (bf) r3 = r10")
++__msg("12: (0f) r3 += r7")
++__msg("frame0: regs=r7 stack= before 11: (bf) r3 = r10")
++__msg("frame0: regs=r7 stack= before 9: (25) if r7 > 0x7 goto pc+0")
+ /* ... skip some insns ... */
+ __msg("frame0: regs=r6,r7 stack= before 3: (bf) r7 = r0")
+ __msg("frame0: regs=r0,r6 stack= before 2: (bf) r6 = r0")
+ /* r{8,9} */
+-__msg("12: (0f) r3 += r9")
+-__msg("frame0: regs=r8,r9 stack= before 11: (0f) r3 += r7")
++__msg("13: (0f) r3 += r9")
++__msg("frame0: regs=r9 stack= before 12: (0f) r3 += r7")
+ /* ... skip some insns ... */
++__msg("frame0: regs=r9 stack= before 10: (25) if r9 > 0x7 goto pc+0")
+ __msg("frame0: regs=r8,r9 stack= before 7: (bf) r9 = r0")
+ __msg("frame0: regs=r0,r8 stack= before 6: (bf) r8 = r0")
+ __flag(BPF_F_TEST_STATE_FREQ)
+@@ -328,8 +266,9 @@ __naked void precision_two_ids(void)
+ "r9 = r0;"
+ /* clear r0 id */
+ "r0 = 0;"
+- /* force checkpoint */
+- "goto +0;"
++ /* propagate equal scalars precision */
++ "if r7 > 7 goto +0;"
++ "if r9 > 7 goto +0;"
+ "r3 = r10;"
+ /* force r7 to be precise, this also marks r6 */
+ "r3 += r7;"
+diff --git a/tools/testing/selftests/bpf/verifier/precise.c b/tools/testing/selftests/bpf/verifier/precise.c
+index b0b1bcc668adb1..59a020c3564742 100644
+--- a/tools/testing/selftests/bpf/verifier/precise.c
++++ b/tools/testing/selftests/bpf/verifier/precise.c
+@@ -106,7 +106,7 @@
+ mark_precise: frame0: regs=r2 stack= before 22\
+ mark_precise: frame0: parent state regs=r2 stack=:\
+ mark_precise: frame0: last_idx 20 first_idx 20\
+- mark_precise: frame0: regs=r2,r9 stack= before 20\
++ mark_precise: frame0: regs=r2 stack= before 20\
+ mark_precise: frame0: parent state regs=r2,r9 stack=:\
+ mark_precise: frame0: last_idx 19 first_idx 17\
+ mark_precise: frame0: regs=r2,r9 stack= before 19\
+--
+2.53.0
+
--- /dev/null
+From 68149056b86877c9bf22ac86a175f7bcec2ce1a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jun 2026 01:27:32 +0800
+Subject: bpf: Track equal scalars history on per-instruction level
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit 4bf79f9be434e000c8e12fe83b2f4402480f1460 ]
+
+Use bpf_verifier_state->jmp_history to track which registers were
+updated by find_equal_scalars() (renamed to collect_linked_regs())
+when conditional jump was verified. Use recorded information in
+backtrack_insn() to propagate precision.
+
+E.g. for the following program:
+
+ while verifying instructions
+ 1: r1 = r0 |
+ 2: if r1 < 8 goto ... | push r0,r1 as linked registers in jmp_history
+ 3: if r0 > 16 goto ... | push r0,r1 as linked registers in jmp_history
+ 4: r2 = r10 |
+ 5: r2 += r0 v mark_chain_precision(r0)
+
+ while doing mark_chain_precision(r0)
+ 5: r2 += r0 | mark r0 precise
+ 4: r2 = r10 |
+ 3: if r0 > 16 goto ... | mark r0,r1 as precise
+ 2: if r1 < 8 goto ... | mark r0,r1 as precise
+ 1: r1 = r0 v
+
+Technically, do this as follows:
+- Use 10 bits to identify each register that gains range because of
+ sync_linked_regs():
+ - 3 bits for frame number;
+ - 6 bits for register or stack slot number;
+ - 1 bit to indicate if register is spilled.
+- Use u64 as a vector of 6 such records + 4 bits for vector length.
+- Augment struct bpf_jmp_history_entry with a field 'linked_regs'
+ representing such vector.
+- When doing check_cond_jmp_op() remember up to 6 registers that
+ gain range because of sync_linked_regs() in such a vector.
+- Don't propagate range information and reset IDs for registers that
+ don't fit in 6-value vector.
+- Push a pair {instruction index, linked registers vector}
+ to bpf_verifier_state->jmp_history.
+- When doing backtrack_insn() check if any of recorded linked
+ registers is currently marked precise, if so mark all linked
+ registers as precise.
+
+This also requires fixes for two test_verifier tests:
+- precise: test 1
+- precise: test 2
+
+Both tests contain the following instruction sequence:
+
+19: (bf) r2 = r9 ; R2=scalar(id=3) R9=scalar(id=3)
+20: (a5) if r2 < 0x8 goto pc+1 ; R2=scalar(id=3,umin=8)
+21: (95) exit
+22: (07) r2 += 1 ; R2_w=scalar(id=3+1,...)
+23: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
+24: (07) r1 += -8 ; R1_w=fp-8
+25: (b7) r3 = 0 ; R3_w=0
+26: (85) call bpf_probe_read_kernel#113
+
+The call to bpf_probe_read_kernel() at (26) forces r2 to be precise.
+Previously, this forced all registers with same id to become precise
+immediately when mark_chain_precision() is called.
+After this change, the precision is propagated to registers sharing
+same id only when 'if' instruction is backtracked.
+Hence verification log for both tests is changed:
+regs=r2,r9 -> regs=r2 for instructions 25..20.
+
+Fixes: 904e6ddf4133 ("bpf: Use scalar ids in mark_chain_precision()")
+Reported-by: Hao Sun <sunhao.th@gmail.com>
+Suggested-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20240718202357.1746514-2-eddyz87@gmail.com
+Closes: https://lore.kernel.org/bpf/CAEf4BzZ0xidVCqB47XnkXcNhkPWF6_nTV7yt+_Lf0kcFEut2Mg@mail.gmail.com/
+[ zhenzhong: backport to 6.6.y verifier layout and adapt
+ sync_linked_regs() to the pre-BPF_ADD_CONST scalar-id code. ]
+Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf_verifier.h | 4 +
+ kernel/bpf/verifier.c | 253 ++++++++++++++++--
+ .../bpf/progs/verifier_subprog_precision.c | 2 +-
+ .../testing/selftests/bpf/verifier/precise.c | 2 +-
+ 4 files changed, 237 insertions(+), 24 deletions(-)
+
+diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
+index dba211d3bb9a0d..9a3b93c24f19f5 100644
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -345,6 +345,10 @@ struct bpf_jmp_history_entry {
+ u32 prev_idx : 22;
+ /* special flags, e.g., whether insn is doing register stack spill/load */
+ u32 flags : 10;
++ /* additional registers that need precision tracking when this
++ * jump is backtracked, vector of six 10-bit records
++ */
++ u64 linked_regs;
+ };
+
+ /* Maximum number of register states that can exist at once */
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 0d90236d0ad94f..2268f095203e21 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -3461,9 +3461,87 @@ static bool is_jmp_point(struct bpf_verifier_env *env, int insn_idx)
+ return env->insn_aux_data[insn_idx].jmp_point;
+ }
+
++#define LR_FRAMENO_BITS 3
++#define LR_SPI_BITS 6
++#define LR_ENTRY_BITS (LR_SPI_BITS + LR_FRAMENO_BITS + 1)
++#define LR_SIZE_BITS 4
++#define LR_FRAMENO_MASK ((1ull << LR_FRAMENO_BITS) - 1)
++#define LR_SPI_MASK ((1ull << LR_SPI_BITS) - 1)
++#define LR_SIZE_MASK ((1ull << LR_SIZE_BITS) - 1)
++#define LR_SPI_OFF LR_FRAMENO_BITS
++#define LR_IS_REG_OFF (LR_SPI_BITS + LR_FRAMENO_BITS)
++#define LINKED_REGS_MAX 6
++
++struct linked_reg {
++ u8 frameno;
++ union {
++ u8 spi;
++ u8 regno;
++ };
++ bool is_reg;
++};
++
++struct linked_regs {
++ int cnt;
++ struct linked_reg entries[LINKED_REGS_MAX];
++};
++
++static struct linked_reg *linked_regs_push(struct linked_regs *s)
++{
++ if (s->cnt < LINKED_REGS_MAX)
++ return &s->entries[s->cnt++];
++
++ return NULL;
++}
++
++/* Use u64 as a vector of 6 10-bit values, use first 4-bits to track
++ * number of elements currently in stack.
++ * Pack one history entry for linked registers as 10 bits in the following format:
++ * - 3-bits frameno
++ * - 6-bits spi_or_reg
++ * - 1-bit is_reg
++ */
++static u64 linked_regs_pack(struct linked_regs *s)
++{
++ u64 val = 0;
++ int i;
++
++ for (i = 0; i < s->cnt; ++i) {
++ struct linked_reg *e = &s->entries[i];
++ u64 tmp = 0;
++
++ tmp |= e->frameno;
++ tmp |= e->spi << LR_SPI_OFF;
++ tmp |= (e->is_reg ? 1 : 0) << LR_IS_REG_OFF;
++
++ val <<= LR_ENTRY_BITS;
++ val |= tmp;
++ }
++ val <<= LR_SIZE_BITS;
++ val |= s->cnt;
++ return val;
++}
++
++static void linked_regs_unpack(u64 val, struct linked_regs *s)
++{
++ int i;
++
++ s->cnt = val & LR_SIZE_MASK;
++ val >>= LR_SIZE_BITS;
++
++ for (i = 0; i < s->cnt; ++i) {
++ struct linked_reg *e = &s->entries[i];
++
++ e->frameno = val & LR_FRAMENO_MASK;
++ e->spi = (val >> LR_SPI_OFF) & LR_SPI_MASK;
++ e->is_reg = (val >> LR_IS_REG_OFF) & 0x1;
++ val >>= LR_ENTRY_BITS;
++ }
++}
++
+ /* for any branch, call, exit record the history of jmps in the given state */
+ static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_state *cur,
+- int insn_flags)
++ int insn_flags, u64 linked_regs)
+ {
+ u32 cnt = cur->jmp_history_cnt;
+ struct bpf_jmp_history_entry *p;
+@@ -3479,6 +3557,10 @@ static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_st
+ "verifier insn history bug: insn_idx %d cur flags %x new flags %x\n",
+ env->insn_idx, env->cur_hist_ent->flags, insn_flags);
+ env->cur_hist_ent->flags |= insn_flags;
++ WARN_ONCE(env->cur_hist_ent->linked_regs != 0,
++ "verifier insn history bug: insn_idx %d linked_regs != 0: %#llx\n",
++ env->insn_idx, env->cur_hist_ent->linked_regs);
++ env->cur_hist_ent->linked_regs = linked_regs;
+ return 0;
+ }
+
+@@ -3493,6 +3575,7 @@ static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_st
+ p->idx = env->insn_idx;
+ p->prev_idx = env->prev_insn_idx;
+ p->flags = insn_flags;
++ p->linked_regs = linked_regs;
+ cur->jmp_history_cnt = cnt;
+ env->cur_hist_ent = p;
+
+@@ -3668,6 +3751,11 @@ static inline bool bt_is_reg_set(struct backtrack_state *bt, u32 reg)
+ return bt->reg_masks[bt->frame] & (1 << reg);
+ }
+
++static inline bool bt_is_frame_reg_set(struct backtrack_state *bt, u32 frame, u32 reg)
++{
++ return bt->reg_masks[frame] & (1 << reg);
++}
++
+ static inline bool bt_is_frame_slot_set(struct backtrack_state *bt, u32 frame, u32 slot)
+ {
+ return bt->stack_masks[frame] & (1ull << slot);
+@@ -3717,6 +3805,42 @@ static void fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask)
+ }
+ }
+
++/* If any register R in hist->linked_regs is marked as precise in bt,
++ * do bt_set_frame_{reg,slot}(bt, R) for all registers in hist->linked_regs.
++ */
++static void bt_sync_linked_regs(struct backtrack_state *bt, struct bpf_jmp_history_entry *hist)
++{
++ struct linked_regs linked_regs;
++ bool some_precise = false;
++ int i;
++
++ if (!hist || hist->linked_regs == 0)
++ return;
++
++ linked_regs_unpack(hist->linked_regs, &linked_regs);
++ for (i = 0; i < linked_regs.cnt; ++i) {
++ struct linked_reg *e = &linked_regs.entries[i];
++
++ if ((e->is_reg && bt_is_frame_reg_set(bt, e->frameno, e->regno)) ||
++ (!e->is_reg && bt_is_frame_slot_set(bt, e->frameno, e->spi))) {
++ some_precise = true;
++ break;
++ }
++ }
++
++ if (!some_precise)
++ return;
++
++ for (i = 0; i < linked_regs.cnt; ++i) {
++ struct linked_reg *e = &linked_regs.entries[i];
++
++ if (e->is_reg)
++ bt_set_frame_reg(bt, e->frameno, e->regno);
++ else
++ bt_set_frame_slot(bt, e->frameno, e->spi);
++ }
++}
++
+ static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
+
+ /* For given verifier state backtrack_insn() is called from the last insn to
+@@ -3756,6 +3880,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
+ print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
+ }
+
++ /* If there is a history record that some registers gained range at this insn,
++ * propagate precision marks to those registers, so that bt_is_reg_set()
++ * accounts for these registers.
++ */
++ bt_sync_linked_regs(bt, hist);
++
+ if (class == BPF_ALU || class == BPF_ALU64) {
+ if (!bt_is_reg_set(bt, dreg))
+ return 0;
+@@ -3985,7 +4115,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
+ */
+ bt_set_reg(bt, dreg);
+ bt_set_reg(bt, sreg);
+- /* else dreg <cond> K
++ } else if (BPF_SRC(insn->code) == BPF_K) {
++ /* dreg <cond> K
+ * Only dreg still needs precision before
+ * this insn, so for the K-based conditional
+ * there is nothing new to be marked.
+@@ -4003,6 +4134,10 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
+ /* to be analyzed */
+ return -ENOTSUPP;
+ }
++ /* Propagate precision marks to linked registers, to account for
++ * registers marked as precise in this function.
++ */
++ bt_sync_linked_regs(bt, hist);
+ return 0;
+ }
+
+@@ -4354,7 +4489,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
+
+ /* If some register with scalar ID is marked as precise,
+ * make sure that all registers sharing this ID are also precise.
+- * This is needed to estimate effect of find_equal_scalars().
++ * This is needed to estimate effect of sync_linked_regs().
+ * Do this at the last instruction of each state,
+ * bpf_reg_state::id fields are valid for these instructions.
+ *
+@@ -4368,7 +4503,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
+ * ...
+ * --- state #1 {r1.id = A, r2.id = A} ---
+ * ...
+- * if (r2 > 10) goto exit; // find_equal_scalars() assigns range to r1
++ * if (r2 > 10) goto exit; // sync_linked_regs() assigns range to r1
+ * ...
+ * --- state #2 {r1.id = A, r2.id = A} ---
+ * r3 = r10
+@@ -4736,7 +4871,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
+ }
+
+ if (insn_flags)
+- return push_jmp_history(env, env->cur_state, insn_flags);
++ return push_jmp_history(env, env->cur_state, insn_flags, 0);
+ return 0;
+ }
+
+@@ -5032,7 +5167,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
+ insn_flags = 0; /* we are not restoring spilled register */
+ }
+ if (insn_flags)
+- return push_jmp_history(env, env->cur_state, insn_flags);
++ return push_jmp_history(env, env->cur_state, insn_flags, 0);
+ return 0;
+ }
+
+@@ -13540,7 +13675,7 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+ ptr_reg = dst_reg;
+ else
+ /* Make sure ID is cleared otherwise dst_reg min/max could be
+- * incorrectly propagated into other registers by find_equal_scalars()
++ * incorrectly propagated into other registers by sync_linked_regs()
+ */
+ dst_reg->id = 0;
+ if (BPF_SRC(insn->code) == BPF_X) {
+@@ -13700,7 +13835,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
+ */
+ if (need_id)
+ /* Assign src and dst registers the same ID
+- * that will be used by find_equal_scalars()
++ * that will be used by sync_linked_regs()
+ * to propagate min/max range.
+ */
+ src_reg->id = ++env->id_gen;
+@@ -13746,7 +13881,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
+ copy_register_state(dst_reg, src_reg);
+ /* Make sure ID is cleared if src_reg is not in u32
+ * range otherwise dst_reg min/max could be incorrectly
+- * propagated into src_reg by find_equal_scalars()
++ * propagated into src_reg by sync_linked_regs()
+ */
+ if (!is_src_reg_u32)
+ dst_reg->id = 0;
+@@ -14564,19 +14699,75 @@ static bool try_match_pkt_pointers(const struct bpf_insn *insn,
+ return true;
+ }
+
+-static void find_equal_scalars(struct bpf_verifier_state *vstate,
+- struct bpf_reg_state *known_reg)
++static void __collect_linked_regs(struct linked_regs *reg_set, struct bpf_reg_state *reg,
++ u32 id, u32 frameno, u32 spi_or_reg, bool is_reg)
+ {
+- struct bpf_func_state *state;
++ struct linked_reg *e;
++
++ if (reg->type != SCALAR_VALUE || reg->id != id)
++ return;
++
++ e = linked_regs_push(reg_set);
++ if (e) {
++ e->frameno = frameno;
++ e->is_reg = is_reg;
++ e->regno = spi_or_reg;
++ } else {
++ reg->id = 0;
++ }
++}
++
++/* For all R being scalar registers or spilled scalar registers
++ * in verifier state, save R in linked_regs if R->id == id.
++ * If there are too many Rs sharing same id, reset id for leftover Rs.
++ */
++static void collect_linked_regs(struct bpf_verifier_state *vstate, u32 id,
++ struct linked_regs *linked_regs)
++{
++ struct bpf_func_state *func;
+ struct bpf_reg_state *reg;
++ int i, j;
+
+- bpf_for_each_reg_in_vstate(vstate, state, reg, ({
+- if (reg->type == SCALAR_VALUE && reg->id == known_reg->id) {
++ for (i = vstate->curframe; i >= 0; i--) {
++ func = vstate->frame[i];
++ for (j = 0; j < BPF_REG_FP; j++) {
++ reg = &func->regs[j];
++ __collect_linked_regs(linked_regs, reg, id, i, j, true);
++ }
++ for (j = 0; j < func->allocated_stack / BPF_REG_SIZE; j++) {
++ if (!is_spilled_reg(&func->stack[j]))
++ continue;
++ reg = &func->stack[j].spilled_ptr;
++ __collect_linked_regs(linked_regs, reg, id, i, j, false);
++ }
++ }
++}
++
++/* For all R in linked_regs, copy known_reg range into R
++ * if R->id == known_reg->id.
++ */
++static void sync_linked_regs(struct bpf_verifier_state *vstate, struct bpf_reg_state *known_reg,
++ struct linked_regs *linked_regs)
++{
++ struct bpf_reg_state *reg;
++ struct linked_reg *e;
++ int i;
++
++ for (i = 0; i < linked_regs->cnt; ++i) {
++ e = &linked_regs->entries[i];
++ reg = e->is_reg ? &vstate->frame[e->frameno]->regs[e->regno]
++ : &vstate->frame[e->frameno]->stack[e->spi].spilled_ptr;
++ if (reg->type != SCALAR_VALUE || reg == known_reg)
++ continue;
++ if (reg->id != known_reg->id)
++ continue;
++ {
+ s32 saved_subreg_def = reg->subreg_def;
++
+ copy_register_state(reg, known_reg);
+ reg->subreg_def = saved_subreg_def;
+ }
+- }));
++ }
+ }
+
+ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+@@ -14587,6 +14778,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+ struct bpf_reg_state *regs = this_branch->frame[this_branch->curframe]->regs;
+ struct bpf_reg_state *dst_reg, *other_branch_regs, *src_reg = NULL;
+ struct bpf_reg_state *eq_branch_regs;
++ struct linked_regs linked_regs = {};
+ u8 opcode = BPF_OP(insn->code);
+ bool is_jmp32;
+ int pred = -1;
+@@ -14704,6 +14896,21 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+ return 0;
+ }
+
++ /* Push scalar registers sharing same ID to jump history,
++ * do this before creating 'other_branch', so that both
++ * 'this_branch' and 'other_branch' share this history
++ * if parent state is created.
++ */
++ if (BPF_SRC(insn->code) == BPF_X && src_reg->type == SCALAR_VALUE && src_reg->id)
++ collect_linked_regs(this_branch, src_reg->id, &linked_regs);
++ if (dst_reg->type == SCALAR_VALUE && dst_reg->id)
++ collect_linked_regs(this_branch, dst_reg->id, &linked_regs);
++ if (linked_regs.cnt > 1) {
++ err = push_jmp_history(env, this_branch, 0, linked_regs_pack(&linked_regs));
++ if (err)
++ return err;
++ }
++
+ other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx,
+ false);
+ if (!other_branch)
+@@ -14746,8 +14953,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+ src_reg, dst_reg, opcode);
+ if (src_reg->id &&
+ !WARN_ON_ONCE(src_reg->id != other_branch_regs[insn->src_reg].id)) {
+- find_equal_scalars(this_branch, src_reg);
+- find_equal_scalars(other_branch, &other_branch_regs[insn->src_reg]);
++ sync_linked_regs(this_branch, src_reg, &linked_regs);
++ sync_linked_regs(other_branch, &other_branch_regs[insn->src_reg],
++ &linked_regs);
+ }
+
+ }
+@@ -14759,8 +14967,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+
+ if (dst_reg->type == SCALAR_VALUE && dst_reg->id &&
+ !WARN_ON_ONCE(dst_reg->id != other_branch_regs[insn->dst_reg].id)) {
+- find_equal_scalars(this_branch, dst_reg);
+- find_equal_scalars(other_branch, &other_branch_regs[insn->dst_reg]);
++ sync_linked_regs(this_branch, dst_reg, &linked_regs);
++ sync_linked_regs(other_branch, &other_branch_regs[insn->dst_reg],
++ &linked_regs);
+ }
+
+ /* if one pointer register is compared to another pointer
+@@ -16182,7 +16391,7 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
+ *
+ * First verification path is [1-6]:
+ * - at (4) same bpf_reg_state::id (b) would be assigned to r6 and r7;
+- * - at (5) r6 would be marked <= X, find_equal_scalars() would also mark
++ * - at (5) r6 would be marked <= X, sync_linked_regs() would also mark
+ * r7 <= X, because r6 and r7 share same id.
+ * Next verification path is [1-4, 6].
+ *
+@@ -16915,7 +17124,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
+ * the current state.
+ */
+ if (is_jmp_point(env, env->insn_idx))
+- err = err ? : push_jmp_history(env, cur, 0);
++ err = err ? : push_jmp_history(env, cur, 0, 0);
+ err = err ? : propagate_precision(env, &sl->state);
+ if (err)
+ return err;
+@@ -17181,7 +17390,7 @@ static int do_check(struct bpf_verifier_env *env)
+ }
+
+ if (is_jmp_point(env, env->insn_idx)) {
+- err = push_jmp_history(env, state, 0);
++ err = push_jmp_history(env, state, 0, 0);
+ if (err)
+ return err;
+ }
+diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
+index 4b8b0f45d17d71..a188e26f04da70 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
++++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
+@@ -141,7 +141,7 @@ __msg("mark_precise: frame0: last_idx 14 first_idx 9")
+ __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7")
+ __msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4")
+ __msg("mark_precise: frame0: regs=r6 stack= before 11: (25) if r6 > 0x3 goto pc+4")
+-__msg("mark_precise: frame0: regs=r6 stack= before 10: (bf) r6 = r0")
++__msg("mark_precise: frame0: regs=r0,r6 stack= before 10: (bf) r6 = r0")
+ __msg("mark_precise: frame0: regs=r0 stack= before 9: (85) call bpf_loop")
+ /* State entering callback body popped from states stack */
+ __msg("from 9 to 17: frame1:")
+diff --git a/tools/testing/selftests/bpf/verifier/precise.c b/tools/testing/selftests/bpf/verifier/precise.c
+index 8a2ff81d835088..b0b1bcc668adb1 100644
+--- a/tools/testing/selftests/bpf/verifier/precise.c
++++ b/tools/testing/selftests/bpf/verifier/precise.c
+@@ -44,7 +44,7 @@
+ mark_precise: frame0: regs=r2 stack= before 23\
+ mark_precise: frame0: regs=r2 stack= before 22\
+ mark_precise: frame0: regs=r2 stack= before 20\
+- mark_precise: frame0: parent state regs=r2 stack=:\
++ mark_precise: frame0: parent state regs=r2,r9 stack=:\
+ mark_precise: frame0: last_idx 19 first_idx 10\
+ mark_precise: frame0: regs=r2,r9 stack= before 19\
+ mark_precise: frame0: regs=r9 stack= before 18\
+--
+2.53.0
+
--- /dev/null
+From ea0d47aa0f73bba93be4ff4ca9651e3e0234bdb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 12:22:54 +0000
+Subject: ring-buffer: Remove ring_buffer_read_prepare_sync()
+
+From: Bjoern Doebel <doebel@amazon.de>
+
+[ Upstream commit 119a5d573622ae90ba730d18acfae9bb75d77b9a ]
+
+When the ring buffer was first introduced, reading the non-consuming
+"trace" file required disabling the writing of the ring buffer. To make
+sure the writing was fully disabled before iterating the buffer with a
+non-consuming read, it would set the disable flag of the buffer and then
+call an RCU synchronization to make sure all the buffers were
+synchronized.
+
+The function ring_buffer_read_start() originally would initialize the
+iterator and call an RCU synchronization, but this was for each individual
+per CPU buffer where this would get called many times on a machine with
+many CPUs before the trace file could be read. The commit 72c9ddfd4c5bf
+("ring-buffer: Make non-consuming read less expensive with lots of cpus.")
+separated ring_buffer_read_start into ring_buffer_read_prepare(),
+ring_buffer_read_sync() and then ring_buffer_read_start() to allow each of
+the per CPU buffers to be prepared, call the read_buffer_read_sync() once,
+and then the ring_buffer_read_start() for each of the CPUs which made
+things much faster.
+
+The commit 1039221cc278 ("ring-buffer: Do not disable recording when there
+is an iterator") removed the requirement of disabling the recording of the
+ring buffer in order to iterate it, but it did not remove the
+synchronization that was happening that was required to wait for all the
+buffers to have no more writers. It's now OK for the buffers to have
+writers and no synchronization is needed.
+
+Remove the synchronization and put back the interface for the ring buffer
+iterator back before commit 72c9ddfd4c5bf was applied.
+
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Link: https://lore.kernel.org/20250630180440.3eabb514@batman.local.home
+Reported-by: David Howells <dhowells@redhat.com>
+Fixes: 1039221cc278 ("ring-buffer: Do not disable recording when there is an iterator")
+Tested-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Assisted-by: Kiro:claude-opus-4.8
+Signed-off-by: Bjoern Doebel <doebel@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/ring_buffer.h | 4 +--
+ kernel/trace/ring_buffer.c | 67 ++++++-------------------------------
+ kernel/trace/trace.c | 14 +++-----
+ kernel/trace/trace_kdb.c | 8 ++---
+ 4 files changed, 18 insertions(+), 75 deletions(-)
+
+diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
+index ded528d23f855b..382fbaa701f930 100644
+--- a/include/linux/ring_buffer.h
++++ b/include/linux/ring_buffer.h
+@@ -129,9 +129,7 @@ ring_buffer_consume(struct trace_buffer *buffer, int cpu, u64 *ts,
+ unsigned long *lost_events);
+
+ struct ring_buffer_iter *
+-ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags);
+-void ring_buffer_read_prepare_sync(void);
+-void ring_buffer_read_start(struct ring_buffer_iter *iter);
++ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags);
+ void ring_buffer_read_finish(struct ring_buffer_iter *iter);
+
+ struct ring_buffer_event *
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 508edf1f3f1e2e..52c7dbccafedde 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -5084,28 +5084,20 @@ ring_buffer_consume(struct trace_buffer *buffer, int cpu, u64 *ts,
+ EXPORT_SYMBOL_GPL(ring_buffer_consume);
+
+ /**
+- * ring_buffer_read_prepare - Prepare for a non consuming read of the buffer
++ * ring_buffer_read_start - start a non consuming read of the buffer
+ * @buffer: The ring buffer to read from
+ * @cpu: The cpu buffer to iterate over
+ * @flags: gfp flags to use for memory allocation
+ *
+- * This performs the initial preparations necessary to iterate
+- * through the buffer. Memory is allocated, buffer recording
+- * is disabled, and the iterator pointer is returned to the caller.
+- *
+- * Disabling buffer recording prevents the reading from being
+- * corrupted. This is not a consuming read, so a producer is not
+- * expected.
+- *
+- * After a sequence of ring_buffer_read_prepare calls, the user is
+- * expected to make at least one call to ring_buffer_read_prepare_sync.
+- * Afterwards, ring_buffer_read_start is invoked to get things going
+- * for real.
++ * This creates an iterator to allow non-consuming iteration through
++ * the buffer. If the buffer is disabled for writing, it will produce
++ * the same information each time, but if the buffer is still writing
++ * then the first hit of a write will cause the iteration to stop.
+ *
+- * This overall must be paired with ring_buffer_read_finish.
++ * Must be paired with ring_buffer_read_finish.
+ */
+ struct ring_buffer_iter *
+-ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags)
++ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags)
+ {
+ struct ring_buffer_per_cpu *cpu_buffer;
+ struct ring_buffer_iter *iter;
+@@ -5130,51 +5122,12 @@ ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags)
+
+ atomic_inc(&cpu_buffer->resize_disabled);
+
+- return iter;
+-}
+-EXPORT_SYMBOL_GPL(ring_buffer_read_prepare);
+-
+-/**
+- * ring_buffer_read_prepare_sync - Synchronize a set of prepare calls
+- *
+- * All previously invoked ring_buffer_read_prepare calls to prepare
+- * iterators will be synchronized. Afterwards, read_buffer_read_start
+- * calls on those iterators are allowed.
+- */
+-void
+-ring_buffer_read_prepare_sync(void)
+-{
+- synchronize_rcu();
+-}
+-EXPORT_SYMBOL_GPL(ring_buffer_read_prepare_sync);
+-
+-/**
+- * ring_buffer_read_start - start a non consuming read of the buffer
+- * @iter: The iterator returned by ring_buffer_read_prepare
+- *
+- * This finalizes the startup of an iteration through the buffer.
+- * The iterator comes from a call to ring_buffer_read_prepare and
+- * an intervening ring_buffer_read_prepare_sync must have been
+- * performed.
+- *
+- * Must be paired with ring_buffer_read_finish.
+- */
+-void
+-ring_buffer_read_start(struct ring_buffer_iter *iter)
+-{
+- struct ring_buffer_per_cpu *cpu_buffer;
+- unsigned long flags;
+-
+- if (!iter)
+- return;
+-
+- cpu_buffer = iter->cpu_buffer;
+-
+- raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
++ guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
+ arch_spin_lock(&cpu_buffer->lock);
+ rb_iter_reset(iter);
+ arch_spin_unlock(&cpu_buffer->lock);
+- raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
++
++ return iter;
+ }
+ EXPORT_SYMBOL_GPL(ring_buffer_read_start);
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 6b35666a4e0be6..f57baf67726da8 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -4792,21 +4792,15 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
+ if (iter->cpu_file == RING_BUFFER_ALL_CPUS) {
+ for_each_tracing_cpu(cpu) {
+ iter->buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter->array_buffer->buffer,
+- cpu, GFP_KERNEL);
+- }
+- ring_buffer_read_prepare_sync();
+- for_each_tracing_cpu(cpu) {
+- ring_buffer_read_start(iter->buffer_iter[cpu]);
++ ring_buffer_read_start(iter->array_buffer->buffer,
++ cpu, GFP_KERNEL);
+ tracing_iter_reset(iter, cpu);
+ }
+ } else {
+ cpu = iter->cpu_file;
+ iter->buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter->array_buffer->buffer,
+- cpu, GFP_KERNEL);
+- ring_buffer_read_prepare_sync();
+- ring_buffer_read_start(iter->buffer_iter[cpu]);
++ ring_buffer_read_start(iter->array_buffer->buffer,
++ cpu, GFP_KERNEL);
+ tracing_iter_reset(iter, cpu);
+ }
+
+diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
+index 59857a1ee44cdf..628c25693cef2f 100644
+--- a/kernel/trace/trace_kdb.c
++++ b/kernel/trace/trace_kdb.c
+@@ -43,17 +43,15 @@ static void ftrace_dump_buf(int skip_entries, long cpu_file)
+ if (cpu_file == RING_BUFFER_ALL_CPUS) {
+ for_each_tracing_cpu(cpu) {
+ iter.buffer_iter[cpu] =
+- ring_buffer_read_prepare(iter.array_buffer->buffer,
+- cpu, GFP_ATOMIC);
+- ring_buffer_read_start(iter.buffer_iter[cpu]);
++ ring_buffer_read_start(iter.array_buffer->buffer,
++ cpu, GFP_ATOMIC);
+ tracing_iter_reset(&iter, cpu);
+ }
+ } else {
+ iter.cpu_file = cpu_file;
+ iter.buffer_iter[cpu_file] =
+- ring_buffer_read_prepare(iter.array_buffer->buffer,
++ ring_buffer_read_start(iter.array_buffer->buffer,
+ cpu_file, GFP_ATOMIC);
+- ring_buffer_read_start(iter.buffer_iter[cpu_file]);
+ tracing_iter_reset(&iter, cpu_file);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8dc4160546b2ef51f215e7a62cb71bfd7ba41711 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:29:00 +0800
+Subject: selftests/bpf: Add test to ensure kprobe_multi is not sleepable
+
+From: Varun R Mallya <varunrmallya@gmail.com>
+
+commit c7cab53f9d5273f0cf2a26bdf178c4e074bdfb50 upstream.
+
+Add a selftest to ensure that kprobe_multi programs cannot be attached
+using the BPF_F_SLEEPABLE flag. This test succeeds when the kernel
+rejects attachment of kprobe_multi when the BPF_F_SLEEPABLE flag is set.
+
+Suggested-by: Leon Hwang <leon.hwang@linux.dev>
+Signed-off-by: Varun R Mallya <varunrmallya@gmail.com>
+Link: https://lore.kernel.org/r/20260408190137.101418-3-varunrmallya@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[shung-hsi.yu: borrowed 'saved_error' variable from commit 00cdcd2900bd
+("selftests/bpf: Don't use libbpf_get_error() in kprobe_multi_test"). ]
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../bpf/prog_tests/kprobe_multi_test.c | 34 +++++++++++++++++++
+ .../bpf/progs/kprobe_multi_sleepable.c | 25 ++++++++++++++
+ 2 files changed, 59 insertions(+)
+ create mode 100644 tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+index 4041cfa670eb4c..d41e140c315083 100644
+--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+@@ -4,6 +4,7 @@
+ #include "trace_helpers.h"
+ #include "kprobe_multi_empty.skel.h"
+ #include "kprobe_multi_override.skel.h"
++#include "kprobe_multi_sleepable.skel.h"
+ #include "bpf/libbpf_internal.h"
+ #include "bpf/hashmap.h"
+
+@@ -214,7 +215,9 @@ static void test_attach_api_syms(void)
+ static void test_attach_api_fails(void)
+ {
+ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
++ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ struct kprobe_multi *skel = NULL;
++ struct kprobe_multi_sleepable *sl_skel = NULL;
+ struct bpf_link *link = NULL;
+ unsigned long long addrs[2];
+ const char *syms[2] = {
+@@ -222,6 +225,7 @@ static void test_attach_api_fails(void)
+ "bpf_fentry_test2",
+ };
+ __u64 cookies[2];
++ int saved_error, err;
+
+ addrs[0] = ksym_get_addr("bpf_fentry_test1");
+ addrs[1] = ksym_get_addr("bpf_fentry_test2");
+@@ -300,9 +304,39 @@ static void test_attach_api_fails(void)
+ if (!ASSERT_EQ(libbpf_get_error(link), -EINVAL, "fail_5_error"))
+ goto cleanup;
+
++ /* fail_9 - sleepable kprobe multi should not attach */
++ sl_skel = kprobe_multi_sleepable__open();
++ if (!ASSERT_OK_PTR(sl_skel, "sleep_skel_open"))
++ goto cleanup;
++
++ sl_skel->bss->user_ptr = sl_skel;
++
++ err = bpf_program__set_flags(sl_skel->progs.handle_kprobe_multi_sleepable,
++ BPF_F_SLEEPABLE);
++ if (!ASSERT_OK(err, "sleep_skel_set_flags"))
++ goto cleanup;
++
++ err = kprobe_multi_sleepable__load(sl_skel);
++ if (!ASSERT_OK(err, "sleep_skel_load"))
++ goto cleanup;
++
++ link = bpf_program__attach_kprobe_multi_opts(sl_skel->progs.handle_kprobe_multi_sleepable,
++ "bpf_fentry_test1", NULL);
++ saved_error = -errno;
++
++ if (!ASSERT_ERR_PTR(link, "fail_9"))
++ goto cleanup;
++
++ if (!ASSERT_EQ(saved_error, -EINVAL, "fail_9_error"))
++ goto cleanup;
++
++ err = bpf_prog_test_run_opts(bpf_program__fd(sl_skel->progs.fentry), &topts);
++ ASSERT_OK(err, "bpf_prog_test_run_opts");
++
+ cleanup:
+ bpf_link__destroy(link);
+ kprobe_multi__destroy(skel);
++ kprobe_multi_sleepable__destroy(sl_skel);
+ }
+
+ static size_t symbol_hash(long key, void *ctx __maybe_unused)
+diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c b/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+new file mode 100644
+index 00000000000000..932e1d9c72e2d0
+--- /dev/null
++++ b/tools/testing/selftests/bpf/progs/kprobe_multi_sleepable.c
+@@ -0,0 +1,25 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include "vmlinux.h"
++#include <bpf/bpf_helpers.h>
++#include <bpf/bpf_tracing.h>
++
++void *user_ptr = 0;
++
++SEC("kprobe.multi")
++int handle_kprobe_multi_sleepable(struct pt_regs *ctx)
++{
++ int a, err;
++
++ err = bpf_copy_from_user(&a, sizeof(a), user_ptr);
++ barrier_var(a);
++ return err;
++}
++
++SEC("fentry/bpf_fentry_test1")
++int BPF_PROG(fentry)
++{
++ return 0;
++}
++
++char _license[] SEC("license") = "GPL";
+--
+2.53.0
+
--- /dev/null
+From 5b907cc78afd5b4ddaa993898b4996a4eae29143 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jun 2026 01:27:34 +0800
+Subject: selftests/bpf: Tests for per-insn sync_linked_regs() precision
+ tracking
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit bebc17b1c03b224a0b4aec6a171815e39f8ba9bc ]
+
+Add a few test cases to verify precision tracking for scalars gaining
+range because of sync_linked_regs():
+- check what happens when more than 6 registers might gain range in
+ sync_linked_regs();
+- check if precision is propagated correctly when operand of
+ conditional jump gained range in sync_linked_regs() and one of
+ linked registers is marked precise;
+- check if precision is propagated correctly when operand of
+ conditional jump gained range in sync_linked_regs() and a
+ other-linked operand of the conditional jump is marked precise;
+- add a minimized reproducer for precision tracking bug reported in [0];
+- Check that mark_chain_precision() for one of the conditional jump
+ operands does not trigger equal scalars precision propagation.
+
+[0] https://lore.kernel.org/bpf/CAEf4BzZ0xidVCqB47XnkXcNhkPWF6_nTV7yt+_Lf0kcFEut2Mg@mail.gmail.com/
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20240718202357.1746514-4-eddyz87@gmail.com
+[ zhenzhong: keep the linked_regs_broken_link_2 reject check, but
+ drop the mark_precise log expectations because 6.6.y does not derive
+ the scalar-vs-scalar range for that non-constant JMP_X comparison. ]
+Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_scalar_ids.c | 162 ++++++++++++++++++
+ 1 file changed, 162 insertions(+)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
+index f70392bf696c62..2eb85eb3a06ccb 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
++++ b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
+@@ -47,6 +47,72 @@ __naked void linked_regs_bpf_k(void)
+ : __clobber_all);
+ }
+
++/* Registers r{0,1,2} share same ID when 'if r1 > ...' insn is processed,
++ * check that verifier marks r{1,2} as precise while backtracking
++ * 'if r1 > ...' with r0 already marked.
++ */
++SEC("socket")
++__success __log_level(2)
++__flag(BPF_F_TEST_STATE_FREQ)
++__msg("frame0: regs=r0 stack= before 5: (2d) if r1 > r3 goto pc+0")
++__msg("frame0: parent state regs=r0,r1,r2,r3 stack=:")
++__msg("frame0: regs=r0,r1,r2,r3 stack= before 4: (b7) r3 = 7")
++__naked void linked_regs_bpf_x_src(void)
++{
++ asm volatile (
++ /* r0 = random number up to 0xff */
++ "call %[bpf_ktime_get_ns];"
++ "r0 &= 0xff;"
++ /* tie r0.id == r1.id == r2.id */
++ "r1 = r0;"
++ "r2 = r0;"
++ "r3 = 7;"
++ "if r1 > r3 goto +0;"
++ /* force r0 to be precise, this eventually marks r1 and r2 as
++ * precise as well because of shared IDs
++ */
++ "r4 = r10;"
++ "r4 += r0;"
++ "r0 = 0;"
++ "exit;"
++ :
++ : __imm(bpf_ktime_get_ns)
++ : __clobber_all);
++}
++
++/* Registers r{0,1,2} share same ID when 'if r1 > r3' insn is processed,
++ * check that verifier marks r{0,1,2} as precise while backtracking
++ * 'if r1 > r3' with r3 already marked.
++ */
++SEC("socket")
++__success __log_level(2)
++__flag(BPF_F_TEST_STATE_FREQ)
++__msg("frame0: regs=r3 stack= before 5: (2d) if r1 > r3 goto pc+0")
++__msg("frame0: parent state regs=r0,r1,r2,r3 stack=:")
++__msg("frame0: regs=r0,r1,r2,r3 stack= before 4: (b7) r3 = 7")
++__naked void linked_regs_bpf_x_dst(void)
++{
++ asm volatile (
++ /* r0 = random number up to 0xff */
++ "call %[bpf_ktime_get_ns];"
++ "r0 &= 0xff;"
++ /* tie r0.id == r1.id == r2.id */
++ "r1 = r0;"
++ "r2 = r0;"
++ "r3 = 7;"
++ "if r1 > r3 goto +0;"
++ /* force r0 to be precise, this eventually marks r1 and r2 as
++ * precise as well because of shared IDs
++ */
++ "r4 = r10;"
++ "r4 += r3;"
++ "r0 = 0;"
++ "exit;"
++ :
++ : __imm(bpf_ktime_get_ns)
++ : __clobber_all);
++}
++
+ /* Same as linked_regs_bpf_k, but break one of the
+ * links, note that r1 is absent from regs=... in __msg below.
+ */
+@@ -280,6 +346,102 @@ __naked void precision_two_ids(void)
+ : __clobber_all);
+ }
+
++SEC("socket")
++__success __log_level(2)
++__flag(BPF_F_TEST_STATE_FREQ)
++/* check thar r0 and r6 have different IDs after 'if',
++ * collect_linked_regs() can't tie more than 6 registers for a single insn.
++ */
++__msg("8: (25) if r0 > 0x7 goto pc+0 ; R0=scalar(id=1")
++__msg("9: (bf) r6 = r6 ; R6_w=scalar(id=2")
++/* check that r{0-5} are marked precise after 'if' */
++__msg("frame0: regs=r0 stack= before 8: (25) if r0 > 0x7 goto pc+0")
++__msg("frame0: parent state regs=r0,r1,r2,r3,r4,r5 stack=:")
++__naked void linked_regs_too_many_regs(void)
++{
++ asm volatile (
++ /* r0 = random number up to 0xff */
++ "call %[bpf_ktime_get_ns];"
++ "r0 &= 0xff;"
++ /* tie r{0-6} IDs */
++ "r1 = r0;"
++ "r2 = r0;"
++ "r3 = r0;"
++ "r4 = r0;"
++ "r5 = r0;"
++ "r6 = r0;"
++ /* propagate range for r{0-6} */
++ "if r0 > 7 goto +0;"
++ /* make r6 appear in the log */
++ "r6 = r6;"
++ /* force r0 to be precise,
++ * this would cause r{0-4} to be precise because of shared IDs
++ */
++ "r7 = r10;"
++ "r7 += r0;"
++ "r0 = 0;"
++ "exit;"
++ :
++ : __imm(bpf_ktime_get_ns)
++ : __clobber_all);
++}
++
++SEC("socket")
++__failure __log_level(2)
++__flag(BPF_F_TEST_STATE_FREQ)
++__msg("div by zero")
++__naked void linked_regs_broken_link_2(void)
++{
++ asm volatile (
++ "call %[bpf_get_prandom_u32];"
++ "r7 = r0;"
++ "r8 = r0;"
++ "call %[bpf_get_prandom_u32];"
++ "if r0 > 1 goto +0;"
++ /* r7.id == r8.id,
++ * thus r7 precision implies r8 precision,
++ * which implies r0 precision because of the conditional below.
++ */
++ "if r8 >= r0 goto 1f;"
++ /* break id relation between r7 and r8 */
++ "r8 += r8;"
++ /* make r7 precise */
++ "if r7 == 0 goto 1f;"
++ "r0 /= 0;"
++"1:"
++ "r0 = 42;"
++ "exit;"
++ :
++ : __imm(bpf_get_prandom_u32)
++ : __clobber_all);
++}
++
++/* Check that mark_chain_precision() for one of the conditional jump
++ * operands does not trigger equal scalars precision propagation.
++ */
++SEC("socket")
++__success __log_level(2)
++__msg("3: (25) if r1 > 0x100 goto pc+0")
++__msg("frame0: regs=r1 stack= before 2: (bf) r1 = r0")
++__naked void cjmp_no_linked_regs_trigger(void)
++{
++ asm volatile (
++ /* r0 = random number up to 0xff */
++ "call %[bpf_ktime_get_ns];"
++ "r0 &= 0xff;"
++ /* tie r0.id == r1.id */
++ "r1 = r0;"
++ /* the jump below would be predicted, thus r1 would be marked precise,
++ * this should not imply precision mark for r0
++ */
++ "if r1 > 256 goto +0;"
++ "r0 = 0;"
++ "exit;"
++ :
++ : __imm(bpf_ktime_get_ns)
++ : __clobber_all);
++}
++
+ /* Verify that check_ids() is used by regsafe() for scalars.
+ *
+ * r9 = ... some pointer with range X ...
+--
+2.53.0
+
--- /dev/null
+From 98cd3c2569986f8bc34dd093556847edd66e3f8d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jun 2026 01:27:35 +0800
+Subject: selftests/bpf: Update comments find_equal_scalars->sync_linked_regs
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit cfbf25481d6dec0089c99c9d33a2ea634fe8f008 ]
+
+find_equal_scalars() is renamed to sync_linked_regs(),
+this commit updates existing references in the selftests comments.
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20240718202357.1746514-5-eddyz87@gmail.com
+[ zhenzhong: only two pre-existing comments still needed updating in 6.6.y. ]
+Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_spill_fill.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+index 1f71f596d33f8b..07a2527a8f47a7 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
++++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+@@ -392,7 +392,7 @@ __naked void spill_32bit_of_64bit_fail(void)
+ *(u32*)(r10 - 8) = r1; \
+ /* 32-bit fill r2 from stack. */ \
+ r2 = *(u32*)(r10 - 8); \
+- /* Compare r2 with another register to trigger find_equal_scalars.\
++ /* Compare r2 with another register to trigger sync_linked_regs.\
+ * Having one random bit is important here, otherwise the verifier cuts\
+ * the corners. If the ID was mistakenly preserved on spill, this would\
+ * cause the verifier to think that r1 is also equal to zero in one of\
+@@ -431,7 +431,7 @@ __naked void spill_16bit_of_32bit_fail(void)
+ *(u16*)(r10 - 8) = r1; \
+ /* 16-bit fill r2 from stack. */ \
+ r2 = *(u16*)(r10 - 8); \
+- /* Compare r2 with another register to trigger find_equal_scalars.\
++ /* Compare r2 with another register to trigger sync_linked_regs.\
+ * Having one random bit is important here, otherwise the verifier cuts\
+ * the corners. If the ID was mistakenly preserved on spill, this would\
+ * cause the verifier to think that r1 is also equal to zero in one of\
+--
+2.53.0
+
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
+bpf-reject-sleepable-kprobe_multi-programs-at-attach.patch
+selftests-bpf-add-test-to-ensure-kprobe_multi-is-not.patch
+af_unix-reject-siocatmark-on-non-stream-sockets.patch
+bpf-track-equal-scalars-history-on-per-instruction-l.patch
+bpf-remove-mark_precise_scalar_ids.patch
+selftests-bpf-tests-for-per-insn-sync_linked_regs-pr.patch
+selftests-bpf-update-comments-find_equal_scalars-syn.patch
+ring-buffer-remove-ring_buffer_read_prepare_sync.patch