| .. SPDX-License-Identifier: GPL-2.0 | |
| .. Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net> | |
| .. Copyright © 2019-2020 ANSSI | |
| ================================== | |
| Landlock LSM: kernel documentation | |
| ================================== | |
| :Author: Mickaël Salaün | |
| :Date: March 2026 | |
| Landlock's goal is to create scoped access-control (i.e. sandboxing). To | |
| harden a whole system, this feature should be available to any process, | |
| including unprivileged ones. Because such a process may be compromised or | |
| backdoored (i.e. untrusted), Landlock's features must be safe to use from the | |
| kernel and other processes point of view. Landlock's interface must therefore | |
| expose a minimal attack surface. | |
| Landlock is designed to be usable by unprivileged processes while following the | |
| system security policy enforced by other access control mechanisms (e.g. DAC, | |
| LSM). A Landlock rule shall not interfere with other access-controls enforced | |
| on the system, only add more restrictions. | |
| Any user can enforce Landlock rulesets on their processes. They are merged and | |
| evaluated against inherited rulesets in a way that ensures that only more | |
| constraints can be added. | |
| User space documentation can be found here: | |
| Documentation/userspace-api/landlock.rst. | |
| Guiding principles for safe access controls | |
| =========================================== | |
| * A Landlock rule shall be focused on access control on kernel objects instead | |
| of syscall filtering (i.e. syscall arguments), which is the purpose of | |
| seccomp-bpf. | |
| * To avoid multiple kinds of side-channel attacks (e.g. leak of security | |
| policies, CPU-based attacks), Landlock rules shall not be able to | |
| programmatically communicate with user space. | |
| * Kernel access check shall not slow down access request from unsandboxed | |
| processes. | |
| * Computation related to Landlock operations (e.g. enforcing a ruleset) shall | |
| only impact the processes requesting them. | |
| * Resources (e.g. file descriptors) directly obtained from the kernel by a | |
| sandboxed process shall retain their scoped accesses (at the time of resource | |
| acquisition) whatever process uses them. | |
| Cf. `File descriptor access rights`_. | |
| * Access denials shall be logged according to system and Landlock domain | |
| configurations. Log entries must contain information about the cause of the | |
| denial and the owner of the related security policy. Such log generation | |
| should have a negligible performance and memory impact on allowed requests. | |
| Design choices | |
| ============== | |
| Inode access rights | |
| ------------------- | |
| All access rights are tied to an inode and what can be accessed through it. | |
| Reading the content of a directory does not imply to be allowed to read the | |
| content of a listed inode. Indeed, a file name is local to its parent | |
| directory, and an inode can be referenced by multiple file names thanks to | |
| (hard) links. Being able to unlink a file only has a direct impact on the | |
| directory, not the unlinked inode. This is the reason why | |
| ``LANDLOCK_ACCESS_FS_REMOVE_FILE`` or ``LANDLOCK_ACCESS_FS_REFER`` are not | |
| allowed to be tied to files but only to directories. | |
| File descriptor access rights | |
| ----------------------------- | |
| Access rights are checked and tied to file descriptors at open time. The | |
| underlying principle is that equivalent sequences of operations should lead to | |
| the same results, when they are executed under the same Landlock domain. | |
| Taking the ``LANDLOCK_ACCESS_FS_TRUNCATE`` right as an example, it may be | |
| allowed to open a file for writing without being allowed to | |
| :manpage:`ftruncate` the resulting file descriptor if the related file | |
| hierarchy doesn't grant that access right. The following sequences of | |
| operations have the same semantic and should then have the same result: | |
| * ``truncate(path);`` | |
| * ``int fd = open(path, O_WRONLY); ftruncate(fd); close(fd);`` | |
| Similarly to file access modes (e.g. ``O_RDWR``), Landlock access rights | |
| attached to file descriptors are retained even if they are passed between | |
| processes (e.g. through a Unix domain socket). Such access rights will then be | |
| enforced even if the receiving process is not sandboxed by Landlock. Indeed, | |
| this is required to keep access controls consistent over the whole system, and | |
| this avoids unattended bypasses through file descriptor passing (i.e. confused | |
| deputy attack). | |
| .. _scoped-flags-interaction: | |
| Interaction between scoped flags and other access rights | |
| -------------------------------------------------------- | |
| The ``scoped`` flags in &struct landlock_ruleset_attr restrict the | |
| use of *outgoing* IPC from the created Landlock domain, while they | |
| permit reaching out to IPC endpoints *within* the created Landlock | |
| domain. | |
| In the future, scoped flags *may* interact with other access rights, | |
| e.g. so that abstract UNIX sockets can be allow-listed by name, or so | |
| that signals can be allow-listed by signal number or target process. | |
| When introducing ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX``, we defined it to | |
| implicitly have the same scoping semantics as a | |
| ``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` flag would have: connecting to | |
| UNIX sockets within the same domain (where | |
| ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX`` is used) is unconditionally | |
| allowed. | |
| The reasoning is: | |
| * Like other IPC mechanisms, connecting to named UNIX sockets in the | |
| same domain should be expected and harmless. (If needed, users can | |
| further refine their Landlock policies with nested domains or by | |
| restricting ``LANDLOCK_ACCESS_FS_MAKE_SOCK``.) | |
| * We reserve the option to still introduce | |
| ``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` in the future. (This would | |
| be useful if we wanted to have a Landlock rule to permit IPC access | |
| to other Landlock domains.) | |
| * But we can postpone the point in time when users have to deal with | |
| two interacting flags visible in the userspace API. (In particular, | |
| it is possible that it won't be needed in practice, in which case we | |
| can avoid the second flag altogether.) | |
| * If we *do* introduce ``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` in the | |
| future, setting this scoped flag in a ruleset does *not reduce* the | |
| restrictions, because access within the same scope is already | |
| allowed based on ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX``. | |
| Tests | |
| ===== | |
| Userspace tests for backward compatibility, ptrace restrictions and filesystem | |
| support can be found here: `tools/testing/selftests/landlock/`_. | |
| Kernel structures | |
| ================= | |
| Object | |
| ------ | |
| .. kernel-doc:: security/landlock/object.h | |
| :identifiers: | |
| Filesystem | |
| ---------- | |
| .. kernel-doc:: security/landlock/fs.h | |
| :identifiers: | |
| Process credential | |
| ------------------ | |
| .. kernel-doc:: security/landlock/cred.h | |
| :identifiers: | |
| Ruleset and domain | |
| ------------------ | |
| A domain is a read-only ruleset tied to a set of subjects (i.e. tasks' | |
| credentials). Each time a ruleset is enforced on a task, the current domain is | |
| duplicated and the ruleset is imported as a new layer of rules in the new | |
| domain. Indeed, once in a domain, each rule is tied to a layer level. To | |
| grant access to an object, at least one rule of each layer must allow the | |
| requested action on the object. A task can then only transit to a new domain | |
| that is the intersection of the constraints from the current domain and those | |
| of a ruleset provided by the task. | |
| The definition of a subject is implicit for a task sandboxing itself, which | |
| makes the reasoning much easier and helps avoid pitfalls. | |
| .. kernel-doc:: security/landlock/ruleset.h | |
| :identifiers: | |
| .. kernel-doc:: security/landlock/domain.h | |
| :identifiers: | |
| Additional documentation | |
| ======================== | |
| * Documentation/userspace-api/landlock.rst | |
| * Documentation/admin-guide/LSM/landlock.rst | |
| * https://landlock.io | |
| .. Links | |
| .. _tools/testing/selftests/landlock/: | |
| https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/landlock/ |