All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 bpf-next 0/5] bpf: Unwinding with unwind_goto and unwind_exit
@ 2026-10-19  5:18 Alexei Starovoitov
  2026-10-19  5:18 ` [PATCH v2 bpf-next 1/5] bpf: Add unwind_goto and unwind_exit insns Alexei Starovoitov
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Alexei Starovoitov @ 2026-10-19  5:18 UTC (permalink / raw)
  To: bpf; +Cc: daniel, andrii, eddyz87, memxor

From: Alexei Starovoitov <ast@kernel.org>

v1 [1] said in r3 how a subprog returns. v2 has two new insns instead,
as Kumar suggested.

1. What is the problem?

A rust panic or a C++ exception has to run Drop impls or destructors of
every frame it passes through. bpf_throw() discards the frames, so the
verifier doesn't let a frame that owns a lock or a reference throw. In rust
every index and every unwrap() can panic.

2. Is it worth solving?

Without it rust-bpf [2] drops all landing pads and a panic is bpf_throw().
A prog that can panic with a guard held doesn't load.

3. Is there a simpler way?

[3] keeps the normal path free of unwind code. llvm emits a table, libbpf
passes it to the kernel, bpf_unwind() walks the stack and rewrites return
addresses, and the verifier models hidden edges from calls to pads. That's
1400 lines in the kernel, with new uapi and two kfuncs, and 440 lines in
libbpf.

Here the edge from a call to its pad is an insn, and so is the other way
to leave a frame [4]:

  ret                            exit
  invoke foo unwind pad          call foo; unwind_goto pad
  resume                         r0 = 0; unwind_exit

Pads are ordinary code. The verifier learns one bit: how the callee left.
The normal path is free of unwind code too: JITs emit nothing for
unwind_goto, and exit is what it was.
170 lines in patch 1 and 80 lines in each JIT.

4. Will the api and the layers last?

Two new insns: one more kind of BPF_JCOND and one more kind of BPF_EXIT.
No kfuncs, no BTF, no changes in libbpf and other loaders.
The source level entry point is _Unwind_RaiseException() of the Itanium
ABI. It's what the runtimes of rust and C++ call on other architectures.
unwind_exit returns r0 like exit does. Today it's 0. That's where an
exception object would go.

5. Is it good taste?

Every frame returns through its own epilogue. The only question is where it
returns to. That's one bit, and it's a bit of control flow. v1 kept it in
a register.

It's not specific to rust. A C++ prog with throw, catch and destructors
compiles, loads and runs. It's a selftest in patch 5.

v1 -> v2:
- unwind_goto and unwind_exit instead of 'if r3 != 0 goto pad' and
  'r3 = 1; exit' (Kumar).
- JIT support is not an optimization anymore. There are no shape tests, no
  look at jump_target, which was stale (sashiko), no exit that looks at r3
  and no fallback to a branch.
- r3 is an argument again and nothing else. In v1 a subprog that didn't
  write it passed it through, and fentry didn't restore it (bpf-ci).
- Async and exception callbacks cannot unwind (sashiko).
- No BTF decl_tag, which was matched by prefix (bpf-ci). It works without
  BTF.
- x86 private stack is supported.
- Tail call, ld_abs and freplace are allowed.
- bpf_unwind_target() is in core.c. num_exentries is counted in
  jit_subprogs().
- selftests: no #ifdef by arch, which broke the build on the rest of them.
  The messages are checked. fentry and freplace are attached and the
  target is run. fmod_ret is gone, it didn't test anything new. Skips say
  why (bpf-ci).
- clang defines __BPF_FEATURE_UNWIND.

Tested in qemu only, x86-64 and arm64 with and without pointer
authentication: the selftests, C, C++ and rust progs built with [4],
with and without bpf_jit_harden=2. test_progs was run on x86-64. On arm64
the same objects were loaded and run by a small loader, and __jited
patterns were matched against the JIT output by a script.

[1] https://lore.kernel.org/bpf/20261018010246.1643877-1-alexei.starovoitov@gmail.com/
[2] https://github.com/4ast/rust-bpf
[3] https://lore.kernel.org/bpf/20261017025129.1914859-1-yonghong.song@linux.dev/
[4] https://github.com/llvm/llvm-project/pull/233140

Alexei Starovoitov (5):
  bpf: Add unwind_goto and unwind_exit insns
  bpf, x86: Support unwind_goto and unwind_exit
  bpf, arm64: Support unwind_goto and unwind_exit
  selftests/bpf: Add tests for unwind_goto and unwind_exit
  selftests/bpf: Add a C++ prog with exceptions

 arch/arm64/net/bpf_jit.h                      |    2 +
 arch/arm64/net/bpf_jit_comp.c                 |   78 ++
 arch/x86/net/bpf_jit_comp.c                   |   83 +-
 include/linux/bpf.h                           |    1 +
 include/linux/bpf_verifier.h                  |    3 +
 include/linux/filter.h                        |   12 +
 include/uapi/linux/bpf.h                      |   11 +
 kernel/bpf/const_fold.c                       |    2 +-
 kernel/bpf/core.c                             |   24 +
 kernel/bpf/disasm.c                           |    7 +-
 kernel/bpf/fixups.c                           |    7 +
 kernel/bpf/states.c                           |    3 +
 kernel/bpf/verifier.c                         |   93 +-
 tools/include/uapi/linux/bpf.h                |   11 +
 tools/testing/selftests/bpf/Makefile.skel     |   11 +
 .../selftests/bpf/prog_tests/unwind_attach.c  |  102 ++
 .../selftests/bpf/prog_tests/unwind_cxx.c     |   76 ++
 .../selftests/bpf/prog_tests/verifier.c       |    2 +
 .../selftests/bpf/progs/unwind_attach.c       |   29 +
 .../selftests/bpf/progs/unwind_cxx.cpp        |  115 ++
 .../selftests/bpf/progs/verifier_unwind.c     | 1047 +++++++++++++++++
 tools/testing/selftests/bpf/test_loader.c     |    3 +-
 22 files changed, 1716 insertions(+), 6 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/unwind_attach.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/unwind_cxx.c
 create mode 100644 tools/testing/selftests/bpf/progs/unwind_attach.c
 create mode 100644 tools/testing/selftests/bpf/progs/unwind_cxx.cpp
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_unwind.c


base-commit: 27dc4fc4ae7b01efb68561f98c5f373e55fb71c2
-- 
2.55.0


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

end of thread, other threads:[~2026-10-20  0:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19  5:18 [PATCH v2 bpf-next 0/5] bpf: Unwinding with unwind_goto and unwind_exit Alexei Starovoitov
2026-10-19  5:18 ` [PATCH v2 bpf-next 1/5] bpf: Add unwind_goto and unwind_exit insns Alexei Starovoitov
2026-10-19  5:45   ` sashiko-bot
2026-10-19  6:59   ` bot+bpf-ci
2026-10-19  5:18 ` [PATCH v2 bpf-next 2/5] bpf, x86: Support unwind_goto and unwind_exit Alexei Starovoitov
2026-10-19  5:18 ` [PATCH v2 bpf-next 3/5] bpf, arm64: " Alexei Starovoitov
2026-10-19  5:18 ` [PATCH v2 bpf-next 4/5] selftests/bpf: Add tests for " Alexei Starovoitov
2026-10-19  6:00   ` bot+bpf-ci
2026-10-19  5:18 ` [PATCH v2 bpf-next 5/5] selftests/bpf: Add a C++ prog with exceptions Alexei Starovoitov
2026-10-19 20:32 ` [PATCH v2 bpf-next 0/5] bpf: Unwinding with unwind_goto and unwind_exit Eduard Zingerman
2026-10-20  0:35   ` Alexei Starovoitov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.