Commit Graph

1463908 Commits

Author SHA1 Message Date
Jiri Olsa
0ca56befcf bpf: Factor stackid_fastpath function from __bpf_get_stackid
The new stackid_fastpath does the fast stack hash and trace check, that
does not need new bucket allocation. It covers both just-ip and buildid
code paths.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260803210149.296496-3-jolsa@kernel.org
2026-08-05 11:32:29 -07:00
Jiri Olsa
15b837759a bpf: Factor stackid_init function from __bpf_get_stackid
The new stackid_init function stores all the necessary bits for stackid
trace and it will be used by other functions in following changes.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260803210149.296496-2-jolsa@kernel.org
2026-08-05 11:32:29 -07:00
Andrii Nakryiko
5b91f44f5b Merge branch 'bpf-inline-the-numeric-open-coded-iterator-kfuncs'
Puranjay Mohan says:

====================
bpf: Inline the numeric open-coded iterator kfuncs

The bpf_for(i, start, end) macro is BPF's open-coded numeric iterator. It
expands into calls to three kfuncs: bpf_iter_num_new() to set the iterator
up, bpf_iter_num_next() once per iteration, and bpf_iter_num_destroy() to
tear it down. The verifier emits these as ordinary kfunc calls, so a
bpf_for() loop pays function-call overhead on setup, teardown, and -- most
importantly -- on every single iteration via bpf_iter_num_next().

All three kfuncs are tiny and only touch the 8-byte on-stack iterator state
(struct bpf_iter_num_kern { int cur; int end; }). That makes them good
candidates for inlining, the same way several other special kfuncs are
already open-coded in bpf_fixup_kfunc_call(). This series replaces each of
the three calls with an equivalent inline BPF instruction sequence:

  - bpf_iter_num_new(): the end - start range check is done with 32-bit
    arithmetic (start <= end is checked first, so the distance fits in a
    u32) and range-checked against BPF_MAX_LOOPS as unsigned. This avoids
    the cpuv4 sign-extension insns that some JITs do not implement. Returns
    the same -EINVAL / -E2BIG / 0 as the kfunc.

  - bpf_iter_num_next(): the hot path. cur and end are int, so the kfunc's
    s->cur + 1 >= s->end test is an ordinary signed 32-bit compare and the
    inlined code needs no sign extension.

  - bpf_iter_num_destroy(): the stack slot is no longer tracked as iterator
    state once destroy() returns, so nothing needs to be written to it.
    Both the kfunc and the inlined form become a no-op, which just drops the
    call.

The emitted instructions are plain BPF and remain valid for the
interpreter, so interpreter fallback stays correct and no jit_required
marking is needed.

Benchmark (./bench -p 1 --nr_loops 1000000 {bpf-loop,bpf-for}):

    +--------+---------------------+---------------------+---------------------+
    |  arch  |       bpf_loop      | bpf_for non-inlined |   bpf_for inlined   |
    +--------+---------------------+---------------------+---------------------+
    | x86-64 |  4252 M/s (0.24 ns) |  3608 M/s (0.28 ns) |  7417 M/s (0.13 ns) |
    +--------+---------------------+---------------------+---------------------+
    | arm64  |  649 M/s (1.54 ns)  |  548 M/s (1.82 ns)  |  546 M/s (1.83 ns)  |
    +--------+---------------------+---------------------+---------------------+

On x86-64 removing the per-iteration call roughly doubles bpf_for()
throughput. On arm64 it is neutral, and rather than guess why this was
checked with perf: inlining removes ~28% of the executed instructions (the
call) but leaves the cycle count unchanged -- IPC drops from ~4.2 to ~3.0
and backend stalls rise from ~50% to ~66%. The loop is bound by the latency
of the iterator's on-stack counter, not by call overhead:
bpf_iter_num_next() loads s->cur from the stack, increments it and stores it
back each iteration, and the next iteration's load depends on that store.
The removed call instructions were executing in the shadow of that
store->load stall and were never on the critical path.

A small userspace microbenchmark isolates the effect: a same-address
store->load->add round-trip (the shape of the on-stack counter) costs
~6 cycles/iteration on the tested arm64 core but ~1 cycle on x86-64, where
the core collapses the same-address round-trip into a register move (memory
renaming / store-to-load-forwarding elimination). So on x86-64 the loop is
not latency-bound and the per-iteration call dominates -- removing it is the
~2x win -- whereas on arm64 the call fits entirely inside the store->load
stall the loop already has, so adding or removing it changes nothing.

bpf_loop() is shown for reference only; it is a different construct (a
callback invoked per iteration) and this series does not change it. Its
counter lives in a register rather than on the stack, so on arm64 it avoids
the store->load latency above and is faster than bpf_for() there.

Changelog:
v4: https://lore.kernel.org/all/20260729203633.213973-1-puranjay@kernel.org/
Changes in v5:
- Inline the new()/next()/destroy() sequences directly in
  bpf_fixup_kfunc_call() instead of via helper functions (Andrii Nakryiko)
- Trim the code comments; keep the explanation in the bpf_iter.c kfuncs and
  leave only brief comments at the inline sites, and shorten the
  bpf_iter_num_destroy() kfunc to /* no-op */ (Andrii Nakryiko)
- Reword the patch 1 comment so it no longer forward-references the inlined
  bpf_iter_num_next(), which is only added later in the series (bpf-ci)
- Switch the bpf_iter_num_next() comment to the networking multi-line style

v3: https://lore.kernel.org/all/20260722132424.450230-1-puranjay@kernel.org/
Changes in v4:
- Drop the "elide range checks for constant bounds" patch (Andrii Nakryiko)
- bpf_iter_num_new(): range-check the distance against BPF_MAX_LOOPS with an
  unsigned compare (Andrii Nakryiko)
- bpf_iter_num_destroy(): make it a no-op in both the kfunc and the inlined
  form instead of zeroing the iterator state (Andrii Nakryiko)
- New patch: fix the misleading overflow comment in bpf_iter_num_next() and
  drop the redundant (s64) cast; the int wraparound is intentional and
  load-bearing (Andrii Nakryiko)
- bpf_for benchmark: nr_loops is int, matching what bpf_for() expects
  (Andrii Nakryiko)
- Corroborate the arm64/x86 benchmark difference with perf counters and a
  store-to-load-forwarding microbenchmark (Kumar Kartikeya Dwivedi,
  Andrii Nakryiko)

v2: https://lore.kernel.org/bpf/20260717120215.2171057-1-puranjay@kernel.org/
Changes in v3:
- Elide the range checks in bpf_iter_num_new() when start and end are
  constant, marking the registers precise so paths reaching the call with
  different constants are not pruned (Eduard Zingerman)
- Add __xlated selftests pinning the inlined new()/next()/destroy() shapes
  (Eduard Zingerman)
- Use the insn_buf[i++] idiom in the inline helpers (Eduard Zingerman)
- Pick up Acked-by on patch 3

v1: https://lore.kernel.org/all/20260715130430.318421-1-puranjay@kernel.org/
Changes in v2:
- Don't emit sign-extending (movsx) moves; some JITs (e.g. x86-32, mips32,
  sparc64) decode them as a plain move and would miscompile the range check
====================

Link: https://patch.msgid.link/20260804134601.2305303-1-puranjay@kernel.org
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2026-08-05 10:44:36 -07:00
Puranjay Mohan
5a1de41147 selftests/bpf: Add bpf_for() benchmark
Add a bpf_for() benchmark modelled on bench_bpf_loop so the per-iteration
iterator cost can be measured and compared against bpf_loop. It runs an
empty bpf_for(i, 0, nr_loops) loop 1000 times per trigger and accounts
nr_loops hits per outer iteration:

  $ ./bench -p 1 --nr_loops 1000 bpf-for

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-7-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Puranjay Mohan
b829bc1677 selftests/bpf: Verify inlined numeric iterator shape with __xlated
Add an __xlated test pinning the inlined bpf_iter_num_{new,next,destroy}()
shapes. The program is __naked, so there is no compiler glue and the whole
sequence is matched instruction for instruction.

Gate it to x86_64 and arm64 (bpf_jit_needs_zext() == false); elsewhere the
verifier interleaves "wN = wN" zero-extensions that would not match. The
inlining is arch independent, so these two are enough.

Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-6-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Puranjay Mohan
39f047682f bpf: Inline bpf_iter_num_destroy() as a no-op
Once destroy() returns the stack slot is no longer tracked as iterator
state, so zeroing it is dead work. Make the kfunc a no-op and inline the
call to a single BPF_JA 0 (the fixup can't drop the instruction outright,
so emit a nop; the JITs elide it).

Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-5-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Puranjay Mohan
e933477048 bpf: Inline bpf_iter_num_next() kfunc
bpf_iter_num_next() runs on every bpf_for() iteration, so inlining it
drops a call from the loop body. R1 points to the iterator; the returned
pointer to s->cur is R1 itself, since s->cur is first.

s->cur and s->end are int, so the kfunc's s->cur + 1 >= s->end is a
signed 32-bit compare and the inlined code needs no sign extension.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-4-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Puranjay Mohan
f8f2b567d5 bpf: Inline bpf_iter_num_new() kfunc
bpf_for() expands to the bpf_iter_num_{new,next,destroy}() kfuncs, which
the verifier emits as regular calls. They are tiny and only touch the
8-byte on-stack iterator state, so open-code them in bpf_fixup_kfunc_call()
like the other special kfuncs there.

Start with bpf_iter_num_new(): R1 points to the iterator, R2/R3 hold
start/end. The inlined sequence mirrors the kfunc and returns the same
-EINVAL / -E2BIG / 0.

start > end is rejected first, so end - start fits in a u32; range-check
it as u32 on both sides ((u32)(end - start) in the kfunc). A movsx-based
check would emit a cpuv4 instruction that some JITs (x86-32, mips32,
sparc64) decode as a plain move and get wrong.

The emitted instructions are plain BPF, so the interpreter path stays
correct and no jit_required marking is needed.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-3-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Puranjay Mohan
8efd87051c bpf: Correct the overflow check comment in bpf_iter_num_next()
The comment on the s->cur + 1 >= s->end check claims the (s64) cast is
needed to avoid overflow when s->cur == s->end == INT_MAX. It isn't:
s->cur + 1 is computed in int and wraps before the cast, so the cast
changes nothing (INT_MAX + 1 compares the same either way).

The wraparound is the point. bpf_iter_num_new() sets s->cur = start - 1,
which wraps to INT_MAX for start == INT_MIN, and the wrapping s->cur + 1
brings it back to start. (s64)s->cur + 1 would instead break iterators
starting at INT_MIN.

Drop the cast and reword the comment. No functional change; the wrap is
well-defined under -fno-strict-overflow.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260804134601.2305303-2-puranjay@kernel.org
2026-08-05 10:44:35 -07:00
Daniel Borkmann
363b15d855 selftests/bpf: Add load-acquire test for dst_reg == src_reg from ctx
Add a verifier test that a load-acquire fetching into its own source
register (dst_reg == src_reg) from a ctx pointer is rejected.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_load_acquire
  [...]
  #614/1   verifier_load_acquire/load-acquire, 8-bit:OK
  #614/2   verifier_load_acquire/load-acquire, 8-bit @unpriv:OK
  #614/3   verifier_load_acquire/load-acquire, 16-bit:OK
  #614/4   verifier_load_acquire/load-acquire, 16-bit @unpriv:OK
  #614/5   verifier_load_acquire/load-acquire, 32-bit:OK
  #614/6   verifier_load_acquire/load-acquire, 32-bit @unpriv:OK
  #614/7   verifier_load_acquire/load-acquire, 64-bit:OK
  #614/8   verifier_load_acquire/load-acquire, 64-bit @unpriv:OK
  #614/9   verifier_load_acquire/load-acquire with uninitialized src_reg:OK
  #614/10  verifier_load_acquire/load-acquire with uninitialized src_reg @unpriv:OK
  #614/11  verifier_load_acquire/load-acquire with non-pointer src_reg:OK
  #614/12  verifier_load_acquire/load-acquire with non-pointer src_reg @unpriv:OK
  #614/13  verifier_load_acquire/misaligned load-acquire:OK
  #614/14  verifier_load_acquire/misaligned load-acquire @unpriv:OK
  #614/15  verifier_load_acquire/load-acquire from ctx pointer:OK
  #614/16  verifier_load_acquire/load-acquire from ctx pointer @unpriv:OK
  #614/17  verifier_load_acquire/load-acquire from ctx pointer, same dst and src register:OK
  #614/18  verifier_load_acquire/load-acquire from ctx pointer, same dst and src register @unpriv:OK
  #614/19  verifier_load_acquire/load-acquire with invalid register R15:OK
  #614/20  verifier_load_acquire/load-acquire with invalid register R15 @unpriv:OK
  #614/21  verifier_load_acquire/load-acquire from pkt pointer:OK
  #614/22  verifier_load_acquire/load-acquire from flow_keys pointer:OK
  #614/23  verifier_load_acquire/load-acquire from sock pointer:OK
  #614     verifier_load_acquire:OK
  Summary: 1/23 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260804201917.253491-2-daniel@iogearbox.net
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-05 12:06:22 +02:00
Daniel Borkmann
b87803391b bpf: Check load-acquire src ptr type before the load
check_atomic_load() calls check_load_mem() before atomic_ptr_type_ok().
For a load-acquire that fetches into its own source register (dst_reg ==
src_reg), check_load_mem() overwrites src_reg's type with the type of the
loaded value, so the subsequent atomic_ptr_type_ok() no longer sees the
source pointer and fails to reject the disallowed types (ctx, pkt,
flow_keys, sock).

