[PATCH 0/3] elf: load the main program from AT_EXECFD

Andreas K. Huettel dilfridge@gentoo.org
Wed Jul 15 12:05:38 GMT 2026


Am Mittwoch, 15. Juli 2026, 19:13:02 Japanische Normalzeit schrieb Christian Brauner:
> A Linux binfmt_misc handler can dispatch a program to a chosen dynamic
> linker.  This is how you run a program under a different or newer ld.so.
> When the handler is registered with the 'O' (open binary) or 'C'
> (credentials) flag, the kernel keeps the executed file open across the
> dispatch.  It hands the descriptor to the interpreter in the AT_EXECFD
> auxiliary vector entry.  This is the SVR4 contract.  AT_EXECFD is "the
> file descriptor of the program to load", the alternative to AT_PHDR.
> FreeBSD's rtld consumes it, and qemu-user has consumed it since 2013.
> 
> The GNU dynamic linker never has.  When such a handler dispatches to
> ld.so, the descriptor is ignored.  It leaks into the new program.  ld.so
> opens the executable again, this time by the path spliced into the
> argument vector.

No matter where this discussion goes, it's post-release material.

> 
> Opening the file again by path is racy, and often it is not possible at
> all.  The file ld.so opens need not be the file the kernel checked and
> executed.  A binary with execute permission but no read permission can be
> run by execve().  It cannot be opened for reading by path, so ld.so
> rejects it with EACCES, even though the descriptor it was handed is
> readable.  Sometimes there is no path to open.  The program may be a
> sealed memfd.
> 
> As Carlos said in [1] "I like where this is going because you can run
> ld.so to execute an isolated AT_EXECFD application." which is a good way
> to think about this.
> 
> Also, nixos wants to use binfmt_misc to execute elf binaries and will be
> invoking the loader this way.  I also have a use-case for this in
> systemd-homed in the future and I'm extending the abilities of
> binfmt_misc a bit.  So I would really appreciate if we could support
> this in the glibc loader.
> 
> This series makes ld.so load the main program from AT_EXECFD when ld.so
> is the program the kernel loaded.  The object comes from the descriptor,
> not from a path opened a second time.  The loaded file is exactly the one
> execve() checked, so there is no race.  A binary with no read permission
> runs.  A program with no accessible path runs.  Applications see no
> difference.  The argument vector they observe is the same as for a direct
> execution.  No kernel changes are needed.  The binfmt_misc 'O' and 'C'
> flags have been around for a long time.  This works against current
> kernels.
> 
> The series also adds the option "ld.so --program-fd N NAME".  This is the
> explicit counterpart to AT_EXECFD, and FreeBSD's ld-elf.so.1 spells it
> -f.  It lets a program run from an inherited descriptor, such as a sealed
> memfd, with no kernel dispatch at all.
> 
> Tested on x86_64.  tst-rtld-program-fd exercises the descriptor loading
> path on its own, with no kernel support needed.  tst-rtld-execfd drives
> the whole path through a real binfmt_misc handler in a private user and
> mount namespace.  That test needs Linux 6.7 or newer and reports
> UNSUPPORTED otherwise.  It covers the case of a binary with no read
> permission.
> 
> I've discussed this on mastodon in [2] with Carlos a little bit a couple
> of days ago.
> 
> An LLM was used to get familiar with this particular part of the glibc
> codebase and for review of the implementation. It's been a while so I
> hope I still got the gist of contributions right.
> 
> Link: https://mastodon.social/deck/@codonell@fosstodon.org/116918469134997346 [1]
> Link: https://mastodon.social/deck/@brauner/116913310306668229 [2]
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
> ---
> Christian Brauner (3):
>       elf: load the main program from AT_EXECFD when run as a binfmt interpreter
>       elf: test AT_EXECFD consumption through a binfmt_misc 'O' handler
>       elf: add ld.so --program-fd
> 
>  NEWS                                           |  15 ++
>  elf/Makefile                                   |   4 +
>  elf/dl-load.c                                  |  50 +++++
>  elf/dl-usage.c                                 |   2 +
>  elf/rtld.c                                     | 166 ++++++++++++++-
>  elf/tst-rtld-program-fd-prog.c                 |  28 +++
>  elf/tst-rtld-program-fd.c                      | 126 +++++++++++
>  sysdeps/generic/ldsodefs.h                     |   7 +
>  sysdeps/unix/sysv/linux/Makefile               |   5 +
>  sysdeps/unix/sysv/linux/tst-rtld-execfd-prog.c |  43 ++++
>  sysdeps/unix/sysv/linux/tst-rtld-execfd.c      | 282 +++++++++++++++++++++++++
>  11 files changed, 719 insertions(+), 9 deletions(-)
> ---
> base-commit: 5396eb704531d9ede0388bffcc21b93bb661d404
> change-id: 20260715-work-glibc-binfmt_misc-939266ac4824
> 
> 


-- 
PD Dr. Andreas K. Hüttel
dilfridge@gentoo.org
Gentoo Linux developer 
(council, comrel, toolchain, base-system, perl, libreoffice)
https://wiki.gentoo.org/wiki/User:Dilfridge
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 870 bytes
Desc: This is a digitally signed message part.
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260715/65ee27f3/attachment.sig>


More information about the Libc-alpha mailing list