| f2b69ea2 | 03-Aug-2026 |
Christian Brauner <brauner@kernel.org> |
selftests/exec: test the pre-opened interpreter limit
- an interpreter opened at registration is charged - an interpreter a 'B' entry binds is charged too - an entry that opens none is not - removin
selftests/exec: test the pre-opened interpreter limit
- an interpreter opened at registration is charged - an interpreter a 'B' entry binds is charged too - an entry that opens none is not - removing an entry gives the charge back - a nested user namespace cannot buy itself budget by raising its own limit
Skips where the sysctl or binfmt_misc is missing. The 'B' case lives in binfmt_misc_bpf.c because binding needs a handler. It binds from a child in a user namespace of its own, through the fd the child inherited, so the charge lands on the child while the interpreter is still opened with the entry file's credentials, and nothing outside the child sees a changed limit.
Link: https://patch.msgid.link/20260803-work-binfmt_misc-interplimit-v1-2-4a2435500bd9@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
show more ...
|
| 7404b147 | 30-Jul-2026 |
Christian Brauner <brauner@kernel.org> |
selftests/exec: test interpreters bound to a 'B' entry
One handler, one entry registered disabled, an interpreter per guest architecture bound to a file one write at a time. The load program picks o
selftests/exec: test interpreters bound to a 'B' entry
One handler, one entry registered disabled, an interpreter per guest architecture bound to a file one write at a time. The load program picks one by name per exec:
- an aarch64 binary runs the interpreter bound as "first" and a riscv one the interpreter bound as "second", from a single entry and a single handler
- unlinking a bound interpreter and putting a different binary in its place changes nothing, which is what the binding exists for
- the entry reports what it bound, under the names it bound them as
- a name the entry did not bind fails the exec with -ENOENT rather than falling back to anything
- activating the entry refuses further binding with -EBUSY, a later disable does not undo that, and an entry registered without 'D' never accepted a '+' write to begin with
- a name binds one interpreter, and control characters are refused
- the command has to end at the write, bytes past an embedded nul are refused
- an entry binds at most 100 interpreters, the next one is refused with -ENOSPC
The test interpreter prints its argv[0], which is the path the kernel ran that copy under, so one binary installed at two paths tells the harness which of them the program picked.
Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-8-4a0b0da71f16@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
show more ...
|
| 145e675d | 30-Jul-2026 |
Christian Brauner <brauner@kernel.org> |
selftests/exec: share the bpf handler preconditions
The bpf handler fixture opens with three probes, each with its own SKIP. More fixtures with the same needs are about to be added, so hoist the pro
selftests/exec: share the bpf handler preconditions
The bpf handler fixture opens with three probes, each with its own SKIP. More fixtures with the same needs are about to be added, so hoist the probes into a helper that reports the first missing precondition.
Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-5-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 ...
|
| 25757bc8 | 28-Jul-2026 |
Christian Brauner <brauner@kernel.org> |
selftests/exec: check that a binfmt_misc instance cannot be pinned
An 'F' entry whose interpreter keeps the binfmt_misc superblock alive pins the instance that owns it forever. Cover both ways to bu
selftests/exec: check that a binfmt_misc instance cannot be pinned
An 'F' entry whose interpreter keeps the binfmt_misc superblock alive pins the instance that owns it forever. Cover both ways to build that:
- an interpreter on the instance's own files, control file and entry file alike
- and an instance used as an overlayfs lower layer.
Check that an ordinary 'F' registration still succeeds so the fix stays honest about not changing what 'F' promises.
Link: https://patch.msgid.link/20260728-work-binfmt_misc-selfpin-v1-2-74df5daeca5b@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 ...
|
| 2a69962b | 12-Dec-2024 |
Mickaël Salaün <mic@digikod.net> |
samples/check-exec: Add an enlighten "inc" interpreter and 28 tests
Add a very simple script interpreter called "inc" that can evaluate two different commands (one per line): - "?" to initialize a c
samples/check-exec: Add an enlighten "inc" interpreter and 28 tests
Add a very simple script interpreter called "inc" that can evaluate two different commands (one per line): - "?" to initialize a counter from user's input; - "+" to increment the counter (which is set to 0 by default).
It is enlighten to only interpret executable files according to AT_EXECVE_CHECK and the related securebits:
# Executing a script with RESTRICT_FILE is only allowed if the script # is executable: ./set-exec -f -- ./inc script-exec.inc # Allowed ./set-exec -f -- ./inc script-noexec.inc # Denied
# Executing stdin with DENY_INTERACTIVE is only allowed if stdin is an # executable regular file: ./set-exec -i -- ./inc -i < script-exec.inc # Allowed ./set-exec -i -- ./inc -i < script-noexec.inc # Denied
# However, a pipe is not executable and it is then denied: cat script-noexec.inc | ./set-exec -i -- ./inc -i # Denied
# Executing raw data (e.g. command argument) with DENY_INTERACTIVE is # always denied. ./set-exec -i -- ./inc -c "+" # Denied ./inc -c "$(<script-ask.inc)" # Allowed
# To directly execute a script, we can update $PATH (used by `env`): PATH="${PATH}:." ./script-exec.inc
# To execute several commands passed as argument:
Add a complete test suite to check the script interpreter against all possible execution cases:
make TARGETS=exec kselftest-install ./tools/testing/selftests/kselftest_install/run_kselftest.sh
Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Cc: Kees Cook <keescook@chromium.org> Cc: Paul Moore <paul@paul-moore.com> Cc: Serge Hallyn <serge@hallyn.com> Signed-off-by: Mickaël Salaün <mic@digikod.net> Link: https://lore.kernel.org/r/20241212174223.389435-8-mic@digikod.net Signed-off-by: Kees Cook <kees@kernel.org>
show more ...
|
| 3545deff | 08-May-2024 |
Kees Cook <kees@kernel.org> |
binfmt_elf: Honor PT_LOAD alignment for static PIE
The p_align values in PT_LOAD were ignored for static PIE executables (i.e. ET_DYN without PT_INTERP). This is because there is no way to request a
binfmt_elf: Honor PT_LOAD alignment for static PIE
The p_align values in PT_LOAD were ignored for static PIE executables (i.e. ET_DYN without PT_INTERP). This is because there is no way to request a non-fixed mmap region with a specific alignment. ET_DYN with PT_INTERP uses a separate base address (ELF_ET_DYN_BASE) and binfmt_elf performs the ASLR itself, which means it can also apply alignment. For the mmap region, the address selection happens deep within the vm_mmap() implementation (when the requested address is 0).
The earlier attempt to implement this:
commit 9630f0d60fec ("fs/binfmt_elf: use PT_LOAD p_align values for static PIE") commit 925346c129da ("fs/binfmt_elf: fix PT_LOAD p_align values for loaders")
did not take into account the different base address origins, and were eventually reverted:
aeb7923733d1 ("revert "fs/binfmt_elf: use PT_LOAD p_align values for static PIE"")
In order to get the correct alignment from an mmap base, binfmt_elf must perform a 0-address load first, then tear down the mapping and perform alignment on the resulting address. Since this is slightly more overhead, only do this when it is needed (i.e. the alignment is not the default ELF alignment). This does, however, have the benefit of being able to use MAP_FIXED_NOREPLACE, to avoid potential collisions.
With this fixed, enable the static PIE self tests again.
Reported-by: H.J. Lu <hjl.tools@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=215275 Link: https://lore.kernel.org/r/20240508173149.677910-3-keescook@chromium.org Signed-off-by: Kees Cook <kees@kernel.org>
show more ...
|