Since bpf_convert_ctx_accesses() does not rewrite atomic loads, the raw
access to the underlying kernel object is left in place. The destination
type is taken from the ctx access itself, so a load-acquire of the sk
field of struct __sk_buff for example leaves the register typed as
PTR_TO_SOCK_COMMON_OR_NULL, which type_is_sk_pointer() does not match
either, while it actually holds unconverted struct sk_buff bytes. Once
the NULL check has passed this is a type confusion, not just a leak of
kernel data.

Validate src_reg with check_reg_arg() and check the source pointer type
with atomic_ptr_type_ok() before the load again, mirroring
check_atomic_rmw(). Out-of-range register numbers are already rejected
earlier by check_and_resolve_insns() (commit 503d21ef8e ("bpf: Do
register range validation early")), and the only exemption there,
is_stack_arg_ldx(), requires BPF_LDX | BPF_MEM | BPF_DW and thus never
matches a BPF_ATOMIC insn. atomic_ptr_type_ok() can therefore not
dereference register state out of bounds, that is, the out-of-bounds
read addressed by the Fixes commit below does not reappear (as proven
also via selftest).

Fixes: c03bb2fa32 ("bpf: Fix out-of-bounds read in check_atomic_load/store()")
Reported-by: STAR Labs SG <info@starlabs.sg>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260804201917.253491-1-daniel@iogearbox.net
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-05 12:06:18 +02:00
Pu Lehui
6655c40970 bpf, cgroup: Fix invalid storage access after __cgroup_bpf_attach failed
A potential invalid storage access issue can occur after replacing a
cgroup bpf prog.

This occurs in the following scenario:
1. prog1 with storage is attached to a cgroup in multi-attach mode.
2. prog1 is replaced with prog2 using BPF_F_REPLACE in multi-attach
   mode, but fails midway (e.g. in bpf_trampoline_link_cgroup_shim or
   update_effective_progs).
3. A new prog3 is attached to the cgroup in multi-attach mode.

The reason is that __cgroup_bpf_attach overwrites pl->storage with the
new storage prior to attachment completion. When attachment fails
midway, the cleanup path calls bpf_cgroup_storages_free(new_storage) to
free the newly allocated storage, but fails to restore pl->storage back
to old_storage.

Consequently, the still-active prog1 holds invalid or dangling storage
pointers, leading to an invalid memory access when prog1 executes and
calls bpf_get_local_storage. Additionally, original pl->flags and
cgrp->bpf.flags[atype] are left unrestored.

Fix this by saving old_pl_flags, old_storage, and old_flags prior to the
update, and properly restoring all of them in the cleanup path on error.

Fixes: 7d9c342789 ("bpf: Make cgroup storages shared between programs on the same cgroup")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/bpf/20260803013934.4036646-1-pulehui@huaweicloud.com
2026-08-04 16:19:04 -07:00
Tushar Vyavahare
e2baf9cc37 selftests/xsk: Decouple xskxceiver and xdp apps from test_progs objects
Build xskxceiver, xdp_hw_metadata, and xdp_features from explicit source
lists instead of reusing helper objects produced by test_progs rules.

Reusing shared objects such as network_helpers.o and xsk.o can pull in
test_progs-only dependency chains and trigger unrelated libarena builds
when invoking a single target.

Keep these standalone binaries self-contained so each target builds only
its own required sources and BPF skeleton dependencies.

Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Tested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://lore.kernel.org/bpf/20260728115036.2049536-1-tushar.vyavahare@intel.com
2026-08-04 15:50:58 -07:00
Kumar Kartikeya Dwivedi
7f333f85f8 Merge branch 'bpf-invalidate-rcu-pointers-after-final-spin-unlock'
Ning Ding says:

====================
bpf: Invalidate RCU pointers after final spin unlock

In a sleepable BPF program, a spin lock can provide the only RCU protection
for a kptr. The final spin unlock ends that protection, but the verifier
leaves the pointer valid. Another CPU can then free the object before the
pointer is used. A capability-limited runtime PoC triggered a
KASAN-confirmed task_struct use-after-free.

Patch 1 invalidates RCU-protected pointers only when an unlock leaves the
final RCU-protected context. Patch 2 adds a negative sleepable test and
positive controls for non-sleepable and explicit-RCU contexts.

Testing used fresh QEMU/KVM guests with KASAN enabled. The patched focused
test passed all three expected outcomes. The full task_kfunc test passed
all 39 subtests, and the selected RCU, refcount, and spin-lock group had no
failures.
---
v2:
  - Rebase onto bpf-next commit 60781269e2.
  - Target bpf-next and split the fix from its selftests, as requested.
  - Add positive controls for RCU contexts that remain valid after unlock.

v1: https://lore.kernel.org/r/20260802231248.2781334-1-dingning04@gmail.com
====================

Link: https://patch.msgid.link/20260803112615.3362122-1-dingning04@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-04 11:34:04 +02:00
Ning Ding
bb2df6fd89 selftests/bpf: Test RCU pointer invalidation after spin unlock
The verifier previously accepted a task kptr after the final spin unlock
ended its RCU protection in a sleepable program. The pointer could then be
used after the task was freed.

Add a negative test for that case. Add positive controls showing that the
pointer remains valid in a non-sleepable program and while an explicit RCU
read-side section is still active.

Assisted-by: Codex:gpt-5.6-sol
Assisted-by: ChatGPT:GPT-5.6-Pro
Signed-off-by: Ning Ding <dingning04@gmail.com>
Link: https://lore.kernel.org/bpf/20260803112615.3362122-3-dingning04@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-04 11:34:02 +02:00
Ning Ding
180c700071 bpf: Invalidate RCU pointers after final spin unlock
In a sleepable BPF program, a spin lock can provide the only RCU protection
for a kptr. The final bpf_spin_unlock() ends that protection, but the
verifier leaves the pointer valid. Another CPU can then free the object
before the pointer is used. A capability-limited runtime PoC triggered a
task_struct use-after-free in __bpf_get_task_stack().

Record whether the program is in an RCU-protected context before releasing
the lock. Invalidate RCU-protected pointers only when the unlock leaves the
final such context. This preserves valid pointers in non-sleepable programs
and inside an explicit RCU read-side section.

Fixes: 5861d1e8db ("bpf: Allow bpf_spin_{lock,unlock} in sleepable progs")
Assisted-by: Codex:gpt-5.6-sol
Assisted-by: ChatGPT:GPT-5.6-Pro
Signed-off-by: Ning Ding <dingning04@gmail.com>
Link: https://lore.kernel.org/bpf/20260803112615.3362122-2-dingning04@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-04 11:33:56 +02:00
Yonghong Song
457d4ecb47 bpf: Remove unused BTF_FMODEL_STRUCT_ARG
Commit 814cba835e ("bpf, x86: Fix trampoline stack size for 128-bit
arguments") changed the x86 trampoline to compute the number of
registers from arg_size for every argument, which removed the last user
of BTF_FMODEL_STRUCT_ARG. No other architecture or verifier code looks
at the flag, so remove the macro and the code in __get_type_fmodel_flags()
which sets it.

Keep BTF_FMODEL_SIGNED_ARG at BIT(1) rather than renumbering it to
BIT(0), so BIT(0) is available for a future flag.

No functional change.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/bpf/20260803052726.2821447-1-yonghong.song@linux.dev
2026-08-03 14:55:22 +02:00
Shivaji Kant
60781269e2 selftests/bpf: Add IP_TRANSPARENT and IPV6_TRANSPARENT to setget_sockopt
Add test coverage for IP_TRANSPARENT and IPV6_TRANSPARENT socket options
in the setget_sockopt BPF selftest to verify bpf_setsockopt() and
bpf_getsockopt() helpers.

Signed-off-by: Shivaji Kant <shivajikant@google.com>
Tested-by: Anubhav Singh <anubhavsinggh@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://lore.kernel.org/bpf/20260801051307.478469-2-shivajikant@google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 03:46:47 +02:00
Shivaji Kant
dec58a70d4 bpf: Allow IP_TRANSPARENT and IPV6_TRANSPARENT in bpf_{set,get}sockopt()
Currently, bpf_setsockopt() and bpf_getsockopt() for SOL_IP and SOL_IPV6
only allow a small subset of socket options (such as IP_TOS,
IPV6_TCLASS, and IPV6_AUTOFLOWLABEL). Calling bpf_setsockopt() with
IP_TRANSPARENT or IPV6_TRANSPARENT fails with -EINVAL.

Transparent proxying (TPROXY) and related networking components often
rely on IP_TRANSPARENT and IPV6_TRANSPARENT to enable binding sockets
to non-local IP addresses.

Allow IP_TRANSPARENT for SOL_IP in sol_ip_sockopt() and
IPV6_TRANSPARENT for SOL_IPV6 in sol_ipv6_sockopt().

Signed-off-by: Shivaji Kant <shivajikant@google.com>
Tested-by: Anubhav Singh <anubhavsinggh@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://lore.kernel.org/bpf/20260801051307.478469-1-shivajikant@google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 03:46:46 +02:00
Jiayuan Chen
0b10b94547 bpf: Fix mmap_lock deadlock on arena lock failure
Reported by the Sashiko AI review.

arena_vm_fault() returns VM_FAULT_RETRY when it can't take
arena->spinlock, but it never took mmap_lock. The fault path assumes a
VM_FAULT_RETRY handler already dropped mmap_lock and re-takes it on the
retry, so mmap_lock gets taken twice and can deadlock:

	do_user_addr_fault()
	{
		fault = handle_mm_fault(...);   // calls arena_vm_fault()
		if (fault & VM_FAULT_RETRY)
			goto retry;   // re-locks mmap_lock
		mmap_read_unlock(mm);
	}

Return VM_FAULT_SIGBUS instead, for two reasons:

1. We could keep VM_FAULT_RETRY, but then we'd have to drop the fault
   lock first and cap the retry ourselves, the way __folio_lock_or_retry()
   does.

2. A failed raw_res_spin_lock_irqsave() already means a possible deadlock
   was detected, so retrying just hits the same lock again.

So returning VM_FAULT_RETRY here is overkill.

Fixes: b8467290ed ("bpf: arena: make arena kfuncs any context safe")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/bpf/20260728060517.95183-1-jiayuan.chen@linux.dev
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 03:22:17 +02:00
Kumar Kartikeya Dwivedi
8f876c773b Merge branch 'generate-bpf_func_proto-for-kfunc'
Amery Hung says:

====================
Generate bpf_func_proto for kfunc

Hi,

This is the second of three patch sets to unify kfunc and helper
argument verification. It:

  1) further aligns the kfunc and helper argument checks,
  2) makes kfunc argument type classification depend solely on BTF, and
  3) generates a bpf_func_proto for each kfunc.

With classification now a pure function of the kfunc's BTF, it is computed
once at add-call time and cached in the generated bpf_func_proto, rather
than re-derived on every verification of the call. Along the way it also
fixes a few issues.

The next patch set will align the argument register compatibility checks
and route helper and kfunc argument verification through a single shared
function.

[1/3] https://lore.kernel.org/bpf/20260715064047.1793790-1-ameryhung@gmail.com/

Changelog

v2 -> v3:
 - Drop a patch that introduces SCALAR_MAYBE_ZERO (Eduard)
 - Drop patch make helper handle mem+size at mem arg, and instead make
   kfunc also handle mem+size at size
 - patch 5: New patch replacing temporary mark_ptr_not_null_reg hack
   with refine_ptr_not_null_reg (Eduard)
 - patch 8: Only allow global subprog to read poisoned stack slots
   (Eduard)
 - patch 11: Test a precision gap when passing NULL to nullable-mem +
   size arg (Eduard)
 - patch 15: Reorganize BTF_ID, MEM, MEM+SIZE classification for
   clarity (Eduard)
 - patch 18: Emded bpf_func_proto in bpf_kfunc_desc and dynamically
   resize bpf_kfunc_desc_tab; Record saved_dst_prog_type early in
   bpf_prog_load to avoid introducing a fallback logic in
   resolve_prog_type (Eduard)

   Link: https://lore.kernel.org/bpf/20260724190813.1458271-1-ameryhung@gmail.com/

v1 -> v2:
 - patch 2: use reg_arg_name() for the map-mismatch message; derive the
   object register correctly on both helper and kfunc paths
 - patch 3: reject non-CONST_PTR_TO_MAP regs (base_type check) to fix
   map-value type confusion
 - patch 15: also reject referenced regs with unsafe modifiers (e.g.
   MEM_PERCPU)
 - patch 17: reject non-SCALAR_VALUE for KF_ARG_MEM_SIZE
====================

Link: https://patch.msgid.link/20260801074633.1595644-1-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:31:27 +02:00
Amery Hung
a49b70400b bpf: Generate kfunc argument prototype at add-call time
Kfunc argument checking re-derives each argument's kfunc_ptr_arg_type
from BTF on every verification of a call in check_kfunc_args(). Now that
get_kfunc_arg_type() is a function of the kfunc's BTF alone, it no
longer inspects register state. The classification can be computed once
when the call is added and cached. This is a step toward describing
kfuncs with a bpf_func_proto and sharing the helper argument-checking
path.

Generate the classification at bpf_add_kfunc_call() time:

- Extend struct bpf_func_proto to be able to describe a kfunc: widen
  arg_type[] and the arg_btf_id[]/arg_size[] union from 5 to
  MAX_BPF_FUNC_ARGS, since a kfunc may take up to 12 arguments (5 in
  registers, 7 on the stack).

- Embed a bpf_func_proto in struct bpf_kfunc_desc, populated by
  gen_kfunc_arg_proto() which runs get_kfunc_arg_type() for each
  argument and stores the result in proto.arg_type[]. Grow the
  descriptor table's descs[] as a flexible array to not waste memory.

- check_kfunc_args() reads the cached classification from meta->fn

The KF_ARG_PTR_TO_CTX classification depends on the resolved program type,
and for BPF_PROG_TYPE_EXT that is the target program's type, which
resolve_prog_type() reads from prog->aux->saved_dst_prog_type. That field
is normally recorded later during verification in check_attach_btf_id(),
after bpf_add_kfunc_call() has run.

Record saved_dst_prog_type and saved_dst_attach_type from dst_prog at
program load time in bpf_prog_load() so the resolved type is available
at add-call time without reordering check_attach_btf_id(). This keeps
e.g. an freplace of an XDP program calling bpf_xdp_metadata_rx_hash()
classifying its struct xdp_md * argument as context.

The classification result is unchanged; it is only computed earlier and
cached.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-19-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:31:26 +02:00
Amery Hung
1690dcf27c bpf: Classify scalar kfunc arguments from BTF
Add kfunc scalar argument types, classify them in get_kfunc_arg_type()
along side with pointer arguments and move scalar type verification
into the main switch in check_kfunc_args(). This keeps BTF-based
classification separate from register validation for every argument,
paving the way for generating the kfunc argument prototype at add-call
time. No functional change intended.

KF_ARG_MEM_SIZE and KF_ARG_CONST_MEM_SIZE now are reachable. Therefore,
remove the fallthrough from KF_ARG_PTR_TO_MEM case and adjust the
register indexing.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-18-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:31:26 +02:00
Amery Hung
ba5b99470c bpf: Tag nullable kfunc pointer args with PTR_MAYBE_NULL
Now that get_kfunc_ptr_arg_type() classifies a kfunc pointer argument
from its BTF alone, express a nullable argument by OR-ing PTR_MAYBE_NULL
into the classified type, and resolve a NULL register after
classification instead of before it.

Previously check_kfunc_args() short-circuited a nullable argument passed
a NULL register with a continue placed before get_kfunc_ptr_arg_type(),
so the NULL never reached classification. That kept a register-state
decision (bpf_register_is_null()) ahead of the BTF-based classification.

This mirrors how helper arguments carry PTR_MAYBE_NULL in their
bpf_arg_type and is a step toward describing kfuncs with a bpf_func_proto:
the nullability now travels with the per-argument classification, so it is
captured when the prototype is generated at add-call time.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-17-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:31:25 +02:00
Amery Hung
c9e995ba0d bpf: Classify kfunc pointer arguments from BTF, resolve type against the register
get_kfunc_ptr_arg_type() decided part of a kfunc pointer argument's type
from the caller's register: a PTR_TO_BTF_ID (or reg2btf_ids) register made
the argument KF_ARG_PTR_TO_BTF_ID, otherwise it fell through to a memory
buffer. Folding register state into argument classification prevents
describing a kfunc's arguments from its BTF alone, which is a prerequisite
for generating a helper-like prototype and eventually sharing the argument
checking (check_func_arg()) between helpers and kfuncs.

Classify pointer arguments from BTF only, and resolve them against the
register in check_kfunc_args():

 - A pointer to a struct that is not paired with a __sz/__szk size
   argument is classified KF_ARG_PTR_TO_BTF_ID and then checked against
   the register. A register carrying a BTF ID (PTR_TO_BTF_ID or a
   reg2btf_ids type) must be referenced or trusted and is matched against
   the expected type. The only relaxation is when the struct is composed
   of scalars, the register may be verified as a fixed-size memory buffer
   sized from the BTF type; anything else is rejected.

 - A pointer paired with a size argument is always a memory buffer and is
   never classified as BTF_ID, so the __sz/__szk case no longer detours
   through BTF_ID.

The new design now accepts one previously rejected case: passing
PTR_TO_BTF_ID to a pointer to scalar w/o a following __sz/__szk. The
argument will be classified as KF_ARG_PTR_TO_MEM | MEM_FIXED_SIZE. The
PTR_TO_BTF_ID register will go through check_mem_reg() ->
check_helper_mem_access() -> check_ptr_to_btf_access(). For a pointer to
scalar arg, a kernel btf id will be rejected unless explicitly granted
by btf_struct_access(); a program allocated btf id will be allowed.

The referenced-or-trusted check thus moves into the KF_ARG_PTR_TO_BTF_ID
resolution, alongside the type match.

get_kfunc_ptr_arg_type() no longer needs the register, so drop its regs
and reg parameters; it is now a pure function of the kfunc's BTF.

When a register cannot satisfy a BTF_ID argument, report the register type
passed and, when the expected struct has a reg2btf_ids mapping, the
register type that would be accepted, instead of a confusing "socket".
Update the affected selftest messages accordingly.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-16-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:30:10 +02:00
Amery Hung
90990ee10b bpf: Distinguish fixed- and variable-size kfunc mem args with MEM_FIXED_SIZE
A kfunc memory-pointer argument comes in two flavors: a fixed-size buffer
whose access size is derived from the pointed-to BTF type, and a
variable-size buffer paired with a following __sz/__szk size argument.
Both were represented by separate kfunc_ptr_arg_type values
(KF_ARG_PTR_TO_MEM vs KF_ARG_PTR_TO_MEM_SIZE) with the pointer classified
as the latter when a size argument followed.

Mirror how helpers describe the same distinction: classify both as
KF_ARG_PTR_TO_MEM and OR in MEM_FIXED_SIZE for the fixed-size case, just
as helpers use ARG_PTR_TO_MEM | MEM_FIXED_SIZE. The switches now key on
base_type(kf_arg_type) so the flag rides along, and the KF_ARG_PTR_TO_MEM
handler either resolves the size from BTF (MEM_FIXED_SIZE) or falls
through to the mem/size-pair check, which validates the buffer against the
following size register and skips it. No functional change.

Currently, KF_ARG_MEM_SIZE and KF_ARG_CONST_MEM_SIZE are only reachable
from ARG_PTR_TO_MEM fallthrough. A patch later will merge scalar
checking into the same switch and remove the fallthrough.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-15-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:16 +02:00
Amery Hung
76fb087504 bpf: Handle NULL kfunc pointer args without a KF_ARG_PTR_TO_NULL type
get_kfunc_ptr_arg_type() returned KF_ARG_PTR_TO_NULL when a nullable
pointer argument was passed a NULL register. This folded a register-state
decision (bpf_register_is_null()) into what is otherwise BTF-based
argument classification, and it short-circuited before the BTF_ID/MEM
resolution.

Drop KF_ARG_PTR_TO_NULL and handle the NULL case in check_kfunc_args()
instead: a nullable argument that is actually NULL is skipped. Note that
it is okay to skip even when it is a mem+size pair because the size
argument check has been moved to the scalar section. The skip is done
before get_kfunc_ptr_arg_type() so that a NULL passed to a nullable
non-scalar-struct argument is not newly rejected by the BTF_ID/MEM
resolution.

