History log of /linux/tools/testing/selftests/exec/binfmt_misc_common.h (Results 1 – 8 of 8)
Revision (<<< Hide revision tags) (Show revision tags >>>) Date Author Comments
# b9cba7eb 17-Aug-2026 Linus Torvalds <torvalds@linux-foundation.org>

Merge tag 'vfs-7.3-rc1.binfmt' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull binfmt updates from Christian Brauner:
"This contains a bunch of work for binfmt_misc. It fixes a bunch

Merge tag 'vfs-7.3-rc1.binfmt' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull binfmt updates from Christian Brauner:
"This contains a bunch of work for binfmt_misc. It fixes a bunch of
old bugs, reworks the locking, and then extends the format registry
so a binary type can be matched programmatically and its interpreter
computed per exec instead of being a fixed string recorded at
registration time.

This allows nixos and other to e.g., implement relocatable binaries
meaning the interpreter/dynamic loader can be determined
programatically, say found relative to the binary. The mechanism is
flexible and can support other policies:

- Handler lookup is now an rcu walk. An exec that matches no
binfmt_misc entry should now never write to a shared cacheline

- remove the VERBOSE_STATUS and USE_DEBUG compile time toggles

- convert the entry file to a seq_file which simplifies things quite
a bit and kills a lot of custom logic

- make flags proper enums

- rename struct Node to binfmt_misc_entry

- allow entries to be removed with unlink(2)

- Add the ability to attach bpf programs to binfmt_misc entries so
it's possible to dynamically choose the execution environment such
as the loader or interpreter on a per binary basis.

A handler is an instance of a binfmt_misc_ops struct_ops with a
->match() and a ->load() program. match() decides from the entry
lookup walk whether the handler applies under the same
registration-order. It can read file content as needed not only the
prefetched 256 bytes in bprm->buf.

load() then selects the interpreter and stages it through the new
bpf_binprm_set_interp(), bpf_binprm_set_interp_arg() and
bpf_binprm_set_flags() kfuncs.

Handlers are published in a registry keyed by the registering
task's user namespace and activated through the existing text
interface with a new 'B' type carrying the handler name:

echo ':origin:B::::nix:' > /proc/sys/fs/binfmt_misc/register

The permission and namespacing model is unchanged. Activating a
handler requires the same write access to an instance as any other
registration. A container mounting its own instance escapes the
host's entries exactly as before. The computed interpreter is
opened with open_exec() under the caller's credentials and goes
through full LSM vetting as the next binprm level. A program can
only ever redirect the caller to something the caller could exec
anyway.

- Two dispatch modes are added. So far the chosen interpreter owns
the whole process identity (argv[0], /proc/pid/cmdline,
/proc/self/exe all name interpreter information). So relocatable
find the dynamic linker instead. Also a binary passed to execveat()
as an inaccessible O_CLOEXEC fd cannot run at all and gdb trips
because AT_ENTRY and AT_PHDR do not match the exe file. So PIE
symbols are unrelocated.

This adds transparent dispatch which allows the interpreter to load
the binary through AT_EXECFD and leaves the argument vector exactly
as the caller built it and labels mm->exe_file and comm with the
binary. It also raises the AT_FLAGS_TRANSPARENT_INTERP aux vector
bit. The interpreter keeps control of mapping the binary.

The second mode is loader substitution. This allows a binary to be
executed natively and only the interpreter to be changed.

- Last, interpreters can be bound at registration time. Each
interpreter is opened by its own write with the credentials the
entry file was opened with. The program picks one per exec with
bpf_binprm_select_interp().

Ucounts are used to properly account for pre-opened interpreters
via /proc/sys/user/max_binfmt_misc_interpreters"

* tag 'vfs-7.3-rc1.binfmt' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (63 commits)
binfmt_misc: document the pre-opened interpreter limit
selftests/exec: test the pre-opened interpreter limit
binfmt_misc: correctly account pre-opened interpreters
binfmt_misc: document interpreters bound by a 'B' entry
selftests/exec: test interpreters bound to a 'B' entry
binfmt_misc: let a 'B' entry bind its interpreters
binfmt_misc: carry pre-opened interpreters in struct binfmt_misc_interp
selftests/exec: share the bpf handler preconditions
binfmt_misc: document registering an entry disabled
selftests/exec: test registering an entry disabled
selftests/exec: let binfmt_flag_supported() return a bool
selftests/exec: check that a binfmt_misc instance cannot be pinned
binfmt_misc: let a register string create an entry disabled
binfmt_misc: document loader substitution
selftests/exec: test binfmt_misc loader substitution
binfmt_misc: let a bpf handler request loader substitution
binfmt_misc: add the 'L' loader substitution flag
binfmt_elf_fdpic: consume a stashed PT_INTERP substitute
binfmt_elf: consume a stashed PT_INTERP substitute
exec: carry a PT_INTERP substitute in struct linux_binprm
...

