From: Anton Protopopov <a.s.protopopov@gmail.com>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Alan Maguire <almagui@kernel.org>,
John Fastabend <john.fastabend@gmail.com>,
Quentin Monnet <qmo@kernel.org>,
Christian Brauner <brauner@kernel.org>,
KP Singh <kpsingh@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Sasha Levin <sashal@kernel.org>,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Anton Protopopov <a.s.protopopov@gmail.com>
Subject: [PATCH v1 bpf-next 00/18] Auto-detect BPF fmodret targets
Date: Fri, 6 Nov 2026 20:55:01 +0000 [thread overview]
Message-ID: <20261106205523.1765622-1-a.s.protopopov@gmail.com> (raw)
Due to recent changes in software development, security fixes and attack-surface
hardening increasingly need to land on production systems _now_. BPF has proven
really useful for producing mitigations, but its error-injection capabilities
remain limited: the list of possible fmodret hooks is static, which no longer
matches reality.
This series allows more kernel functions to be targeted by fmodret BPF
programs. New functions are marked as fmodret-attachable _automatically_, if
CONFIG_CLANG_PLUGIN_BPF_SCAN_IR is on. The latter is off by default, but can be
enabled with CLANG >= 19 with a matching llvm-config and host C++ compiler.
Supported archs are x86_64 and arm64. (The existing static lists are, of
course, still supported.)
The decision on "if this function is safe to inject error" left to BPF program
writers. The motivation/discussion can be found in the recent talk [1]. The
safety/operation model of this new functionality can be briefly stated as
"a trusted operator can already do this with live patch". However, the BPF
approach is more flexible. See the recent talk on shirudo [2] for more details
on how to build a trusted system managing such policies.
The changes introduced are as follows.
The first part of the series changes the way the lists of fmodret-attachable
functions are passed to kernel, namely, now a function is considered as a
fmodret target if it has a bpf_fmodret BTF tag. This tag is generated by the
resolve_btfids tool. The sleepable hooks are in addition tagged with
bpf_fmodret_sleepable. The old-style static hooks, explicitly defined in
kernel/modules, also get the bpf_fmodret tag. The security_*, syscall, and
error-injection hooks are _not_ all marked with the tag, and any new rules do
not apply to them.
Currently static hooks are defined using sets (BTF_FMODRET_START/END). When
the minimal versions of GCC and pahole will support tags, the sets will go away
in favour of just declaring a proper tag.
The second part enables automatic search and usage of fmodret targets:
* The search is performed by a new compiler pass via a compiler plugin.
The candidates are written into a new .BTF_fmodret_candidates section which
is dropped later in the final object. Roughly speaking, a candidate is a
function with a clean (side-effectless) path to "return -errno".
* After the compilation is done, the resolve_btfids tool scans the candidates,
drops some of them (redefined weak, non-ftracable, etc.), and assigns proper
BTF tags: bpf_fmodret/bpf_fmodret_sleepable and bpf_fmodret_retval. The latter
lists all possible return values the analysis found. The verifier rejects
the values outside this list. (An alternative approach, maybe a followup,
is to auto-convert all negative error values returned by a BPF program with
a value from this list.)
The following selftests are added:
* Test fmod_ret BTF decl tags and attach permission: the declared targets get
the right tags, and fmod_ret programs attach only to tagged functions.
* Test fmod_ret candidates found by bpf_scan_ir: functions in bpf_testmod
annotated with the values the analysis must find, checked against the
generated tags. The verifier allows only these values on every path and
rejects extensions and tail calls of such programs.
Finally, the last patch adds a new `bpftool fmodret` command to simplify listing
the functions having bpf_fmodret* tags.
Planned follow ups, more or less in order:
* LLVM LTO support
* GCC support
* Allow injecting errors into functions returning pointers
* More complex logic to gather more candidates (mainly, error propagation,
left out for now to reduce the number of commits in the series)
Build times with and without plugin enabled are nearly the same:
with: without:
real 5m48.377s real 5m47.543s
user 136m7.002s user 135m57.994s
sys 10m13.739s sys 10m12.635s
Links:
[1] Scaling BPF LSM hooks and error injection across the kernel,
https://lpc.events/event/20/contributions/2435/
[2] Shirudo: BPF live-patching infra for the agentic era,
https://lpc.events/event/20/contributions/2437/
Anton Protopopov (18):
bpf: Add BTF ID sets for fmod_ret targets
bpf: Add a btf_id_set8_entry helper
bpf: Build fmod_ret target sets from BTF decl tags
selftests/bpf: Declare bpf_fentry_test1 in tracing tests
bpf: Declare fmod_ret targets with BTF_FMODRET sets
selftests/bpf: Test fmod_ret BTF decl tags and attach permission
scripts: Add LLVM plugin infrastructure
bpf: Add the bpf_scan_ir LLVM plugin
bpf: Find fmod_ret candidates in bpf_scan_ir
bpf: Allow writes to private stack objects in bpf_scan_ir
bpf: Follow PHIs in bpf_scan_ir
bpf: Follow integer casts in bpf_scan_ir
bpf: Check the return values of fmod_ret programs on found targets
bpf: Require the JIT for fmod_ret programs on found 64-bit targets
resolve_btfids: Tag fmod_ret candidates as targets
selftests/bpf: Test fmod_ret candidates found by bpf_scan_ir
selftests/bpf: Enable bpf_scan_ir in the config
bpftool: List and show fmod_ret targets
MAINTAINERS | 10 +
Makefile | 6 +-
arch/Kconfig | 1 +
arch/arm64/kernel/pi/Makefile | 1 +
arch/x86/boot/startup/Makefile | 2 +
arch/x86/um/vdso/Makefile | 2 +-
drivers/firmware/efi/libstub/Makefile | 2 +-
include/asm-generic/vmlinux.lds.h | 7 +-
include/linux/bpf.h | 6 +
include/linux/btf.h | 9 +-
include/linux/btf_ids.h | 24 +-
include/linux/compiler-version.h | 5 +
kernel/bpf/btf.c | 124 +-
kernel/bpf/syscall.c | 1 +
kernel/bpf/verifier.c | 149 ++
lib/vdso/Makefile.include | 3 +
net/bpf/test_run.c | 12 +-
net/mptcp/bpf.c | 15 +-
scripts/Makefile | 1 +
scripts/Makefile.btf | 1 +
scripts/Makefile.llvm-plugins | 10 +
scripts/Makefile.modfinal | 1 +
scripts/Makefile.vmlinux | 3 +
scripts/bpf/fmodret.lds | 6 +
scripts/bpf/fmodret_metadata.h | 29 +
scripts/gen-btf.sh | 4 +-
scripts/link-vmlinux.sh | 7 +
scripts/llvm-plugins/Kconfig | 33 +
scripts/llvm-plugins/Makefile | 21 +
scripts/llvm-plugins/bpf_scan_ir.cpp | 374 +++++
scripts/mod/modpost.c | 1 +
scripts/module.lds.S | 5 +
.../bpftool/Documentation/bpftool-fmodret.rst | 111 ++
tools/bpf/bpftool/Documentation/bpftool.rst | 2 +-
tools/bpf/bpftool/bash-completion/bpftool | 31 +
tools/bpf/bpftool/fmodret.c | 906 ++++++++++++
tools/bpf/bpftool/main.c | 3 +-
tools/bpf/bpftool/main.h | 1 +
tools/bpf/resolve_btfids/Build | 1 +
tools/bpf/resolve_btfids/fmodret.c | 1215 +++++++++++++++++
tools/bpf/resolve_btfids/fmodret.h | 28 +
tools/bpf/resolve_btfids/main.c | 180 ++-
tools/include/linux/btf_ids.h | 24 +-
tools/objtool/check.c | 1 +
tools/testing/selftests/bpf/config | 2 +
.../selftests/bpf/prog_tests/fmodret_retval.c | 205 +++
.../selftests/bpf/prog_tests/fmodret_tags.c | 155 +++
.../selftests/bpf/progs/fmodret_retval.c | 196 +++
.../selftests/bpf/progs/fmodret_retval_ext.c | 44 +
.../selftests/bpf/progs/fsession_test.c | 2 +
.../bpf/progs/get_func_ip_fsession_test.c | 2 +
.../selftests/bpf/progs/tracing_multi_check.c | 2 +-
.../testing/selftests/bpf/test_kmods/Makefile | 11 +-
.../{bpf_testmod.c => bpf_testmod_main.c} | 11 +-
.../bpf/test_kmods/bpf_testmod_retval.c | 314 +++++
.../test_kmods/bpf_testmod_retval_strong.c | 28 +
56 files changed, 4271 insertions(+), 79 deletions(-)
create mode 100644 scripts/Makefile.llvm-plugins
create mode 100644 scripts/bpf/fmodret.lds
create mode 100644 scripts/bpf/fmodret_metadata.h
create mode 100644 scripts/llvm-plugins/Kconfig
create mode 100644 scripts/llvm-plugins/Makefile
create mode 100644 scripts/llvm-plugins/bpf_scan_ir.cpp
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-fmodret.rst
create mode 100644 tools/bpf/bpftool/fmodret.c
create mode 100644 tools/bpf/resolve_btfids/fmodret.c
create mode 100644 tools/bpf/resolve_btfids/fmodret.h
create mode 100644 tools/testing/selftests/bpf/prog_tests/fmodret_retval.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/fmodret_tags.c
create mode 100644 tools/testing/selftests/bpf/progs/fmodret_retval.c
create mode 100644 tools/testing/selftests/bpf/progs/fmodret_retval_ext.c
rename tools/testing/selftests/bpf/test_kmods/{bpf_testmod.c => bpf_testmod_main.c} (99%)
create mode 100644 tools/testing/selftests/bpf/test_kmods/bpf_testmod_retval.c
create mode 100644 tools/testing/selftests/bpf/test_kmods/bpf_testmod_retval_strong.c
--
2.43.0
reply other threads:[~2026-11-06 20:44 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261106205523.1765622-1-a.s.protopopov@gmail.com \
--to=a.s.protopopov@gmail.com \
--cc=almagui@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=memxor@gmail.com \
--cc=qmo@kernel.org \
--cc=sashal@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®