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

4 messages, 3 authors, 17d ago · open the first message on its own page

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

From: Ken Grimes <hidden>
Date: 2026-07-14 21:08:16

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!


Summary
-------

On Linux 7.1.3 (Fedora 44, Landlock ABI version 9), a minimal, correctly
constructed Landlock ruleset denies execve()/execveat() of that file with
EACCES. This directly contradicts the expected behavior of the official
selftest assertion: tools/testing/selftests/landlock/fs_test.c's
TEST_F_FORK(layout1, execute), specifically the file1_s1d2 case,
expects exactly this shape of rule to permit execution
(test_execute(_metadata, 0, file1_s1d2)).

This was confirmed two ways: a minimal standalone reproduction (below),
and by building and running your own unmodified
tools/testing/selftests/landlock/fs_test.c from the v7.1.3 tag (exact
match to the running kernel and its kernel-headers package) against this
kernel. layout1.execute fails on this kernel:

    #  RUN           layout1.execute ...
    # fs_test.c:1949:execute:Expected err ? -1 : 0 (0) == execve(path, argv, NULL) (-1)
    # fs_test.c:1951:execute:Failed to execute "tmp/s1d1/s1d2/f1": Permission denied
    # execute: Test terminated by assertion
    #          FAIL  layout1.execute
    not ok 29 layout1.execute

tmp/s1d1/s1d2/f1 is file1_s1d2 is the file living directly inside
dir_s1d2, which is the directory the test's own PathBeneath rule
anchors on (rules[0] = { .path = dir_s1d2, .access =
LANDLOCK_ACCESS_FS_EXECUTE }). The failing assertion is
test_execute(_metadata, 0, file1_s1d2) (fs_test.c:1949 in the v7.1.3
tree, quoted below). The test's author expects this call to succeed
(err == 0), and on this kernel it doesn't. Full raw test output is
attached (official-selftest-output.log).

Relevant excerpt of the actual test body (identical across the v7.1.3
tag and current master):

    TEST_F_FORK(layout1, execute)
    {
    const struct rule rules[] = {
    {
    .path = dir_s1d2,
    .access = LANDLOCK_ACCESS_FS_EXECUTE,
    },
    {},
    };

    copy_file(_metadata, bin_true, file1_s1d1);
    copy_file(_metadata, bin_true, file1_s1d2);
    copy_file(_metadata, bin_true, file1_s1d3);

    /* Checks before file1_s1d1 being denied. */
    test_execute(_metadata, 0, file1_s1d1);
    test_check_exec(_metadata, 0, file1_s1d1);

    enforce_fs(_metadata, rules[0].access, rules);

    ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
    ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
    test_execute(_metadata, EACCES, file1_s1d1);
    test_check_exec(_metadata, EACCES, file1_s1d1);

    ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
    ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
    test_execute(_metadata, 0, file1_s1d2);        /* <-- fails here */
    test_check_exec(_metadata, 0, file1_s1d2);
    ...

(Reproducing the official fixture required running from a
world-writable directory: prepare_layout_opt() calls disable_caps()
which drops CAP_DAC_OVERRIDE from the otherwise-root test process,
before creating its working directory, so it must be run from
somewhere an unprivileged-DAC root can still write, e.g. under /tmp
directly. This is unrelated to the actual bug, just a note for anyone
else reproducing it.)

Environment
-----------

- Kernel: 7.1.3-200.fc44.x86_64 (Fedora 44 Workstation)
- Landlock ABI version: 9 (via landlock_create_ruleset(NULL, 0,
  LANDLOCK_CREATE_RULESET_VERSION))
- kernel-headers package: kernel-headers-7.1.3-200.fc44.x86_64
  (exact version match to the running kernel; the reproduction below was
  built against these headers)
- No root/CAP_SYS_ADMIN involved anywhere in the reproduction -- Landlock
  is unprivileged by design, and this reproduces identically as an
  ordinary user.

Reproduction
------------

Official selftest (strongest evidence):

    $ git clone --branch v7.1.3 --depth 1 https://github.com/gregkh/linux
    $ cd linux/tools/testing/selftests/landlock
    $ gcc -O0 -g -Wall -o fs_test fs_test.c -lcap -lpthread
    $ gcc -O0 -o true true.c
    $ mkdir -p /tmp/lltest && chmod 1777 /tmp/lltest
    $ cp fs_test true /tmp/lltest/ && cd /tmp/lltest
    $ sudo ./fs_test -f layout1 -t execute

(Run from a world-writable directory. See the note above about
disable_caps()) Full output attached as official-selftest-output.log.

Minimal standalone reproduction (self-contained, no external
dependencies beyond libc and the system's own <linux/landlock.h>,
unprivileged, attached as repro.c):

    /*
     * Minimal standalone reproduction of a Landlock EXECUTE-right denial that
     * contradicts the upstream kernel's own selftest expectation.
     *
     * This mirrors tools/testing/selftests/landlock/fs_test.c's
     * TEST_F_FORK(layout1, execute) -- specifically the file1_s1d2 case: a
     * PathBeneath rule granting only LANDLOCK_ACCESS_FS_EXECUTE, anchored on a
     * directory, is expected to permit execve() of a file directly inside that
     * directory (upstream asserts test_execute(_metadata, 0, file1_s1d2), i.e.
     * "no error"). On this kernel it is denied with EACCES instead.
     *
     * No root/CAP_SYS_ADMIN required -- Landlock is designed for unprivileged
     * use, and this reproduces the same way as an ordinary user.
     *
     * Build:   gcc -O0 -g -Wall -o repro repro.c
     * Run:     ./repro
     *
     * Observed on: Linux 7.1.3-200.fc44.x86_64 (Fedora 44 Workstation),
     * Landlock ABI version 9 (per landlock_create_ruleset(NULL, 0,
     * LANDLOCK_CREATE_RULESET_VERSION)).
     */

    #define _GNU_SOURCE
    #include <errno.h>
    #include <fcntl.h>
    #include <linux/landlock.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/prctl.h>
    #include <sys/stat.h>
    #include <sys/syscall.h>
    #include <sys/wait.h>
    #include <unistd.h>

    static int landlock_create_ruleset(const struct landlock_ruleset_attr *attr,
       size_t size, __u32 flags)
    {
    return syscall(SYS_landlock_create_ruleset, attr, size, flags);
    }

    static int landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,
         const void *attr, __u32 flags)
    {
    return syscall(SYS_landlock_add_rule, ruleset_fd, type, attr, flags);
    }

    static int landlock_restrict_self(int ruleset_fd, __u32 flags)
    {
    return syscall(SYS_landlock_restrict_self, ruleset_fd, flags);
    }

    static void die(const char *what)
    {
    fprintf(stderr, "%s: %s\n", what, strerror(errno));
    exit(1);
    }

    /* Runs `path` via a fresh execve() in a child, prints and returns its result. */
    static int try_execve(const char *path)
    {
    pid_t pid = fork();
    if (pid < 0)
    die("fork");
    if (pid == 0) {
    char *const argv[] = { (char *)path, NULL };
    execve(path, argv, NULL);
    /* Only reached on failure. */
    fprintf(stderr, "execve(%s) failed: %s (errno %d)\n", path,
    strerror(errno), errno);
    _exit(1);
    }
    int status;
    waitpid(pid, &status, 0);
    if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
    return 0;
    return 1;
    }

    int main(void)
    {
    int abi = landlock_create_ruleset(NULL, 0,
      LANDLOCK_CREATE_RULESET_VERSION);
    printf("Landlock ABI version: %d\n", abi);
    if (abi < 0)
    die("landlock_create_ruleset(VERSION)");

    /* Build tmp/dir/exe, matching layout1's dir_s1d2/file1_s1d2 shape:
    * a rule anchored on the parent directory, target file directly
    * inside it (zero levels of extra nesting). */
    if (mkdir("repro-dir", 0700) < 0 && errno != EEXIST)
    die("mkdir repro-dir");

    /* Copy /bin/true in as our target executable. */
    {
    char cmd[256];
    snprintf(cmd, sizeof(cmd),
    "cp /bin/true repro-dir/exe && chmod 755 repro-dir/exe");
    if (system(cmd) != 0)
    die("cp /bin/true");
    }

    /* Baseline: confirm it executes fine before Landlock is involved. */
    if (try_execve("repro-dir/exe") != 0) {
    fprintf(stderr, "baseline execve failed even without Landlock -- "
    "environment problem, not a Landlock issue\n");
    return 1;
    }
    printf("Baseline (no Landlock): execve succeeded, as expected.\n");

    /* Minimal ruleset: EXECUTE only, matching the official selftest's
    * rules[0].access = LANDLOCK_ACCESS_FS_EXECUTE for layout1.execute. */
    struct landlock_ruleset_attr ruleset_attr = {
    .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
    };
    int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
     sizeof(ruleset_attr), 0);
    if (ruleset_fd < 0)
    die("landlock_create_ruleset");

    int parent_fd = open("repro-dir", O_PATH);
    if (parent_fd < 0)
    die("open repro-dir O_PATH");

    struct landlock_path_beneath_attr path_beneath = {
    .allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
    .parent_fd = parent_fd,
    };
    if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
          &path_beneath, 0) != 0)
    die("landlock_add_rule");
    close(parent_fd);

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)
    die("prctl(PR_SET_NO_NEW_PRIVS)");

    if (landlock_restrict_self(ruleset_fd, 0) != 0)
    die("landlock_restrict_self");
    close(ruleset_fd);

    printf("Landlock ruleset installed: EXECUTE-only, one PathBeneath "
          "rule anchored on repro-dir (the target file's own parent).\n");

    int result = try_execve("repro-dir/exe");
    if (result == 0) {
    printf("PASS: execve succeeded, as the upstream selftest "
          "(layout1.execute, file1_s1d2 case) expects.\n");
    } else {
    printf("FAIL: execve was denied (EACCES) despite an "
          "explicit, correctly-anchored PathBeneath rule "
          "granting LANDLOCK_ACCESS_FS_EXECUTE on the file's "
          "own parent directory -- this contradicts "
          "tools/testing/selftests/landlock/fs_test.c's "
          "TEST_F_FORK(layout1, execute) expectation for the "
          "file1_s1d2 case.\n");
    }

    system("rm -rf repro-dir");
    return result;
    }

Build and run:

    $ gcc -O0 -g -Wall -o repro repro.c
    $ ./repro
    Landlock ABI version: 9
    Baseline (no Landlock): execve succeeded, as expected.
    Landlock ruleset installed: EXECUTE-only, one PathBeneath rule anchored on repro-dir (the target file's own parent).
    execve(repro-dir/exe) failed: Permission denied (errno 13)
    FAIL: execve was denied (EACCES) despite an explicit, correctly-anchored PathBeneath rule granting LANDLOCK_ACCESS_FS_EXECUTE on the file's own parent directory -- this contradicts tools/testing/selftests/landlock/fs_test.c's TEST_F_FORK(layout1, execute) expectation for the file1_s1d2 case.

What was ruled out before concluding this is a kernel-level issue
--------------------------------------------------------------------

This was investigated extensively in the course of debugging a real
downstream project (a Rust codebase using the landlock crate 0.4.5) that
hit this exact denial. Before concluding it's a kernel bug rather than a
userspace mistake, the following were each tested and ruled out as the
cause:

1. SELinux: this host runs SELinux Enforcing, but the reproduction
   above runs entirely under the interactive shell's unconfined_t
   domain, and the identical target file executes fine via a plain
   (non-Landlock) execve() beforehand in the same process. Only adding
   the Landlock ruleset flips the result to EACCES.

2. IPE (Integrity Policy Enforcement): enforce=1 on this host, but
   /sys/kernel/security/ipe/policies/ is empty (no policy loaded), and
   no IPE-related denial appears in the audit log around the failure. A
   plain execve() of the same file with no Landlock domain active
   succeeds, which would not be the case if IPE were unconditionally
   denying this file.

3. Kernel lockdown mode: active at "integrity" level on this host
   (Fedora enables this automatically under Secure Boot), but lockdown's
   documented restrictions (module signing, /dev/mem, hibernation,
   kexec, debugfs, etc.) govern kernel-image-integrity operations, not
   ordinary unprivileged LSM policy decisions like Landlock's own
   filesystem checks, and no documented interaction between the two was
   found.

4. tmpfs vs. a real on-disk filesystem: the denial reproduces
   identically whether the target directory is on tmpfs (/tmp) or a
   real on-disk btrfs filesystem (the root filesystem).

5. fd-based (execveat+AT_EMPTY_PATH) vs. path-based execve(): both
   fail identically; this is not specific to executing via an
   already-open file descriptor.

6. Direct child vs. nested subdirectory: a file nested one level deeper
   than the anchored rule fails identically to a file directly in the
   anchored directory.

7. O_PATH vs. plain open() for the rule's anchor fd: no difference
   (the landlock Rust crate's own documentation warns plain File opens
   "may lead to unexpected errors," but explicitly testing O_PATH
   produced the identical denial).

8. Ruleset rights breadth: tested with handled_access_fs as EXECUTE-only
   as the full V3-era 15-right set, and with an additional explicit
   file-anchored rule (correctly scoped to file-valid rights) layered
   alongside the directory rule. All identical.

9. landlock_ruleset_attr struct size: tested with the struct passed at
   24, 32, 48, and 64 bytes (padded with zeroed trailing fields, in case
   of an extensible-struct zero-extension gap for fields introduced at
   ABI 8/9, e.g. the quiet_access_fs/quiet_access_net/quiet_scoped
   fields added around ABI 7-9). No difference; the reproduction
   attached uses sizeof(ruleset_attr) against the real system header,
   matching upstream selftest convention exactly.

10. Published errata: checked all three currently-documented entries
    in security/landlock/errata/ (disconnected-directory rename
    widening, TCP socket protocol misclassification, thread signal
    scoping). None match this symptom.

11. Direct read of security/landlock/fs.c on torvalds/linux master:
    the is_access_to_paths_allowed()/current_check_access_path()/
    hook_file_open() hierarchy-walk logic appears correct for this
    simple case (walk starts at the target file's own dentry, checks
    find_rule() at each level while walking up via dget_parent(), and
    our anchor is exactly one level up). No obvious logic defect was
    found by inspection, which is part of why this is being reported
    rather than fixed downstream.

Given (11), if the master-branch logic is correct, this may already be
fixed in a tree newer than 7.1.3, or the regression window may be
narrow but as of this exact kernel, the discrepancy against the
selftest's own documented expectation is real and reproducible.

Impact
------

This affects any unprivileged (or privileged, self-restricting) process
that installs a minimal Landlock domain and then tries to execute a file
covered by a directory-anchored rule which is a common Landlock usage
pattern (matching the kernel's own selftest).
Downstream, it silently breaks a security-hardening code path
(Landlock-based filesystem confinement for a privileged process tree)
with no diagnostic beyond a generic EACCES, since the process attempting
the exec has already dropped privileges and cannot meaningfully report
the failure back to a parent through advanced means.

Request
-------

Could you confirm whether this is a known/already-fixed issue, and if
not, whether the attached reproduction is sufficient to track down the
regression? Let me know if you'd like me test a patch or provide more
instrumentation from this exact kernel build if useful.

Attachments
-----------

- repro.c - minimal standalone reproduction (also inlined above)
- official-selftest-output.log - full raw TAP output from running the
  unmodified v7.1.3 fs_test -f layout1 -t execute against this kernel

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

From: Günther Noack <gnoack@google.com>
Date: 2026-07-15 08:39:38

Hello Ken!

(Also adding landlock@lists.linux.dev 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/

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

From: Mickaël Salaün <mic@digikod.net>
Date: 2026-07-16 09:45:28

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 landlock@lists.linux.dev to CC)

On Tue, Jul 14, 2026 at 09:07:56PM +0000, Ken Grimes wrote:
quoted
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/

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

From: Ken Grimes <hidden>
Date: 2026-07-16 20:15:08

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 [off-list ref] 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:
quoted
Hello Ken!

(Also adding landlock@lists.linux.dev to CC)

On Tue, Jul 14, 2026 at 09:07:56PM +0000, Ken Grimes wrote:
quoted
Hey all, this is my first bug report for linux. The issue was discovered 
quoted
quoted
alongside llm-assisted coding on a downstream project. The 
quoted
quoted
investigation/testing of the bug was a mostly manual process so I could 
quoted
quoted
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/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help