Skip to content

BPF: Allow all libcalls - #165353

Open
vadorovsky wants to merge 1 commit into
rust-lang:mainfrom
vadorovsky:vad/bpf-allow-all-libcalls
Open

vadorovsky wants to merge 1 commit into
rust-lang:mainfrom
vadorovsky:vad/bpf-allow-all-libcalls

Conversation

@vadorovsky

@vadorovsky vadorovsky commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

By default, BPF backend in LLVM allows only memcpy, memset and memmove libcalls.

However, core/src/opts/arith.rs:932 emits an __extendhfsf2 libcall.

LLVM 23 provides an opt-in mode that lets BPF runtimes supply implementations for otherwise unsupported libcalls.[0] Enable it unconditionally instead of enforcing LLVM's fixed allowlist.

This defers validation of libcalls (and rejection of undefined ones) to BPF program consumers such as loaders and VMs. libbpf rejects ordinary undefined functions without BTF metadata.[1] Aya generally rejects unresolved calls during relocation.[2] If LLVM's unresolved call -1 placeholder reaches the Linux verifier unchanged,[3] its relative target is the call itself, so the verifier rejects it as recursion.[4] SBPF's ELF loader rejects external symbols absent from the loader's function registry when reject_broken_elfs option is enabled.[5] Agave enables it while deploying and upgrading programs.[6]

Users can therefore satisfy a libcall through a linked implementation or a runtime-provided function, while genuinely unresolved calls still fail during loading, verification or execution. Runtimes can also add libcalls without coordinating an allowlist change with LLVM.

Code in this change is generated by (an open-weight and self-hosted) LLM, it was agreed on in the Zulip thread [7], where @nagisa volunteered as a reviewer.

Fixes: #165352

[0] llvm/llvm-project@8446b9ffb
[1] llvm/llvm-project#199542
[2] https://github.com/libbpf/libbpf/blob/f7081a/src/libbpf.c#L4345-L4350
[3] https://github.com/aya-rs/aya/blob/15a0de/aya-obj/src/relocation.rs#L606-L614
[4] https://github.com/torvalds/linux/blob/f5bbbfec5/kernel/bpf/verifier.c#L2798-L2800
[5] https://github.com/torvalds/linux/blob/f5bbbfec5/kernel/bpf/verifier.c#L2952-L2958
[6] https://github.com/anza-xyz/sbpf/blob/45bbcb/src/elf.rs#L1223-L1227
[7] https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-reviews/topic/Seeking.20review.20for.20BPF.20bytecode.20linking.20.28issue.20.23135175.29/near/631892496

r? @nagisa

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 2, 2026
@vadorovsky
vadorovsky marked this pull request as ready for review November 2, 2026 14:12
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 2, 2026
@rustbot

This comment has been minimized.

@vadorovsky
vadorovsky force-pushed the vad/bpf-allow-all-libcalls branch from a3aa819 to eb1245c Compare November 2, 2026 14:13
@rust-log-analyzer

This comment has been minimized.

@vadorovsky
vadorovsky force-pushed the vad/bpf-allow-all-libcalls branch from eb1245c to 1eddb5e Compare November 2, 2026 15:28
@rust-log-analyzer

This comment has been minimized.

@nagisa

nagisa commented Nov 2, 2026

Copy link
Copy Markdown
Member

This will need some sort of gating on llvm23. Your best bet to find how to do that is to look at earlier LLVM upgrades/old version removals which will be removing code conditional on llvm version.

@vadorovsky
vadorovsky force-pushed the vad/bpf-allow-all-libcalls branch from 1eddb5e to f698433 Compare November 7, 2026 21:17
@rustbot rustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Nov 7, 2026
@vadorovsky

Copy link
Copy Markdown
Contributor Author

This will need some sort of gating on llvm23. Your best bet to find how to do that is to look at earlier LLVM upgrades/old version removals which will be removing code conditional on llvm version.

Good point. To avoid slapping if target == bpf && llvm_version > 23 in llvm_util, I added a dedicated field in TargetOptions.

@vadorovsky
vadorovsky force-pushed the vad/bpf-allow-all-libcalls branch from f698433 to 23240bd Compare November 9, 2026 16:37
}

if get_version() < (24, 0, 0) && wants_wasm_eh(&sess.target) {
if llvm_major < 24 && wants_wasm_eh(&sess.target) {

@vadorovsky vadorovsky Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to switch WASM over to llvm_args_by_version in a follow-up change.

View changes since the review

@rust-log-analyzer

This comment has been minimized.

By default, BPF backend in LLVM allows only `memcpy`, `memset` and
`memmove` libcalls.

However, `core/src/ops/arith.rs:932` emits an `__extendhfsf2` libcall.

LLVM 23 provides an opt-in mode that lets BPF runtimes supply
implementations for otherwise unsupported libcalls.[0] Enable it
unconditionally instead of enforcing LLVM's fixed allowlist.

This defers validation of libcalls (and rejection of undefined ones) to
BPF program consumers such as loaders and VMs. libbpf rejects ordinary
undefined functions without BTF metadata.[1] Aya generally rejects
unresolved calls during relocation.[2] If LLVM's unresolved `call -1`
placeholder reaches the Linux verifier unchanged,[3] its relative target
is the call itself, so the verifier rejects it as recursion.[4] SBPF's
ELF loader rejects external symbols absent from the loader's function
registry when `reject_broken_elfs` option is enabled.[5] Agave enables
it while deploying and upgrading programs.[6]

Users can therefore satisfy a libcall through a linked implementation or
a runtime-provided function, while genuinely unresolved calls still fail
during loading, verification or execution. Runtimes can also add
libcalls without coordinating an allowlist change with LLVM.

Given that the opt-in flag for libcalls is available only in specific
LLVM versions (>=23), add `llvm_args_by_version` field to
`TargetOptions`, that allows to specify LLVM arguments by version.

Code in this change is generated by (an open-weight and self-hosted)
LLM, it was agreed on in the Zulip thread [7], where @nagisa volunteered
as a reviewer.

[0] llvm/llvm-project@8446b9ffb
[1] llvm/llvm-project#199542
[2] https://github.com/libbpf/libbpf/blob/f7081a/src/libbpf.c#L4345-L4350
[3] https://github.com/aya-rs/aya/blob/15a0de/aya-obj/src/relocation.rs#L606-L614
[4] https://github.com/torvalds/linux/blob/f5bbbfec5/kernel/bpf/verifier.c#L2798-L2800
[5] https://github.com/torvalds/linux/blob/f5bbbfec5/kernel/bpf/verifier.c#L2952-L2958
[6] https://github.com/anza-xyz/sbpf/blob/45bbcb/src/elf.rs#L1223-L1227
[7] https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-reviews/topic/Seeking.20review.20for.20BPF.20bytecode.20linking.20.28issue.20.23135175.29/near/631892496
@vadorovsky
vadorovsky force-pushed the vad/bpf-allow-all-libcalls branch from 23240bd to ec59c78 Compare November 9, 2026 17:54
@rust-bors

rust-bors Bot commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #165777) made this pull request unmergeable. Please resolve the merge conflicts by rebasing.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BPF: core: ops/arith.rs emits __extendhfsf2 libcall, LLVM rejects it

4 participants