History log of /linux/tools/testing/selftests/exec/binfmt_misc_interplimit.c (Results 1 – 3 of 3)
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
# 68aabd01 03-Aug-2026 Christian Brauner <brauner@kernel.org>

Merge patch series "binfmt_misc: bound the interpreters an entry can pre-open"

Christian Brauner <brauner@kernel.org> says:

An 'F' entry opens its interpreter at registration and every exec runs a

Merge patch series "binfmt_misc: bound the interpreters an entry can pre-open"

Christian Brauner <brauner@kernel.org> says:

An 'F' entry opens its interpreter at registration and every exec runs a
clone of it. A 'B' entry does the same for each interpreter it binds. That
file stays open for as long as the entry lives. So it pins the file, its
inode, the mount it came from and that mount's superblock.

An entry binds at most 100 interpreters, but nothing caps the entries.
binfmt_misc is container mountable so all of this is reachable by
unprivileged users.

While the pins go away when the instance is unmounted, it's still weird
for an unprivileged namespace to be allowed to do this. And the fix is
simple.

Charge each binding to the user namespace and uid that makes it against
a new UCOUNT_BINFMT_MISC_INTERPRETERS and refuse with -ENOSPC when the
limit is hit.

A per-instance cap won't do. Instances are keyed on the user namespace, so
whatever constant I pick gets multiplied by however many namespaces the
caller cares to create. inc_ucount() charges the namespace and every one
of its ancestors, and a namespace can only ever raise its own limit, so
nesting buys nothing.

The knob is /proc/sys/user/max_binfmt_misc_interpreters, per namespace like
every other ucount. I left it at the max_threads/2 default that
fork_init() hands a new ucount type. Nothing anyone runs today comes
anywhere near that.

Selftests for all of it, including that a nested namespace can't buy
itself budget.

* patches from https://patch.msgid.link/20260803-work-binfmt_misc-interplimit-v1-0-4a2435500bd9@kernel.org:
binfmt_misc: document the pre-opened interpreter limit
selftests/exec: test the pre-opened interpreter limit
binfmt_misc: correctly account pre-opened interpreters

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

show more ...


# 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 ...