Commit graph

1,481,701 commits

Author SHA1 Message Date
Mahe Tardy
c7838e3dc6 selftests/bpf: Add ksock kfunc test
Add a selftest that exercises the ksock kfuncs end-to-end. One syscall
BPF setup program creates a ksock context and connects the socket.
Another LSM sleepable BPF program looks up the context and send test
data. The userspace harness creates a network namespace and a new socket
on loopback, run the setup syscall prog and send LSM BPF prog then check
that the userspace socket received the data from BPF.

Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://lore.kernel.org/bpf/20260813110540.103550-4-mahe.tardy@gmail.com
2026-08-15 23:36:18 +02:00
Mahe Tardy
7ae4eb14c5 bpf: Add ksock kfuncs
Add BPF kfuncs that allow BPF LSM programs to create and use sockets for
sending data. This provides a mechanism for BPF programs to emit
telemetry. For this first patch set, it's restricted to SOCK_DGRAM
socket types with IPPROTO_UDP protocol but could be easily extended to
SOCK_STREAM and IPPROTO_TCP in the future.

The API consists of five kfuncs:

  bpf_ksock_create()   - Create a socket (sleepable)
  bpf_ksock_connect()  - Connect socket to remote address (sleepable)
  bpf_ksock_send()     - Send data through the socket (sleepable)
  bpf_ksock_acquire()  - Acquire a reference to a socket context
  bpf_ksock_release()  - Release a reference (cleanup via
                         queue_rcu_work since sock_release sleeps)

The setup kfuncs bpf_ksock_create, bpf_ksock_connect, can be called from
SYSCALL programs only. While bpf_ksock_acquire, bpf_ksock_release and
bpf_ksock_send can be called from SYSCALL and LSM programs.

The implementation follows the established kfunc lifecycle pattern
(create/acquire/release with refcounting, kptr map storage, dtor
registration). The kernel socket is wrapped in a refcounted bpf_ksock
struct. Cleanup is deferred via queue_rcu_work() because sock_release()
may sleep.

The kfuncs are only compiled when CONFIG_INET is enabled, as they
specifically support AF_INET and AF_INET6 sockets.

The socket operations go through the expected LSM hooks instead of
by-passing them like many kernel sockets since those are created by BPF
programs and thus system users. Thus, the bpf_ksock_send() kfunc, which
is exposed to LSM progs has a verifier filter protection to avoid
recursion so that the whole bpf_kfunc_set kfunc set cannot be called in
a program attached to security_socket_sendmsg(). Also, because of the
LSM checks, we prevent the use of the kfuncs from asynchronous workqueue
as the current value would then be invalid.

In bpf_ksock_create(), we copy the arg values to avoid TOCTOU races
since the kfunc can sleep and the arg values could be stored in a map
that could be re-written by BPF progs or even userspace programs if the
map is mmaped.

Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Acked-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/bpf/20260813110540.103550-3-mahe.tardy@gmail.com
2026-08-15 23:36:18 +02:00
Mahe Tardy
5bd369c055 net: Add connect_socket() helper
Add a helper that connects an existing socket while invoking the LSM
hook. Reuse it in __sys_connect_file() to avoid duplicating the connect
logic. Other socket operations have equivalent helpers that trigger the
appropriate LSM hooks that can be reused, this one was the only one
missing. This will be used in the next commit for a new BPF kfunc that
needs to connect a socket and trigger the LSM hook.

Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Acked-by: Song Liu <song@kernel.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://lore.kernel.org/bpf/20260813110540.103550-2-mahe.tardy@gmail.com
2026-08-15 23:36:18 +02:00
Yichong Chen
d5e81a5650 kernfs: avoid iattr allocation in listxattr
kernfs_iop_listxattr() only needs to report existing xattrs, but it uses
kernfs_iattrs(), which allocates kernfs_iattrs when the node does not
have one yet.

This makes a query operation create persistent per-node metadata even
when the xattr list is empty.

Use kernfs_iattrs_noalloc() instead and return an empty list when no
iattrs exist.

Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Acked-by: Tejun Heo <tj@kernel.org>
Link: https://patch.msgid.link/20260731120554.630147-1-chenyichong@uniontech.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2026-08-15 23:09:10 +02:00
Yijie Yang
e1c13aed4a dt-bindings: interconnect: qcom-bwmon: Add Maili cpu-bwmon compatible
Add the Qualcomm Maili SoC compatible string for the CPU bandwidth
monitor (BWMONv4). This falls back to the sdm845-bwmon compatible,
consistent with the existing pattern used by other recent SoCs such as
sm8750 and kaanapali.

Signed-off-by: Yijie Yang <yijie.yang@oss.qualcomm.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
Link: https://patch.msgid.link/20260811-bwmon-v2-1-80f7f150ab9e@oss.qualcomm.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
2026-08-15 15:46:52 -05:00
Eduard Bostina
b568b68320 dt-bindings: mailbox: Convert TI Message Manager to DT schema
Convert the Texas Instruments Message Manager binding
to DT schema.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Surendra Singh Chouhan
7dffb1a4a3 mailbox: cix: fix DT property name string typo and use dev_err_probe()
cix_mbox_probe() logged property error messages referencing
"cix,mbox_dir" (with an underscore) instead of the actual DT property
string "cix,mbox-dir".

Fix the DT property string in error log messages and convert probe error
paths to dev_err_probe().

Signed-off-by: Surendra Singh Chouhan <kr494167@gmail.com>
Reviewed-by: Guomin Chen <Guomin.Chen@cixtech.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Pengpeng Hou
11d5af151b mailbox: riscv-sbi-mpxy: validate RPMI notification lengths
The SBI return value controls how many bytes are copied from shared
memory into the RPMI notification buffer. It is not validated against
the negotiated shared-memory size before that copy. The event walker
also uses a reversed loop condition and can inspect a short event record.

Validate the complete notification length before copying it, iterate only
while a full event header remains, and stop when a declared event payload
extends beyond the copied notification data.

Fixes: bf3022a4eb ("mailbox: Add RISC-V SBI message proxy (MPXY) based mailbox driver")
Assisted-by: Codex:gpt-5
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Rosen Penev
3ccffcc367 mailbox: bcm2835: use platform_get_irq and simplify probe
Replace irq_of_parse_and_map() with platform_get_irq() for the mailbox
interrupt lookup, and move IRQ and MMIO resource acquisition to the top
of the probe function before any memory allocation.

Simplify error handling throughout: use direct return of platform_get_irq
and PTR_ERR values, remove the redundant platform_set_drvdata and
dev_info log, and inline the final return.

Assisted-by: Opencode:Big-Pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Anup Vishwakarma
66c7bcad72 mailbox: qcom-ipcc: fix duplicate channel allocation across holes
The IPCC of_xlate() both scans for a free mailbox channel and checks
for duplicate references to the same underlying IPCC channel. When a
channel has been shutdown it might have left a hole in the channel
list, which would terminate the search without considering duplicates
later in the list.

Continue the traversal of the channel list to detect and reject
duplicates, while keeping track of the first free channel.

Fixes: d6fbfdbc12 ("mailbox: qcom-ipcc: Fix IPCC mbox channel exhaustion")
Cc: stable@vger.kernel.org
Signed-off-by: Anup Vishwakarma <anup.vishwakarma@oss.qualcomm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Griffin Kroah-Hartman
b37c4d0a2f mailbox: mchp-ipc-sbi: Add null check for devm_kasprintf()
Add a check to see if devm_kasprintf() is not NULL in
mchp_ipc_get_cluster_aggr_irq(), returning -ENOMEM if the function
failed.