show more ...


Revision tags: v7.2, v7.2-rc7, v7.2-rc6
# e98067e7 31-Jul-2026 Christian Brauner <brauner@kernel.org>

Merge patch series "binfmt_misc: bind interpreters to a bpf-backed entry"

Christian Brauner <brauner@kernel.org> says:

binfmt_misc: bind interpreters to a bpf-backed entry

A 'B' entry's load progr

Merge patch series "binfmt_misc: bind interpreters to a bpf-backed entry"

Christian Brauner <brauner@kernel.org> says:

binfmt_misc: bind interpreters to a bpf-backed entry

A 'B' entry's load program hands the kernel an absolute path and
open_exec() resolves it at exec time in the mount namespace of whoever
runs the binary. So the handler names an interpreter but never gets to
say which file that is. Whoever controls the filesystem view of the exec
does.

Static entries have had the answer for a while. 'F' opens the file at
registration and every exec runs a clone of it. I can't just reuse it as
it stands. It pre-opens the one interpreter named in the register string
and a 'B' entry has no fixed interpreter. The program picks per exec,
and a qemu-user shaped handler wants one per guest architecture. So it
may want a whole set of them and that doesn't fit in a register string.

An entry is matchable the moment it is registered, so everything it
needs has to fit in that one write. Patch 1 adds a 'D' flag that creates
the entry disabled and splits a registration into create and activate:

echo ':qemu:B::::qemu_user:D' > register
echo '+aarch64 /usr/bin/qemu-aarch64' > qemu
echo '+arm /usr/bin/qemu-arm' > qemu
echo 1 > qemu

Each path is opened by its write, with the credentials the entry file was
opened with. Same open_exec() call, same place as 'F'. The program picks
one per exec with bpf_binprm_select_interp() and gets a clone of the
file. Nothing is resolved again, in any namespace.

A 'D' entry simply isn't hashed until that first '1', so the rcu
insertion that publishes the entry also publishes its interpreters and
the exec side needs no barriers. Reading the entry file doesn't take any
locks either. Bindings are rcu-published and the open file already pins
everything the read looks at. We use paths, not fds which makes the
config remain nice and static and can be shipped via /etc/binfmt.d.

* patches from https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-0-4a0b0da71f16@kernel.org:
binfmt_misc: document interpreters bound by a 'B' entry
selftests/exec: test interpreters bound to a 'B' entry
binfmt_misc: let a 'B' entry bind its interpreters
binfmt_misc: carry pre-opened interpreters in struct binfmt_misc_interp
selftests/exec: share the bpf handler preconditions
binfmt_misc: document registering an entry disabled
selftests/exec: test registering an entry disabled
selftests/exec: let binfmt_flag_supported() return a bool
binfmt_misc: let a register string create an entry disabled

Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-0-4a0b0da71f16@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...


# 6bd0c7ab 30-Jul-2026 Christian Brauner <brauner@kernel.org>

selftests/exec: test registering an entry disabled

A magic entry registered with 'D' and the same entry without it, to pin
down what the flag decides and what it leaves alone:

- the entry reports i

selftests/exec: test registering an entry disabled

A magic entry registered with 'D' and the same entry without it, to pin
down what the flag decides and what it leaves alone:

- the entry reports itself disabled and nothing dispatches until '1' is
written to it

- without 'D' it dispatches straight away

- 'D' is not read back among the entry's flags

- enabling and disabling afterwards works as it does for any entry

- 'D' composes with the flags that shape the invocation

- '-1' to the status file removes a staged entry like any other

- a file handle held across a removal cannot resurrect the entry

Put the entry write and read-back helpers into binfmt_misc_common.h.
The bpf suite will need them as well.

Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-3-4a0b0da71f16@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...


# 686585ec 30-Jul-2026 Christian Brauner <brauner@kernel.org>

selftests/exec: let binfmt_flag_supported() return a bool

binfmt_flag_supported() returns 0 when the flag is supported and -1
when it is not, so every caller reads backwards:

if (binfmt_flag_suppo

selftests/exec: let binfmt_flag_supported() return a bool

binfmt_flag_supported() returns 0 when the flag is supported and -1
when it is not, so every caller reads backwards:

if (binfmt_flag_supported('T'))
SKIP(return, "kernel without the 'T' flag");

Make it return a bool and flip the callers. errno from a failed probe
is still set for callers that check it.

Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-2-4a0b0da71f16@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com>

show more ...


Revision tags: v7.2-rc5
# b2a52381 25-Jul-2026 Christian Brauner <brauner@kernel.org>

Merge patch series "binfmt_misc: transparent interpreters and PT_INTERP loader substitution"

Christian Brauner <brauner@kernel.org> says:

binfmt_misc has exactly one execution model where the regis

Merge patch series "binfmt_misc: transparent interpreters and PT_INTERP loader substitution"

Christian Brauner <brauner@kernel.org> says:

binfmt_misc has exactly one execution model where the registered
interpreter becomes the executed program and the matched binary is
handed to it as an argument. For wine or qemu-user that is the point.
For a per-binary loader it is backwards. The interpreter is an
implementation detail of running the binary, yet it owns the entire
process identity:

- argv[0] and /proc/pid/cmdline show the interpreter invocation, not
what the caller executed.

- /proc/self/exe names the interpreter. Relocatable programs commonly
locate themselves through it and find the dynamic linker instead.

- A binary passed to execveat() as an inaccessible O_CLOEXEC fd
cannot run at all as the interpreter has no path to open it by.

- gdb cross-validates AT_ENTRY/AT_PHDR against the exe file and
discards the load displacement on mismatch leaving PIE symbols
unrelocated.

This series adds two dispatch modes that close the gap from opposite
ends:

(1) transparent dispatch

Registered with the 'T' flag or chosen per exec with
BPF_BINPRM_TRANSPARENT. The binary is sent to the interpreter through
AT_EXECFD, the argument vector stays exactly as the caller built it,
and the kernel labels mm->exe_file and comm with the binary. A new
AT_FLAGS_TRANSPARENT_INTERP aux vector bit is raised indicating that
nothing was spliced, argv belongs to the program, and to load it from
the descriptor.

The interpreter keeps control of mapping the binary, so the mode
covers foreign architectures and non-ELF payloads.

The exe label is not a new privilege. It names precisely the file the
caller passed to execve(), not a file of the process's choosing. That
file is permission-checked, write-denied while the process runs and
recorded by audit. Credential derivation does not change exactly as
today.

(2) loader substitution

The kernel executes the matched binary natively as the main image
and substitutes the registered interpreter for the binary's
PT_INTERP. binfmt_misc functions as a PT_INTERP override. There is
no contract and no identity to reconstruct. So a stock dynamic
loader works unchanged. Hence, 'L' is for native-arch ELF with
PT_INTERP.

The two modes compose. A bpf handler reads the ELF header from bprm->buf
and grades per binary, picking 'L' where it applies and 'T' or classic
dispatch for the rest. If userspace control over relocation is wanted
'T' is the way to go.

* patches from https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-0-e57866e4ae0f@kernel.org: (21 commits)
binfmt_misc: document loader substitution
selftests/exec: test binfmt_misc loader substitution
binfmt_misc: let a bpf handler request loader substitution
binfmt_misc: add the 'L' loader substitution flag
binfmt_elf_fdpic: consume a stashed PT_INTERP substitute
binfmt_elf: consume a stashed PT_INTERP substitute
exec: carry a PT_INTERP substitute in struct linux_binprm
binfmt_misc: document the transparent identity contract
selftests/exec: test the transparent binfmt_misc mode
binfmt_misc: let a bpf handler run the interpreter transparently
binfmt_misc: add a static transparent flag 'T'
binfmt_misc: add transparent interpreter dispatch
exec: label mm->exe_file with the binary for a transparent dispatch
exec: add AT_FLAGS_TRANSPARENT_INTERP
selftests/exec: convert the binfmt_misc bpf test to the kselftest harness
exec: release the replaced file with do_close_execat()
binfmt_misc: split out entry_open_interpreter() and build_interp_argv()
binfmt_misc: normalize the per-exec invocation flags
binfmt_misc: table-drive the register string flags
docs, binfmt_misc: keep general usage out of the handler sections
...

Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-0-e57866e4ae0f@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...


# 87c50a58 21-Jul-2026 Christian Brauner <brauner@kernel.org>

selftests/exec: test binfmt_misc loader substitution

Exercise the 'L' flag end to end. The payload runs as the main image
with a copy of the system loader substituted for its PT_INTERP, and
asserts

selftests/exec: test binfmt_misc loader substitution

Exercise the 'L' flag end to end. The payload runs as the main image
with a copy of the system loader substituted for its PT_INTERP, and
asserts the native identity from inside:

- argv exactly as the caller built it
- no AT_EXECFD
- AT_FLAGS clear
- AT_BASE set but outside its own image
- AT_PHDR/AT_ENTRY inside it
- /proc/self/{exe,comm,stat} and AT_EXECFN all describing the binary
- ETXTBSY on the running binary
- the substituted loader visible in /proc/self/maps under its real path

Magic matching pokes a marker into the ELF header's e_ident padding
(EI_PAD, offset 9), which sits inside the match window and is ignored by
kernel and loader alike. the same binary is also matched by extension.

Two cases cover the paths where the substitution does not happen. A '#!'
file that matched an 'L' entry is claimed by binfmt_script rather than by
binfmt_elf, so the staged substitute has to be released when the
interpreter replaces the file; the test opens the loader for writing
afterwards, which fails with ETXTBSY if the write denial was leaked
instead. A relative interpreter path is rejected at registration for both
'L' and 'C', neither of which may resolve one against the working
directory of whoever runs the binary.

The bpf-side BPF_BINPRM_LOADER path shares all machinery past the flag
mapping. A harness case for it can join the bpf runtime coverage of
the transparent series.

Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-20-e57866e4ae0f@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...


# 7baee96f 21-Jul-2026 Christian Brauner <brauner@kernel.org>

selftests/exec: test the transparent binfmt_misc mode

Verify the identity a transparent dispatch constructs, from both
activation paths.

- binfmt_misc_transparent: registers a magic entry with the

selftests/exec: test the transparent binfmt_misc mode

Verify the identity a transparent dispatch constructs, from both
activation paths.

- binfmt_misc_transparent: registers a magic entry with the static 'T'
flag and execs a matched binary with arguments.

- binfmt_misc_bpf: a handler whose load program sets
BPF_BINPRM_TRANSPARENT.

Both dispatch to a shared asserting interpreter that runs in place of
the binary and checks the contract from the inside:

- AT_FLAGS carries AT_FLAGS_TRANSPARENT_INTERP
- AT_EXECFD refers to the very inode of the binary
- /proc/self/exe resolves to the binary
- argv and /proc/self/cmdline are exactly what the caller passed with
nothing spliced in
- comm is the binary's basename
- the binary is write-denied while it runs

The static test also validates the registration. 'T' combined with 'P'
must be rejected. A kernel that does not know 'T' turns the test into a
skip. The asserting interpreter and the static test build without the
bpf toolchain so the core transparent semantics stay covered on systems
where the bpf cases are skipped.

The flag support probe, the canonical payload argv with the
run_payload() helper that execs it, and the identity assertions (exe
link, comm, write denial) live in binfmt_misc_common.h; the loader
substitution test reuses all of them.

Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-13-e57866e4ae0f@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...


# 26860105 21-Jul-2026 Christian Brauner <brauner@kernel.org>

selftests/exec: convert the binfmt_misc bpf test to the kselftest harness

The test reports its own pass and fail lines, returns a bare 4 for
KSFT_SKIP and runs both cases in one process, so a failur

selftests/exec: convert the binfmt_misc bpf test to the kselftest harness

The test reports its own pass and fail lines, returns a bare 4 for
KSFT_SKIP and runs both cases in one process, so a failure in the first
takes the second with it. It also open-codes the register, unregister,
file-copy and mount helpers that the tests for the upcoming transparent
and loader dispatch modes need again.

Convert it to the kselftest harness: a fixture for the common setup and
teardown, one TEST_F per case so each is reported and isolated
separately, and SKIP() for the root, BTF and binfmt_misc preconditions.
Move the helpers to a shared header on the way, with the register
helper preserving the write's errno so a caller can tell a rejected
flag combination (EINVAL) from a kernel that does not know the flag at
all. The synthetic ELF header gains an e_machine argument and uses the
elf.h constants instead of open-coded numbers.

The fixture no longer mounts bpffs. The handler is attached with
bpf_map__attach_struct_ops() and nothing is ever pinned, the mount was
carried along from a bpftool-based draft. The bpf objects are compiled
with -DBPF_NO_KFUNC_PROTOTYPES - the guard bpftool emits for exactly
this - instead of sed'ing the prototypes out of the generated
vmlinux.h. And the config fragment records the options the binfmt_misc
tests need so a merge-config kernel can run them.

No change in what is tested.

Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-7-e57866e4ae0f@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

show more ...