Re: [RFC PATCH v14 10/10] landlock: Add user and kernel documentation
From: Mickaël Salaün <mic@digikod.net>
Date: 2020-03-02 10:03:41
Also in:
linux-arch, linux-doc, linux-fsdevel, linux-kselftest, linux-security-module, lkml
On 29/02/2020 18:23, Randy Dunlap wrote:
Hi, Here are a few corrections for you to consider. On 2/24/20 8:02 AM, Mickaël Salaün wrote:quoted
This documentation can be built with the Sphinx framework. Another location might be more appropriate, though. Signed-off-by: Mickaël Salaün <mic@digikod.net> Reviewed-by: Vincent Dagonneau <redacted> Cc: Andy Lutomirski <luto@amacapital.net> Cc: James Morris <jmorris@namei.org> Cc: Kees Cook <redacted> Cc: Serge E. Hallyn <serge@hallyn.com> --- Changes since v13: * Rewrote the documentation according to the major revamp. Previous version: https://lore.kernel.org/lkml/20191104172146.30797-8-mic@digikod.net/ (local) --- Documentation/security/index.rst | 1 + Documentation/security/landlock/index.rst | 18 ++ Documentation/security/landlock/kernel.rst | 44 ++++ Documentation/security/landlock/user.rst | 233 +++++++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 Documentation/security/landlock/index.rst create mode 100644 Documentation/security/landlock/kernel.rst create mode 100644 Documentation/security/landlock/user.rstdiff --git a/Documentation/security/landlock/index.rst b/Documentation/security/landlock/index.rst new file mode 100644 index 000000000000..dbd33b96ce60 --- /dev/null +++ b/Documentation/security/landlock/index.rst@@ -0,0 +1,18 @@ +========================================= +Landlock LSM: unprivileged access control +========================================= + +:Author: Mickaël Salaün + +The goal of Landlock is to enable to restrict ambient rights (e.g. global +filesystem access) for a set of processes. Because Landlock is a stackable +LSM, it makes possible to create safe security sandboxes as new 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 or +unexpected/malicious behaviors in user-space applications. Landlock empower anyempowersquoted
+process, including unprivileged ones, to securely restrict themselves. + +.. toctree:: + + user + kerneldiff --git a/Documentation/security/landlock/kernel.rst b/Documentation/security/landlock/kernel.rst new file mode 100644 index 000000000000..b87769909029 --- /dev/null +++ b/Documentation/security/landlock/kernel.rst@@ -0,0 +1,44 @@ +============================== +Landlock: kernel documentation +============================== + +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 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). Indeed, 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 according to the inherited ones in a way that ensure that only moreensuresquoted
+constraints can be added. + + +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 kind of side-channel attacks (e.g. leak of securitykindsquoted
+ 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. enforce a ruleset) shall + only impact the processes requesting them. + + +Landlock rulesets and domains +============================= + +A domain is a read-only ruleset tied to a set of subjects (i.e. tasks). A +domain can transition to a new one which is the intersection of the constraints +from the current and a new ruleset. The definition of a subject is implicit +for a task sandboxing itself, which makes the reasoning much easier and helps +avoid pitfalls.diff --git a/Documentation/security/landlock/user.rst b/Documentation/security/landlock/user.rst new file mode 100644 index 000000000000..cbd7f61fca8c --- /dev/null +++ b/Documentation/security/landlock/user.rst@@ -0,0 +1,233 @@ +================================= +Landlock: userspace documentation +================================= + +Landlock rules +============== + +A Landlock rule enables to describe an action on an object. An object is +currently a file hierarchy, and the related filesystem actions are defined in +`Access rights`_. A set of rules are aggregated in a ruleset, which can thenisquoted
+restricts the thread enforcing it, and its future children.restrictquoted
+ + +Defining and enforcing a security policy +---------------------------------------- + +Before defining a security policy, an application should first probe for the +features supported by the running kernel, which is important to be compatible +with older kernels. This can be done thanks to the `landlock` syscall (cf. +:ref:`syscall`). + +.. code-block:: c + + struct landlock_attr_features attr_features; + + if (landlock(LANDLOCK_CMD_GET_FEATURES, LANDLOCK_OPT_GET_FEATURES, + sizeof(attr_features), &attr_features)) { + perror("Failed to probe the Landlock supported features"); + return 1; + } + +Then, we need to create the ruleset that will contains our rules. For thiscontainquoted
+example, the ruleset will contains rules which only allow read actions, butcontainquoted
+write actions will be denied. The ruleset then needs to handle both of these +kind of actions. To have a backward compatibility, these actions should be +ANDed with the supported ones. + +.. code-block:: c + + int ruleset_fd; + struct landlock_attr_ruleset ruleset = { + .handled_access_fs = + LANDLOCK_ACCESS_FS_READ | + LANDLOCK_ACCESS_FS_READDIR | + LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_WRITE | + LANDLOCK_ACCESS_FS_TRUNCATE | + LANDLOCK_ACCESS_FS_CHMOD | + LANDLOCK_ACCESS_FS_CHOWN | + LANDLOCK_ACCESS_FS_CHGRP | + LANDLOCK_ACCESS_FS_LINK_TO | + LANDLOCK_ACCESS_FS_RENAME_FROM | + LANDLOCK_ACCESS_FS_RENAME_TO | + LANDLOCK_ACCESS_FS_RMDIR | + LANDLOCK_ACCESS_FS_UNLINK | + 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, + }; + + ruleset.handled_access_fs &= attr_features.access_fs; + ruleset_fd = landlock(LANDLOCK_CMD_CREATE_RULESET, + LANDLOCK_OPT_CREATE_RULESET, sizeof(ruleset), &ruleset); + if (ruleset_fd < 0) { + perror("Failed to create a ruleset"); + return 1; + } + +We can now add a new rule to this ruleset thanks to the returned file +descriptor referring to this ruleset. The rule will only enable to read the +file hierarchy ``/usr``. Without other rule, write actions would then beWithout other rules, or Without another rule,quoted
+denied by the ruleset. To add ``/usr`` to the ruleset, we open it with the +``O_PATH`` flag and fill the &struct landlock_attr_path_beneath with this file +descriptor. + +.. code-block:: c + + int err; + struct landlock_attr_path_beneath path_beneath = { + .ruleset_fd = ruleset_fd, + .allowed_access = + LANDLOCK_ACCESS_FS_READ | + LANDLOCK_ACCESS_FS_READDIR | + LANDLOCK_ACCESS_FS_EXECUTE, + }; + + path_beneath.allowed_access &= attr_features.access_fs; + path_beneath.parent_fd = open("/usr", O_PATH | O_CLOEXEC); + if (path_beneath.parent_fd < 0) { + perror("Failed to open file"); + close(ruleset_fd); + return 1; + } + err = landlock(LANDLOCK_CMD_ADD_RULE, LANDLOCK_OPT_ADD_RULE_PATH_BENEATH, + sizeof(path_beneath), &path_beneath); + close(path_beneath.parent_fd); + if (err) { + perror("Failed to update ruleset"); + close(ruleset_fd); + return 1; + } + +We now have a ruleset with one rule allowing read access to ``/usr`` while +denying all accesses featured in ``attr_features.access_fs`` to everything else +on the filesystem. The next step is to restrict the current thread from +gaining more privileges (e.g. thanks to a SUID binary). + +.. code-block:: c + + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("Failed to restrict privileges"); + close(ruleset_fd); + return 1; + } + +The current thread is now ready to sandbox itself with the ruleset. + +.. code-block:: c + + struct landlock_attr_enforce attr_enforce = { + .ruleset_fd = ruleset_fd, + }; + + if (landlock(LANDLOCK_CMD_ENFORCE_RULESET, LANDLOCK_OPT_ENFORCE_RULESET, + sizeof(attr_enforce), &attr_enforce)) { + perror("Failed to enforce ruleset"); + close(ruleset_fd); + return 1; + } + close(ruleset_fd); + +If this last system call succeeds, the current thread is now restricted andIf this last landlock system call succeeds, [because close() is the last system call]quoted
+this policy will be enforced on all its subsequently created children as well. +Once a thread is landlocked, there is no way to remove its security policy,preferably: policy;quoted
+only adding more restrictions is allowed. These threads are now in a new +Landlock domain, merge of their parent one (if any) with the new ruleset. + +A full working code can be found in `samples/landlock/sandboxer.c`_.Full working codequoted
+ + +Inheritance +----------- + +Every new thread resulting from a :manpage:`clone(2)` inherits Landlock program +restrictions from its parent. This is similar to the seccomp inheritance (cf. +:doc:`/userspace-api/seccomp_filter`) or any other LSM dealing with task's +:manpage:`credentials(7)`. For instance, one process' thread may applyprocess'squoted
+Landlock rules to itself, but they will not be automatically applied to other +sibling threads (unlike POSIX thread credential changes, cf. +:manpage:`nptl(7)`).[snip] thanks for the documentation.
Done. Thanks for this attentive review!