Assisted-by: gkh_clanker_t1000
CC: Jassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: Griffin Kroah-Hartman <griffin@kroah.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Pan Chuang
c8235bbe5d mailbox: Remove redundant dev_err()/dev_err_probe()
Since commit 55b48e23f5 ("genirq/devres: Add error handling in
devm_request_*_irq()"), devm_request_irq() and devm_request_threaded_irq()
automatically log detailed error messages on failure. Remove the
now-redundant driver-specific dev_err() and dev_err_probe() calls.

Signed-off-by: Pan Chuang <panchuang@vivo.com>
Acked-by: Chen-Yu Tsai <wens@kernel.org>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Varadarajan Narayanan
9411c0832b dt-bindings: mailbox: qcom: Add IPQ5210 APCS compatible
Add the APCS mailbox compatible for the IPQ5210 SoC. It uses the IPQ6018
APCS mailbox compatible as a fallback, so document the valid compatible
string combination in the binding.

Signed-off-by: Varadarajan Narayanan <varadarajan.narayanan@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Deepti Jaggi
b8032527db dt-bindings: mailbox: qcom-ipcc: Document Nord IPCC
Document Inter-Processor Communication Controller on Qualcomm Nord SoC.

Signed-off-by: Deepti Jaggi <deepti.jaggi@oss.qualcomm.com>
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:13 -05:00
Alexey Klimov
4ff8c9df5e mailbox: exynos: Add support for Exynos850 mailbox
Exynos850-based platforms support ACPM and has similar workflow
of communicating with ACPM via mailbox, however mailbox controller
registers are located at different offsets and writes/reads could be
different. To distinguish between such different behaviours,
the registers offsets for Exynos850 and the platform-specific data
structs are introduced and configuration is described in such structs
for gs101 and exynos850 based SoCs. Probe routine now selects the
corresponding platform-specific data via device_get_match_data().

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Alexey Klimov
fd8dc36a12 dt-bindings: mailbox: google,gs101-mbox: Add samsung,exynos850-mbox
Document support for a mailbox present on Exynos850-based platforms.
The registers offsets are different from gs101 mailbox, but the
workflow is similar, hence new compatible.

Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Huisong Li
3360b08817 mailbox: pcc: Fix command timeout due to missed interrupt
PCC command execution can time out when a fast platform completes a
transaction and signals the platform interrupt before pcc_send_data()
marks the channel as in use. For shared platform interrupts, the type 3
handler uses chan_in_use to decide whether the interrupt belongs to the
channel. If it observes false, it ignores the completion and the caller
waits until timeout.

Publish chan_in_use before ringing the doorbell. Use WRITE_ONCE() for
the lockless flag updates and READ_ONCE() in the interrupt handler. The
following ordered I/O accessor orders the flag store before the platform
is notified.

Clear chan_in_use if ringing the doorbell fails. Otherwise, leave it set
until the interrupt handler completes the transaction, clearing it before
the mailbox core can submit another transfer.

Fixes: 3db174e478 ("mailbox: pcc: Support shared interrupt for multiple subspaces")
Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Tested-by: Adam Young <admiyo@os.amperecomputing.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Sudeep Holla
0ffc8ef661 mailbox: pcc: Check shared memory signature on request
ACPI 6.6 Tables 14.9 and 14.12 define the PCC shared memory
signature as the bitwise OR of 0x50434300 and the PCC subspace ID.
They also clarify that the signature is populated by the platform and
verified by OSPM. The signature is at byte offset 0 in the generic,
extended and reduced PCC shared memory layouts.

Check the signature when a client requests a PCC mailbox channel,
after mapping shared memory and before binding the mailbox client.
This keeps the check in the PCC mailbox controller instead of
duplicating it in individual clients.

Treat a signature mismatch as a warning rather than rejecting the
channel request. Making this newly added check fatal could break
existing systems whose firmware did not populate the signature
correctly even though PCC communication works. Continue to reject
shared memory that is too small to contain a signature because it
cannot be inspected safely.

Cc: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Tested_by: Adam Young <admiyo@os.amperecomputing.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Sudeep Holla
1b7fd72295 mailbox: pcc: Notify clients on polled completion
PCC channels without a platform interrupt rely on the mailbox
polling path to detect command completion.

That path currently only reports transmit completion to the mailbox
core, so clients that wait for their receive callback do not get
notified when the command completes.

Call mbox_chan_received_data() when polling observes completion on a
channel without a platform IRQ, matching the interrupt-driven
completion path.

Reported-by: Cristian Marussi <cristian.marussi@arm.com>
Acked-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Reviewed-by: Adam Young <admiyo@os.amperecomputing.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Linmao Li
ef24ff4f5c mailbox: rockchip: drop unneeded runtime pointer (pclk)
The pclk pointer is only used in rockchip_mbox_probe() and is not needed
after probe completes.

Make it a local variable and drop it from struct rockchip_mbox, which
saves a little bit of runtime memory.

Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Linmao Li
ded48fcbdc mailbox: rockchip: disable pclk on probe failure and unbind
rockchip_mbox_probe() enables the peripheral clock and then keeps going.
None of the later failure paths - platform_get_irq(),
devm_request_threaded_irq() and devm_mbox_controller_register() - disables
it again. The driver has no remove callback either, so the clock also stays
prepared and enabled once the device is unbound, and its enable count keeps
growing over bind/unbind cycles.

Use devm_clk_get_enabled() to tie disabling and unpreparing the clock to
the device lifetime. It is registered before the interrupts and the mailbox
controller, so devres releases it after both are gone.

While rewriting the error path, switch it to dev_err_probe() so that a
deferred probe is not reported as an error.

Fixes: f70ed3b5dc ("mailbox: rockchip: Add Rockchip mailbox driver")
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Jia Yang
fc4f2f9953 mailbox: qcom-cpucp: handle NULL data in send_data callback
mailbox_clear_channel() calls mbox_send_message() with NULL data to
notify the remote side that the RX channel has been cleared.
qcom_cpucp_mbox_send_data() blindly dereferenced the data pointer,
causing a NULL pointer dereference kernel panic when invoked from
this path under PREEMPT_RT.

Add an explicit NULL check and return early without writing to the
TX register, which is the correct behaviour for a channel-clear
notification.

Fixes: 0e2a9a0310 ("mailbox: Add support for QTI CPUCP mailbox controller")
Signed-off-by: Jia Yang <jia.yang@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Jia Yang
3690aaa6d1 mailbox: qcom-cpucp: fix PREEMPT_RT self-deadlock in IRQ handler
qcom_cpucp_mbox_irq_fn() calls mbox_chan_received_data() while holding
chan->lock. Under PREEMPT_RT, spin_lock_irqsave() is converted to an
rt_spinlock (rtmutex-based), which tracks ownership and can sleep.

The callback chain triggered by mbox_chan_received_data() eventually
reaches mailbox_clear_channel() -> mbox_send_message() -> add_to_rbuf(),
which attempts to re-acquire the same chan->lock. Since rtmutex detects
the re-entrant lock attempt by the same owner, the thread blocks waiting
for a lock it already holds, causing a permanent deadlock.

This deadlock manifests as 'irq/N-apss_cpucp_mbox' stuck in D state
with the following call trace:
  rt_spin_lock -> mbox_send_message -> mailbox_clear_channel ->
  scmi_rx_callback -> mbox_chan_received_data [<- held chan->lock here]

Fix by saving chan->cl locally and clearing the HW interrupt register
inside the lock, then invoking mbox_chan_received_data() after releasing
the lock. This preserves the mutual exclusion for chan->cl access while
avoiding the lock re-entrancy that causes the PREEMPT_RT deadlock.

Fixes: 0e2a9a0310 ("mailbox: Add support for QTI CPUCP mailbox controller")
Signed-off-by: Jia Yang <jia.yang@oss.qualcomm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Kunihiko Hayashi
9e9afcb436 mailbox: arm_mhuv2: Use generic firmware property APIs
The protocol parsing code only requires reading firmware
properties and does not depend on OF-specific interfaces.

Replace OF property helpers with the generic device property API.

Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:12 -05:00
Kunihiko Hayashi
ea9bdec20a mailbox: arm_mhuv2: Convert channel translation to fw_xlate()
The MHUv2 channel translation callback only uses the mailbox specifier
arguments and does not depend on any OF-specific data from struct
of_phandle_args.

Switch to the generic fw_xlate() callback and use struct
fwnode_reference_args instead.

This aligns the driver with the mailbox framework's fwnode based channel
lookup support while preserving existing DT based operation.

Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
2026-08-15 15:41:09 -05:00
Jani Nikula
d900723d78
modpost: use mod_warn() and mod_error(), clean up logging
Convert all module name logging to use the mod_warn() and mod_error()
helpers, and pass the module to modpost_log() where used directly, to
always have the module name prefixed in the log message, with .ko suffix
for modules.

Pass struct module *mod around in a few places instead of just
mod->name.

Further unify the logging while at it. Use single quotes instead of
double quotes for symbols, sections, and namespaces. Explicitly state
it's a "symbol" when referencing symbols.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patch.msgid.link/17ed1bce5d54fb32533ba83bc83c429cb71adcb0.1786120005.git.jani.nikula@intel.com
Reviewed-by: Nicolas Schier <nsc@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Nicolas Schier <nsc@kernel.org>
2026-08-15 21:01:51 +02:00
Eduard Zingerman
ce7c9f6c59 Merge branch 'redesign-verification-errors'
Kumar Kartikeya Dwivedi says:

====================
Redesign Verification Errors

TL;DR: This set reworks verifier error messages to include source and
instruction annotations, together with more causal context, making
failures easier to understand and more actionable when debugging and
repairing BPF programs.

Changelog:
----------
v4 -> v5
v4: https://lore.kernel.org/bpf/20260812233326.3575958-1-memxor@gmail.com

 * Defer Verifier Limit reports and the dependent call-chain allocation
   guards to follow-up work, reducing the series from 16 to 14 patches.
   (Eduard)
 * Make kfunc-name disassembly read-only before module-kfunc metadata is
   resolved, retain instruction context without usable source metadata,
   consolidate its fallback, and restrict source discovery to the containing
   subprogram. (Eduard, Sashiko)
 * Retain the newest diagnostic history in a bounded 64 MiB rotating buffer,
   use absolute logical positions across verifier path switches, report
   evicted shared history, and grow storage geometrically. (Eduard)
 * Complete active-path history for BPF_LD_IMM64 and atomic fetches, call
   clobbers and returns, outgoing stack arguments, legacy packet loads, and
   RCU pointer transitions. (Eduard, Sashiko)
 * Preserve causal lineage across equal snapshots, nullable pointer-cast
   branches, and repeated same-depth function invocations using unique
   diagnostic frame identities. Bound each rendered causal path to the oldest
   and newest 32 matching events with an omission summary. (Eduard)
 * Harden diagnostics for malformed release-kfunc signatures, fixed-size
   argument ranges, and dynptr, iterator, memory-size, and required-RCU
   failures by reporting the actual offending type or invariant. (Eduard,
   Sashiko)
 * Remove unrelated formatting and cross-patch churn, dead or single-use
   helpers and filter paths, and align helper placement, includes, and commit
   descriptions with the patches that first need them. (Eduard)

v3 -> v4
v3: https://lore.kernel.org/bpf/20260713153910.2556007-1-memxor@gmail.com

 * Introduce helpers with their first callers and add printf annotations.
   (Eduard, Sashiko)
 * Remove "report" from diagnostic function names. (Sashiko)
 * Reuse bpf_linfo_source and seq_buf, simplify internal names, and use shared
   formatting storage. (Eduard)
 * Use compact common event fields and record branches at successor entry.
   (Eduard)
 * Bound event storage at 1 MiB, use kvrealloc(), and drop events non-fatally.
   (Eduard, Sashiko)
 * Restore diagnostic history only for activated queued states, preserving the
   active failure trace during cleanup. (Eduard, Sashiko)
 * Record register changes through begin/end and scrub helpers, deriving targets
   and origins without caller-saved snapshots. (Eduard)
 * Store lineage marks on events and rewind shared formatting storage after
   rendering each event. (Eduard)
 * Record iterator return values before snapshotting alternate paths. (Sashiko)
 * Use the current verifier instruction for global-subprogram dynptr errors.
   (Sashiko)
 * Use the supplied call name for nullable global-subprogram arguments.
   (Sashiko)
 * Describe global calls under locks as a verifier restriction rather than a
   sleepability failure. (Sashiko)
 * Keep diagnostic strings unsplit and put long call openings on their own
   line. (Eduard)
 * Keep kfunc metadata zeroed before early fetch and allowability failures.
   (Sashiko)
 * Drop the Verifier Internal Error report patch. (Eduard)
 * Distinguish never-initialized registers from invalidated registers.
   (local review)
 * Preserve the legacy different-lock verifier message. (local review)
 * Preserve nullable type qualifiers and stable mismatch formatting.
   (local review)
 * Mark truncated call chains with an ellipsis. (local review)

v2 -> v3
v2: https://lore.kernel.org/bpf/20260619205934.1312876-1-memxor@gmail.com

 * Address various comments from Eduard and Sashiko.
 * Move instruction context from a separate gutter into a new section
   following source context, since surrounding source lines and BPF
   instructions do not map one-to-one.
 * Fix active-path branch reconstruction when switching to queued states,
   and expand register histories to follow value lineage across spills,
   fills, stack reads, helper/kfunc clobbers, and dynptr invalidation.
 * Misc improvements and refinements.

v1 -> v2
v1: https://lore.kernel.org/bpf/20260605063412.974640-1-memxor@gmail.com

 * Reworked diagnostic history from per-verifier-state log to active
   path log with positions saved and reset when verifier search
   backtracks. (Eduard)
 * Moved reusable diagnostic formatting storage into struct bpf_diag
   under struct bpf_verifier_env, and removed large per-report scratch
   buffers from verifier stack frames. (Eduard)
 * Added stack-slot events so diagnostics follow ordinary stack
   spill/fill value flow and invalidations in register-scoped
   histories. (Eduard)
 * Reused existing source and BTF formatting helpers for diagnostics,
   including bpf_get_linfo_file_line() and
   btf_type_snprintf_show_name(). (Eduard)
 * Fixed diagnostic edge cases around signed offset text,
   BPF_MAX_VAR_OFF reporting, negative-offset clamping, poisoned
   stack reads, and borrowed-reference invalidations. (Eduard)
 * Fixed various miscellaneous diagnostic bugs. (Sashiko)
 * Misc improvements and refinements.
---

Motivation
~~~~~~~~~~

The verifier log is the primary interface through which the verifier
communicates to the user its verdict on whether a program was accepted
or rejected.

To aid the debugging of rejection decisions, the verifier also reports
the symbolic state of the program at each instruction, across every explored
path of the BPF program. Such detailed information is critical to
introspect the correctness of verification decisions, and provide
insight into why a given program may have failed to load in the kernel.

A constant pain point in the BPF ecosystem throughout the years has
been the difficulty of debugging verification errors. The human-readable error
messages produced in response to a failure in satisfying safety-related
constraints are often terse, context-dependent, or insufficient for
understanding why a given error may have happened. Users must fall back
to the verbose instruction-by-instruction breakdown of how the symbolic
state evolved to surface the root cause. For programs with a huge log
volume due to high verification complexity, such logs quickly become
inscrutable.

All of this has made life difficult for users lacking an understanding
of how the verifier works, and the various heuristics and idiosyncrasies
used by it. In some cases, even seasoned BPF experts spend significant
time reverse engineering why a program may have failed, and have to
reach into the verifier's source code to form a complete picture of the
verification process.

Such a steep learning curve and cognitive burden also hurts the speed of
BPF development, as the verifier sits right in the middle of the user's
iteration loop while they make use of BPF to solve any given problem.
Expertise in debugging verifier errors does not scale in terms of teams
deploying these programs in production across a diverse set of kernels.

Overall, this leads to a poorer developer experience, causes visible
user dissatisfaction, and remains a drag on wider BPF adoption. With
some of the more recent developments where users increasingly leverage
AI tooling [0] to author their code, this bottleneck becomes even more
critical to address, since it throttles the much faster iteration loop
of AI agents.

  [0]: https://lwn.net/Articles/1075067

Approach
~~~~~~~~

This series starts moving selected failures from terse terminal messages
toward diagnostics that carry the relevant context for a verification
failure. The existing verbose log remains the low-level trace. For selected
failures, the new report is emitted after this trace and answers the
immediate debugging questions:

  - what verifier rule failed,
  - why the current state does not satisfy it,
  - where the failing instruction maps to source,
  - which earlier branch or state event made this path fail,
  - what kind of source change would satisfy the verifier.

The series adds a text-only diagnostics framework under kernel/bpf and
uses it to augment selected verifier errors. Existing verbose(env, ...)
messages are kept, so current selftest expectations and existing log
consumers continue to see the legacy text. The new report has a uniform
outer shape:

  Verification failed: <category>: <problem>

  Reason:
    exact reason for the verification failure, with details

  At:
    source and instruction annotation

  Causal path:
    compressed branch and verifier-state events relevant for debugging

  Suggestion:
    speculation on potential fixes to repair the program

The outer shape is shared, but report construction is category-specific.

The categories are intentionally broad and reviewable. This revision
covers representative cases in Register Type Safety, Memory Safety,
Resource Lifetime Safety, Call Type Safety, Execution Context Safety,
Program Structure and Policy.
It does not attempt to convert every verbose(env, ...) site for now.
Additional verbose-only errors can be moved into the same framework
incrementally.

The following excerpts are copied from this current run on this branch:

  ./test_progs -j1 \
    -a cpumask/test_populate_invalid_destination,\
    cpumask/test_alloc_no_release,\
    verifier_helper_value_access/via_variable_no_max_check_1,\
    verifier_sock/invalidate_pkt_pointers_from_global_func \
    -vv

They show the old terminal error and the exact new diagnostic report,
including the source and instruction annotations.

Call Type Safety, cpumask/test_populate_invalid_destination:

  Legacy:
    R1 type=scalar expected=fp

  Diagnostic:
    Verification failed: Call Type Safety: Invalid call argument

    Reason:
      The first argument (R1) to bpf_cpumask_populate does not satisfy the verifier contract: the kfunc
      expects 24 bytes of memory for (struct bpf_cpumask), but it is an integer scalar and not
      verifier-known memory.

    At:
      test_populate_invalid_destination @ cpumask_failure.c:234:8
      Source context:
          232 | ...
          233 | ...
      >>> 234 |         ret = bpf_cpumask_populate(invalid, &bits, sizeof(bits));
              |         ^-- error: invalid first argument (R1) for bpf_cpumask_populate
          235 |         if (!ret)
          236 |                 err = 2;
      Instruction context:
           2 | (b7) r1 = 1193046
           3 | (b7) r3 = 8
      >>>  4 | (85) call bpf_cpumask_populate#62860
           5 | (56) if w0 != 0x0 goto pc+4
           6 | (18) r1 = 0xffffc9000028e000

    Causal path:
      test_populate_invalid_destination @ cpumask_failure.c:234:8
      Source context:
          232 | ...
          233 | ...
      >>> 234 |         ret = bpf_cpumask_populate(invalid, &bits, sizeof(bits));
              |         ^-- update: R1 changed from context pointer at offset 0 to integer scalar value
              |             1193046
          235 |         if (!ret)
          236 |                 err = 2;
      Instruction context:
           0 | (bf) r2 = r10
           1 | (07) r2 += -8
      >>>  2 | (b7) r1 = 1193046
           3 | (b7) r3 = 8
           4 | (85) call bpf_cpumask_populate#62860

    Suggestion:
      Pass stack, map, context, or other verifier-known memory of the expected type and size, not an
      integer cast to a pointer.

Register Type Safety, verifier_sock/invalidate_pkt_pointers_from_global_func:

  Legacy:
    R7 invalid mem access 'scalar'

  Diagnostic:
    Verification failed: Register Type Safety: Invalid dereference

    Reason:
      R7 is an integer scalar here, not a pointer to memory.

    At:
      invalidate_pkt_pointers_from_global_func @ verifier_sock.c:1067:5
      Source context:
          1065 | ...
          1066 |         skb_pull_data1(sk, 0);
      >>> 1067 |         *p = 42; /* this is unsafe */
               |         ^-- error: invalid dereference of R7 (an integer scalar)
          1068 | ...
          1069 | }
      Instruction context:
           8 | (85) call pc+4
           9 | (b4) w1 = 42
      >>> 10 | (63) *(u32 *)(r7 +0) = r1
          11 | (bc) w0 = w6
          12 | (95) exit

    Causal path:
      invalidate_pkt_pointers_from_global_func @ verifier_sock.c:1062:29
      Source context:
          1060 | int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk)
          1061 | ...
      >>> 1062 |         int *p = (void *)(long)sk->data;
               |         ^-- update: R7 changed from uninitialized value to pkt at offset 0
          1063 | ...
          1064 |         if ((void *)(p + 1) > (void *)(long)sk->data_end)
      Instruction context:
           0 | (b4) w6 = 2
           1 | (61) r2 = *(u32 *)(r1 +80)
      >>>  2 | (61) r7 = *(u32 *)(r1 +76)
           3 | (bf) r3 = r7
           4 | (07) r3 += 4

      invalidate_pkt_pointers_from_global_func @ verifier_sock.c:1064:22
      Source context:
          1062 |         int *p = (void *)(long)sk->data;
          1063 | ...
      >>> 1064 |         if ((void *)(p + 1) > (void *)(long)sk->data_end)
               |         ^-- branch: took the false branch of this conditional, goto not followed
          1065 | ...
          1066 |         skb_pull_data1(sk, 0);
      Instruction context:
           3 | (bf) r3 = r7
           4 | (07) r3 += 4
      >>>  5 | (2d) if r3 > r2 goto pc+5
           6 | (b4) w6 = 0
           7 | (b4) w2 = 0

      invalidate_pkt_pointers_from_global_func @ verifier_sock.c:1066:2
      Source context:
          1064 |         if ((void *)(p + 1) > (void *)(long)sk->data_end)
          1065 | ...
      >>> 1066 |         skb_pull_data1(sk, 0);
               |         ^-- invalidated: R7: packet data may have moved; previous value was pkt at
               |             offset 0
          1067 |         *p = 42; /* this is unsafe */
          1068 | ...
      Instruction context:
           6 | (b4) w6 = 0
           7 | (b4) w2 = 0
      >>>  8 | (85) call pc+4
           9 | (b4) w1 = 42
          10 | (63) *(u32 *)(r7 +0) = r1

    Suggestion:
      Preserve a pointer-valued register where needed, or reload and revalidate the pointer after scalar
      arithmetic, helper calls, or other operations that can invalidate it.

