[PATCH 0/9] binfmt_misc: bind interpreters to a bpf-backed entry

Christian Brauner <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.bpf,org.kvack.linux-mm
Message-ID <[email protected]>
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.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
Christian Brauner (9):
      binfmt_misc: let a register string create an entry disabled
      selftests/exec: let binfmt_flag_supported() return a bool
      selftests/exec: test registering an entry disabled
      binfmt_misc: document registering an entry disabled
      selftests/exec: share the bpf handler preconditions
      binfmt_misc: carry pre-opened interpreters in struct binfmt_misc_interp
      binfmt_misc: let a 'B' entry bind its interpreters
      selftests/exec: test interpreters bound to a 'B' entry
      binfmt_misc: document interpreters bound by a 'B' entry

 Documentation/admin-guide/binfmt-misc.rst          |  75 +++-
 fs/binfmt_misc.c                                   | 459 +++++++++++++++++----
 fs/binfmt_misc_bpf.c                               |  75 +++-
 fs/exec.c                                          |   2 +
 include/linux/binfmt_misc.h                        |  39 +-
 include/linux/binfmts.h                            |   3 +
 tools/testing/selftests/exec/Makefile              |  11 +-
 tools/testing/selftests/exec/binfmt_bind_interp.c  |  14 +
 tools/testing/selftests/exec/binfmt_misc_bpf.c     | 306 ++++++++++++--
 tools/testing/selftests/exec/binfmt_misc_common.h  |  45 +-
 .../testing/selftests/exec/binfmt_misc_disabled.c  | 172 ++++++++
 .../selftests/exec/binfmt_misc_transparent.c       |   2 +-
 tools/testing/selftests/exec/interp_bind.bpf.c     |  76 ++++
 13 files changed, 1164 insertions(+), 115 deletions(-)
---
base-commit: 4bdcf682a476e8d9f52b2c5c01e998d70e45656c
change-id: 20260729-work-binfmt_misc-preopen-9653fb9d1d04
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.