Re: [PATCH 0/3] elf: load the main program from AT_EXECFD
"Andreas K. Huettel" <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Gentoo Linux |
| Message-ID | <[email protected]> |
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/@[email protected]/116918469134997346 [1] > Link: https://mastodon.social/deck/@brauner/116913310306668229 [2] > Signed-off-by: Christian Brauner (Amutable) <[email protected]> > --- > 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 [email protected] Gentoo Linux developer (council, comrel, toolchain, base-system, perl, libreoffice) https://wiki.gentoo.org/wiki/User:Dilfridge
signature.asc
(application/pgp-signature, 870 B)
-----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEE/Rnm0xsZLuTcY+rT3CsWIV7VQSoFAmpXd5IbFIAAAAAABAAO bWFudTIsMi41KzEuMTIsMiwyAAoJENwrFiFe1UEqvcEP/jpL8dsqrP+aCorMjmbe jd9k1IgybFBqbJh7kGjeGOYJRPh9WfhjaseEj3l/OXxC+/VHPLiWXrPF/zfeXIG2 Z9qH/kHC968dn2vTypEaFGQ3f/xQUBESi8fvQpwie/5/Wj6SLEN4/4bpurl+tjED zXAEAoVIYEutLU4r9isQJjD6X4AffsvOGruzu4wTrvPU19BBCOqNQ3IlHyoKCl7O LNCAosphK/GQq8PZ8XRDV6eJwpmKG51760qw5RSFuC5W/hvOBsKcqSiAzHvaWvQ6 5C8ABwjAZQRu1An2pQCqQQddl9FK2/pkLaO4jbo++NnqvewwrtyzHQVnZnY4t0hR peNLy5o6qLgc0DkDvbP7vy3p7rF5ZB1nQ9bKLiojtZhckysb0TdmPqJQxkREotCA OxquN6k6ChKRjQghBgPoPZdlFDCvDdiwqBRqjzT/KMpbPEvANA7+Uz5BxhNEA2Wn +QUTIgmljDVp0Uq767oT23DjMIfT9w8pYdKoJW8Prl74ZRVbOnNaJnyIg72PkDgE SGPuDbVis4YR62M9yGmlZFp4l6bvv6tllT+kxPPKD68ymxgJ7WHFmAKZWofZazEC eosXgrTCJqEieJk//fY1lzw7cItW1BuhWmnieOZrvdj5TR/XkGHRYinkwGjxfRfn HEw9eqYMMl2i3Ffd0WdVqKk6 =XkO1 -----END PGP SIGNATURE-----