mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
Add the bpf plumbing for binary type handlers whose matching and
interpreter selection are implemented by bpf programs instead of a
fixed magic/extension and a fixed interpreter string recorded at
registration time. This serves relocatable binary formats where the
interpreter must be computed per binary, e.g. relative to the location
of the binary itself, as discussed for hermetic Nix-style executables.
A handler is an instance of the new binfmt_misc_ops struct_ops with a
name that binfmt_misc entries reference it by and two ops:
bool (*match)(struct linux_binprm *bprm);
int (*load)(struct linux_binprm *bprm);
struct_ops is the sanctioned mechanism for this kind of user-supplied
policy callback: program types, attach types, and the uapi helper list
are frozen, and every recently added subsystem hook (bpf qdisc, SMC
handshake control, io_uring loop ops, sched_ext) is a struct_ops user.
The ops receive the bprm as a trusted BTF pointer, so a program can
match on the header in bprm->buf, read arbitrary file content via
bpf_dynptr_from_file() to parse e.g. ELF program headers, and inspect
the binary's location. No dedicated program type, ctx blob, or uapi
helper is needed.
The two ops split along what they decide, not what they may do: the
match program decides whether the handler applies to a binary, the
load program decides how a matched binary is run. Both are required
to be sleepable. Matching cannot be limited to the prefetched 256
bytes in bprm->buf: deciding whether a handler applies takes e.g.
parsing the ELF program headers to find an interpreter segment, which
sits at an arbitrary file offset, and non-sleepable file reads are
limited to whatever happens to be resident in the page cache. A match
program that cannot read the file reliably would have to match
broadly and leave the rejection to its load program, which breaks
first-match-wins entry semantics the moment more than one handler is
registered. Reliable file reads at exec time fault in the file's
pages, so both ops must be able to sleep. This also constrains the
caller: binfmt_misc must invoke both from sleepable context, which a
later patch takes care of. Both ops are required; a handler that
wants to decide everything from the load program supplies a match
program that just returns true.
The load program communicates its decisions through three new kfuncs:
int bpf_binprm_set_interp(struct linux_binprm *bprm,
const char *path, size_t path__sz);
selects the interpreter and enforces an absolute path shorter than
PATH_MAX.
int bpf_binprm_set_interp_arg(struct linux_binprm *bprm,
const char *arg, size_t arg__sz);
passes a single optional argument to the interpreter, mirroring the
optional argument of a #! interpreter line - something a static entry
cannot express at all.
int bpf_binprm_set_flags(struct linux_binprm *bprm,
enum bpf_binprm_flags flags);
chooses the invocation flags for this exec, with
BPF_BINPRM_PRESERVE_ARGV0, BPF_BINPRM_CREDENTIALS and
BPF_BINPRM_EXECFD mapping to 'P', 'C' and 'O'. Unknown bits are
rejected so a program built against a newer kernel fails loudly on an
older one rather than silently losing a flag. Repeated calls replace
the staged flags and a zero argument clears them again - the
set-or-clear semantics of bpf_bprm_opts_set() on the same struct. A
flags word carries this better than a kfunc per flag: it is one call,
it is set atomically, and new behaviour is a new bit rather than new
surface - the same shape the register string's flags field already
has.
All three stage their result in the bprm; consuming it from
load_misc_binary() is wired up by the following patches. The bprm is
exclusively owned by the task doing the exec, so no shared or per-CPU
state is involved and nothing here can race. The kfuncs are registered
for struct_ops programs with a filter that limits them to the load
program of a binfmt_misc_ops instance, keyed off the struct_ops member
offset the program attaches to: match decides whether a handler
applies, load decides how the binary is run, and the verifier enforces
that split at program load time.
Registering an ops instance (updating the struct_ops map or attaching
its link) publishes the handler under its name in a registry keyed by
the registering task's user namespace. Lookups do not walk that
hierarchy: a handler is only visible in the user namespace it was
registered in, so an entry can only reference a handler registered in
the same user namespace as its binfmt_misc instance. Consumers take a
reference on the ops via bpf_struct_ops_get() which pins the underlying
map and programs, so an activated handler keeps working even if the map
is deleted or the registering container goes away; deregistration only
prevents new activations, exactly like unregistering a tcp congestion
ops with live users.
Link: https://lore.kernel.org/20260704211409.1978485-1-farid.m.zakaria@gmail.com
Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-2-57b7529c002c@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
211 lines
7.3 KiB
Plaintext
211 lines
7.3 KiB
Plaintext
# SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
menu "Executable file formats"
|
|
|
|
config BINFMT_ELF
|
|
bool "Kernel support for ELF binaries"
|
|
depends on MMU
|
|
select ELFCORE
|
|
default y
|
|
help
|
|
ELF (Executable and Linkable Format) is a format for libraries and
|
|
executables used across different architectures and operating
|
|
systems. Saying Y here will enable your kernel to run ELF binaries
|
|
and enlarge it by about 13 KB. ELF support under Linux has now all
|
|
but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
|
|
because it is portable (this does *not* mean that you will be able
|
|
to run executables from different architectures or operating systems
|
|
however) and makes building run-time libraries very easy. Many new
|
|
executables are distributed solely in ELF format. You definitely
|
|
want to say Y here.
|
|
|
|
Information about ELF is contained in the ELF HOWTO available from
|
|
<http://www.tldp.org/docs.html#howto>.
|
|
|
|
If you find that after upgrading from Linux kernel 1.2 and saying Y
|
|
here, you still can't run any ELF binaries (they just crash), then
|
|
you'll have to install the newest ELF runtime libraries, including
|
|
ld.so (check the file <file:Documentation/Changes> for location and
|
|
latest version).
|
|
|
|
config BINFMT_ELF_KUNIT_TEST
|
|
bool "Build KUnit tests for ELF binary support" if !KUNIT_ALL_TESTS
|
|
depends on KUNIT=y && BINFMT_ELF=y
|
|
default KUNIT_ALL_TESTS
|
|
help
|
|
This builds the ELF loader KUnit tests, which try to gather
|
|
prior bug fixes into a regression test collection. This is really
|
|
only needed for debugging. Note that with CONFIG_COMPAT=y, the
|
|
compat_binfmt_elf KUnit test is also created.
|
|
|
|
config COMPAT_BINFMT_ELF
|
|
def_bool y
|
|
depends on COMPAT && BINFMT_ELF
|
|
select ELFCORE
|
|
|
|
config ARCH_BINFMT_ELF_STATE
|
|
bool
|
|
|
|
config ARCH_BINFMT_ELF_EXTRA_PHDRS
|
|
bool
|
|
|
|
config ARCH_HAVE_ELF_PROT
|
|
bool
|
|
|
|
config ARCH_USE_GNU_PROPERTY
|
|
bool
|
|
|
|
config BINFMT_ELF_FDPIC
|
|
bool "Kernel support for FDPIC ELF binaries"
|
|
default y if !BINFMT_ELF
|
|
depends on ARM || ((M68K || RISCV || SUPERH || XTENSA) && !MMU)
|
|
select ELFCORE
|
|
help
|
|
ELF FDPIC binaries are based on ELF, but allow the individual load
|
|
segments of a binary to be located in memory independently of each
|
|
other. This makes this format ideal for use in environments where no
|
|
MMU is available as it still permits text segments to be shared,
|
|
even if data segments are not.
|
|
|
|
It is also possible to run FDPIC ELF binaries on MMU linux also.
|
|
|
|
config ELFCORE
|
|
bool
|
|
help
|
|
This option enables kernel/elfcore.o.
|
|
|
|
config CORE_DUMP_DEFAULT_ELF_HEADERS
|
|
bool "Write ELF core dumps with partial segments"
|
|
default y
|
|
depends on BINFMT_ELF && ELF_CORE
|
|
help
|
|
ELF core dump files describe each memory mapping of the crashed
|
|
process, and can contain or omit the memory contents of each one.
|
|
The contents of an unmodified text mapping are omitted by default.
|
|
|
|
For an unmodified text mapping of an ELF object, including just
|
|
the first page of the file in a core dump makes it possible to
|
|
identify the build ID bits in the file, without paying the i/o
|
|
cost and disk space to dump all the text. However, versions of
|
|
GDB before 6.7 are confused by ELF core dump files in this format.
|
|
|
|
The core dump behavior can be controlled per process using
|
|
the /proc/PID/coredump_filter pseudo-file; this setting is
|
|
inherited. See Documentation/filesystems/proc.rst for details.
|
|
|
|
This config option changes the default setting of coredump_filter
|
|
seen at boot time. If unsure, say Y.
|
|
|
|
config BINFMT_SCRIPT
|
|
tristate "Kernel support for scripts starting with #!"
|
|
default y
|
|
help
|
|
Say Y here if you want to execute interpreted scripts starting with
|
|
#! followed by the path to an interpreter.
|
|
|
|
You can build this support as a module; however, until that module
|
|
gets loaded, you cannot run scripts. Thus, if you want to load this
|
|
module from an initramfs, the portion of the initramfs before loading
|
|
this module must consist of compiled binaries only.
|
|
|
|
Most systems will not boot if you say M or N here. If unsure, say Y.
|
|
|
|
config ARCH_HAS_BINFMT_FLAT
|
|
bool
|
|
|
|
config BINFMT_FLAT
|
|
bool "Kernel support for flat binaries"
|
|
depends on ARCH_HAS_BINFMT_FLAT
|
|
help
|
|
Support uClinux FLAT format binaries.
|
|
|
|
config BINFMT_FLAT_ARGVP_ENVP_ON_STACK
|
|
bool
|
|
|
|
config BINFMT_FLAT_OLD_ALWAYS_RAM
|
|
bool
|
|
|
|
config BINFMT_FLAT_NO_DATA_START_OFFSET
|
|
bool
|
|
|
|
config BINFMT_FLAT_OLD
|
|
bool "Enable support for very old legacy flat binaries"
|
|
depends on BINFMT_FLAT
|
|
help
|
|
Support decade old uClinux FLAT format binaries. Unless you know
|
|
you have some of those say N here.
|
|
|
|
config BINFMT_ZFLAT
|
|
bool "Enable ZFLAT support"
|
|
depends on BINFMT_FLAT
|
|
select ZLIB_INFLATE
|
|
help
|
|
Support FLAT format compressed binaries
|
|
|
|
config BINFMT_MISC
|
|
tristate "Kernel support for MISC binaries"
|
|
help
|
|
If you say Y here, it will be possible to plug wrapper-driven binary
|
|
formats into the kernel. You will like this especially when you use
|
|
programs that need an interpreter to run like Java, Python, .NET or
|
|
Emacs-Lisp. It's also useful if you often run DOS executables under
|
|
the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
|
|
<http://www.tldp.org/docs.html#howto>). Once you have
|
|
registered such a binary class with the kernel, you can start one of
|
|
those programs simply by typing in its name at a shell prompt; Linux
|
|
will automatically feed it to the correct interpreter.
|
|
|
|
You can do other nice things, too. Read the file
|
|
<file:Documentation/admin-guide/binfmt-misc.rst> to learn how to use this
|
|
feature, <file:Documentation/admin-guide/java.rst> for information about how
|
|
to include Java support. and <file:Documentation/admin-guide/mono.rst> for
|
|
information about how to include Mono-based .NET support.
|
|
|
|
To use binfmt_misc, you will need to mount it:
|
|
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
|
|
|
You may say M here for module support and later load the module when
|
|
you have use for it; the module is called binfmt_misc. If you
|
|
don't know what to answer at this point, say Y.
|
|
|
|
config BINFMT_MISC_BPF
|
|
bool "BPF-selected interpreters for misc binaries"
|
|
depends on BINFMT_MISC=y
|
|
depends on BPF_SYSCALL && BPF_JIT && DEBUG_INFO_BTF
|
|
help
|
|
Allow binfmt_misc binary type handlers to be implemented as bpf
|
|
struct_ops programs. Instead of matching a fixed magic and
|
|
redirecting to a fixed interpreter recorded at registration time
|
|
such handlers match binaries programmatically and compute the
|
|
interpreter to use per binary, e.g. relative to the location of
|
|
the binary itself.
|
|
|
|
If you don't know what to answer at this point, say N.
|
|
|
|
config COREDUMP
|
|
bool "Enable core dump support" if EXPERT
|
|
default y
|
|
help
|
|
This option enables support for performing core dumps. You almost
|
|
certainly want to say Y here. Not necessary on systems that never
|
|
need debugging or only ever run flawless code.
|
|
|
|
config EXEC_KUNIT_TEST
|
|
bool "Build execve tests" if !KUNIT_ALL_TESTS
|
|
depends on KUNIT=y
|
|
default KUNIT_ALL_TESTS
|
|
help
|
|
This builds the exec KUnit tests, which tests boundary conditions
|
|
of various aspects of the exec internals.
|
|
|
|
config ARCH_HAS_ELF_CORE_EFLAGS
|
|
bool
|
|
depends on BINFMT_ELF && ELF_CORE
|
|
default n
|
|
help
|
|
Select this option if the architecture makes use of the e_flags
|
|
field in the ELF header to store ABI or other architecture-specific
|
|
information that should be preserved in core dumps.
|
|
|
|
endmenu
|