From: Christian Brauner Date: Tue, 21 Jul 2026 14:14:03 +0000 (+0200) Subject: binfmt_misc: document loader substitution X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=bf9008534ed0faa220cfc44a9fc6d8b9f1317b74;p=thirdparty%2Flinux.git binfmt_misc: document loader substitution Describe the L mode next to the transparent one. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-21-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) --- diff --git a/Documentation/admin-guide/binfmt-misc.rst b/Documentation/admin-guide/binfmt-misc.rst index 03c6806785f5..27391fcb43fa 100644 --- a/Documentation/admin-guide/binfmt-misc.rst +++ b/Documentation/admin-guide/binfmt-misc.rst @@ -260,6 +260,53 @@ direct execution is the address space layout. The interpreter occupies the main-image position and the program lives in the mmap region. +Loader substitution +------------------- + +The ``L`` flag turns the execution model around. Instead of running the +registered interpreter with the binary as its payload the kernel loads +the matched binary itself as the main image and substitutes the registered +interpreter for the loader named in the binary's ``PT_INTERP``. + +Because the exec is native, there is no dispatch identity to +reconstruct and no contract the substitute has to implement. A stock +dynamic loader works unchanged. The argument vector is untouched, +credentials and ``AT_SECURE`` derive from the binary, there is no +``AT_EXECFD`` and no marker in the aux vector, the binary sits in the +main-image slot with the native brk placement so ``/proc/pid/maps``, +core dumps and perf mmap records have the native shape, and the +identity is already complete when ``PTRACE_EVENT_EXEC`` stops the +tracee. So launching under a debugger works, not just attaching. ``L`` +entries are for ELF binaries of a native architecture. Foreign-arch +emulation and non-ELF payloads remain the domain of the classic and +transparent modes. + +The override applies when the format that finally claims the file is +ELF with a ``PT_INTERP``. A matched binary without one or an +interpreter-less ``ET_DYN`` drops the override and runs natively. A file +claimed by another format - a ``#!`` script, say - is handled by that +format as if the entry had not matched. ``L`` is therefore not an +enforcement mechanism: it decides how a binary that asks for a loader is +run, it does not guarantee that everything matching the entry runs under +the substitute. A format that cannot consume the override at all instead +refuses the exec with ``ENOEXEC`` before the point of no return. + +A wrong-architecture ELF fails the whole exec with ``ENOEXEC`` exactly +as if no entry had matched. A substitute that is not ELF of the right +architecture fails with ``ELIBBAD``. The usual ``PT_INTERP`` sanity +checks on the binary still apply. But the segment's content is otherwise +irrelevant. + +``L`` rejects the classic-dispatch flags ``T``, ``P``, ``O`` and ``C`` +at registration. ``F`` composes and is valuable: with it the substitute +is opened at registration time, so later mount namespace or path changes +cannot redirect it. Without it the substitute is opened when the binary +is executed, and the path is resolved in the mount namespace and root of +whoever runs the binary, which is why it has to be absolute. As with +``C``, register only trusted interpreters. The substituted loader runs +with credentials derived from the binary. + + Hints -----