diff options
Diffstat (limited to 'Documentation/userspace-api/landlock.rst')
| -rw-r--r-- | Documentation/userspace-api/landlock.rst | 212 |
1 files changed, 170 insertions, 42 deletions
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst index ad587f53fe41..fd8b78c31f2f 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -8,7 +8,7 @@ Landlock: unprivileged access control ===================================== :Author: Mickaël Salaün -:Date: January 2025 +:Date: March 2026 The goal of Landlock is to enable restriction of ambient rights (e.g. global filesystem or network access) for a set of processes. Because Landlock @@ -77,7 +77,8 @@ to be explicit about the denied-by-default access rights. LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_TRUNCATE | - LANDLOCK_ACCESS_FS_IOCTL_DEV, + LANDLOCK_ACCESS_FS_IOCTL_DEV | + LANDLOCK_ACCESS_FS_RESOLVE_UNIX, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP, @@ -127,6 +128,10 @@ version, and only use the available subset of access rights: /* Removes LANDLOCK_SCOPE_* for ABI < 6 */ ruleset_attr.scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | LANDLOCK_SCOPE_SIGNAL); + __attribute__((fallthrough)); + case 6 ... 8: + /* Removes LANDLOCK_ACCESS_FS_RESOLVE_UNIX for ABI < 9 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_RESOLVE_UNIX; } This enables the creation of an inclusive ruleset that will contain our rules. @@ -142,11 +147,11 @@ This enables the creation of an inclusive ruleset that will contain our rules. } We can now add a new rule to this ruleset thanks to the returned file -descriptor referring to this ruleset. The rule will only allow reading the -file hierarchy ``/usr``. Without another rule, write actions would then be -denied by the ruleset. To add ``/usr`` to the ruleset, we open it with the -``O_PATH`` flag and fill the &struct landlock_path_beneath_attr with this file -descriptor. +descriptor referring to this ruleset. The rule will allow reading and +executing the file hierarchy ``/usr``. Without another rule, write actions +would then be denied by the ruleset. To add ``/usr`` to the ruleset, we open +it with the ``O_PATH`` flag and fill the &struct landlock_path_beneath_attr with +this file descriptor. .. code-block:: c @@ -191,10 +196,39 @@ number for a specific action: HTTPS connections. err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, &net_port, 0); +When passing a non-zero ``flags`` argument to ``landlock_restrict_self()``, a +similar backwards compatibility check is needed for the restrict flags +(see sys_landlock_restrict_self() documentation for available flags): + +.. code-block:: c + + __u32 restrict_flags = + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON | + LANDLOCK_RESTRICT_SELF_TSYNC; + switch (abi) { + case 1 ... 6: + /* Removes logging flags for ABI < 7 */ + restrict_flags &= ~(LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF | + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON | + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF); + __attribute__((fallthrough)); + case 7: + /* + * Removes multithreaded enforcement flag for ABI < 8 + * + * WARNING: Without this flag, calling landlock_restrict_self(2) is + * only equivalent if the calling process is single-threaded. Below + * ABI v8 (and as of ABI v8, when not using this flag), a Landlock + * policy would only be enforced for the calling thread and its + * children (and not for all threads, including parents and siblings). + */ + restrict_flags &= ~LANDLOCK_RESTRICT_SELF_TSYNC; + } + 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 rule -allowing read access to ``/usr`` while denying all other handled accesses for -the filesystem, and a second rule allowing HTTPS connections. +allowing read and execute access to ``/usr`` while denying all other handled +accesses for the filesystem, and a second rule allowing HTTPS connections. .. code-block:: c @@ -208,7 +242,7 @@ The current thread is now ready to sandbox itself with the ruleset. .. code-block:: c - if (landlock_restrict_self(ruleset_fd, 0)) { + if (landlock_restrict_self(ruleset_fd, restrict_flags)) { perror("Failed to enforce ruleset"); close(ruleset_fd); return 1; @@ -317,41 +351,40 @@ IPC scoping ----------- Similar to the implicit `Ptrace restrictions`_, we may want to further restrict -interactions between sandboxes. Each Landlock domain can be explicitly scoped -for a set of actions by specifying it on a ruleset. For example, if a -sandboxed process should not be able to :manpage:`connect(2)` to a -non-sandboxed process through abstract :manpage:`unix(7)` sockets, we can -specify such a restriction with ``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``. -Moreover, if a sandboxed process should not be able to send a signal to a -non-sandboxed process, we can specify this restriction with -``LANDLOCK_SCOPE_SIGNAL``. - -A sandboxed process can connect to a non-sandboxed process when its domain is -not scoped. If a process's domain is scoped, it can only connect to sockets -created by processes in the same scope. -Moreover, if a process is scoped to send signal to a non-scoped process, it can -only send signals to processes in the same scope. - -A connected datagram socket behaves like a stream socket when its domain is -scoped, meaning if the domain is scoped after the socket is connected, it can -still :manpage:`send(2)` data just like a stream socket. However, in the same -scenario, a non-connected datagram socket cannot send data (with -:manpage:`sendto(2)`) outside its scope. - -A process with a scoped domain can inherit a socket created by a non-scoped -process. The process cannot connect to this socket since it has a scoped -domain. - -IPC scoping does not support exceptions, so if a domain is scoped, no rules can -be added to allow access to resources or processes outside of the scope. +interactions between sandboxes. Therefore, at ruleset creation time, each +Landlock domain can restrict the scope for certain operations, so that these +operations can only reach out to processes within the same Landlock domain or in +a nested Landlock domain (the "scope"). + +The operations which can be scoped are: + +``LANDLOCK_SCOPE_SIGNAL`` + This limits the sending of signals to target processes which run within the + same or a nested Landlock domain. + +``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET`` + This limits the set of abstract :manpage:`unix(7)` sockets to which we can + :manpage:`connect(2)` to socket addresses which were created by a process in + the same or a nested Landlock domain. + + A :manpage:`sendto(2)` on a non-connected datagram socket is treated as if + it were doing an implicit :manpage:`connect(2)` and will be blocked if the + remote end does not stem from the same or a nested Landlock domain. + + A :manpage:`sendto(2)` on a socket which was previously connected will not + be restricted. This works for both datagram and stream sockets. + +IPC scoping does not support exceptions via :manpage:`landlock_add_rule(2)`. +If an operation is scoped within a domain, no rules can be added to allow access +to resources or processes outside of the scope. Truncating files ---------------- The operations covered by ``LANDLOCK_ACCESS_FS_WRITE_FILE`` and ``LANDLOCK_ACCESS_FS_TRUNCATE`` both change the contents of a file and sometimes -overlap in non-intuitive ways. It is recommended to always specify both of -these together. +overlap in non-intuitive ways. It is strongly recommended to always specify +both of these together (either granting both, or granting none). A particularly surprising example is :manpage:`creat(2)`. The name suggests that this system call requires the rights to create and write files. However, @@ -363,6 +396,10 @@ It should also be noted that truncating files does not require the system call, this can also be done through :manpage:`open(2)` with the flags ``O_RDONLY | O_TRUNC``. +At the same time, on some filesystems, :manpage:`fallocate(2)` offers a way to +shorten file contents with ``FALLOC_FL_COLLAPSE_RANGE`` when the file is opened +for writing, sidestepping the ``LANDLOCK_ACCESS_FS_TRUNCATE`` right. + The truncate right is associated with the opened file (see below). Rights associated with file descriptors @@ -432,9 +469,68 @@ system call: printf("Landlock supports LANDLOCK_ACCESS_FS_REFER.\n"); } -The following kernel interfaces are implicitly supported by the first ABI -version. Features only supported from a specific version are explicitly marked -as such. +All Landlock kernel interfaces are supported by the first ABI version unless +explicitly noted in their documentation. + +Landlock errata +--------------- + +In addition to ABI versions, Landlock provides an errata mechanism to track +fixes for issues that may affect backwards compatibility or require userspace +awareness. The errata bitmask can be queried using: + +.. code-block:: c + + int errata; + + errata = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_ERRATA); + if (errata < 0) { + /* Landlock not available or disabled */ + return 0; + } + +The returned value is a bitmask where each bit represents a specific erratum. +If bit N is set (``errata & (1 << (N - 1))``), then erratum N has been fixed +in the running kernel. + +.. warning:: + + **Most applications should NOT check errata.** In 99.9% of cases, checking + errata is unnecessary, increases code complexity, and can potentially + decrease protection if misused. For example, disabling the sandbox when an + erratum is not fixed could leave the system less secure than using + Landlock's best-effort protection. When in doubt, ignore errata. + +.. kernel-doc:: security/landlock/errata/abi-4.h + :doc: erratum_1 + +.. kernel-doc:: security/landlock/errata/abi-6.h + :doc: erratum_2 + +.. kernel-doc:: security/landlock/errata/abi-1.h + :doc: erratum_3 + +How to check for errata +~~~~~~~~~~~~~~~~~~~~~~~ + +If you determine that your application needs to check for specific errata, +use this pattern: + +.. code-block:: c + + int errata = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_ERRATA); + if (errata >= 0) { + /* Check for specific erratum (1-indexed) */ + if (errata & (1 << (erratum_number - 1))) { + /* Erratum N is fixed in this kernel */ + } else { + /* Erratum N is NOT fixed - consider implications for your use case */ + } + } + +**Important:** Only check errata if your application specifically relies on +behavior that changed due to the fix. The fixes generally make Landlock less +restrictive or more correct, not more restrictive. Kernel interface ================ @@ -595,6 +691,31 @@ Starting with the Landlock ABI version 6, it is possible to restrict :manpage:`signal(7)` sending by setting ``LANDLOCK_SCOPE_SIGNAL`` to the ``scoped`` ruleset attribute. +Logging (ABI < 7) +----------------- + +Starting with the Landlock ABI version 7, it is possible to control logging of +Landlock audit events with the ``LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF``, +``LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON``, and +``LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF`` flags passed to +sys_landlock_restrict_self(). See Documentation/admin-guide/LSM/landlock.rst +for more details on audit. + +Thread synchronization (ABI < 8) +-------------------------------- + +Starting with the Landlock ABI version 8, it is now possible to +enforce Landlock rulesets across all threads of the calling process +using the ``LANDLOCK_RESTRICT_SELF_TSYNC`` flag passed to +sys_landlock_restrict_self(). + +Pathname UNIX sockets (ABI < 9) +------------------------------- + +Starting with the Landlock ABI version 9, it is possible to restrict +connections to pathname UNIX domain sockets (:manpage:`unix(7)`) using +the new ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX`` right. + .. _kernel_support: Kernel support @@ -683,9 +804,16 @@ fine-grained restrictions). Moreover, their complexity can lead to security issues, especially when untrusted processes can manipulate them (cf. `Controlling access to user namespaces <https://lwn.net/Articles/673597/>`_). +How to disable Landlock audit records? +-------------------------------------- + +You might want to put in place filters as explained here: +Documentation/admin-guide/LSM/landlock.rst + Additional documentation ======================== +* Documentation/admin-guide/LSM/landlock.rst * Documentation/security/landlock.rst * https://landlock.io |