No functional change.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-14-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:16 +02:00
Amery Hung
ea5ab23898 bpf: Classify kfunc mem_size args from BTF without register state
check_kfunc_args() already makes sure a scalar value is passed to a
scalar kfunc argument. Drop the check in is_kfunc_arg_mem_size() and
is_kfunc_arg_const_mem_size() to further decouple
get_kfunc_ptr_arg_type() from register state (a prerequisite for
generating a helper-like prototype from kfunc's BTF).

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-13-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:15 +02:00
Amery Hung
f88caee62e selftests/bpf: Test __szk precision with a NULL nullable buffer
When a nullable buffer is passed as NULL, check_mem_size_reg() is skipped,
so the __szk memory size must be marked precise through the scalar argument
path instead. Exercise this with bpf_dynptr_slice() and a NULL buffer.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-12-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:15 +02:00
Amery Hung
f16e80c2c4 bpf: Fold __szk const size handling into the scalar arg path
To align helper and kfunc pointer to memory argument handling, move
kfunc constant memorry size argument handling to the kfunc scalar
section. In addition, factor out constant scalar argument handling.

The constant size argument (__szk) of a kfunc memory/size pair was
recorded into meta->arg_constant by a dedicated block in the
KF_ARG_PTR_TO_MEM_SIZE case, duplicating the "only one constant
argument" and "must be a known constant" checks already in the generic
scalar argument handling. That block also did an explicit i++ to skip
the size argument.

This also fixes a precision gap: the old dedicated block did not mark
the size register precise, relying on check_mem_size_reg() for that. But
check_mem_size_reg() is skipped when the buffer is a nullable arg passed
as NULL (e.g. bpf_dynptr_slice(_rdwr) with a NULL buffer), so in that
case the __szk value was recorded and used for regs[R0].mem_size without
marking it precise. Routing the size through the scalar path marks it
precise in all cases.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-11-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:15 +02:00
Amery Hung
c0e091f30f bpf: Rename ARG_CONST_SIZE{,_OR_ZERO} to ARG_MEM_SIZE{,_OR_ZERO}
ARG_CONST_SIZE does not require a constant: check_mem_size_reg() accepts
any bounded scalar and verifies the memory access against its maximum
(reg_umax). Rename ARG_CONST_SIZE and ARG_CONST_SIZE_OR_ZERO to
ARG_MEM_SIZE and ARG_MEM_SIZE_OR_ZERO to reflect that. ARG_CONST_ALLOC_
SIZE_OR_ZERO, which does require a constant, is left unchanged.

Pure rename, no functional change.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-10-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:14 +02:00
Amery Hung
e566701b9b bpf: Check fixed-size mem args of helpers and kfuncs the same way
Fixed-size memory arguments went through two paths: helpers called
check_helper_mem_access() directly, while kfuncs and global subprogs
used check_mem_reg(). Route the helper MEM_FIXED_SIZE case through
check_mem_reg() too so all three share the same check.

This also fixes a bug in the helper path. When passing a NULL to
PTR_MAYBE_NULL | ARG_PTR_TO_FIXED_SIZE_MEM argument, the program would
be falsely rejected by check_helper_mem_access(). This is not
triggerable since there is no such kind of helper. Also, note that
check_reg_type() still make sure NULL cannot be passed to an argument
not marked with PTR_MAYBE_NULL.

It also tightens the poisoned-stack-slot check. check_mem_reg() encoded
"a STACK_POISON slot may be read" as a negative access size for any
PTR_TO_STACK argument, but that is only sound for global subprogs, where
static stack liveness proved the callee body does not read those slots
(2cb27158ad ("bpf: poison dead stack slots")). Since check_mem_reg() is
also used for kfuncs, kfuncs accidentally inherited it and could read a
poisoned (dead, possibly uninitialized) stack slot. Restrict the negative
size to global subprogs (meta == NULL) so kfuncs, like helpers, require
the whole argument initialized.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-9-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:14 +02:00
Amery Hung
e6d200dd10 selftests/bpf: Test map lookup result refinement
A map-of-maps lookup value is refined to a map pointer (map_ptr_or_null)
at lookup time by refine_map_lookup_value(). Test that it is rejected
wherever a raw map value would be read as bytes, so the inner map
descriptor cannot leak.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-8-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:13 +02:00
Amery Hung
d4e7fb59c0 bpf: Check helper and kfunc mem+size arguments identically
Helper ARG_CONST_SIZE and kfunc KF_ARG_PTR_TO_MEM_SIZE memory arguments
already share check_mem_size_reg(), but the kfunc path reached it
through a thin wrapper, check_kfunc_mem_size_reg(). The wrapper existed
only to invoke check_mem_size_reg() twice. Once for BPF_READ and once for
BPF_WRITE because a kfunc mem argument may be both read and written,
whereas a helper argument carries a single access direction.

Let check_mem_size_reg() take a bitmask of access directions (widening
access_type to u32) and perform each requested access, then pass
BPF_READ | BPF_WRITE from the kfunc call site. This removes the
check_kfunc_mem_size_reg() wrapper so helper and kfunc mem+size arguments
run through exactly the same code.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-7-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:13 +02:00
Eduard Zingerman
341d227fa5 bpf: Resolve map lookup result type at lookup time
bpf_map_lookup_elem() is typed to return PTR_TO_MAP_VALUE for every
map, but for some map kinds the looked up value is actually a
different object: an inner map, a socket or an xsk socket.
Until now this reinterpretation happened once the pointer was
converted from its NULL-able form to a concrete value.

Such reinterpretation logic placement led to mark_ptr_not_null_reg()
being called for a temporary register copy in check_mem_reg() and
check_kfunc_mem_size_reg() (check_mem_size_reg() was buggy because of
not calling it). The temporary copy was necessary to pass
reinterpreted parameters as nullable helper and kfunc arguments.

Avoid this complication by refining map lookup result type right away.

The test case verifier_map_in_map/on_the_inner_map_pointer needs an
update because the verifier now prints a concrete NULL-able type for
the lookup.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-6-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:12 +02:00
Amery Hung
9f52714dd8 bpf: Pass kfunc meta to mem and mem_size check
kfunc now shares the same bpf_call_arg_meta with helpers. Pass kfunc's
own meta to check_mem_reg() and check_kfunc_mem_size() instead of NULL
or a temporary meta on the stack.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-5-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:12 +02:00
Amery Hung
c82b998777 bpf: Split kfunc map argument into __const_map and __map
Kfuncs used a single '__map' suffix (KF_ARG_PTR_TO_MAP) for two different
things: a verifier-known map matched by map_uid against a bound
timer/wq/task_work object (bpf_wq_init, bpf_task_work_schedule*), and an
opaque 'struct bpf_map *' used only at runtime (bpf_arena_*), which may be a
map fd or a PTR_TO_BTF_ID struct bpf_map (e.g. a bpf_map iterator's ctx->map).

That combined path only accepted the btf map form due to type confusion. The
'if (!reg->map_ptr)' check reads reg->map_ptr, which aliases reg->btf in the
bpf_reg_state union. A PTR_TO_BTF_ID register always has a non-NULL reg->btf,
so the guard silently passed and validation fell through to
process_kf_arg_ptr_to_btf_id(). It also recorded PTR_TO_BTF_ID info in
meta->map, which would be meaningless.

Split the annotation to avoid such type confusion and to align with
helper:

- '__const_map' -> KF_ARG_CONST_MAP_PTR: verifier-known map, handled by
  process_map_ptr_arg() like helper ARG_CONST_MAP_PTR.

- '__map' -> KF_ARG_PTR_TO_BTF_ID: opaque struct bpf_map, validated by
  process_kf_arg_ptr_to_btf_id(). A map fd still matches via
  reg2btf_ids[CONST_PTR_TO_MAP], so bpf_arena_alloc_pages(&map) keeps
  working.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-4-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:11 +02:00
Amery Hung
b33d09b4d9 bpf: Unify const map ptr argument checking for helpers and kfuncs
Both the helper ARG_CONST_MAP_PTR and the kfunc KF_ARG_PTR_TO_MAP
recorded the map pointer in meta->map and, when a map was already
bound by a preceding timer/workqueue/task_work argument, rejected a
mismatching map.

Factor the logic into a single process_map_ptr_arg() used by both
paths. The bound-object name (timer, workqueue, or bpf_task_work) is
derived from the bound map's btf_record, and the register numbers in
the message are computed from the map argument position instead of
being hard-coded.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-3-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:11 +02:00
Amery Hung
70a841617a bpf: Drop process_timer_func wrappers
Drop process_timer_{helper,kfunc}() since bpf_call_arg_meta is now
shared by helper and kfunc. Call process_timer_func() directly.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260801074633.1595644-2-ameryhung@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-03 00:29:07 +02:00
Matt Bobrowski
28e911d61d bpf: update BPF LSM maintainer list
I've recently left Google, so my mattbobrowski@google.com mail address
is now inactive. Update the BPF LSM maintainer entry with a mail
address that I do still have access to and use.

Note that I lost access to my mattbobrowski@google.com mail address
before being able to make this MAINTAINER entry change from it.

Signed-off-by: Matt Bobrowski <matt@bobrowski.net>
Link: https://lore.kernel.org/bpf/am3uorMW7_UWA5An@lima-development
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-01 16:51:18 +02:00
Kumar Kartikeya Dwivedi
682b1c17f8 Merge branch 'bpf-fix-trampoline-handling-of-128-bit-values'
Yonghong Song says:

====================
bpf: Fix trampoline handling of 128-bit values

The BPF trampoline preserves only 8 bytes of a target function's return
value (R0), and its register save area under-allocates space for 128-bit
arguments for x86_64. These two problems lead to memory corruption or
incorrect values observed by BPF programs and the real caller.

This series fixes both issues and adds two selftests, otherwise, each of
them will fail if without the corresponding fix.

Changelogs:
  v4 -> v5:
    - v4: https://lore.kernel.org/bpf/1c4223ae-a5ba-48a4-95d3-57c8ff241055@linux.dev/
    - For function test_fexit_int128_ret(), guard with __x86_64__ and __aarch64__
      to avoid s390x failure
  v3 -> v4:
    - v3: https://lore.kernel.org/bpf/20260710225206.4013062-1-yonghong.song@linux.dev/
    - Add Ack from Leon Hwang
  v2 -> v3:
    - v2: https://lore.kernel.org/bpf/20260710182204.1085329-1-yonghong.song@linux.dev/
    - Align __int128 argument at even position enforced by arm64.
  v1 -> v2:
    - v1: https://lore.kernel.org/bpf/20260710144404.2579671-1-yonghong.song@linux.dev/
    - Also handle __int128 arguments for x86_64.
====================

Link: https://patch.msgid.link/20260729050154.2585468-1-yonghong.song@linux.dev
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-01 03:00:18 +02:00
Yonghong Song
13cc6b788b selftests/bpf: Add tests for >8 byte return value and 128-bit arguments
The BPF trampoline preserves only 8 bytes of the target's return value
(R0), so attaching an fexit/fmod_ret/fsession program to a function that
returns a >8 byte value is now rejected by the verifier. Add a bpf_testmod
function returning __int128 and an fexit program that targets it. The
program is expected to fail to load with the "with a >8 byte return value
is not supported for this attach type" message.

A 128-bit __int128 argument is passed in a register pair and occupies two
trampoline context slots. Add a bpf_testmod function taking a leading
__int128 argument followed by an int and a long, and an fexit program that
reads those two trailing arguments and the return value, verifying that the
trampoline reserves enough stack for the 128-bit argument and places the
following arguments and the return value at the right context slots.

__int128 is only available on 64-bit targets (where the compiler defines
__SIZEOF_INT128__). The argument test additionally depends on the calling
convention: x86_64 and arm64 pass an __int128 in a register pair as the
trampoline expects, while other architectures pass it differently (e.g.
s390x passes larger arguments by reference), so that subtest runs only on
x86_64 and arm64 and is skipped elsewhere.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/bpf/20260729050209.2587581-1-yonghong.song@linux.dev
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-01 03:00:17 +02:00
Yonghong Song
814cba835e bpf, x86: Fix trampoline stack size for 128-bit arguments
btf_distill_func_proto() accepts a function argument up to 16 bytes, so a
128-bit scalar such as __int128 reaches the x86 trampoline with
arg_size == 16. But the current implementation assumes an __int128
argument only needs one register, so the register save area is
under-allocated and save_args() overwrites adjacent stack slots.

Compute the register count from arg_size for all arguments to fix it.

Fixes: a9c5ad31fb ("bpf: x86: Support in-register struct arguments in trampoline programs")
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/bpf/20260729050204.2586457-1-yonghong.song@linux.dev
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-01 03:00:16 +02:00
Yonghong Song
c48796aa6c bpf: Reject >8 byte return values on return-reading trampoline paths
btf_distill_func_proto() builds the function model used for the
fentry/fexit/fmod_ret/fsession trampolines and struct_ops. It has
accepted a 16-byte __int128 return value since the trampoline was
introduced: __get_type_size() returns the integer's type size, and the
return-type check only rejected ret < 0.

But the BPF trampoline preserves only 8 bytes of the return value (RAX on
x86, i.e. R0). For an attach type that reads the target's return value the
second half (RDX / R3) is neither saved nor restored, so a program
attached to a function returning a 16-byte value corrupts the value seen
by the real caller and itself observes only half of it. struct_ops
trampolines have the same limitation.

This affects the attach types that read the target's return value: fexit,
fmod_ret and fsession (plus the _multi variants of fexit and fsession),
and struct_ops. fentry/fentry_multi run before the target returns and are
unaffected.

Reject a >8 byte return value for these attach types in
bpf_check_attach_target() and bpf_check_attach_btf_id_multi(), and for
struct_ops in bpf_struct_ops_desc_init().

Fixes: fec56f5890 ("bpf: Introduce BPF trampoline")
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/bpf/20260729050159.2585809-1-yonghong.song@linux.dev
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
2026-08-01 03:00:09 +02:00
Xu Xin
f0e80dee4e bpf: Log error code on trampoline unlink failure
Replace silent WARN_ON_ONCE with WARN_ONCE that prints the actual error
code from bpf_trampoline_unlink_prog(). This aids debugging of race
conditions during link teardown, while keeping the warning rate limited
to avoid log flooding.

This will be very helpful for speeding up trouble-shooting of some crash
UAF due to bpf_trampoline_unlink_prog failures.

No change to unlink behavior.

Signed-off-by: Xu Xin <xu.xin16@zte.com.cn>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/bpf/20260729141159128mEJmS_aujBKr-cBu1p_UI@zte.com.cn
2026-07-30 16:29:03 -07:00
Pu Lehui
863f3ddd0b bpf: Fix potential UAF when reading bpf link info
In bpf_link_show_fdinfo and bpf_link_get_info_by_fd, link->prog is
accessed without holding any locks. If the prog is concurrently replaced
via bpf_link_update, the old prog can be freed, leading to a potential
UAF issue.

Fix this by accessing link->prog under RCU protection to safely fetch
the pointer and guarantee its lifetime while reading its fields.

Fixes: 0c991ebc8c ("bpf: Implement bpf_prog replacement for an active bpf_cgroup_link")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Amery Hung <ameryhung@gmail.com>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/bpf/f87b53c0-8f00-45a6-82db-8242fa9b143f@huaweicloud.com [0]
Link: https://lore.kernel.org/bpf/20260728025457.2814876-1-pulehui@huaweicloud.com
2026-07-30 15:29:51 -07:00
Pu Lehui
5c59978363 bpf: Fix potential UAF in bpf_netns_link_update_prog
In bpf_netns_link_update_prog, the checks for old_prog and prog type
are currently performed locklessly before acquiring netns_bpf_mutex.
This creates a race condition that can lead to a UAF issue.

If two threads concurrently execute BPF_LINK_UPDATE on the same netns
link, the following execution path can trigger a UAF:

CPU0                                          CPU1
bpf_netns_link_update_prog
  if (old_prog && old_prog != link->prog)
    return -EPERM;
                                              bpf_netns_link_update_prog
                                                if (old_prog && old_prog != link->prog)
                                                ...
                                                old_prog = xchg(&link->prog, new_prog);
                                                bpf_prog_put(old_prog);
  if (new_prog->type != link->prog->type) <-- trigger UAF

Fix this by moving the old_prog and prog->type checks inside the
netns_bpf_mutex critical section. Meanwhile, use guard() to simplify
lock management and avoid all the goto jumping.

Fixes: 7f045a49fe ("bpf: Add link-based BPF program attachment to network namespace")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Amery Hung <ameryhung@gmail.com>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/bpf/f87b53c0-8f00-45a6-82db-8242fa9b143f@huaweicloud.com [0]
Link: https://lore.kernel.org/bpf/20260728023259.2813482-1-pulehui@huaweicloud.com
2026-07-30 15:28:46 -07:00
Andrii Nakryiko
2659f94ed3 Merge branch 'resolve_btfids-discover-kfuncs-from-btf-id-sets'
Ihor Solodrai says:

====================
resolve_btfids: Discover kfuncs from BTF ID sets

This series develops resolve_btfids in preparation for bringing
kernel-specific BTF transformations in tree, which will reduce kbuild
dependency on pahole's features.

resolve_btfids currently identifies kfuncs by reading the "bpf_kfunc"
decl tags pahole emits into vmlinux BTF. The series switches the
source of truth to the BTF ID sets registered with
BTF_KFUNCS_START()/END() in the kernel, which is the mechanism BPF
verifier uses.

The series is based on patches #5 and #6 from the original
"resolve_btfids: Implement BTF tags emission for kfuncs" series [1],
and includes a few significant additions. Particularly the build time
enforcement of kfunc flags consistency [2].

The series consists of:
  - patches #1-#3 implement supporting infrastructure for the proper
    kfunc discovery and deduplication
  - patches #4-#5 expose btf__find_by_name_kind_own() and use it to
    fix a latent bug in _impl func lookup
  - patch #6 fixes inconsistent kfunc flags for HID kfuncs
  - patch #7 implements kfunc discovery from BTF ID sets
  - patch #8 adds enforcement of kfunc flags consistency

The resolve_btfids selftests patches have landed earlier [3].

[1] https://lore.kernel.org/bpf/20260601221805.821394-1-ihor.solodrai@linux.dev/
[2] https://lore.kernel.org/bpf/9b2196dd-443b-4632-ae11-030cdbdc59b4@linux.dev/
[3] https://lore.kernel.org/bpf/20260617210619.1562858-1-ihor.solodrai@linux.dev/
Tested-by: Alan Maguire <alan.maguire@oracle.com>
---

Changes compared to [1]:
  - Drop the idempotency (ensure_*) machinery: assume valid input BTF (Andrii)
  - Use rbtree to store the kfuncs (Andrii)
  - Enforce full KF_* flag consistency as a build error (Eduard)
  - Various cleanups and nits (Andrii, Emil, Jiri)

---
====================

Link: https://patch.msgid.link/20260722233518.778854-1-ihor.solodrai@linux.dev
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2026-07-30 12:48:15 -07:00
Ihor Solodrai
140a3479ef resolve_btfids: Enforce consistent kfunc flags across BTF ID sets
A kfunc may be listed in several BTF ID sets, which is expected
because different kfuncs are available to BPF programs depending on
their type.

However kfunc flags across different BTF ID sets must be consistent [1].
The flags should be considered a part of the kfunc declaration,
because they influence its BTF representation and verifier handling.

Enforce the kfunc flag consistency in resolve_btifds by hard failing
on error and blocking kernel (or module) build.

[1] https://lore.kernel.org/bpf/9b2196dd-443b-4632-ae11-030cdbdc59b4@linux.dev/

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260722233518.778854-9-ihor.solodrai@linux.dev
2026-07-30 12:48:12 -07:00
Ihor Solodrai
f9f60d41ba resolve_btfids: Discover kfuncs from BTF ID sets
collect_kfuncs() currently uses bpf_kfunc decl tags to identify the
list of kfuncs. The decl tags are generated by pahole, which makes
current implementation implicitly rely on those tags being generated.

The authoritative source, used by the the BPF verifier for kfunc
registration, of functions being BPF kfuncs are
BTF_KFUNCS_START()/END() declarations. These are BTF_ID_SET8 under the
hood. Currently resolve_btfids reads kfunc flags from these sets, and
populates them with BTF IDs.

Implement kfunc discovery from BTF_ID_SET8 symbols in resolve_btfids,
removing the dependency on pahole's emmission of decl tags.

Walk BTF_ID_KIND_SET8 sets, and use the address-to-symbol index to
look up set entry's BTF_ID symbol name (before .BTF_ids is patched),
recording the paired flags directly. This makes find_kfunc_flags()
helper unnecessary, so it's removed.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20260722233518.778854-8-ihor.solodrai@linux.dev
2026-07-30 12:48:11 -07:00