Skip to content

Commit 2fc0e78

Browse files
committed
Merge tag 'landlock-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux
Pull landlock updates from Mickaël Salaün: "This brings ioctl control to Landlock, contributed by Günther Noack. This also adds him as a Landlock reviewer, and fixes an issue in the sample" * tag 'landlock-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: MAINTAINERS: Add Günther Noack as Landlock reviewer fs/ioctl: Add a comment to keep the logic in sync with LSM policies MAINTAINERS: Notify Landlock maintainers about changes to fs/ioctl.c landlock: Document IOCTL support samples/landlock: Add support for LANDLOCK_ACCESS_FS_IOCTL_DEV selftests/landlock: Exhaustive test for the IOCTL allow-list selftests/landlock: Check IOCTL restrictions for named UNIX domain sockets selftests/landlock: Test IOCTLs on named pipes selftests/landlock: Test ioctl(2) and ftruncate(2) with open(O_PATH) selftests/landlock: Test IOCTL with memfds selftests/landlock: Test IOCTL support landlock: Add IOCTL access right for character and block devices samples/landlock: Fix incorrect free in populate_ruleset_net
2 parents 89721e3 + 5bf9e57 commit 2fc0e78

File tree

10 files changed

+811
-46
lines changed

10 files changed

+811
-46
lines changed

Documentation/userspace-api/landlock.rst

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Landlock: unprivileged access control
88
=====================================
99

1010
:Author: Mickaël Salaün
11-
:Date: October 2023
11+
:Date: April 2024
1212

1313
The goal of Landlock is to enable to restrict ambient rights (e.g. global
1414
filesystem or network access) for a set of processes. Because Landlock
@@ -76,7 +76,8 @@ to be explicit about the denied-by-default access rights.
7676
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
7777
LANDLOCK_ACCESS_FS_MAKE_SYM |
7878
LANDLOCK_ACCESS_FS_REFER |
79-
LANDLOCK_ACCESS_FS_TRUNCATE,
79+
LANDLOCK_ACCESS_FS_TRUNCATE |
80+
LANDLOCK_ACCESS_FS_IOCTL_DEV,
8081
.handled_access_net =
8182
LANDLOCK_ACCESS_NET_BIND_TCP |
8283
LANDLOCK_ACCESS_NET_CONNECT_TCP,
@@ -85,10 +86,10 @@ to be explicit about the denied-by-default access rights.
8586
Because we may not know on which kernel version an application will be
8687
executed, it is safer to follow a best-effort security approach. Indeed, we
8788
should try to protect users as much as possible whatever the kernel they are
88-
using. To avoid binary enforcement (i.e. either all security features or
89-
none), we can leverage a dedicated Landlock command to get the current version
90-
of the Landlock ABI and adapt the handled accesses. Let's check if we should
91-
remove access rights which are only supported in higher versions of the ABI.
89+
using.
90+
91+
To be compatible with older Linux versions, we detect the available Landlock ABI
92+
version, and only use the available subset of access rights:
9293

9394
.. code-block:: c
9495
@@ -114,6 +115,10 @@ remove access rights which are only supported in higher versions of the ABI.
114115
ruleset_attr.handled_access_net &=
115116
~(LANDLOCK_ACCESS_NET_BIND_TCP |
116117
LANDLOCK_ACCESS_NET_CONNECT_TCP);
118+
__attribute__((fallthrough));
119+
case 4:
120+
/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */
121+
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
117122
}
118123
119124
This enables to create an inclusive ruleset that will contain our rules.
@@ -225,6 +230,7 @@ access rights per directory enables to change the location of such directory
225230
without relying on the destination directory access rights (except those that
226231
are required for this operation, see ``LANDLOCK_ACCESS_FS_REFER``
227232
documentation).
233+
228234
Having self-sufficient hierarchies also helps to tighten the required access
229235
rights to the minimal set of data. This also helps avoid sinkhole directories,
230236
i.e. directories where data can be linked to but not linked from. However,
@@ -318,18 +324,26 @@ It should also be noted that truncating files does not require the
318324
system call, this can also be done through :manpage:`open(2)` with the flags
319325
``O_RDONLY | O_TRUNC``.
320326

321-
When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE``
322-
right is associated with the newly created file descriptor and will be used for
323-
subsequent truncation attempts using :manpage:`ftruncate(2)`. The behavior is
324-
similar to opening a file for reading or writing, where permissions are checked
325-
during :manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and
327+
The truncate right is associated with the opened file (see below).
328+
329+
Rights associated with file descriptors
330+
---------------------------------------
331+
332+
When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE`` and
333+
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` rights is associated with the newly created
334+
file descriptor and will be used for subsequent truncation and ioctl attempts
335+
using :manpage:`ftruncate(2)` and :manpage:`ioctl(2)`. The behavior is similar
336+
to opening a file for reading or writing, where permissions are checked during
337+
:manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and
326338
:manpage:`write(2)` calls.
327339

328-
As a consequence, it is possible to have multiple open file descriptors for the
329-
same file, where one grants the right to truncate the file and the other does
330-
not. It is also possible to pass such file descriptors between processes,
331-
keeping their Landlock properties, even when these processes do not have an
332-
enforced Landlock ruleset.
340+
As a consequence, it is possible that a process has multiple open file
341+
descriptors referring to the same file, but Landlock enforces different things
342+
when operating with these file descriptors. This can happen when a Landlock
343+
ruleset gets enforced and the process keeps file descriptors which were opened
344+
both before and after the enforcement. It is also possible to pass such file
345+
descriptors between processes, keeping their Landlock properties, even when some
346+
of the involved processes do not have an enforced Landlock ruleset.
333347

334348
Compatibility
335349
=============
@@ -458,6 +472,28 @@ Memory usage
458472
Kernel memory allocated to create rulesets is accounted and can be restricted
459473
by the Documentation/admin-guide/cgroup-v1/memory.rst.
460474

475+
IOCTL support
476+
-------------
477+
478+
The ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right restricts the use of
479+
:manpage:`ioctl(2)`, but it only applies to *newly opened* device files. This
480+
means specifically that pre-existing file descriptors like stdin, stdout and
481+
stderr are unaffected.
482+
483+
Users should be aware that TTY devices have traditionally permitted to control
484+
other processes on the same TTY through the ``TIOCSTI`` and ``TIOCLINUX`` IOCTL
485+
commands. Both of these require ``CAP_SYS_ADMIN`` on modern Linux systems, but
486+
the behavior is configurable for ``TIOCSTI``.
487+
488+
On older systems, it is therefore recommended to close inherited TTY file
489+
descriptors, or to reopen them from ``/proc/self/fd/*`` without the
490+
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right, if possible.
491+
492+
Landlock's IOCTL support is coarse-grained at the moment, but may become more
493+
fine-grained in the future. Until then, users are advised to establish the
494+
guarantees that they need through the file hierarchy, by only allowing the
495+
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right on files where it is really required.
496+
461497
Previous limitations
462498
====================
463499

@@ -495,6 +531,16 @@ bind and connect actions to only a set of allowed ports thanks to the new
495531
``LANDLOCK_ACCESS_NET_BIND_TCP`` and ``LANDLOCK_ACCESS_NET_CONNECT_TCP``
496532
access rights.
497533

534+
IOCTL (ABI < 5)
535+
---------------
536+
537+
IOCTL operations could not be denied before the fifth Landlock ABI, so
538+
:manpage:`ioctl(2)` is always allowed when using a kernel that only supports an
539+
earlier ABI.
540+
541+
Starting with the Landlock ABI version 5, it is possible to restrict the use of
542+
:manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right.
543+
498544
.. _kernel_support:
499545

500546
Kernel support

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12374,12 +12374,14 @@ F: net/l3mdev
1237412374

1237512375
LANDLOCK SECURITY MODULE
1237612376
M: Mickaël Salaün <mic@digikod.net>
12377+
R: Günther Noack <gnoack@google.com>
1237712378
L: linux-security-module@vger.kernel.org
1237812379
S: Supported
1237912380
W: https://landlock.io
1238012381
T: git https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git
1238112382
F: Documentation/security/landlock.rst
1238212383
F: Documentation/userspace-api/landlock.rst
12384+
F: fs/ioctl.c
1238312385
F: include/uapi/linux/landlock.h
1238412386
F: samples/landlock/
1238512387
F: security/landlock/

fs/ioctl.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
796796
*
797797
* When you add any new common ioctls to the switches above and below,
798798
* please ensure they have compatible arguments in compat mode.
799+
*
800+
* The LSM mailing list should also be notified of any command additions or
801+
* changes, as specific LSMs may be affected.
799802
*/
800803
static int do_vfs_ioctl(struct file *filp, unsigned int fd,
801804
unsigned int cmd, unsigned long arg)

include/uapi/linux/landlock.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ struct landlock_net_port_attr {
128128
* files and directories. Files or directories opened before the sandboxing
129129
* are not subject to these restrictions.
130130
*
131-
* A file can only receive these access rights:
131+
* The following access rights apply only to files:
132132
*
133133
* - %LANDLOCK_ACCESS_FS_EXECUTE: Execute a file.
134134
* - %LANDLOCK_ACCESS_FS_WRITE_FILE: Open a file with write access. Note that
@@ -138,12 +138,13 @@ struct landlock_net_port_attr {
138138
* - %LANDLOCK_ACCESS_FS_READ_FILE: Open a file with read access.
139139
* - %LANDLOCK_ACCESS_FS_TRUNCATE: Truncate a file with :manpage:`truncate(2)`,
140140
* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with
141-
* ``O_TRUNC``. Whether an opened file can be truncated with
142-
* :manpage:`ftruncate(2)` is determined during :manpage:`open(2)`, in the
143-
* same way as read and write permissions are checked during
144-
* :manpage:`open(2)` using %LANDLOCK_ACCESS_FS_READ_FILE and
145-
* %LANDLOCK_ACCESS_FS_WRITE_FILE. This access right is available since the
146-
* third version of the Landlock ABI.
141+
* ``O_TRUNC``. This access right is available since the third version of the
142+
* Landlock ABI.
143+
*
144+
* Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
145+
* with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
146+
* read and write permissions are checked during :manpage:`open(2)` using
147+
* %LANDLOCK_ACCESS_FS_READ_FILE and %LANDLOCK_ACCESS_FS_WRITE_FILE.
147148
*
148149
* A directory can receive access rights related to files or directories. The
149150
* following access right is applied to the directory itself, and the
@@ -198,13 +199,33 @@ struct landlock_net_port_attr {
198199
* If multiple requirements are not met, the ``EACCES`` error code takes
199200
* precedence over ``EXDEV``.
200201
*
202+
* The following access right applies both to files and directories:
203+
*
204+
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
205+
* character or block device.
206+
*
207+
* This access right applies to all `ioctl(2)` commands implemented by device
208+
* drivers. However, the following common IOCTL commands continue to be
209+
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
210+
*
211+
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
212+
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
213+
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
214+
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
215+
* * Some IOCTL commands which do not make sense when used with devices, but
216+
* whose implementations are safe and return the right error codes
217+
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
218+
*
219+
* This access right is available since the fifth version of the Landlock
220+
* ABI.
221+
*
201222
* .. warning::
202223
*
203224
* It is currently not possible to restrict some file-related actions
204225
* accessible through these syscall families: :manpage:`chdir(2)`,
205226
* :manpage:`stat(2)`, :manpage:`flock(2)`, :manpage:`chmod(2)`,
206227
* :manpage:`chown(2)`, :manpage:`setxattr(2)`, :manpage:`utime(2)`,
207-
* :manpage:`ioctl(2)`, :manpage:`fcntl(2)`, :manpage:`access(2)`.
228+
* :manpage:`fcntl(2)`, :manpage:`access(2)`.
208229
* Future Landlock evolutions will enable to restrict them.
209230
*/
210231
/* clang-format off */
@@ -223,6 +244,7 @@ struct landlock_net_port_attr {
223244
#define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12)
224245
#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
225246
#define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
247+
#define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
226248
/* clang-format on */
227249

228250
/**

samples/landlock/sandboxer.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ static int parse_path(char *env_path, const char ***const path_list)
8181
LANDLOCK_ACCESS_FS_EXECUTE | \
8282
LANDLOCK_ACCESS_FS_WRITE_FILE | \
8383
LANDLOCK_ACCESS_FS_READ_FILE | \
84-
LANDLOCK_ACCESS_FS_TRUNCATE)
84+
LANDLOCK_ACCESS_FS_TRUNCATE | \
85+
LANDLOCK_ACCESS_FS_IOCTL_DEV)
8586

8687
/* clang-format on */
8788

@@ -153,7 +154,7 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
153154
const __u64 allowed_access)
154155
{
155156
int ret = 1;
156-
char *env_port_name, *strport;
157+
char *env_port_name, *env_port_name_next, *strport;
157158
struct landlock_net_port_attr net_port = {
158159
.allowed_access = allowed_access,
159160
.port = 0,
@@ -165,7 +166,8 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
165166
env_port_name = strdup(env_port_name);
166167
unsetenv(env_var);
167168

168-
while ((strport = strsep(&env_port_name, ENV_DELIMITER))) {
169+
env_port_name_next = env_port_name;
170+
while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) {
169171
net_port.port = atoi(strport);
170172
if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
171173
&net_port, 0)) {
@@ -201,11 +203,12 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
201203
LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
202204
LANDLOCK_ACCESS_FS_MAKE_SYM | \
203205
LANDLOCK_ACCESS_FS_REFER | \
204-
LANDLOCK_ACCESS_FS_TRUNCATE)
206+
LANDLOCK_ACCESS_FS_TRUNCATE | \
207+
LANDLOCK_ACCESS_FS_IOCTL_DEV)
205208

206209
/* clang-format on */
207210

208-
#define LANDLOCK_ABI_LAST 4
211+
#define LANDLOCK_ABI_LAST 5
209212

210213
int main(const int argc, char *const argv[], char *const *const envp)
211214
{
@@ -319,6 +322,11 @@ int main(const int argc, char *const argv[], char *const *const envp)
319322
ruleset_attr.handled_access_net &=
320323
~(LANDLOCK_ACCESS_NET_BIND_TCP |
321324
LANDLOCK_ACCESS_NET_CONNECT_TCP);
325+
__attribute__((fallthrough));
326+
case 4:
327+
/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */
328+
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
329+
322330
fprintf(stderr,
323331
"Hint: You should update the running kernel "
324332
"to leverage Landlock features "

0 commit comments

Comments
 (0)