BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next 00/17] bpf: Indirect calls of bpf subprogs (callx)
@ 2026-09-22  1:13 Alexei Starovoitov
  2026-09-22  1:13 ` [PATCH bpf-next 01/17] bpf: Fix infinite loop in check_max_stack_depth() Alexei Starovoitov
                   ` (16 more replies)
  0 siblings, 17 replies; 44+ messages in thread
From: Alexei Starovoitov @ 2026-09-22  1:13 UTC (permalink / raw)
  To: bpf; +Cc: daniel, andrii, eddyz87, memxor, a.s.protopopov

From: Alexei Starovoitov <ast@kernel.org>

Introduce BPF_JMP | BPF_CALL | BPF_X 'callx dst_reg' instruction: indirect
call of bpf subprog with address in a register. LLVM emits it for calls
via function pointer. The verifier rejected it as unknown opcode.

Only static subprogs can be called. The callee is verified in the context
of the caller like a direct call of static subprog. No callx into global
subprogs, helpers or kfuncs.

All callees are known before the main verifier pass. The address of
the callee comes from:

- ld_imm64 BPF_PSEUDO_FUNC, which is allowed for static subprogs only.
  add_subprogs() and check_cfg() see them already.

- 64-bit load from read-only data: tables of functions, struct ops,
  vtables, where pointers are mixed with other data. Rust needs that:

    r6 = vtable ll
    r1 = *(u64 *)(r6 + 0)      // data
    r2 = *(u64 *)(r6 + 8)      // pointer to a function
    callx r2

  libbpf keeps the data in a frozen read-only array map, one per prog,
  and stores byte offset of static function in the prog into the pointer.
  The kernel guesses pointers by that value before check_cfg() (patch 10).
  Wrong guess is safe. Functions referenced by data only are found via
  func_info (patch 9). After JIT the kernel replaces the offsets in
  the map with addresses. The prog must be the only user of the map,
  since other progs would have been verified with its old content. The
  prog reads addresses as data, so CAP_PERFMON is required.

Both produce PTR_TO_FUNC.

The passes before the main one don't know the callee and treat callx
conservatively (patch 4). The main pass records caller -> callee edges.
Recursion and stack depth checks use them afterwards (patch 6).

In C:

  static const struct shape_ops square_ops = { 1, area, 10, perimeter };
  ...
  return ops->area(x) * ops->scale + ops->perimeter(ops->id);

and

  static int (* const handlers[])(struct xdp_md *) = { foo, bar, baz };
  ...
  if (i < ARRAY_SIZE(handlers))
          return handlers[i](ctx);

plus what clang compiles without data: picking one of several functions,
passing a function pointer into another function.

Patches 1-3 are fixes I hit along the way and are independent: a prog
without callx that hangs bpf_prog_load() in check_max_stack_depth(),
its test, and const folding of loads from insn_array.

Not supported:
- JITs other than x86-64 and arm64. No interpreter support.
- x86-64 with FineIBT: bpf_jit_supports_callx() returns false.
- tail calls in callees of callx.
- pointers to functions in writable data, misaligned pointers.

Alexei Starovoitov (17):
  bpf: Fix infinite loop in check_max_stack_depth()
  selftests/bpf: Test recursion through a global function and a callback
  bpf: Don't fold loads from insn_array maps into constants
  bpf: Prepare static analysis passes for callx instruction
  bpf: Add callx instruction to call bpf subprogs indirectly
  bpf: Add callx calls to the call graph
  bpf, x86: Add JIT support for callx
  bpf, arm64: Add JIT support for callx
  bpf: Discover subprogs described by func_info
  bpf: Recognize pointers to functions in read-only maps
  libbpf: Support pointers to static functions in data when linking
  libbpf: Resolve pointers to functions in read-only data
  libbpf: Treat .data.rel.ro as read-only data
  libbpf: Support pointers to functions in read-only data in light
    skeleton
  selftests/bpf: Add tests for callx
  selftests/bpf: Add tests for callx through pointers in read-only data
  bpf, docs: Document callx instruction

 Documentation/bpf/clang-notes.rst             |   7 +-
 Documentation/bpf/linux-notes.rst             |  31 +-
 arch/arm64/net/bpf_jit_comp.c                 |  16 +
 arch/x86/net/bpf_jit_comp.c                   |  68 ++
 include/linux/bpf.h                           |  10 +
 include/linux/bpf_verifier.h                  |  43 +
 include/linux/filter.h                        |   1 +
 kernel/bpf/backtrack.c                        |  20 +-
 kernel/bpf/cfg.c                              |  75 ++
 kernel/bpf/const_fold.c                       |  11 +-
 kernel/bpf/core.c                             |  12 +
 kernel/bpf/disasm.c                           |   5 +-
 kernel/bpf/fixups.c                           |  55 +
 kernel/bpf/liveness.c                         |  35 +-
 kernel/bpf/verifier.c                         | 632 ++++++++++-
 tools/lib/bpf/bpf_gen_internal.h              |  13 +-
 tools/lib/bpf/gen_loader.c                    | 172 ++-
 tools/lib/bpf/libbpf.c                        | 430 +++++++-
 tools/lib/bpf/linker.c                        |  18 +
 tools/testing/selftests/bpf/Makefile.skel     |   2 +-
 .../bpf/prog_tests/callx_func_ptr_map.c       | 192 ++++
 .../bpf/prog_tests/callx_rodata_lskel.c       |  55 +
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/callx_rodata.c        |  43 +
 .../selftests/bpf/progs/verifier_callx.c      | 984 ++++++++++++++++++
 .../bpf/progs/verifier_callx_rodata.c         | 651 ++++++++++++
 .../bpf/progs/verifier_global_subprogs.c      |  31 +
 .../selftests/bpf/verifier/basic_call.c       |   2 +-
 28 files changed, 3507 insertions(+), 111 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/callx_func_ptr_map.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/callx_rodata_lskel.c
 create mode 100644 tools/testing/selftests/bpf/progs/callx_rodata.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_callx.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_callx_rodata.c


base-commit: 79dc258c9392051420a26f1504c647bd3d27c66a
-- 
2.55.0


^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2026-09-24  2:13 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-22  1:13 [PATCH bpf-next 00/17] bpf: Indirect calls of bpf subprogs (callx) Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 01/17] bpf: Fix infinite loop in check_max_stack_depth() Alexei Starovoitov
2026-09-22  2:01   ` bot+bpf-ci
2026-09-22  2:56     ` Alexei Starovoitov
2026-09-23 22:35   ` Eduard Zingerman
2026-09-22  1:13 ` [PATCH bpf-next 02/17] selftests/bpf: Test recursion through a global function and a callback Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 03/17] bpf: Don't fold loads from insn_array maps into constants Alexei Starovoitov
2026-09-23 22:39   ` Eduard Zingerman
2026-09-23 23:12     ` Alexei Starovoitov
2026-09-24  0:19   ` bot+bpf-ci
2026-09-22  1:13 ` [PATCH bpf-next 04/17] bpf: Prepare static analysis passes for callx instruction Alexei Starovoitov
2026-09-23 23:10   ` Eduard Zingerman
2026-09-23 23:51     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 05/17] bpf: Add callx instruction to call bpf subprogs indirectly Alexei Starovoitov
2026-09-24  0:09   ` Eduard Zingerman
2026-09-22  1:13 ` [PATCH bpf-next 06/17] bpf: Add callx calls to the call graph Alexei Starovoitov
2026-09-22  1:27   ` sashiko-bot
2026-09-22  2:54     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 07/17] bpf, x86: Add JIT support for callx Alexei Starovoitov
2026-09-22  1:27   ` sashiko-bot
2026-09-22  2:53     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 08/17] bpf, arm64: " Alexei Starovoitov
2026-09-22 15:05   ` Puranjay Mohan
2026-09-22  1:13 ` [PATCH bpf-next 09/17] bpf: Discover subprogs described by func_info Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 10/17] bpf: Recognize pointers to functions in read-only maps Alexei Starovoitov
2026-09-22  1:31   ` sashiko-bot
2026-09-22  3:01     ` Alexei Starovoitov
2026-09-24  0:46   ` bot+bpf-ci
2026-09-24  2:12     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 11/17] libbpf: Support pointers to static functions in data when linking Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 12/17] libbpf: Resolve pointers to functions in read-only data Alexei Starovoitov
2026-09-24  0:33   ` bot+bpf-ci
2026-09-24  2:13     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 13/17] libbpf: Treat .data.rel.ro as " Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 14/17] libbpf: Support pointers to functions in read-only data in light skeleton Alexei Starovoitov
2026-09-22  2:01   ` bot+bpf-ci
2026-09-22  2:55     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 15/17] selftests/bpf: Add tests for callx Alexei Starovoitov
2026-09-24  0:33   ` bot+bpf-ci
2026-09-24  2:13     ` Alexei Starovoitov
2026-09-22  1:13 ` [PATCH bpf-next 16/17] selftests/bpf: Add tests for callx through pointers in read-only data Alexei Starovoitov
2026-09-22  2:01   ` bot+bpf-ci
2026-09-24  0:33   ` bot+bpf-ci
2026-09-22  1:13 ` [PATCH bpf-next 17/17] bpf, docs: Document callx instruction Alexei Starovoitov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox