Re: [BUG] Landlock denies LANDLOCK_ACCESS_FS_EXECUTE despite a correctly-anchored PathBeneath rule (contradicts selftest layout1.execute)

Ken Grimes <[email protected]> Thu, 16 Jul 2026 20:14:55 +0000
Newsgroups org.kernel.vger.linux-security-module,dev.linux.lists.landlock
Message-ID <kDUhcqAqpOGRVoTEYarGa-jMnCbwREPlvCWcJ8gmPH7wZ8CHdDWEJ-nL8j0LnjiffeNtG9_kE0XjRsUZ-hHfXZA0m1zpdTofgNXTcqMqBRs=@kengrimes.com>
Thanks so much Günther & Mickaël for the fast and thorough responses, it's very appreciated!

Günther, that's exactly what I found. I went down the path of 2; file-scoped LANDLOCK_ACCESS_FS_EXECUTE grant on dynamic loader, discovered at runtime since the loader's path varies across distros (/lib64/ld-linux-x86-64.so.2 here, but that's obviously not portable).

The fix resolves the target binary's PT_INTERP entry from ELF headers, then runs the interpreter in its own --list mode (invoked in a privilege-dropped, sandboxed child) to get the full shared-object closure. Not just the loader itself, but the DT_NEEDED dependencies (/etc/ld.so.cache and /etc/ld.so.preload) when present. I grant Execute|ReadFile on the interpreter and ReadFile on everything else, each file-scoped instead of directory wide, so not opening up all of /lib64. Just the files the loader will actually touch for the binary. I reproduced the failure standalone first (execveat under a single rule landlock domain, EACCESS, adding the loader's file as a second rule) before building the real fix, so I feel confident this is what you're describing.

Regarding the docs, yes please do add a note about this to LANDLOCK_ACCESS_FS_EXECUTE docs! That would have definitely saved a decent amount of effort, and I could see others running into the same issue.

Mickaël, thank you! I hadn't looked into the audit log support closely, I'll be sure to use this instead of building standalone reproductions, very helpful!

Thanks again for the help and all the great work you do.

-Ken


On Thursday, July 16th, 2026 at 2:37 AM, Mickaël Salaün <[email protected]> wrote:

> Hi!
> 

> You should also get a look at the audit logs:
> https://docs.kernel.org/admin-guide/LSM/landlock.html#audit
> 

>  Mickaël
> 

> On Wed, Jul 15, 2026 at 10:39:29AM +0200, Günther Noack wrote:
> > Hello Ken!
> >
> > (Also adding [email protected] to CC)
> >
> > On Tue, Jul 14, 2026 at 09:07:56PM +0000, Ken Grimes wrote:
> > > Hey all, this is my first bug report for linux. The issue was discovered 

> > > alongside llm-assisted coding on a downstream project. The 

> > > investigation/testing of the bug was a mostly manual process so I could 

> > > be sure this was something real. Please let me know if I can provide any
> > > further details or assistance. Hope this is helpful, thank you for all of your
> > > hard work!
> >
> > Welcome and thanks for reporting your first issue!
> >
> > I believe the issue you are observing is that the /bin/true program you are
> > starting is a dynamically linked executable.  As such, executing it requires
> > both the LANDLOCK_ACCESS_FS_EXECUTE right on the binary itself and on
> > the system's dynamic loader binary, which usually lives in /lib/ld-linux.so.*
> > (but there are symlinks and 32/64-bit differences at play as well, which
> > influence the actual final location).
> >
> > You can try this out with the following experiments:
> >
> > (1) Compile a "true" program statically and try using that:
> >
> >     $ echo 'int main() { return 0; }' > true.c
> >     $ CFLAGS=-static make true
> >
> >     This can be started with the test you have,
> >     unlike the dynamically linked version.
> >
> > (2) Alternatively, add execute permissions for the dynamic loader:
> >
> >     Add an additional "path beneath" rule that allow-lists the execution
> >     access right on /lib/ld-linux.so.2, /lib64/ld-linux-x86-64.so.2 or
> >     wherever else your dynamic loader is.  (You can discover the actual
> >     location using "ldd /bin/true".)
> >
> > With either one of these two changes, your standalone reproducer program
> > starts working again.  Or at least it does on my machine.  If it still doesn't
> > work on your end that way, please let us know. :)
> >
> > I admit that we should probably point this out in the Landlock documentation
> > for the LANDLOCK_ACCESS_FS_EXECUTE right, as dynamic linking is common and it
> > is a potential issue that many people might run into.
> >
> > For background on the dynamic loading mechanism, see the man page ld.so(8) [1]
> > and the LWN article "How programs get run: ELF binaries" [2] (specifically the
> > section "Dynamically linked programs").
> >
> > —Günther
> >
> >
> > [1] https://man7.org/linux/man-pages/man8/ld.so.8.html
> > [2] https://lwn.net/Articles/631631/
> >
> >
>
publickey - [email protected] - 0xEDFCC5BC.asc (application/pgp-keys, 645 B)
-----BEGIN PGP PUBLIC KEY BLOCK-----

xjMEX2/OLRYJKwYBBAHaRw8BAQdA0b0Ka0ZUVXJRzsm4m9lS9nVt89a3TJB3
1OrTKRKyJgXNJWtlbkBrZW5ncmltZXMuY29tIDxrZW5Aa2VuZ3JpbWVzLmNv
bT7CjwQQFgoAIAUCX2/OLQYLCQcIAwIEFQgKAgQWAgEAAhkBAhsDAh4BACEJ
EFM+b7eKZbghFiEE7fzFvCsf4mDRMPm5Uz5vt4pluCFXMAD+O4dBKdhLcUXW
lltxZx1sY61gEUX4EHwK5QGGN88TtcUBAMOj01PrW+eR6uhdgs8zyCgXSkle
EMVZep0Ly5LYI0wPzjgEX2/OLRIKKwYBBAGXVQEFAQEHQLoSjmlmtgMcjALS
K1a98FgYDsD9h+ptHPM3NW6abiB7AwEIB8J4BBgWCAAJBQJfb84tAhsMACEJ
EFM+b7eKZbghFiEE7fzFvCsf4mDRMPm5Uz5vt4pluCFTyAD/QIol/gUBcepe
EGv2geww/HfWKXcgv+eKgwboF/DZnskA/3trnzWm5C0iKz/j7IG1pPSifbJs
wC6FGQq8O4eYoHwF
=FFUh
-----END PGP PUBLIC KEY BLOCK-----
signature.asc (application/pgp-signature, 343 B)
-----BEGIN PGP SIGNATURE-----
Version: ProtonMail

wrsEARYKAG0FgmpZO7AJEFM+b7eKZbghRRQAAAAAABwAIHNhbHRAbm90YXRp
b25zLm9wZW5wZ3Bqcy5vcmfHBPla/wGR38Zz0/z8o0ubXOCA8FyEEIt8d9ev
xSZG1xYhBO38xbwrH+Jg0TD5uVM+b7eKZbghAAAAUAD/XxwdjhG0BpoVfIJI
OmctLe3mZcntuysNS0eKySqk0z4A/R594kkkoCz+8KYGBZoxosUfTY9VO2xJ
09S5cfd56TQK
=klzG
-----END PGP SIGNATURE-----