landlock_restrict_self(2)

โœจ landlock_restrict_self โ€” enforce a Landlock ruleset โœจ

hiii bestie ๐Ÿซถ welcome to the System Calls Manual, aka the syscall girlies' section of the man pages. This one's about landlock_restrict_self, and honestly? she's giving final boss of sandboxing energy. Let's get into it ๐Ÿ’…


๐Ÿ’– NAME ๐Ÿ’–

landlock_restrict_self โ€” enforce a Landlock ruleset. That's the whole job, and she ate.

๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc). Yes queen, it's right there in libc.

๐ŸŽ€ SYNOPSIS ๐ŸŽ€

#include <linux/landlock.h>  /* Definition of LANDLOCK_* constants */
#include <sys/syscall.h>     /* Definition of SYS_* constants */

int syscall(SYS_landlock_restrict_self, int ruleset_fd,
            uint32_t flags);

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so picture this: you've got a Landlock ruleset, and you've loaded it up with all the rules you want. Once it's populated, calling landlock_restrict_self() is the moment of truth โ€” it enforces that ruleset on the calling thread. If you want the big-picture lore, go read landlock(7) for a global overview. ๐Ÿ“–

A thread can be restricted with multiple rulesets, and those rulesets get composed together to form the thread's Landlock domain. Think of it like a stack of rulesets, but it's implemented in a way more efficient way than literally stacking them (efficiency slay ๐Ÿ’…). Here's the thing though: a domain can only be updated in a way where the constraints of every past and future composed ruleset will restrict the thread and its future children for their entire life. So you can gradually enforce tailored access control policies with multiple independent rulesets coming from different sources โ€” for example, init system configuration, user session policy, or built-in application policy. Cute, right?

But lowkey โ€” most applications should only need ONE call to landlock_restrict_self(). They should avoid arbitrary numbers of such calls because of the composed rulesets limit. Instead, developers are encouraged to build a single tailored ruleset with multiple calls to landlock_add_rule(2). Periodt.

So, to actually enforce a ruleset, one of these has to be true:

  • the caller must have the CAP_SYS_ADMIN capability in its user namespace, or
  • the thread must already have the no_new_privs bit set.

Same vibe as seccomp(2), and the reason is that this avoids scenarios where unprivileged processes can affect the behavior of privileged children โ€” like, say, because of set-user-ID binaries. ๐Ÿ™ˆ If that bit was not already set by an ancestor of this thread, the thread has to make the following call:

prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);

ruleset_fd is a Landlock ruleset file descriptor you got from landlock_create_ruleset(2) and fully populated with a set of calls to landlock_add_rule(2). No skipping steps, bestie.

By default, denied accesses originating from programs that sandbox themselves are logged via the audit subsystem. Those events typically mean something unexpected happened โ€” bugs or exploitation attempts, yikes. But to avoid excessive logging, access requests denied by a domain that was not created by the originating program are not logged by default. The rationale there is that programs should know their own behavior, but not necessarily the behavior of other programs. That default configuration is suitable for most programs that sandbox themselves. For specific use cases though, the following flags let programs modify this default logging behavior โœจ

The LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF and LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON flags apply to the newly created Landlock domain.

  • LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF (since Landlock ABI version 7) โ€” Disables logging of denied accesses originating from the thread creating the Landlock domain, plus its children, as long as they keep running the same executable code (i.e., without an intervening execve(2) call). This is intended for programs that execute unknown code without invoking execve(2), like script interpreters. Programs that only sandbox themselves should not set this flag, so users can still be notified of unauthorized access attempts via system logs. ๐Ÿ‘€
  • LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON (since Landlock ABI version 7) โ€” Enables logging of denied accesses after an execve(2) call, giving you visibility into unauthorized access attempts by newly executed programs inside the Landlock domain you created. This flag is recommended only when all potential executables in the domain are expected to comply with the access restrictions, because excessive audit log entries could make it harder to spot the critical events. ๐Ÿ˜ญ
  • LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF (since Landlock ABI version 7) โ€” Disables logging of denied accesses originating from nested Landlock domains created by the caller or its descendants. Set this one according to runtime configuration, not hardcoded, to avoid suppressing important security events. It's useful for container runtimes or sandboxing tools that may launch programs which themselves create Landlock domains and could otherwise generate excessive logs. Unlike LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF, this flag only affects future nested domains, not the one being created. Bonus: it can also be used with a ruleset_fd value of -1 to mute subdomain logs without creating a domain. ๐Ÿคซ

And the following flag supports policy enforcement in multithreaded processes:

  • LANDLOCK_RESTRICT_SELF_TSYNC (since Landlock ABI version 8) โ€” Applies the new Landlock configuration atomically to all threads of the current process, including the Landlock domain and logging configuration. This overrides the Landlock configuration of sibling threads, irrespective of previously established Landlock domains and logging configurations on those threads. Also: if the calling thread is running with no_new_privs, this operation enables no_new_privs on the sibling threads as well. Group chat, but make it security policy. ๐Ÿ’…

๐ŸŒŸ RETURN VALUE ๐ŸŒŸ

On success, landlock_restrict_self() returns 0. On error, -1 is returned and errno is set to indicate the error. Simple! We love a clean return value.

๐Ÿ’€ ERRORS ๐Ÿ’€

landlock_restrict_self() can fail for the following reasons:

  • E2BIG โ€” The maximum number of composed rulesets is reached for the calling thread. This limit is currently 64.
  • EBADF โ€” ruleset_fd is not a file descriptor for the current thread.
  • EBADFD โ€” ruleset_fd is not a ruleset file descriptor.
  • EINVAL โ€” Invalid value in flags.
  • EOPNOTSUPP โ€” Landlock is supported by the kernel but disabled at boot time.
  • EPERM โ€” ruleset_fd has no read access to the underlying ruleset, or the calling thread is not running with no_new_privs, or it doesn't have CAP_SYS_ADMIN in its user namespace.

๐Ÿ“œ STANDARDS ๐Ÿ“œ

Linux. ๐Ÿง She's a Linux girlie, that's the standard.

๐Ÿ•ฐ๏ธ HISTORY ๐Ÿ•ฐ๏ธ

Linux 5.13. So she's been iconic since 5.13.

๐Ÿงช EXAMPLES ๐Ÿงช

See landlock(7). (Yes bestie, go read it, it's the whole vibe.)

๐Ÿ”— SEE ALSO ๐Ÿ”—


and that's the page, bestie ๐ŸŽ€ one last thing for the credits scroll: this was brought to you by Linux man-pages 6.20, dated 2026-05-04, for landlock_restrict_self(2). no cap, go sandbox something responsibly ๐Ÿ’–โœจ๐ŸŒธ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms