Skip to content

Commit cb44e4f

Browse files
committed
Merge tag 'landlock-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux
Pull Landlock updates from Mickaël Salaün: - improve the path_rename LSM hook implementations for RENAME_EXCHANGE; - fix a too-restrictive filesystem control for a rare corner case; - set the nested sandbox limitation to 16 layers; - add a new LANDLOCK_ACCESS_FS_REFER access right to properly handle file reparenting (i.e. full rename and link support); - add new tests and documentation; - format code with clang-format to make it easier to maintain and contribute. * tag 'landlock-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: (30 commits) landlock: Explain how to support Landlock landlock: Add design choices documentation for filesystem access rights landlock: Document good practices about filesystem policies landlock: Document LANDLOCK_ACCESS_FS_REFER and ABI versioning samples/landlock: Add support for file reparenting selftests/landlock: Add 11 new test suites dedicated to file reparenting landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER LSM: Remove double path_rename hook calls for RENAME_EXCHANGE landlock: Move filesystem helpers and add a new one landlock: Fix same-layer rule unions landlock: Create find_rule() from unmask_layers() landlock: Reduce the maximum number of layers to 16 landlock: Define access_mask_t to enforce a consistent access mask size selftests/landlock: Test landlock_create_ruleset(2) argument check ordering landlock: Change landlock_restrict_self(2) check ordering landlock: Change landlock_add_rule(2) argument check ordering selftests/landlock: Add tests for O_PATH selftests/landlock: Fully test file rename with "remove" access selftests/landlock: Extend access right tests to directories selftests/landlock: Add tests for unknown access rights ...
2 parents efd1df1 + 5e46982 commit cb44e4f

24 files changed

Lines changed: 2646 additions & 760 deletions

File tree

Documentation/security/landlock.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Landlock LSM: kernel documentation
77
==================================
88

99
:Author: Mickaël Salaün
10-
:Date: March 2021
10+
:Date: May 2022
1111

1212
Landlock's goal is to create scoped access-control (i.e. sandboxing). To
1313
harden a whole system, this feature should be available to any process,
@@ -42,6 +42,21 @@ Guiding principles for safe access controls
4242
* Computation related to Landlock operations (e.g. enforcing a ruleset) shall
4343
only impact the processes requesting them.
4444

45+
Design choices
46+
==============
47+
48+
Filesystem access rights
49+
------------------------
50+
51+
All access rights are tied to an inode and what can be accessed through it.
52+
Reading the content of a directory doesn't imply to be allowed to read the
53+
content of a listed inode. Indeed, a file name is local to its parent
54+
directory, and an inode can be referenced by multiple file names thanks to
55+
(hard) links. Being able to unlink a file only has a direct impact on the
56+
directory, not the unlinked inode. This is the reason why
57+
`LANDLOCK_ACCESS_FS_REMOVE_FILE` or `LANDLOCK_ACCESS_FS_REFER` are not allowed
58+
to be tied to files but only to directories.
59+
4560
Tests
4661
=====
4762

Documentation/userspace-api/landlock.rst

Lines changed: 157 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
.. SPDX-License-Identifier: GPL-2.0
22
.. Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
33
.. Copyright © 2019-2020 ANSSI
4-
.. Copyright © 2021 Microsoft Corporation
4+
.. Copyright © 2021-2022 Microsoft Corporation
55
66
=====================================
77
Landlock: unprivileged access control
88
=====================================
99

1010
:Author: Mickaël Salaün
11-
:Date: March 2021
11+
:Date: May 2022
1212

1313
The goal of Landlock is to enable to restrict ambient rights (e.g. global
1414
filesystem access) for a set of processes. Because Landlock is a stackable
@@ -18,6 +18,13 @@ is expected to help mitigate the security impact of bugs or
1818
unexpected/malicious behaviors in user space applications. Landlock empowers
1919
any process, including unprivileged ones, to securely restrict themselves.
2020

21+
We can quickly make sure that Landlock is enabled in the running system by
22+
looking for "landlock: Up and running" in kernel logs (as root): ``dmesg | grep
23+
landlock || journalctl -kg landlock`` . Developers can also easily check for
24+
Landlock support with a :ref:`related system call <landlock_abi_versions>`. If
25+
Landlock is not currently supported, we need to :ref:`configure the kernel
26+
appropriately <kernel_support>`.
27+
2128
Landlock rules
2229
==============
2330

@@ -29,14 +36,15 @@ the thread enforcing it, and its future children.
2936
Defining and enforcing a security policy
3037
----------------------------------------
3138

32-
We first need to create the ruleset that will contain our rules. For this
39+
We first need to define the ruleset that will contain our rules. For this
3340
example, the ruleset will contain rules that only allow read actions, but write
3441
actions will be denied. The ruleset then needs to handle both of these kind of
35-
actions.
42+
actions. This is required for backward and forward compatibility (i.e. the
43+
kernel and user space may not know each other's supported restrictions), hence
44+
the need to be explicit about the denied-by-default access rights.
3645

3746
.. code-block:: c
3847
39-
int ruleset_fd;
4048
struct landlock_ruleset_attr ruleset_attr = {
4149
.handled_access_fs =
4250
LANDLOCK_ACCESS_FS_EXECUTE |
@@ -51,9 +59,34 @@ actions.
5159
LANDLOCK_ACCESS_FS_MAKE_SOCK |
5260
LANDLOCK_ACCESS_FS_MAKE_FIFO |
5361
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
54-
LANDLOCK_ACCESS_FS_MAKE_SYM,
62+
LANDLOCK_ACCESS_FS_MAKE_SYM |
63+
LANDLOCK_ACCESS_FS_REFER,
5564
};
5665
66+
Because we may not know on which kernel version an application will be
67+
executed, it is safer to follow a best-effort security approach. Indeed, we
68+
should try to protect users as much as possible whatever the kernel they are
69+
using. To avoid binary enforcement (i.e. either all security features or
70+
none), we can leverage a dedicated Landlock command to get the current version
71+
of the Landlock ABI and adapt the handled accesses. Let's check if we should
72+
remove the `LANDLOCK_ACCESS_FS_REFER` access right which is only supported
73+
starting with the second version of the ABI.
74+
75+
.. code-block:: c
76+
77+
int abi;
78+
79+
abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
80+
if (abi < 2) {
81+
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
82+
}
83+
84+
This enables to create an inclusive ruleset that will contain our rules.
85+
86+
.. code-block:: c
87+
88+
int ruleset_fd;
89+
5790
ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
5891
if (ruleset_fd < 0) {
5992
perror("Failed to create a ruleset");
@@ -92,6 +125,11 @@ descriptor.
92125
return 1;
93126
}
94127
128+
It may also be required to create rules following the same logic as explained
129+
for the ruleset creation, by filtering access rights according to the Landlock
130+
ABI version. In this example, this is not required because
131+
`LANDLOCK_ACCESS_FS_REFER` is not allowed by any rule.
132+
95133
We now have a ruleset with one rule allowing read access to ``/usr`` while
96134
denying all other handled accesses for the filesystem. The next step is to
97135
restrict the current thread from gaining more privileges (e.g. thanks to a SUID
@@ -125,6 +163,27 @@ ruleset.
125163

126164
Full working code can be found in `samples/landlock/sandboxer.c`_.
127165

166+
Good practices
167+
--------------
168+
169+
It is recommended setting access rights to file hierarchy leaves as much as
170+
possible. For instance, it is better to be able to have ``~/doc/`` as a
171+
read-only hierarchy and ``~/tmp/`` as a read-write hierarchy, compared to
172+
``~/`` as a read-only hierarchy and ``~/tmp/`` as a read-write hierarchy.
173+
Following this good practice leads to self-sufficient hierarchies that don't
174+
depend on their location (i.e. parent directories). This is particularly
175+
relevant when we want to allow linking or renaming. Indeed, having consistent
176+
access rights per directory enables to change the location of such directory
177+
without relying on the destination directory access rights (except those that
178+
are required for this operation, see `LANDLOCK_ACCESS_FS_REFER` documentation).
179+
Having self-sufficient hierarchies also helps to tighten the required access
180+
rights to the minimal set of data. This also helps avoid sinkhole directories,
181+
i.e. directories where data can be linked to but not linked from. However,
182+
this depends on data organization, which might not be controlled by developers.
183+
In this case, granting read-write access to ``~/tmp/``, instead of write-only
184+
access, would potentially allow to move ``~/tmp/`` to a non-readable directory
185+
and still keep the ability to list the content of ``~/tmp/``.
186+
128187
Layers of file path access rights
129188
---------------------------------
130189

@@ -192,6 +251,58 @@ To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
192251
process, a sandboxed process should have a subset of the target process rules,
193252
which means the tracee must be in a sub-domain of the tracer.
194253

254+
Compatibility
255+
=============
256+
257+
Backward and forward compatibility
258+
----------------------------------
259+
260+
Landlock is designed to be compatible with past and future versions of the
261+
kernel. This is achieved thanks to the system call attributes and the
262+
associated bitflags, particularly the ruleset's `handled_access_fs`. Making
263+
handled access right explicit enables the kernel and user space to have a clear
264+
contract with each other. This is required to make sure sandboxing will not
265+
get stricter with a system update, which could break applications.
266+
267+
Developers can subscribe to the `Landlock mailing list
268+
<https://subspace.kernel.org/lists.linux.dev.html>`_ to knowingly update and
269+
test their applications with the latest available features. In the interest of
270+
users, and because they may use different kernel versions, it is strongly
271+
encouraged to follow a best-effort security approach by checking the Landlock
272+
ABI version at runtime and only enforcing the supported features.
273+
274+
.. _landlock_abi_versions:
275+
276+
Landlock ABI versions
277+
---------------------
278+
279+
The Landlock ABI version can be read with the sys_landlock_create_ruleset()
280+
system call:
281+
282+
.. code-block:: c
283+
284+
int abi;
285+
286+
abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
287+
if (abi < 0) {
288+
switch (errno) {
289+
case ENOSYS:
290+
printf("Landlock is not supported by the current kernel.\n");
291+
break;
292+
case EOPNOTSUPP:
293+
printf("Landlock is currently disabled.\n");
294+
break;
295+
}
296+
return 0;
297+
}
298+
if (abi >= 2) {
299+
printf("Landlock supports LANDLOCK_ACCESS_FS_REFER.\n");
300+
}
301+
302+
The following kernel interfaces are implicitly supported by the first ABI
303+
version. Features only supported from a specific version are explicitly marked
304+
as such.
305+
195306
Kernel interface
196307
================
197308

@@ -228,21 +339,6 @@ Enforcing a ruleset
228339
Current limitations
229340
===================
230341

231-
File renaming and linking
232-
-------------------------
233-
234-
Because Landlock targets unprivileged access controls, it is needed to properly
235-
handle composition of rules. Such property also implies rules nesting.
236-
Properly handling multiple layers of ruleset, each one of them able to restrict
237-
access to files, also implies to inherit the ruleset restrictions from a parent
238-
to its hierarchy. Because files are identified and restricted by their
239-
hierarchy, moving or linking a file from one directory to another implies to
240-
propagate the hierarchy constraints. To protect against privilege escalations
241-
through renaming or linking, and for the sake of simplicity, Landlock currently
242-
limits linking and renaming to the same directory. Future Landlock evolutions
243-
will enable more flexibility for renaming and linking, with dedicated ruleset
244-
flags.
245-
246342
Filesystem topology modification
247343
--------------------------------
248344

@@ -267,8 +363,8 @@ restrict such paths with dedicated ruleset flags.
267363
Ruleset layers
268364
--------------
269365

270-
There is a limit of 64 layers of stacked rulesets. This can be an issue for a
271-
task willing to enforce a new ruleset in complement to its 64 inherited
366+
There is a limit of 16 layers of stacked rulesets. This can be an issue for a
367+
task willing to enforce a new ruleset in complement to its 16 inherited
272368
rulesets. Once this limit is reached, sys_landlock_restrict_self() returns
273369
E2BIG. It is then strongly suggested to carefully build rulesets once in the
274370
life of a thread, especially for applications able to launch other applications
@@ -281,6 +377,44 @@ Memory usage
281377
Kernel memory allocated to create rulesets is accounted and can be restricted
282378
by the Documentation/admin-guide/cgroup-v1/memory.rst.
283379

380+
Previous limitations
381+
====================
382+
383+
File renaming and linking (ABI 1)
384+
---------------------------------
385+
386+
Because Landlock targets unprivileged access controls, it needs to properly
387+
handle composition of rules. Such property also implies rules nesting.
388+
Properly handling multiple layers of rulesets, each one of them able to
389+
restrict access to files, also implies inheritance of the ruleset restrictions
390+
from a parent to its hierarchy. Because files are identified and restricted by
391+
their hierarchy, moving or linking a file from one directory to another implies
392+
propagation of the hierarchy constraints, or restriction of these actions
393+
according to the potentially lost constraints. To protect against privilege
394+
escalations through renaming or linking, and for the sake of simplicity,
395+
Landlock previously limited linking and renaming to the same directory.
396+
Starting with the Landlock ABI version 2, it is now possible to securely
397+
control renaming and linking thanks to the new `LANDLOCK_ACCESS_FS_REFER`
398+
access right.
399+
400+
.. _kernel_support:
401+
402+
Kernel support
403+
==============
404+
405+
Landlock was first introduced in Linux 5.13 but it must be configured at build
406+
time with `CONFIG_SECURITY_LANDLOCK=y`. Landlock must also be enabled at boot
407+
time as the other security modules. The list of security modules enabled by
408+
default is set with `CONFIG_LSM`. The kernel configuration should then
409+
contains `CONFIG_LSM=landlock,[...]` with `[...]` as the list of other
410+
potentially useful security modules for the running system (see the
411+
`CONFIG_LSM` help).
412+
413+
If the running kernel doesn't have `landlock` in `CONFIG_LSM`, then we can
414+
still enable it by adding ``lsm=landlock,[...]`` to
415+
Documentation/admin-guide/kernel-parameters.rst thanks to the bootloader
416+
configuration.
417+
284418
Questions and answers
285419
=====================
286420

include/linux/lsm_hook_defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ LSM_HOOK(int, 0, path_link, struct dentry *old_dentry,
100100
const struct path *new_dir, struct dentry *new_dentry)
101101
LSM_HOOK(int, 0, path_rename, const struct path *old_dir,
102102
struct dentry *old_dentry, const struct path *new_dir,
103-
struct dentry *new_dentry)
103+
struct dentry *new_dentry, unsigned int flags)
104104
LSM_HOOK(int, 0, path_chmod, const struct path *path, umode_t mode)
105105
LSM_HOOK(int, 0, path_chown, const struct path *path, kuid_t uid, kgid_t gid)
106106
LSM_HOOK(int, 0, path_chroot, const struct path *path)

include/linux/lsm_hooks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@
358358
* @old_dentry contains the dentry structure of the old link.
359359
* @new_dir contains the path structure for parent of the new link.
360360
* @new_dentry contains the dentry structure of the new link.
361+
* @flags may contain rename options such as RENAME_EXCHANGE.
361362
* Return 0 if permission is granted.
362363
* @path_chmod:
363364
* Check for permission to change a mode of the file @path. The new

include/uapi/linux/landlock.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,14 @@ struct landlock_ruleset_attr {
2121
/**
2222
* @handled_access_fs: Bitmask of actions (cf. `Filesystem flags`_)
2323
* that is handled by this ruleset and should then be forbidden if no
24-
* rule explicitly allow them. This is needed for backward
25-
* compatibility reasons.
24+
* rule explicitly allow them: it is a deny-by-default list that should
25+
* contain as much Landlock access rights as possible. Indeed, all
26+
* Landlock filesystem access rights that are not part of
27+
* handled_access_fs are allowed. This is needed for backward
28+
* compatibility reasons. One exception is the
29+
* LANDLOCK_ACCESS_FS_REFER access right, which is always implicitly
30+
* handled, but must still be explicitly handled to add new rules with
31+
* this access right.
2632
*/
2733
__u64 handled_access_fs;
2834
};
@@ -33,7 +39,9 @@ struct landlock_ruleset_attr {
3339
* - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
3440
* version.
3541
*/
42+
/* clang-format off */
3643
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
44+
/* clang-format on */
3745

3846
/**
3947
* enum landlock_rule_type - Landlock rule type
@@ -60,8 +68,9 @@ struct landlock_path_beneath_attr {
6068
*/
6169
__u64 allowed_access;
6270
/**
63-
* @parent_fd: File descriptor, open with ``O_PATH``, which identifies
64-
* the parent directory of a file hierarchy, or just a file.
71+
* @parent_fd: File descriptor, preferably opened with ``O_PATH``,
72+
* which identifies the parent directory of a file hierarchy, or just a
73+
* file.
6574
*/
6675
__s32 parent_fd;
6776
/*
@@ -109,6 +118,22 @@ struct landlock_path_beneath_attr {
109118
* - %LANDLOCK_ACCESS_FS_MAKE_FIFO: Create (or rename or link) a named pipe.
110119
* - %LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device.
111120
* - %LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link.
121+
* - %LANDLOCK_ACCESS_FS_REFER: Link or rename a file from or to a different
122+
* directory (i.e. reparent a file hierarchy). This access right is
123+
* available since the second version of the Landlock ABI. This is also the
124+
* only access right which is always considered handled by any ruleset in
125+
* such a way that reparenting a file hierarchy is always denied by default.
126+
* To avoid privilege escalation, it is not enough to add a rule with this
127+
* access right. When linking or renaming a file, the destination directory
128+
* hierarchy must also always have the same or a superset of restrictions of
129+
* the source hierarchy. If it is not the case, or if the domain doesn't
130+
* handle this access right, such actions are denied by default with errno
131+
* set to EXDEV. Linking also requires a LANDLOCK_ACCESS_FS_MAKE_* access
132+
* right on the destination directory, and renaming also requires a
133+
* LANDLOCK_ACCESS_FS_REMOVE_* access right on the source's (file or
134+
* directory) parent. Otherwise, such actions are denied with errno set to
135+
* EACCES. The EACCES errno prevails over EXDEV to let user space
136+
* efficiently deal with an unrecoverable error.
112137
*
113138
* .. warning::
114139
*
@@ -120,6 +145,7 @@ struct landlock_path_beneath_attr {
120145
* :manpage:`access(2)`.
121146
* Future Landlock evolutions will enable to restrict them.
122147
*/
148+
/* clang-format off */
123149
#define LANDLOCK_ACCESS_FS_EXECUTE (1ULL << 0)
124150
#define LANDLOCK_ACCESS_FS_WRITE_FILE (1ULL << 1)
125151
#define LANDLOCK_ACCESS_FS_READ_FILE (1ULL << 2)
@@ -133,5 +159,7 @@ struct landlock_path_beneath_attr {
133159
#define LANDLOCK_ACCESS_FS_MAKE_FIFO (1ULL << 10)
134160
#define LANDLOCK_ACCESS_FS_MAKE_BLOCK (1ULL << 11)
135161
#define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12)
162+
#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
163+
/* clang-format on */
136164

137165
#endif /* _UAPI_LINUX_LANDLOCK_H */

0 commit comments

Comments
 (0)