Memory Safety, verifier_helper_value_access/via_variable_no_max_check_1:

  Legacy:
    R1 unbounded memory access, make sure to bounds check any such access

  Diagnostic:
    Verification failed: Memory Safety: Access outside bounds

    Reason:
      The verifier cannot prove offset + access_size <= object_size. Here, the maximal bound for a
      memory access is 4294967295 and exceeds maximum allowed offset of 536870912. R1 is map_value;
      offset is variable: known bits 0x0, unknown mask 0xffffffff; signed range [0, 4294967295],
      unsigned range [0, 4294967295]; access_size is 1; object_size is 48.

    At:
      via_variable_no_max_check_1 @ verifier_helper_value_access.c:627:2
      Source context:
          625 | ...
          626 | ...
      >>> 627 |         asm volatile ("                                 \
              |         ^-- error: access may be outside object bounds
          628 | ...
          629 | ...
      Instruction context:
          11 | (b7) r2 = 1
          12 | (b7) r3 = 0
      >>> 13 | (85) call bpf_probe_read_kernel#113
          14 | (95) exit

    Causal path:
      via_variable_no_max_check_1 @ verifier_helper_value_access.c:627:2
      Source context:
          625 | ...
          626 | ...
      >>> 627 |         asm volatile ("                                 \
              |         ^-- update: R0 changed from uninitialized value to nullable map value from
              |             map_hash_48b at offset 0
          628 | ...
          629 | ...
      Instruction context:
           4 | (18) r1 = 0xffff88810a3ea000
      >>>  6 | (85) call bpf_map_lookup_elem#1
           7 | (15) if r0 == 0x0 goto pc+6
           8 | (bf) r1 = r0

      via_variable_no_max_check_1 @ verifier_helper_value_access.c:627:2
      Source context:
          625 | ...
          626 | ...
      >>> 627 |         asm volatile ("                                 \
              |         ^-- branch: took the false branch of this conditional, goto not followed
          628 | ...
          629 | ...
      Instruction context:
           6 | (85) call bpf_map_lookup_elem#1
      >>>  7 | (15) if r0 == 0x0 goto pc+6
           8 | (bf) r1 = r0
           9 | (61) r3 = *(u32 *)(r0 +0)

      via_variable_no_max_check_1 @ verifier_helper_value_access.c:627:2
      Source context:
          625 | ...
          626 | ...
      >>> 627 |         asm volatile ("                                 \
              |         ^-- update: R1 changed from uninitialized value to map value from map_hash_48b
              |             at offset 0
          628 | ...
          629 | ...
      Instruction context:
           6 | (85) call bpf_map_lookup_elem#1
           7 | (15) if r0 == 0x0 goto pc+6
      >>>  8 | (bf) r1 = r0
           9 | (61) r3 = *(u32 *)(r0 +0)
          10 | (0f) r1 += r3

      via_variable_no_max_check_1 @ verifier_helper_value_access.c:627:2
      Source context:
          625 | ...
          626 | ...
      >>> 627 |         asm volatile ("                                 \
              |         ^-- update: R1 changed from map value from map_hash_48b at offset 0 to map value
              |             from map_hash_48b with variable offset: known bits 0x0, unknown mask
              |             0xffffffff, signed range [0, 4294967295], unsigned range [0, 4294967295]
          628 | ...
          629 | ...
      Instruction context:
           8 | (bf) r1 = r0
           9 | (61) r3 = *(u32 *)(r0 +0)
      >>> 10 | (0f) r1 += r3
          11 | (b7) r2 = 1
          12 | (b7) r3 = 0

    Suggestion:
      Add or adjust a bounds check that proves offset + access_size stays within the object.

Resource Lifetime Safety, cpumask/test_alloc_no_release:

  Legacy:
    Unreleased reference id=2 alloc_insn=0
    BPF_EXIT instruction in main prog would lead to reference leak

  Diagnostic:
    Verification failed: Resource Lifetime Safety: Unreleased resource

    Reason:
      Owned resource (id=2) was acquired at instruction 0 and still needs to be released before this
      exit path.

    At:
      test_alloc_no_release @ cpumask_failure.c:36:5
      Source context:
          34 | ...
          35 | ...
      >>> 36 | int BPF_PROG(test_alloc_no_release, struct task_struct *task, u64 clone_flags)
             | ^-- error: owned resource (id=2) still needs release
          37 | ...
          38 | ...
      Instruction context:
          19 | (7b) *(u64 *)(r10 -8) = r6
          20 | (b4) w0 = 0
      >>> 21 | (95) exit

    Causal path:
      test_alloc_no_release @ cpumask_common.h:78:12
      Source context:
          76 | ...
          77 | ...
      >>> 78 |         cpumask = bpf_cpumask_create();
             |         ^-- acquired: owned resource (id=2)
          79 |         if (!cpumask) {
          80 |                 err = 1;
      Instruction context:
      >>>  0 | (85) call bpf_cpumask_create#62851
           1 | (bf) r6 = r0
           2 | (55) if r6 != 0x0 goto pc+5

      test_alloc_no_release @ cpumask_common.h:79:6
      Source context:
          77 | ...
          78 |         cpumask = bpf_cpumask_create();
      >>> 79 |         if (!cpumask) {
             |         ^-- branch: took the true branch of this conditional, goto followed
          80 |                 err = 1;
          81 | ...
      Instruction context:
           0 | (85) call bpf_cpumask_create#62851
           1 | (bf) r6 = r0
      >>>  2 | (55) if r6 != 0x0 goto pc+5
           3 | (18) r1 = 0xffffc90000252000

      test_alloc_no_release @ cpumask_common.h:84:6
      Source context:
          82 | ...
          83 | ...
      >>> 84 |         if (!bpf_cpumask_empty(cast(cpumask))) {
             |         ^-- branch: took the true branch of this conditional, goto followed
          85 |                 err = 2;
          86 |                 bpf_cpumask_release(cpumask);
      Instruction context:
           9 | (85) call bpf_cpumask_empty#62852
          10 | (54) w0 &= 1
      >>> 11 | (56) if w0 != 0x0 goto pc+7
          12 | (18) r1 = 0xffffc90000252000

    Suggestion:
      Release or transfer ownership of the acquired resource on every path before the program exits.

Patch layout:

  - Patches 1-2 add the initial renderer, source-line lookup, and separate
    source and instruction context blocks. Reusable report sections arrive with their first
    category-specific consumers.
  - Patches 3-7 add bounded, growable environment-owned diagnostic
    history. It grows to 64 MiB and then retains the newest events in a
    rotating buffer. The history follows the active verifier path and is
    pruned when backtracking; it records branch outcomes, material register
    changes, reference lifetime events, and execution-context events so
    reports can explain the path and causal state transitions that led to
    the failure.
  - Patches 8-14 add the first category-specific reports. These patches
    hook selected verifier failure sites and choose the evidence that is
    useful for that error class.

Evaluation
~~~~~~~~~~

The evaluation below is retained from v4 while v5 changes are in progress.
It includes two Verifier Limit cases removed from v5 and must be refreshed
before posting.

To quantitatively assess diagnostic quality beyond subjective human
feedback, we use AI models (called over APIs) and veristat metrics to
compare results.

Models are used as a way to measure repair utility of the extra
diagnostics over a fixed test set. Each prompt contains only a sanitized
source snippet and either the legacy verifier log or the new diagnostic
log. To avoid leaking the answer through the test itself, comments,
annotations, and other source hints that describe the intended failure
were removed. The model is not given internet access, repository access,
test execution, verifier access, or the expected fix. The expected
causes and intended repairs are kept outside the prompt. Under those
constraints, correctness, exact repair rate, output size, reasoning
tokens, cost, and wall time provide a proxy for whether the additional
verifier context makes the failure easier to understand and turn into a
source-level fix.

Verifier cost is assessed by forcing the collection of diagnostics
information during normal verification. By default, this information is
collected and processed only when verbose logs are enabled, but forcing
it even without a verbose log helps us measure the CPU time and memory
cost of the extra data.

Both evaluations are covered in the sections below.

Repair Quality
--------------

Repair quality is measured by asking API-only models to propose source
fixes from a sanitized source snippet and verifier log. The criterion is
score >= 3 on a 0-4 local grading scale, where 3 means a likely fix with
incomplete detail and 4 means an actionable source-level fix. Score 4 is
reported separately as the exact repair rate. The reported model set
contains 596 completed API responses: 298 diagnostic and 298 legacy.

Main results (details available in Appendix):

  Metric                              Diagnostic   Legacy       Delta
  ----------------------------------  -----------  -----------  --------
  Answers                             298          298
  Success rate                        97.0%        97.3%        -0.3 pp
  Exact repair rate                   82.2%        72.1%        +10.1 pp
  Mean score                          3.79         3.69         +0.10
  Solver cost                         $8.93        $10.37       -13.8%
  Mean output tokens per answer       1662         1975         -15.8%
  Mean reasoning tokens per answer    951          1080         -11.9%
  Mean wall time per answer           37.3s        44.1s        -15.4%

Diagnostic prompts carry more input context. The resulting answers are
still shorter and cheaper. In this run, diagnostics do not materially
change the coarse success rate, but they increase exact repairs by 10.1
percentage points while reducing cost, output tokens, reasoning tokens,
and wall time.

Verifier cost
-------------

Verifier cost is measured with veristat over the BPF selftest programs
selected by tools/testing/selftests/bpf/veristat.cfg, with five
repetitions per configuration. With diagnostics gated by log level, wall
time and verifier duration stay close to baseline. Forcing diagnostics
on for every verifier run adds modest overhead on this workload.

memory.peak is measured with cgroup v2 memory accounting for each
program load. The table reports the mean wall time, the mean summed
verifier duration, and the mean of the per-repetition maximum
memory.peak values.

  Configuration                 Wall time mean   Verifier duration    memory.peak
  ----------------------------  --------------   -----------------    -----------
  bpf-next baseline                 25.78s            9.86s              142 MiB
  diagnostics, gated                26.64s           10.16s              144 MiB
  diagnostics, forced on            28.01s           11.00s              148 MiB

TODO
~~~~

Known follow-up work:

  - Convert more verbose-only verifier errors into category-specific
    reports.
  - Integrate loop-convergence failure summarization from Eduard.
  - Report candidate kfuncs/helpers for releasing owned resources.
  - Explore association of source variables with verifier registers
    where debug info permits it.
  - Refine suggestions per category and, where useful, link diagnostics
    to maintained documentation.
  - Bring verifier warnings into the same reporting framework.

Appendix: AI repair details
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The 20 verifier-failing selftest cases are:

  Case     Diff    Category                    Selftest selector
  -------  ------  --------------------------  ---------------------------------------------
  case-001 easy    Call Type Safety            cpumask/test_populate_invalid_destination
  case-002 easy    Resource Lifetime Safety    cpumask/test_alloc_no_release
  case-003 easy    Register Type Safety        verifier_spill_fill/check_corrupted_spill_fill
  case-004 easy    Register Type Safety        test_global_funcs/global_func12
  case-005 easy    Execution Context Safety    preempt_lock/preempt_sleepable_helper
  case-006 easy    Policy                      verifier_helper_restricted/in_bpf_prog_type_kprobe_1
  case-007 medium  Memory Safety               dynptr/dynptr_slice_var_len1
  case-008 medium  Call Type Safety            dynptr/test_dynptr_skb_small_buff
  case-009 medium  Call Type Safety            task_kfunc/task_kfunc_acquire_untrusted
  case-010 medium  Register Type Safety        test_global_funcs/global_func6
  case-011 medium  Resource Lifetime Safety    dynptr/ringbuf_missing_release2
  case-012 medium  Execution Context Safety    irq/irq_sleepable_helper_global_subprog
  case-013 medium  Verifier Limit              test_global_funcs/global_func1
  case-014 hard    Memory Safety               verifier_helper_value_access/via_variable_no_max_check_1
  case-015 hard    Register Type Safety        verifier_sock/invalidate_pkt_pointers_from_global_func
  case-016 hard    Resource Lifetime Safety    verifier_ref_tracking/check_free_in_one_subbranch
  case-017 hard    Resource Lifetime Safety    irq/irq_restore_ooo
  case-018 hard    Resource Lifetime Safety    res_spin_lock_failure/res_spin_lock_ooo_unlock
  case-019 hard    Program Structure           verifier_loops1/bounded_recursion
  case-020 hard    Verifier Limit              verifier_liveness_exp/liveness_exponential_complexity

The grading scale is:

  - 4: identifies the verifier cause and gives an actionable source-level fix.
  - 3: gives a likely fix, but with incomplete explanation or detail.
  - 2: identifies part of the issue, but not enough to fix confidently.
  - 1: gives only a broad verifier-area answer, or a wrong/insufficient fix.
  - 0: does not identify the intended verifier failure.

Detailed effort metrics for the model set:

  Metric                   Variant      Mean      Median       P99
  -----------------------  ----------  --------  --------  --------
  Cost per answer          diagnostic   $0.030    $0.019    $0.203
  Cost per answer          legacy       $0.035    $0.018    $0.223
  Input tokens             diagnostic     1391      1220      4048
  Input tokens             legacy         1052       805      3655
  Output tokens            diagnostic     1662       954      8680
  Output tokens            legacy         1975      1034      9912
  Reasoning tokens         diagnostic      951       208      8108
  Reasoning tokens         legacy         1080       228      6322
  Wall time                diagnostic    37.3s     18.3s    222.7s
  Wall time                legacy        44.1s     19.8s    255.5s

Per-model results for diagnostic prompts:

  Model profile                              Ans  Succ   Exact  Mean  Cost     OutK  ReasK  Wall
  -----------------------------------------  ---  -----  -----  ----  -------  ----  -----  -----
  anthropic-haiku-4.5-default                 20   90.0   80.0  3.70  $0.087   11.4    0.0   5.0s
  anthropic-opus-4.8-high                     20  100.0   90.0  3.90  $0.819   25.5    0.0  15.5s
  anthropic-opus-4.8-medium                   20   95.0   90.0  3.85  $0.870   27.5    0.0  12.7s
  anthropic-sonnet-4.6-high                   20   95.0   80.0  3.75  $0.824   48.9    0.0  21.6s
  anthropic-sonnet-4.6-medium                 20  100.0   65.0  3.65  $0.278   12.4    0.0   6.6s
  openai-gpt-5.3-codex-high                   20  100.0   80.0  3.80  $0.601   39.8   33.9  25.0s
  openai-gpt-5.3-codex-medium                 20   95.0   85.0  3.80  $0.287   17.5   11.4  13.5s
  openai-gpt-5.5-high                         20  100.0   90.0  3.90  $2.356   74.4   65.2  56.8s
  openai-gpt-5.5-low                          20  100.0   90.0  3.90  $0.686   18.7    8.5  21.3s
  openai-gpt-5.5-medium                       19  100.0   84.2  3.84  $1.353   41.1   31.8  37.4s
  openai-gpt-5.5-none                         20   95.0   90.0  3.85  $0.457   11.1    0.0  10.4s
  openrouter-deepseek-r1-0528                 20  100.0   75.0  3.75  $0.145   61.5   53.8  98.3s
  openrouter-deepseek-v3.2                    19  100.0   78.9  3.79  $0.028   64.2   58.1  87.3s
  openrouter-glm-5.1-high                     20   95.0   80.0  3.75  $0.113   28.8   20.7  19.3s
  openrouter-qwen3-coder                      20   90.0   75.0  3.65  $0.028   12.4    0.0   7.1s

Per-model results for legacy prompts:

  Model profile                              Ans  Succ   Exact  Mean  Cost     OutK  ReasK  Wall
  -----------------------------------------  ---  -----  -----  ----  -------  ----  -----  -----
  anthropic-haiku-4.5-default                 20   90.0   45.0  3.35  $0.081   11.6    0.0   5.0s
  anthropic-opus-4.8-high                     20   90.0   70.0  3.60  $1.192   42.2    0.0  17.5s
  anthropic-opus-4.8-medium                   20   95.0   85.0  3.80  $1.001   34.5    0.0  13.4s
  anthropic-sonnet-4.6-high                   20  100.0   75.0  3.75  $1.181   74.1    0.0  24.4s
  anthropic-sonnet-4.6-medium                 20   95.0   65.0  3.60  $0.420   23.4    0.0  12.3s
  openai-gpt-5.3-codex-high                   20  100.0   85.0  3.85  $0.562   37.8   31.6  27.1s
  openai-gpt-5.3-codex-medium                 20  100.0   75.0  3.75  $0.318   20.3   13.7  13.6s
  openai-gpt-5.5-high                         19  100.0   78.9  3.79  $2.613   84.0   75.4  98.1s
  openai-gpt-5.5-low                          20  100.0   75.0  3.75  $0.664   19.0    9.7  21.7s
  openai-gpt-5.5-medium                       20  100.0   75.0  3.75  $1.602   50.2   41.0  56.1s
  openai-gpt-5.5-none                         20   95.0   85.0  3.80  $0.416   10.7    0.0  10.9s
  openrouter-deepseek-r1-0528                 20   95.0   70.0  3.65  $0.149   64.6   57.5  92.5s
  openrouter-deepseek-v3.2                    20  100.0   60.0  3.60  $0.030   74.3   67.8  98.3s
  openrouter-glm-5.1-high                     19  100.0   63.2  3.63  $0.115   32.1   24.9  30.4s
  openrouter-qwen3-coder                      20  100.0   75.0  3.75  $0.022    9.5    0.0   5.4s
====================

Link: https://patch.msgid.link/20260815064612.378577-1-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:18 -07:00
Kumar Kartikeya Dwivedi
ac545b00ca bpf: Report Policy helper and kfunc errors
Augment selected helper and kfunc allowability failures with Policy reports.
These reports explain which requested operation is forbidden and why, without
adding path history for non-path-dependent policy checks.

Cover unprivileged bpf2bpf and kfunc use, helper program-type restrictions,
GPL-only helpers, helper-specific allow callbacks, kfunc allowability, and
destructive kfunc capability checks.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-15-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:17 -07:00
Kumar Kartikeya Dwivedi
a8f4278353 bpf: Report Program Structure CFG errors
Augment selected whole-program and subprogram CFG validation failures with
Program Structure reports. These errors are structural rather than
path-dependent, so the reports focus on source and instruction context
instead of causal history.

Cover direct and indirect jumps outside the program or current subprogram,
unprivileged backedges, missing and out-of-range jump tables, targets in the
second half of an ldimm64, unreachable instructions, subprogram fallthrough,
and recursive bpf2bpf call graph edges.

Format long jump-range reasons directly in diagnostics.c, and keep the
fallthrough suggestion aligned with the verifier check by suggesting exit or
explicit jumps.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-14-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:17 -07:00
Kumar Kartikeya Dwivedi
99a6a288a8 bpf: Report Execution Context Safety errors
Augment selected sleepability and critical-section failures with Execution
Context Safety reports. Keep the existing verifier messages and add source
context, path history, and suggestions tied to the active context.

Use the context history recorded earlier to anchor causal paths to lock, IRQ,
RCU, and preempt regions instead of unrelated register updates.

Cover global calls while holding a lock, sleepable global function calls,
sleepable helpers, sleepable kfunc calls from disallowed contexts, operations
that exit while a context is still active, and unmatched context exits.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-13-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:17 -07:00
Kumar Kartikeya Dwivedi
66e2727395 bpf: Report Call Type Safety argument errors
Augment selected helper and kfunc argument-contract failures with Call Type
Safety reports. Keep the existing terse verifier messages and add reason,
source context, causal register or stack-argument history, and targeted
suggestions.

Cover helper register-type mismatch, helper and kfunc non-NULL pointer
requirements, release-helper ownership requirements, scalar and constant kfunc
arguments, trusted and RCU pointer contracts, kfunc memory arguments,
memory/length pairs, refcounted kptrs, constant strings, and IRQ flag stack
arguments.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-12-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:17 -07:00
Kumar Kartikeya Dwivedi
5d57646275 bpf: Report Resource Lifetime reference leaks
Augment selected Resource Lifetime Safety failures with structured diagnostics
while preserving the existing verifier messages.

Report unreleased references from check_reference_leak() using
reference-scoped diagnostic history, and add state reports for dynptr,
iterator, lock, and IRQ-flag lifetime misuse.

IRQ restore mismatch and out-of-order diagnostics use IRQ context-scoped
history when an IRQ-disabled region is active, so retained save/restore context
is still visible after per-state history removal.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-11-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:17 -07:00
Kumar Kartikeya Dwivedi
2bdc90f531 bpf: Report Memory Safety bounds errors
Augment selected memory-range verifier failures with Memory Safety reports
while preserving the existing terse verifier messages for compatibility.

Cover stack spill corruption, uninitialized stack reads, variable stack helper
accesses, and check_mem_region_access() range-proof failures. The bounds report
spells out the required offset + access_size <= object_size proof with concrete
values and uses scoped diagnostic history for causal context.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-10-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:15:07 -07:00
Kumar Kartikeya Dwivedi
d63284e62b bpf: Report Register Type Safety errors
Augment selected register-state verifier failures with Register Type Safety
reports. The existing verbose verifier messages remain in place; the new
reports add reason, source context, causal path, and suggestions.

Cover invalid pointer dereferences, unreadable registers, missing outgoing
stack arguments for bpf2bpf and kfunc calls, and rejected pointer arithmetic.
Use scoped diagnostic history so reports start from the latest relevant value
change and then show later branch outcomes.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-9-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
956a66e5c3 bpf: Track verifier context diagnostic events
Record verifier context transitions in the diagnostic history so later reports
can anchor causal paths to the critical section that made an operation invalid.

This covers lock, IRQ, RCU, and preempt regions without adding any new
verifier error reports. Category-specific commits decide where those recorded
events should be rendered.

Use context depth when selecting scoped history so nested regions anchor at the
outer active region, and fall back to the earliest retained event when the
matching entry was pruned.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-8-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
9ecd70304e bpf: Track verifier reference diagnostic events
Add reference acquire and release events to diagnostic history so Resource
Lifetime Safety reports can show the lifetime of a specific reference id along
the path.

Record acquisitions after the verifier assigns the reference id. Record
releases only after release_reference_nomark() succeeds, including the
kptr_xchg RCU conversion path and owning-to-non-owning conversion path that
consume an owning reference.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-7-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
af4ea6e20f bpf: Track verifier register diagnostic events
Record material register and outgoing stack argument changes so diagnostics can
explain how a value reached its current type, bounds, or unreadable state.

Store old and new register types, scalar ranges, tnum value and mask, map and
BTF type identity, and basic operand metadata in the environment-owned
diagnostic event stream.

Record invalidations when packet data moves, references are released, or
borrowed references leave their protected region. Register-scoped history
starts at the latest matching modification and then shows later branch
outcomes.

Also record fixed stack spills and overwrites, and tag register fills from
stack so register-scoped history can follow value flow through spilled stack
slots.

The type_is_map_ptr() helper previously lived as a static function in
kernel/bpf/log.c since commit 0c95c9fdb6 ("bpf: emit map name in register
state if applicable and available"). Move it verbatim to
include/linux/bpf_verifier.h as a static inline, next to the other type
classifiers, so diagnostics.c can reuse it without duplicating the case list.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-6-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
a6debd5f25 bpf: Prune verifier diagnostics when switching paths
Save the diagnostic event-log position with each verifier stack entry and
reset the environment-owned stream together with the normal verifier log
when a queued state is popped. Also reset the diagnostic stream after
successful subprogram verification even when level-2 logging preserves the
normal verifier log.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-5-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
daf8248701 bpf: Add verifier diagnostic event log
Add an environment-owned diagnostic history for verifier reports. Event
payloads keep the user-facing branch history shape, while storage lives
in bpf_verifier_env and follows the active verifier path.

Grow the event array geometrically up to a 64 MiB limit. Once storage
reaches the limit, or an allocation fails, overwrite the oldest event so
diagnostics retain the newest useful suffix without adding per-event
metadata.

Represent saved positions as absolute logical sequence numbers. A restore
truncates to a retained position. If its prefix has already been evicted,
clear the abandoned suffix and preserve the missing-history position. This
keeps marks stable across rotation without increasing their size.

Add the branch event renderer and branch recording.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-4-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
b9c5d822f6 bpf: Add source and instruction diagnostic context
Teach verifier diagnostics to annotate an instruction with BTF source
line information and nearby BPF instructions. The renderer keeps source
text in a fixed-width lane and prints instructions in a stable right-hand
gutter.

Wrap annotation text under the source line so long error labels remain
readable while the source and instruction lanes keep their fixed layout.

Keeping source and instruction context in one commit preserves the visual
layout contract that later diagnostic reports rely on.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-3-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Kumar Kartikeya Dwivedi
5ad7461663 bpf: Add verifier diagnostics report helpers
Add the initial diagnostics renderer for verifier reports and wire it into
the BPF build. The helper emits the common failure header through the
verifier log.

Later patches add prose wrapping, reusable report sections, and source and
instruction context for category-specific diagnostics.

Gate the helpers on normal verifier log output from the start, so
BPF_LOG_STATS-only loads do not collect or render diagnostics.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260815064612.378577-2-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-15 11:11:16 -07:00
Rafael J. Wysocki
d657aa1b8e cpufreq: intel_pstate: Avoid using DESIRED_PERF when DEC is enabled
In principle, the desired performance level can be set in MSR_HWP_REQUEST
to indicate to the processor what performance level the OS would like
the given CPU to run at, but if the Dynamic Efficiency Control (DEC)
feature is enabled in the processor, doing so may result in confusing
the processor firmware.  It is then better to let the processor firmware
figure out the most suitable performance level by itself.

Accordingly, make intel_pstate always set the desired performance level
to zero (which means "no preference") when running on a platform with
DEC enabled.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://patch.msgid.link/4758098.LvFx2qVVIh@rafael.j.wysocki
2026-08-15 19:10:48 +02:00
Rafael J. Wysocki
c659fa329e cpufreq: intel_pstate: Consolidate HWP P-states initialization
After previous changes, intel_pstate_hybrid_hwp_adjust() does not do
much and its name and kerneldoc comment (which is not really necessary
because the function is static) have become a bit confusing.  Moreover,
the initialization of P-states on systems with HWP enabled is divided
between it and a direct conditional statement branch in
intel_pstate_get_cpu_pstates() which is not super-easy to follow.

Address this by introducing intel_pstate_get_hwp_pstates() for the
entire HWP-specific initialization of P-states and moving the code from
intel_pstate_hybrid_hwp_adjust() into it along with some HWP-related
code from intel_pstate_get_cpu_pstates().

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/6021518.DvuYhMxLoT@rafael.j.wysocki
2026-08-15 19:08:20 +02:00
Hui Su
3bff8f8e95 cpufreq: schedutil: Fix rate limit overflow
rate_limit_us is an unsigned int, while NSEC_PER_USEC is defined as
1000L. On 32-bit systems, the multiplication is therefore performed
using 32-bit unsigned arithmetic before the result is assigned to
freq_update_delay_ns.

For example, writing 4294968 to rate_limit_us wraps the delay from
4294968000 ns to 704 ns. This makes schedutil update far more often
than configured.

Add sugov_update_rate_limit_us() to widen rate_limit_us to s64 before
converting it to nanoseconds. Use the helper when updating the tunable
through sysfs and when starting the governor, so both paths perform the
conversion without overflow.

Fixes: 9bdcb44e39 ("cpufreq: schedutil: New governor based on scheduler utilization data")
Signed-off-by: Hui Su <sh_def@163.com>
Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
Cc: All applicable <stable@vger.kernel.org>
Link: https://patch.msgid.link/20260806142304.1761454-1-sh_def@163.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2026-08-15 19:00:11 +02:00
Linus Torvalds
3eb40771c0 SoC fixes for 7.2, part 3
These are three last-minute fixes for the 7.2 release,
 though nothing alarming:
 
  - one error handling fix for optee firmware
  - incorrect i2c data for the apple M3 that was added in 7.2
  - a boot time warning fix for nvidia tegra
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmp/kkEACgkQmmx57+YA
 GNn0sRAAnDh3M8YkrmeGdU4aLCEIFDa+SB4+5OF2ANtjunGy3kUlPj1f9y9Sk7aq
 CEA2foLgAOThE7anz3VrV5RC+OHBqfe3OD39kMqdlTJlqZNLpVEbqFsyoMr8owAw
 zpfwDl8n1u9ROjGEyQ7t6QAE512ZLbwZ3wducoQPFGXZfjTpiuF4P00lpXa729xF
 H+Pb0WOMz3zytIfGKvKx4RWkiH0/xatiLoy0AO+73b2lCQgkJF4bhdkM+G5XAIvG
 XBhzO488Pu9vuoXpNnY0lizE2xZiJdhBJkR8/Ad0KrTlaLsjwJkF237ozWQ89F8U
 /00wS8zE9FXsEQNw9uJj7EjW7nKItxTloq3MELjoXbGV7xW5sEsjWZM3xsvFX5rD
 uJo4laNmjp7LZgTvlOZ9T5HM3XIMes3MNTqa4qx0bmrpxwy8BiaTuED9ugrUAIkv
 xR2xejKQdFEIEfJRga9YSVbVhF1fDH0dFG+8BVchx6npFWwFRk/RI0JycFGqUul7
 8CNXuweWNaVb0Q/zfwWz99pVNqdDySJpAMh4Pl4GKB++jYRvnHU4sCSqDYrkqWRo
 UGMpZhuXHpwzVWu3B/gPdk2YW/Mo1jfGN6dPFP3JsfdQx1BaUx/2j4ggJn20nTUw
 v7bBU2i0ljMvNkClCqY8sIfgWDxiI1vsFzabW5o2PRzm8R+jm94=
 =xgY+
 -----END PGP SIGNATURE-----

Merge tag 'soc-fixes-7.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull SoC fixes from Arnd Bergmann:
 "These are three last-minute fixes for the 7.2 release, though nothing
  alarming:

   - one error handling fix for optee firmware

   - incorrect i2c data for the apple M3 that was added in 7.2

   - a boot time warning fix for nvidia tegra"

* tag 'soc-fixes-7.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc:
  arm64: tegra: Add EL2 virtual timer interrupt for Tegra194
  arm64: dts: apple: t8122: Fix I2C resources
  optee: ffa: Add NULL check in optee_ffa_lend_protmem
2026-08-15 08:36:26 -07:00
Linus Torvalds
5e060ff9d1 OpenRISC fix for 7.2
A bug fix found by researchers.
 
  * Ensure to mask all privileged bits when restoring the supervisor
    register from sigreturn.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE2cRzVK74bBA6Je/xw7McLV5mJ+QFAmqABmQACgkQw7McLV5m
 J+TL9A/7BmXvg+A5KT0xKxYrC//OCvD5dGwwKVhc5tEtNhpcWZU4fQo9WioRUpcz
 OfbBcKN4RGrpm9Do685mqc2+nOGFcK9SId6eN47ri2G1ZJ1+wXE1IVKLIddlpBzp
 rBJJyStBAKG2ICQfgoKM26JGbRttH19hJWSDITLzA2vAMp2gxpV7I1tSiLMrbOym
 e/fKuclQ2tlH3DX+CJrRia/azeKRMjhlTCsSCH+FQSG+oegtCd6PP+rWi+i7cIas
 pdSrDes+ES6LcGncK+uaNQfIi4D9tm37POYOK1zq4cyQknl4yl0mCWzHDegHocM3
 EMAeZXgIxWR2sDn/xGl42gXsEjsIxgwUn9eufvAaNNVomFKOE8cVTsTAI7sgOCsj
 9eiLLTCAQdGt8wiKYZLfnSm/tkIrtUs+Uc0v1OWslWUN9pVOuhiE5RYVwt6oOgyf
 /16K0OFVggElHSyCkk9WPWryER1fg2n/eaOHflyOCO7YaQj9LL2e6TkVae7jQ+re
 vZ1ZgNuSO9ZchcemvtQ0gH28sceRy+R2ICQV7ytuR+7Isxk1kQwXuKFhjNkKcy35
 pTVFaFY1d/PwrtgUglk45/9ITFLJZNiz4ToE8jrP8P9+DlQhdp7tmZ2gNmtPb3Ll
 H0fOU2Bh4QeAQm4T0XDGlm1U2eGA5gy3HFUUNMXomLdNfpT2vIU=
 =p9Ll
 -----END PGP SIGNATURE-----

Merge tag 'for-linus' of https://github.com/openrisc/linux

Pull OpenRISC fix from Stafford Horne:
 "A bug fix found by researchers:

   - mask all privileged bits when restoring the supervisor register
     from sigreturn"

* tag 'for-linus' of https://github.com/openrisc/linux:
  openrisc: signal: do not restore privileged SR bits on sigreturn
2026-08-15 08:05:58 -07:00
PVS Narasimha Rao
6ae6fb96cc perf test sample-parsing: Validate PERF_FORMAT_GROUP values without LOST
The sample parsing test only validates grouped read values when
PERF_FORMAT_LOST is present.

For PERF_FORMAT_GROUP without PERF_FORMAT_LOST, the contents of
read.group.values[] are not validated, allowing corruption of the parsed
value and id fields to go undetected.

The values are also handed to the synthesis as a plain array of struct
sample_read_value, which always has a 24-byte stride, while
read.group.values is expected to be packed according to read_format --
evsel__parse_sample() points it into the event data.  Without
PERF_FORMAT_LOST the stride is 16, so both the synthesis and the
comparison walk overlapping bytes and the test passes regardless of the
contents.

Validate value and id for grouped reads and continue to validate lost
when PERF_FORMAT_LOST is present, walking the entries with
next_sample_read_value().  Also build the input packed using
sample_read_value_size() so the compared fields are the real ones.

Verified with a deliberate stride bug in copy_read_group_values(): the
test still passes without this change and fails at read_format 0xc with
it applied.

Signed-off-by: PVS Narasimha Rao <venkatasuryapala@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:18 -07:00
Arnaldo Carvalho de Melo
62972e5644 perf dso: Replace assert with runtime check in dso__read_symbol()
dso__read_symbol() asserts that len <= jited_prog_len, where len comes
from sym->end - sym->start (parsed from PERF_RECORD_KSYMBOL in
perf.data).  Both values originate from untrusted file input.

With NDEBUG (production builds), the assert is compiled out, allowing
an out-of-bounds heap read when the BPF program buffer is accessed.
Without NDEBUG, a crafted perf.data crashes perf with an assertion
failure.

Replace the assert with a runtime bounds check that returns NULL with
an appropriate error code, matching the existing error handling
pattern in this function.

Fixes: aa04707f50 ("perf dso: Support BPF programs in dso__read_symbol()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Song Liu <song@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:14 -07:00
Arnaldo Carvalho de Melo
390a9461cd perf dso: Guard against cache underflow on short reads in dso_cache__memcpy()
dso_cache__memcpy() computes cache_offset = offset - cache->offset,
then cache_size = min(cache->size - cache_offset, size).  The RB tree
lookup in __dso_cache__find() matches using the full
DSO__DATA_CACHE_SIZE window, but cache->size reflects the actual pread
return value from dso_cache__populate().

A short pread (e.g. near end-of-file) makes cache->size smaller than
DSO__DATA_CACHE_SIZE.  If a subsequent access targets an offset past
cache->offset + cache->size but within the DSO__DATA_CACHE_SIZE
window, the cache entry is found but cache_offset exceeds cache->size.
Since both are u64, the subtraction cache->size - cache_offset wraps
to a large value, min() selects the caller's size, and memcpy reads
out of bounds.

Return 0 for an offset past the valid cached data.  For a regular
file a short pread only happens at end-of-file, so 0 is what a direct
pread() at that offset would return: cached_io() stops its read loop
as on EOF.  Re-reading from the backing file would not help — a
second pread at the same offset returns the same short count.

Fixes: 366df72657 ("perf dso: Refactor dso_cache__read()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:09 -07:00
Arnaldo Carvalho de Melo
075d2c3235 perf dso: Use stored fd error instead of stale errno in file_read() and file_size()
file_read() and file_size() use ret = -errno when
dso__data(dso)->fd is negative after try_to_open_dso() fails.  By this
point errno has been through mutex_lock(), nsinfo__mountns_enter(), and
multiple open() attempts inside try_to_open_dso() — it no longer
reflects the actual open failure.  If errno happens to be 0, ret = 0
looks like EOF rather than an error, and file_size() callers like
dso__data_size() would then report a zero-sized file instead of
failing.

dso__data(dso)->fd is always negative on failure — -errno from
__open_dso() when no filename could be built (e.g. -EINVAL, -ENOENT),
or -1 when do_open() itself failed — and never 0, so use it directly
instead of reading the stale global errno.

No assert() or comment is needed after the assignment: the enclosing
if (dso__data(dso)->fd < 0) already guarantees ret < 0
[Namhyung Kim review].

Fixes: 33bdedcea2 ("perf tools: Protect dso cache fd with a mutex")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:04 -07:00