Landlock: unprivileged access control¶
- Author:
Mickaël Salaün
- Date:
March 2025
The goal of Landlock is to enable restriction of ambient rights (e.g. globalfilesystem or network access) for a set of processes. Because Landlockis a stackable LSM, it makes it possible to create safe security sandboxes asnew security layers in addition to the existing system-wide access-controls.This kind of sandbox is expected to help mitigate the security impact of bugs orunexpected/malicious behaviors in user space applications. Landlock empowersany process, including unprivileged ones, to securely restrict themselves.
We can quickly make sure that Landlock is enabled in the running system bylooking for “landlock: Up and running” in kernel logs (as root):dmesg|greplandlock||journalctl-kb-glandlock .Developers can also easily check for Landlock support with arelated system call.If Landlock is not currently supported, we need toconfigure the kernel appropriately.
Landlock rules¶
A Landlock rule describes an action on an object which the process intends toperform. A set of rules is aggregated in a ruleset, which can then restrictthe thread enforcing it, and its future children.
The two existing types of rules are:
- Filesystem rules
For these rules, the object is a file hierarchy,and the related filesystem actions are defined withfilesystem access rights.
- Network rules (since ABI v4)
For these rules, the object is a TCP port,and the related actions are defined withnetwork access rights.
Defining and enforcing a security policy¶
We first need to define the ruleset that will contain our rules.
For this example, the ruleset will contain rules that only allow filesystemread actions and establish a specific TCP connection. Filesystem writeactions and other TCP actions will be denied.
The ruleset then needs to handle both these kinds of actions. This isrequired for backward and forward compatibility (i.e. the kernel and userspace may not know each other’s supported restrictions), hence the needto be explicit about the denied-by-default access rights.
structlandlock_ruleset_attrruleset_attr={.handled_access_fs=LANDLOCK_ACCESS_FS_EXECUTE|LANDLOCK_ACCESS_FS_WRITE_FILE|LANDLOCK_ACCESS_FS_READ_FILE|LANDLOCK_ACCESS_FS_READ_DIR|LANDLOCK_ACCESS_FS_REMOVE_DIR|LANDLOCK_ACCESS_FS_REMOVE_FILE|LANDLOCK_ACCESS_FS_MAKE_CHAR|LANDLOCK_ACCESS_FS_MAKE_DIR|LANDLOCK_ACCESS_FS_MAKE_REG|LANDLOCK_ACCESS_FS_MAKE_SOCK|LANDLOCK_ACCESS_FS_MAKE_FIFO|LANDLOCK_ACCESS_FS_MAKE_BLOCK|LANDLOCK_ACCESS_FS_MAKE_SYM|LANDLOCK_ACCESS_FS_REFER|LANDLOCK_ACCESS_FS_TRUNCATE|LANDLOCK_ACCESS_FS_IOCTL_DEV,.handled_access_net=LANDLOCK_ACCESS_NET_BIND_TCP|LANDLOCK_ACCESS_NET_CONNECT_TCP,.scoped=LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET|LANDLOCK_SCOPE_SIGNAL,};
Because we may not know which kernel version an application will be executedon, it is safer to follow a best-effort security approach. Indeed, weshould try to protect users as much as possible whatever the kernel they areusing.
To be compatible with older Linux versions, we detect the available Landlock ABIversion, and only use the available subset of access rights:
intabi;abi=landlock_create_ruleset(NULL,0,LANDLOCK_CREATE_RULESET_VERSION);if(abi<0){/* Degrades gracefully if Landlock is not handled. */perror("The running kernel does not enable to use Landlock");return0;}switch(abi){case1:/* Removes LANDLOCK_ACCESS_FS_REFER for ABI < 2 */ruleset_attr.handled_access_fs&=~LANDLOCK_ACCESS_FS_REFER;__attribute__((fallthrough));case2:/* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */ruleset_attr.handled_access_fs&=~LANDLOCK_ACCESS_FS_TRUNCATE;__attribute__((fallthrough));case3:/* Removes network support for ABI < 4 */ruleset_attr.handled_access_net&=~(LANDLOCK_ACCESS_NET_BIND_TCP|LANDLOCK_ACCESS_NET_CONNECT_TCP);__attribute__((fallthrough));case4:/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */ruleset_attr.handled_access_fs&=~LANDLOCK_ACCESS_FS_IOCTL_DEV;__attribute__((fallthrough));case5:/* Removes LANDLOCK_SCOPE_* for ABI < 6 */ruleset_attr.scoped&=~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET|LANDLOCK_SCOPE_SIGNAL);}
This enables the creation of an inclusive ruleset that will contain our rules.
intruleset_fd;ruleset_fd=landlock_create_ruleset(&ruleset_attr,sizeof(ruleset_attr),0);if(ruleset_fd<0){perror("Failed to create a ruleset");return1;}
We can now add a new rule to this ruleset thanks to the returned filedescriptor referring to this ruleset. The rule will only allow reading thefile hierarchy/usr. Without another rule, write actions would then bedenied by the ruleset. To add/usr to the ruleset, we open it with theO_PATH flag and fill the &structlandlock_path_beneath_attr with this filedescriptor.
interr;structlandlock_path_beneath_attrpath_beneath={.allowed_access=LANDLOCK_ACCESS_FS_EXECUTE|LANDLOCK_ACCESS_FS_READ_FILE|LANDLOCK_ACCESS_FS_READ_DIR,};path_beneath.parent_fd=open("/usr",O_PATH|O_CLOEXEC);if(path_beneath.parent_fd<0){perror("Failed to open file");close(ruleset_fd);return1;}err=landlock_add_rule(ruleset_fd,LANDLOCK_RULE_PATH_BENEATH,&path_beneath,0);close(path_beneath.parent_fd);if(err){perror("Failed to update ruleset");close(ruleset_fd);return1;}
It may also be required to create rules following the same logic as explainedfor the ruleset creation, by filtering access rights according to the LandlockABI version. In this example, this is not required because all of the requestedallowed_access rights are already available in ABI 1.
For network access-control, we can add a set of rules that allow to use a portnumber for a specific action: HTTPS connections.
structlandlock_net_port_attrnet_port={.allowed_access=LANDLOCK_ACCESS_NET_CONNECT_TCP,.port=443,};err=landlock_add_rule(ruleset_fd,LANDLOCK_RULE_NET_PORT,&net_port,0);
The next step is to restrict the current thread from gaining more privileges(e.g. through a SUID binary). We now have a ruleset with the first ruleallowing read access to/usr while denying all other handled accesses forthe filesystem, and a second rule allowing HTTPS connections.
if(prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0)){perror("Failed to restrict privileges");close(ruleset_fd);return1;}
The current thread is now ready to sandbox itself with the ruleset.
if(landlock_restrict_self(ruleset_fd,0)){perror("Failed to enforce ruleset");close(ruleset_fd);return1;}close(ruleset_fd);
If thelandlock_restrict_self system call succeeds, the current thread isnow restricted and this policy will be enforced on all its subsequently createdchildren as well. Once a thread is landlocked, there is no way to remove itssecurity policy; only adding more restrictions is allowed. These threads arenow in a new Landlock domain, which is a merger of their parent one (if any)with the new ruleset.
Full working code can be found insamples/landlock/sandboxer.c.
Good practices¶
It is recommended to set access rights to file hierarchy leaves as much aspossible. For instance, it is better to be able to have~/doc/ as aread-only hierarchy and~/tmp/ as a read-write hierarchy, compared to~/ as a read-only hierarchy and~/tmp/ as a read-write hierarchy.Following this good practice leads to self-sufficient hierarchies that do notdepend on their location (i.e. parent directories). This is particularlyrelevant when we want to allow linking or renaming. Indeed, having consistentaccess rights per directory enables changing the location of such directorieswithout relying on the destination directory access rights (except those thatare required for this operation, seeLANDLOCK_ACCESS_FS_REFERdocumentation).
Having self-sufficient hierarchies also helps to tighten the required accessrights to the minimal set of data. This also helps avoid sinkhole directories,i.e. directories where data can be linked to but not linked from. However,this depends on data organization, which might not be controlled by developers.In this case, granting read-write access to~/tmp/, instead of write-onlyaccess, would potentially allow moving~/tmp/ to a non-readable directoryand still keep the ability to list the content of~/tmp/.
Layers of file path access rights¶
Each time a thread enforces a ruleset on itself, it updates its Landlock domainwith a new layer of policy. This complementary policy is stacked with anyother rulesets potentially already restricting this thread. A sandboxed threadcan then safely add more constraints to itself with a new enforced ruleset.
One policy layer grants access to a file path if at least one of its rulesencountered on the path grants the access. A sandboxed thread can only accessa file path if all its enforced policy layers grant the access as well as allthe other system access controls (e.g. filesystem DAC, other LSM policies,etc.).
Bind mounts and OverlayFS¶
Landlock enables restricting access to file hierarchies, which means that theseaccess rights can be propagated with bind mounts (cf.Shared Subtrees) but not withOverlay Filesystem.
A bind mount mirrors a source file hierarchy to a destination. The destinationhierarchy is then composed of the exact same files, on which Landlock rules canbe tied, either via the source or the destination path. These rules restrictaccess when they are encountered on a path, which means that they can restrictaccess to multiple file hierarchies at the same time, whether these hierarchiesare the result of bind mounts or not.
An OverlayFS mount point consists of upper and lower layers. These layers arecombined in a merge directory, and that merged directory becomes available atthe mount point. This merge hierarchy may include files from the upper andlower layers, but modifications performed on the merge hierarchy only reflecton the upper layer. From a Landlock policy point of view, all OverlayFS layersand merge hierarchies are standalone and each contains their own set of filesand directories, which is different from bind mounts. A policy restricting anOverlayFS layer will not restrict the resulted merged hierarchy, and vice versa.Landlock users should then only think about file hierarchies they want to allowaccess to, regardless of the underlying filesystem.
Inheritance¶
Every new thread resulting from aclone(2) inherits Landlock domainrestrictions from its parent. This is similar to seccomp inheritance (cf.Seccomp BPF (SECure COMPuting with filters)) or any other LSM dealing withtask’scredentials(7). For instance, one process’s thread may applyLandlock rules to itself, but they will not be automatically applied to othersibling threads (unlike POSIX thread credential changes, cf.nptl(7)).
When a thread sandboxes itself, we have the guarantee that the related securitypolicy will stay enforced on all this thread’s descendants. This allowscreating standalone and modular security policies per application, which willautomatically be composed between themselves according to their runtime parentpolicies.
Ptrace restrictions¶
A sandboxed process has less privileges than a non-sandboxed process and mustthen be subject to additional restrictions when manipulating another process.To be allowed to useptrace(2) and related syscalls on a targetprocess, a sandboxed process should have a superset of the target process’saccess rights, which means the tracee must be in a sub-domain of the tracer.
IPC scoping¶
Similar to the implicitPtrace restrictions, we may want to further restrictinteractions between sandboxes. Therefore, at ruleset creation time, eachLandlock domain can restrict the scope for certain operations, so that theseoperations can only reach out to processes within the same Landlock domain or ina nested Landlock domain (the “scope”).
The operations which can be scoped are:
LANDLOCK_SCOPE_SIGNALThis limits the sending of signals to target processes which run within thesame or a nested Landlock domain.
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKETThis limits the set of abstractunix(7) sockets to which we canconnect(2) to socket addresses which were created by a process inthe same or a nested Landlock domain.
Asendto(2) on a non-connected datagram socket is treated as ifit were doing an implicitconnect(2) and will be blocked if theremote end does not stem from the same or a nested Landlock domain.
Asendto(2) on a socket which was previously connected will notbe restricted. This works for both datagram and stream sockets.
IPC scoping does not support exceptions vialandlock_add_rule(2).If an operation is scoped within a domain, no rules can be added to allow accessto resources or processes outside of the scope.
Truncating files¶
The operations covered byLANDLOCK_ACCESS_FS_WRITE_FILE andLANDLOCK_ACCESS_FS_TRUNCATE both change the contents of a file and sometimesoverlap in non-intuitive ways. It is recommended to always specify both ofthese together.
A particularly surprising example iscreat(2). The name suggeststhat this system call requires the rights to create and write files. However,it also requires the truncate right if an existing file under the same name isalready present.
It should also be noted that truncating files does not require theLANDLOCK_ACCESS_FS_WRITE_FILE right. Apart from thetruncate(2)system call, this can also be done throughopen(2) with the flagsO_RDONLY|O_TRUNC.
The truncate right is associated with the opened file (see below).
Rights associated with file descriptors¶
When opening a file, the availability of theLANDLOCK_ACCESS_FS_TRUNCATE andLANDLOCK_ACCESS_FS_IOCTL_DEV rights is associated with the newly createdfile descriptor and will be used for subsequent truncation and ioctl attemptsusingftruncate(2) andioctl(2). The behavior is similarto opening a file for reading or writing, where permissions are checked duringopen(2), but not during the subsequentread(2) andwrite(2) calls.
As a consequence, it is possible that a process has multiple open filedescriptors referring to the same file, but Landlock enforces different thingswhen operating with these file descriptors. This can happen when a Landlockruleset gets enforced and the process keeps file descriptors which were openedboth before and after the enforcement. It is also possible to pass such filedescriptors between processes, keeping their Landlock properties, even when someof the involved processes do not have an enforced Landlock ruleset.
Compatibility¶
Backward and forward compatibility¶
Landlock is designed to be compatible with past and future versions of thekernel. This is achieved thanks to the system call attributes and theassociated bitflags, particularly the ruleset’shandled_access_fs. Makinghandled access rights explicit enables the kernel and user space to have a clearcontract with each other. This is required to make sure sandboxing will notget stricter with a system update, which could break applications.
Developers can subscribe to theLandlock mailing list to knowingly update andtest their applications with the latest available features. In the interest ofusers, and because they may use different kernel versions, it is stronglyencouraged to follow a best-effort security approach by checking the LandlockABI version at runtime and only enforcing the supported features.
Landlock ABI versions¶
The Landlock ABI version can be read with thesys_landlock_create_ruleset()system call:
intabi;abi=landlock_create_ruleset(NULL,0,LANDLOCK_CREATE_RULESET_VERSION);if(abi<0){switch(errno){caseENOSYS:printf("Landlock is not supported by the current kernel.\n");break;caseEOPNOTSUPP:printf("Landlock is currently disabled.\n");break;}return0;}if(abi>=2){printf("Landlock supports LANDLOCK_ACCESS_FS_REFER.\n");}
The following kernel interfaces are implicitly supported by the first ABIversion. Features only supported from a specific version are explicitly markedas such.
Kernel interface¶
Access rights¶
A set of actions on kernel objects may be defined by an attribute (e.g.structlandlock_path_beneath_attr) including a bitmask of access.
Filesystem flags¶
These flags enable to restrict a sandboxed process to a set of actions onfiles and directories. Files or directories opened before the sandboxingare not subject to these restrictions.
The following access rights apply only to files:
LANDLOCK_ACCESS_FS_EXECUTE: Execute a file.LANDLOCK_ACCESS_FS_WRITE_FILE: Open a file with write access. Whenopening files for writing, you will often additionally need theLANDLOCK_ACCESS_FS_TRUNCATEright. In many cases, these system callstruncate existing files when overwriting them (e.g.,creat(2)).LANDLOCK_ACCESS_FS_READ_FILE: Open a file with read access.LANDLOCK_ACCESS_FS_TRUNCATE: Truncate a file withtruncate(2),ftruncate(2),creat(2), oropen(2) withO_TRUNC. This access right is available since the third version of theLandlock ABI.LANDLOCK_ACCESS_FS_IOCTL_DEV: Invokeioctl(2) commands on an openedcharacter or block device.This access right applies to allioctl(2) commands implemented by devicedrivers. However, the following common IOCTL commands continue to beinvokable independent of the
LANDLOCK_ACCESS_FS_IOCTL_DEVright:IOCTL commands targeting file descriptors (
FIOCLEX,FIONCLEX),IOCTL commands targeting file descriptions (
FIONBIO,FIOASYNC),IOCTL commands targeting file systems (
FIFREEZE,FITHAW,FIGETBSZ,FS_IOC_GETFSUUID,FS_IOC_GETFSSYSFSPATH)Some IOCTL commands which do not make sense when used with devices, butwhose implementations are safe and return the right error codes(
FS_IOC_FIEMAP,FICLONE,FICLONERANGE,FIDEDUPERANGE)
This access right is available since the fifth version of the LandlockABI.
Whether an opened file can be truncated withftruncate(2) or usedwithioctl(2) is determined duringopen(2), in the same way asread and write permissions are checked duringopen(2) usingLANDLOCK_ACCESS_FS_READ_FILE andLANDLOCK_ACCESS_FS_WRITE_FILE.
A directory can receive access rights related to files or directories. Thefollowing access right is applied to the directory itself, and thedirectories beneath it:
LANDLOCK_ACCESS_FS_READ_DIR: Open a directory or list its content.
However, the following access rights only apply to the content of adirectory, not the directory itself:
LANDLOCK_ACCESS_FS_REMOVE_DIR: Remove an empty directory or rename one.LANDLOCK_ACCESS_FS_REMOVE_FILE: Unlink (or rename) a file.LANDLOCK_ACCESS_FS_MAKE_CHAR: Create (or rename or link) a characterdevice.LANDLOCK_ACCESS_FS_MAKE_DIR: Create (or rename) a directory.LANDLOCK_ACCESS_FS_MAKE_REG: Create (or rename or link) a regular file.LANDLOCK_ACCESS_FS_MAKE_SOCK: Create (or rename or link) a UNIX domainsocket.LANDLOCK_ACCESS_FS_MAKE_FIFO: Create (or rename or link) a named pipe.LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device.LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link.LANDLOCK_ACCESS_FS_REFER: Link or rename a file from or to a differentdirectory (i.e. reparent a file hierarchy).This access right is available since the second version of the LandlockABI.
This is the only access right which is denied by default by any ruleset,even if the right is not specified as handled at ruleset creation time.The only way to make a ruleset grant this right is to explicitly allow itfor a specific directory by adding a matching rule to the ruleset.
In particular, when using the first Landlock ABI version, Landlock willalways deny attempts to reparent files between different directories.
In addition to the source and destination directories having the
LANDLOCK_ACCESS_FS_REFERaccess right, the attempted link or renameoperation must meet the following constraints:The reparented file may not gain more access rights in the destinationdirectory than it previously had in the source directory. If this isattempted, the operation results in an
EXDEVerror.When linking or renaming, the
LANDLOCK_ACCESS_FS_MAKE_*right for therespective file type must be granted for the destination directory.Otherwise, the operation results in anEACCESerror.When renaming, the
LANDLOCK_ACCESS_FS_REMOVE_*right for therespective file type must be granted for the source directory. Otherwise,the operation results in anEACCESerror.
If multiple requirements are not met, the
EACCESerror code takesprecedence overEXDEV.
Warning
It is currently not possible to restrict some file-related actionsaccessible through these syscall families:chdir(2),stat(2),flock(2),chmod(2),chown(2),setxattr(2),utime(2),fcntl(2),access(2).Future Landlock evolutions will enable to restrict them.
Network flags¶
These flags enable to restrict a sandboxed process to a set of networkactions.
This is supported since Landlock ABI version 4.
The following access rights apply to TCP port numbers:
LANDLOCK_ACCESS_NET_BIND_TCP: Bind a TCP socket to a local port.LANDLOCK_ACCESS_NET_CONNECT_TCP: Connect an active TCP socket toa remote port.
Scope flags¶
These flags enable to isolate a sandboxed process from a set of IPC actions.Setting a flag for a ruleset will isolate the Landlock domain to forbidconnections to resources outside the domain.
This is supported since Landlock ABI version 6.
Scopes:
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: Restrict a sandboxed process fromconnecting to an abstract UNIX socket created by a process outside therelated Landlock domain (e.g., a parent domain or a non-sandboxed process).LANDLOCK_SCOPE_SIGNAL: Restrict a sandboxed process from sending a signalto another process outside the domain.
Creating a new ruleset¶
- longsys_landlock_create_ruleset(conststructlandlock_ruleset_attr__user*constattr,constsize_tsize,const__u32flags)¶
Create a new ruleset
Parameters
conststructlandlock_ruleset_attr__user*constattrPointer to a
structlandlock_ruleset_attridentifying the scope ofthe new ruleset.constsize_tsizeSize of the pointed
structlandlock_ruleset_attr(needed forbackward and forward compatibility).const__u32flagsSupported values:
Description
LANDLOCK_CREATE_RULESET_VERSION
LANDLOCK_CREATE_RULESET_ERRATA
This system call enables to create a new Landlock ruleset, and returns therelated file descriptor on success.
IfLANDLOCK_CREATE_RULESET_VERSION orLANDLOCK_CREATE_RULESET_ERRATA isset, thenattr must be NULL andsize must be 0.
Possible returned errors are:
EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;EINVAL: unknownflags, or unknown access, or unknown scope, or too smallsize;E2BIG:attr orsize inconsistencies;EFAULT:attr orsize inconsistencies;ENOMSG: emptylandlock_ruleset_attr.handled_access_fs.
Flags
LANDLOCK_CREATE_RULESET_VERSIONGet the highest supported Landlock ABI version (starting at 1).
LANDLOCK_CREATE_RULESET_ERRATAGet a bitmask of fixed issues for the current Landlock ABI version.
- structlandlock_ruleset_attr¶
Ruleset definition.
Definition:
struct landlock_ruleset_attr { __u64 handled_access_fs; __u64 handled_access_net; __u64 scoped;};Members
handled_access_fsBitmask of handled filesystem actions(cf.Filesystem flags).
handled_access_netBitmask of handled network actions (cf.Networkflags).
scopedBitmask of scopes (cf.Scope flags)restricting a Landlock domain from accessing outsideresources (e.g. IPCs).
Description
Argument ofsys_landlock_create_ruleset().
This structure defines a set ofhandled access rights, a set of actions ondifferent object types, which should be denied by default when the ruleset isenacted. Vice versa, access rights that are not specifically listed here arenot going to be denied by this ruleset when it is enacted.
For historical reasons, theLANDLOCK_ACCESS_FS_REFER right is always deniedby default, even when its bit is not set inhandled_access_fs. In order toadd new rules with this access right, the bit must still be set explicitly(cf.Filesystem flags).
The explicit listing ofhandled access rights is required for backwardscompatibility reasons. In most use cases, processes that use Landlock willhandle a wide range or all access rights that they know about at build time(and that they have tested with a kernel that supported them all).
This structure can grow in future Landlock versions.
Extending a ruleset¶
- longsys_landlock_add_rule(constintruleset_fd,constenumlandlock_rule_typerule_type,constvoid__user*construle_attr,const__u32flags)¶
Add a new rule to a ruleset
Parameters
constintruleset_fdFile descriptor tied to the ruleset that should be extendedwith the new rule.
constenumlandlock_rule_typerule_typeIdentify the structure type pointed to byrule_attr:
LANDLOCK_RULE_PATH_BENEATHorLANDLOCK_RULE_NET_PORT.constvoid__user*construle_attrPointer to a rule (matching therule_type).
const__u32flagsMust be 0.
Description
This system call enables to define a new rule and add it to an existingruleset.
Possible returned errors are:
EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;EAFNOSUPPORT:rule_type isLANDLOCK_RULE_NET_PORTbut TCP/IP is notsupported by the running kernel;EINVAL:flags is not 0;EINVAL: The rule accesses are inconsistent (i.e.landlock_path_beneath_attr.allowed_accessorlandlock_net_port_attr.allowed_accessis not a subset of the rulesethandled accesses)EINVAL:landlock_net_port_attr.portis greater than 65535;ENOMSG: Empty accesses (e.g.landlock_path_beneath_attr.allowed_accessis0);EBADF:ruleset_fd is not a file descriptor for the current thread, or amember ofrule_attr is not a file descriptor as expected;EBADFD:ruleset_fd is not a ruleset file descriptor, or a member ofrule_attr is not the expected file descriptor type;EPERM:ruleset_fd has no write access to the underlying ruleset;EFAULT:rule_attr was not a valid address.
- enumlandlock_rule_type¶
Landlock rule type
Constants
LANDLOCK_RULE_PATH_BENEATHType of a
structlandlock_path_beneath_attr.LANDLOCK_RULE_NET_PORTType of a
structlandlock_net_port_attr.
Description
Argument ofsys_landlock_add_rule().
- structlandlock_path_beneath_attr¶
Path hierarchy definition
Definition:
struct landlock_path_beneath_attr { __u64 allowed_access; __s32 parent_fd;};Members
allowed_accessBitmask of allowed actions for this file hierarchy(cf.Filesystem flags).
parent_fdFile descriptor, preferably opened with
O_PATH,which identifies the parent directory of a file hierarchy, or just afile.
Description
Argument ofsys_landlock_add_rule().
- structlandlock_net_port_attr¶
Network port definition
Definition:
struct landlock_net_port_attr { __u64 allowed_access; __u64 port;};Members
allowed_accessBitmask of allowed network actions for a port(cf.Network flags).
portNetwork port in host endianness.
It should be noted that port 0 passed tobind(2) will bindto an available port from the ephemeral port range. This can beconfigured with the
/proc/sys/net/ipv4/ip_local_port_rangesysctl(also used for IPv6).A Landlock rule with port 0 and the
LANDLOCK_ACCESS_NET_BIND_TCPright means that requesting to bind on port 0 is allowed and it willautomatically translate to binding on the related port range.
Description
Argument ofsys_landlock_add_rule().
Enforcing a ruleset¶
- longsys_landlock_restrict_self(constintruleset_fd,const__u32flags)¶
Enforce a ruleset on the calling thread
Parameters
constintruleset_fdFile descriptor tied to the ruleset to merge with the target.
const__u32flagsSupported values:
Description
LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF
LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON
LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF
This system call enables to enforce a Landlock ruleset on the currentthread. Enforcing a ruleset requires that the task hasCAP_SYS_ADMIN in itsnamespace or is running with no_new_privs. This avoids scenarios whereunprivileged tasks can affect the behavior of privileged children.
Possible returned errors are:
EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;EINVAL:flags contains an unknown bit.EBADF:ruleset_fd is not a file descriptor for the current thread;EBADFD:ruleset_fd is not a ruleset file descriptor;EPERM:ruleset_fd has no read access to the underlying ruleset, or thecurrent thread is not running with no_new_privs, or it doesn’t haveCAP_SYS_ADMINin its namespace.E2BIG: The maximum number of stacked rulesets is reached for the currentthread.
Flags
By default, denied accesses originating from programs that sandbox themselvesare logged via the audit subsystem. Such events typically indicate unexpectedbehavior, such as bugs or exploitation attempts. However, to avoid excessivelogging, access requests denied by a domain not created by the originatingprogram are not logged by default. The rationale is that programs should knowtheir own behavior, but not necessarily the behavior of other programs. Thisdefault configuration is suitable for most programs that sandbox themselves.For specific use cases, the following flags allow programs to modify thisdefault logging behavior.
TheLANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF andLANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON flags apply to the newly createdLandlock domain.
LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFFDisables logging of denied accesses originating from the thread creatingthe Landlock domain, as well as its children, as long as they continuerunning the same executable code (i.e., without an interveningexecve(2) call). This is intended for programs that executeunknown code without invokingexecve(2), such as scriptinterpreters. Programs that only sandbox themselves should not set thisflag, so users can be notified of unauthorized access attempts via systemlogs.
LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ONEnables logging of denied accesses after anexecve(2) call,providing visibility into unauthorized access attempts by newly executedprograms within the created Landlock domain. This flag is recommendedonly when all potential executables in the domain are expected to complywith the access restrictions, as excessive audit log entries could makeit more difficult to identify critical events.
LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFFDisables logging of denied accesses originating from nested Landlockdomains created by the caller or its descendants. This flag should be setaccording to runtime configuration, not hardcoded, to avoid suppressingimportant security events. It is useful for container runtimes orsandboxing tools that may launch programs which themselves createLandlock domains and could otherwise generate excessive logs. Unlike
LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF, this flag only affectsfuture nested domains, not the one being created. It can also be usedwith aruleset_fd value of -1 to mute subdomain logs without creating adomain.
Current limitations¶
Filesystem topology modification¶
Threads sandboxed with filesystem restrictions cannot modify filesystemtopology, whether viamount(2) orpivot_root(2).However,chroot(2) calls are not denied.
Special filesystems¶
Access to regular files and directories can be restricted by Landlock,according to the handled accesses of a ruleset. However, files that do notcome from a user-visible filesystem (e.g. pipe, socket), but can still beaccessed through/proc/<pid>/fd/*, cannot currently be explicitlyrestricted. Likewise, some special kernel filesystems such as nsfs, which canbe accessed through/proc/<pid>/ns/*, cannot currently be explicitlyrestricted. However, thanks to theptrace restrictions, access to suchsensitive/proc files are automatically restricted according to domainhierarchies. Future Landlock evolutions could still enable to explicitlyrestrict such paths with dedicated ruleset flags.
Ruleset layers¶
There is a limit of 16 layers of stacked rulesets. This can be an issue for atask willing to enforce a new ruleset in complement to its 16 inheritedrulesets. Once this limit is reached,sys_landlock_restrict_self() returnsE2BIG. It is then strongly suggested to carefully build rulesets once in thelife of a thread, especially for applications able to launch other applicationsthat may also want to sandbox themselves (e.g. shells, container managers,etc.).
Memory usage¶
Kernel memory allocated to create rulesets is accounted and can be restrictedby theMemory Resource Controller.
IOCTL support¶
TheLANDLOCK_ACCESS_FS_IOCTL_DEV right restricts the use ofioctl(2), but it only applies tonewly opened device files. Thismeans specifically that pre-existing file descriptors like stdin, stdout andstderr are unaffected.
Users should be aware that TTY devices have traditionally permitted to controlother processes on the same TTY through theTIOCSTI andTIOCLINUX IOCTLcommands. Both of these requireCAP_SYS_ADMIN on modern Linux systems, butthe behavior is configurable forTIOCSTI.
On older systems, it is therefore recommended to close inherited TTY filedescriptors, or to reopen them from/proc/self/fd/* without theLANDLOCK_ACCESS_FS_IOCTL_DEV right, if possible.
Landlock’s IOCTL support is coarse-grained at the moment, but may become morefine-grained in the future. Until then, users are advised to establish theguarantees that they need through the file hierarchy, by only allowing theLANDLOCK_ACCESS_FS_IOCTL_DEV right on files where it is really required.
Previous limitations¶
File renaming and linking (ABI < 2)¶
Because Landlock targets unprivileged access controls, it needs to properlyhandle composition of rules. Such property also implies rules nesting.Properly handling multiple layers of rulesets, each one of them able torestrict access to files, also implies inheritance of the ruleset restrictionsfrom a parent to its hierarchy. Because files are identified and restricted bytheir hierarchy, moving or linking a file from one directory to another impliespropagation of the hierarchy constraints, or restriction of these actionsaccording to the potentially lost constraints. To protect against privilegeescalations through renaming or linking, and for the sake of simplicity,Landlock previously limited linking and renaming to the same directory.Starting with the Landlock ABI version 2, it is now possible to securelycontrol renaming and linking thanks to the newLANDLOCK_ACCESS_FS_REFERaccess right.
File truncation (ABI < 3)¶
File truncation could not be denied before the third Landlock ABI, so it isalways allowed when using a kernel that only supports the first or second ABI.
Starting with the Landlock ABI version 3, it is now possible to securely controltruncation thanks to the newLANDLOCK_ACCESS_FS_TRUNCATE access right.
TCP bind and connect (ABI < 4)¶
Starting with the Landlock ABI version 4, it is now possible to restrict TCPbind and connect actions to only a set of allowed ports thanks to the newLANDLOCK_ACCESS_NET_BIND_TCP andLANDLOCK_ACCESS_NET_CONNECT_TCPaccess rights.
Device IOCTL (ABI < 5)¶
IOCTL operations could not be denied before the fifth Landlock ABI, soioctl(2) is always allowed when using a kernel that only supports anearlier ABI.
Starting with the Landlock ABI version 5, it is possible to restrict the use ofioctl(2) on character and block devices using the newLANDLOCK_ACCESS_FS_IOCTL_DEV right.
Abstract UNIX socket (ABI < 6)¶
Starting with the Landlock ABI version 6, it is possible to restrictconnections to an abstractunix(7) socket by settingLANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET to thescoped ruleset attribute.
Signal (ABI < 6)¶
Starting with the Landlock ABI version 6, it is possible to restrictsignal(7) sending by settingLANDLOCK_SCOPE_SIGNAL to thescoped ruleset attribute.
Logging (ABI < 7)¶
Starting with the Landlock ABI version 7, it is possible to control logging ofLandlock audit events with theLANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF,LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON, andLANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF flags passed tosys_landlock_restrict_self(). SeeLandlock: system-wide managementfor more details on audit.
Kernel support¶
Build time configuration¶
Landlock was first introduced in Linux 5.13 but it must be configured at buildtime withCONFIG_SECURITY_LANDLOCK=y. Landlock must also be enabled at boottime like other security modules. The list of security modules enabled bydefault is set withCONFIG_LSM. The kernel configuration should thencontainCONFIG_LSM=landlock,[...] with[...] as the list of otherpotentially useful security modules for the running system (see theCONFIG_LSM help).
Boot time configuration¶
If the running kernel does not havelandlock inCONFIG_LSM, then we canenable Landlock by addinglsm=landlock,[...] toThe kernel’s command-line parameters in the boot loaderconfiguration.
For example, if the current built-in configuration is:
$zgrep-h"^CONFIG_LSM=""/boot/config-$(uname-r)"/proc/config.gz2>/dev/nullCONFIG_LSM="lockdown,yama,integrity,apparmor"
...and if the cmdline doesn’t containlandlock either:
$sed-n's/.*\(\<lsm=\S\+\).*/\1/p'/proc/cmdlinelsm=lockdown,yama,integrity,apparmor
...we should configure the boot loader to set a cmdline extending thelsmlist with thelandlock, prefix:
lsm=landlock,lockdown,yama,integrity,apparmor
After a reboot, we can check that Landlock is up and running by looking atkernel logs:
#dmesg|greplandlock||journalctl-kb-glandlock[ 0.000000] Command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor[ 0.000000] Kernel command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor[ 0.000000] LSM: initializing lsm=lockdown,capability,landlock,yama,integrity,apparmor[ 0.000000] landlock: Up and running.
The kernel may be configured at build time to always load thelockdown andcapability LSMs. In that case, these LSMs will appear at the beginning oftheLSM:initializing log line as well, even if they are not configured inthe boot loader.
Network support¶
To be able to explicitly allow TCP operations (e.g., adding a network rule withLANDLOCK_ACCESS_NET_BIND_TCP), the kernel must support TCP(CONFIG_INET=y). Otherwise,sys_landlock_add_rule() returns anEAFNOSUPPORT error, which can safely be ignored because this kind of TCPoperation is already not possible.
Questions and answers¶
What about user space sandbox managers?¶
Using user space processes to enforce restrictions on kernel resources can leadto race conditions or inconsistent evaluations (i.e.Incorrect mirroring ofthe OS code and state).
What about namespaces and containers?¶
Namespaces can help create sandboxes but they are not designed foraccess-control and then miss useful features for such use case (e.g. nofine-grained restrictions). Moreover, their complexity can lead to securityissues, especially when untrusted processes can manipulate them (cf.Controlling access to user namespaces).
How to disable Landlock audit records?¶
You might want to put in place filters as explained here:Landlock: system-wide management