A Linux process can voluntarily remove access that its UID, capabilities, mount namespace, and other security layers would otherwise permit. Landlock implements this as a stackable Linux Security Module: a process creates a ruleset, adds allowed objects, then places itself in a Landlock domain.
The resulting policy is an additional restriction. It does not grant access denied by DAC, ACLs, SELinux, AppArmor, mount permissions, or another active control. Once enforced, the Landlock layer cannot be removed from that thread; later Landlock domains can only add restrictions.
This makes Landlock materially different from changing filesystem ownership or constructing a separate mount namespace. The process can narrow its own ambient authority while leaving the system-wide policy and filesystem topology intact.
A ruleset declares the access classes it controls
landlock_create_ruleset() creates a file descriptor representing a ruleset. Its handled_access_fs, handled_access_net, and scoped fields declare which access classes that ruleset is prepared to restrict.
For a filesystem-only policy, the shape is conceptually:
struct landlock_ruleset_attr attr = {
.handled_access_fs =
LANDLOCK_ACCESS_FS_READ_FILE |
LANDLOCK_ACCESS_FS_READ_DIR |
LANDLOCK_ACCESS_FS_WRITE_FILE,
};
int ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);Declaring a handled right is significant. For handled filesystem access, the ruleset starts from denial and rules add permission for selected objects. An omitted handled right is generally outside that layer’s policy, subject to special ABI semantics such as LANDLOCK_ACCESS_FS_REFER.
That distinction prevents a ruleset from being interpreted as a universal filesystem allowlist when it actually controls only a selected set of operations.
Path rules attach permission to filesystem hierarchies
A filesystem rule uses LANDLOCK_RULE_PATH_BENEATH. The object is identified by a file descriptor, preferably opened with O_PATH, rather than by storing a pathname string in the policy.
int dir_fd = open("/srv/app/data", O_PATH | O_CLOEXEC);
struct landlock_path_beneath_attr rule = {
.parent_fd = dir_fd,
.allowed_access =
LANDLOCK_ACCESS_FS_READ_FILE |
LANDLOCK_ACCESS_FS_READ_DIR,
};
landlock_add_rule(
ruleset_fd,
LANDLOCK_RULE_PATH_BENEATH,
&rule,
0
);For the handled rights above, this rule permits reads beneath /srv/app/data but does not permit LANDLOCK_ACCESS_FS_WRITE_FILE there. A different hierarchy can receive a different subset.
The policy is tied to kernel filesystem objects and hierarchy traversal, not to textual prefix matching. Bind mounts and OverlayFS therefore have distinct consequences: bind-mounted hierarchies refer to the same underlying files, while OverlayFS layers and the merged hierarchy are treated as separate hierarchies for Landlock policy.
Enforcement creates a new security domain
After rules are populated, landlock_restrict_self() applies the ruleset to the calling thread. On kernels before Landlock ABI 11, an unprivileged caller normally sets no_new_privs first:
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
landlock_restrict_self(ruleset_fd, 0);ABI 11 adds LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS, allowing successful enforcement to set no_new_privs as part of the operation. Code that targets multiple kernel generations must negotiate the running Landlock ABI rather than assuming the newest flag exists.
A successfully restricted thread enters a Landlock domain. Children created afterward inherit the restrictions. Stacking another ruleset creates a domain that combines the existing restrictions with the new ones; it cannot restore rights removed by an earlier layer.
This monotonic property is central to the security model. Untrusted code cannot use the Landlock API to expand its authority.
Existing file descriptors form an important boundary
Filesystem rights checked when opening a file apply to opens performed after the sandbox is active. Files already opened before enforcement are not retroactively invalidated.
That boundary matters in process design:
open sensitive fd
apply Landlock
use existing fdThe existing descriptor may continue to provide operations established before the Landlock domain was entered. Landlock is therefore not a mechanism for revoking every resource already held by a process.
A sandbox boundary should account for inherited descriptors, descriptors opened during initialization, UNIX sockets, pipes, shared memory, and other capabilities already present in the process. Closing unneeded descriptors before enforcement reduces authority that sits outside later path checks.
Filesystem coverage is explicit rather than universal
Landlock has expanded across ABI versions, but it does not mediate every filesystem-related operation. Current kernel documentation lists operations such as chdir(2), stat(2), flock(2), chmod(2), chown(2), setxattr(2), utime(2), fcntl(2), and access(2) among actions that are not currently restrictable through Landlock filesystem rights.
This boundary is security-relevant. A policy that controls file reads, writes, creation, removal, execution, and selected other operations should not be described as controlling every metadata or descriptor operation.
The available rights also depend on the Landlock ABI supported by the running kernel. Applications should query the ABI version and mask policy features accordingly. Treating a compile-time header as proof of runtime support can produce either failed setup or a weaker policy than intended.
Network rules use ports as policy objects
Landlock is not limited to filesystem access. Network rules were added in later ABI versions. A LANDLOCK_RULE_NET_PORT rule associates allowed network actions with a port.
The ruleset declares handled network rights, then adds selected ports:
struct landlock_net_port_attr net_rule = {
.allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP,
.port = 443,
};
landlock_add_rule(
ruleset_fd,
LANDLOCK_RULE_NET_PORT,
&net_rule,
0
);The exact set of network rights is ABI-dependent. Recent ABIs extend coverage beyond the initial TCP operations. As with filesystem policy, portable code must negotiate support instead of sending rights unknown to an older kernel.
Landlock network controls complement rather than replace network namespaces, firewall policy, seccomp, or service-level authorization. Each mechanism constrains a different part of the system.
Landlock composes with existing security layers
Landlock is stackable. A process subject to ordinary UNIX permissions and another LSM remains subject to those controls after entering a Landlock domain.
The effective access is an intersection:
effective access
= system-wide permission
AND existing security layers
AND Landlock domainThis composition is useful for applications that already run under a distribution or administrator policy. The application can add a self-imposed boundary without needing to own the host’s global security configuration.
It also means a successful Landlock rule does not prove an operation will succeed. Another layer can still deny it.
The useful boundary is least authority after initialization
Landlock fits processes whose initialization phase needs broader access than their steady state. A service may load configuration and libraries, open its listening resources, prepare runtime state, then enter a domain that exposes only the file hierarchies and network operations required afterward.
The security value comes from reducing ambient authority before parsing less-trusted input or entering a long-running request loop. If a later memory-safety flaw or logic bug causes unintended filesystem or network operations, the kernel evaluates them against the additional Landlock domain.
That guarantee remains bounded by the rights Landlock actually mediates, the ABI available on the running kernel, and resources acquired before enforcement. A precise Landlock policy is therefore an irreversible reduction layer, not a complete isolation boundary.