Skip to content

Commit

Permalink
Merge tag 'landlock-6.10-rc1' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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
  • Loading branch information
torvalds committed May 18, 2024
2 parents 89721e3 + 5bf9e57 commit 2fc0e78
Show file tree
Hide file tree
Showing 10 changed files with 811 additions and 46 deletions.
78 changes: 62 additions & 16 deletions Documentation/userspace-api/landlock.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Landlock: unprivileged access control
=====================================

:Author: Mickaël Salaün
:Date: October 2023
:Date: April 2024

The goal of Landlock is to enable to restrict ambient rights (e.g. global
filesystem or network access) for a set of processes. Because Landlock
Expand Down Expand Up @@ -76,7 +76,8 @@ to be explicit about the denied-by-default access rights.
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
LANDLOCK_ACCESS_FS_MAKE_SYM |
LANDLOCK_ACCESS_FS_REFER |
LANDLOCK_ACCESS_FS_TRUNCATE,
LANDLOCK_ACCESS_FS_TRUNCATE |
LANDLOCK_ACCESS_FS_IOCTL_DEV,
.handled_access_net =
LANDLOCK_ACCESS_NET_BIND_TCP |
LANDLOCK_ACCESS_NET_CONNECT_TCP,
Expand All @@ -85,10 +86,10 @@ to be explicit about the denied-by-default access rights.
Because we may not know on which kernel version an application will be
executed, it is safer to follow a best-effort security approach. Indeed, we
should try to protect users as much as possible whatever the kernel they are
using. To avoid binary enforcement (i.e. either all security features or
none), we can leverage a dedicated Landlock command to get the current version
of the Landlock ABI and adapt the handled accesses. Let's check if we should
remove access rights which are only supported in higher versions of the ABI.
using.

To be compatible with older Linux versions, we detect the available Landlock ABI
version, and only use the available subset of access rights:

.. code-block:: c
Expand All @@ -114,6 +115,10 @@ remove access rights which are only supported in higher versions of the ABI.
ruleset_attr.handled_access_net &=
~(LANDLOCK_ACCESS_NET_BIND_TCP |
LANDLOCK_ACCESS_NET_CONNECT_TCP);
__attribute__((fallthrough));
case 4:
/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
}
This enables to create an inclusive ruleset that will contain our rules.
Expand Down Expand Up @@ -225,6 +230,7 @@ access rights per directory enables to change the location of such directory
without relying on the destination directory access rights (except those that
are required for this operation, see ``LANDLOCK_ACCESS_FS_REFER``
documentation).

Having self-sufficient hierarchies also helps to tighten the required access
rights to the minimal set of data. This also helps avoid sinkhole directories,
i.e. directories where data can be linked to but not linked from. However,
Expand Down Expand Up @@ -318,18 +324,26 @@ 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``.

When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE``
right is associated with the newly created file descriptor and will be used for
subsequent truncation attempts using :manpage:`ftruncate(2)`. The behavior is
similar to opening a file for reading or writing, where permissions are checked
during :manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and
The truncate right is associated with the opened file (see below).

Rights associated with file descriptors
---------------------------------------

When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE`` and
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` rights is associated with the newly created
file descriptor and will be used for subsequent truncation and ioctl attempts
using :manpage:`ftruncate(2)` and :manpage:`ioctl(2)`. The behavior is similar
to opening a file for reading or writing, where permissions are checked during
:manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and
:manpage:`write(2)` calls.

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

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

IOCTL support
-------------

The ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right restricts the use of
:manpage:`ioctl(2)`, but it only applies to *newly opened* device files. This
means specifically that pre-existing file descriptors like stdin, stdout and
stderr are unaffected.

Users should be aware that TTY devices have traditionally permitted to control
other processes on the same TTY through the ``TIOCSTI`` and ``TIOCLINUX`` IOCTL
commands. Both of these require ``CAP_SYS_ADMIN`` on modern Linux systems, but
the behavior is configurable for ``TIOCSTI``.

On older systems, it is therefore recommended to close inherited TTY file
descriptors, or to reopen them from ``/proc/self/fd/*`` without the
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right, if possible.

Landlock's IOCTL support is coarse-grained at the moment, but may become more
fine-grained in the future. Until then, users are advised to establish the
guarantees that they need through the file hierarchy, by only allowing the
``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right on files where it is really required.

Previous limitations
====================

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

IOCTL (ABI < 5)
---------------

IOCTL operations could not be denied before the fifth Landlock ABI, so
:manpage:`ioctl(2)` is always allowed when using a kernel that only supports an
earlier ABI.

Starting with the Landlock ABI version 5, it is possible to restrict the use of
:manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right.

.. _kernel_support:

Kernel support
Expand Down
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -12374,12 +12374,14 @@ F: net/l3mdev

LANDLOCK SECURITY MODULE
M: Mickaël Salaün <[email protected]>
R: Günther Noack <[email protected]>
L: [email protected]
S: Supported
W: https://landlock.io
T: git https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git
F: Documentation/security/landlock.rst
F: Documentation/userspace-api/landlock.rst
F: fs/ioctl.c
F: include/uapi/linux/landlock.h
F: samples/landlock/
F: security/landlock/
Expand Down
3 changes: 3 additions & 0 deletions fs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,9 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
*
* When you add any new common ioctls to the switches above and below,
* please ensure they have compatible arguments in compat mode.
*
* The LSM mailing list should also be notified of any command additions or
* changes, as specific LSMs may be affected.
*/
static int do_vfs_ioctl(struct file *filp, unsigned int fd,
unsigned int cmd, unsigned long arg)
Expand Down
38 changes: 30 additions & 8 deletions include/uapi/linux/landlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct landlock_net_port_attr {
* files and directories. Files or directories opened before the sandboxing
* are not subject to these restrictions.
*
* A file can only receive these access rights:
* The following access rights apply only to files:
*
* - %LANDLOCK_ACCESS_FS_EXECUTE: Execute a file.
* - %LANDLOCK_ACCESS_FS_WRITE_FILE: Open a file with write access. Note that
Expand All @@ -138,12 +138,13 @@ struct landlock_net_port_attr {
* - %LANDLOCK_ACCESS_FS_READ_FILE: Open a file with read access.
* - %LANDLOCK_ACCESS_FS_TRUNCATE: Truncate a file with :manpage:`truncate(2)`,
* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with
* ``O_TRUNC``. Whether an opened file can be truncated with
* :manpage:`ftruncate(2)` is determined during :manpage:`open(2)`, in the
* same way as read and write permissions are checked during
* :manpage:`open(2)` using %LANDLOCK_ACCESS_FS_READ_FILE and
* %LANDLOCK_ACCESS_FS_WRITE_FILE. This access right is available since the
* third version of the Landlock ABI.
* ``O_TRUNC``. This access right is available since the third version of the
* Landlock ABI.
*
* Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
* with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
* read and write permissions are checked during :manpage:`open(2)` using
* %LANDLOCK_ACCESS_FS_READ_FILE and %LANDLOCK_ACCESS_FS_WRITE_FILE.
*
* A directory can receive access rights related to files or directories. The
* following access right is applied to the directory itself, and the
Expand Down Expand Up @@ -198,13 +199,33 @@ struct landlock_net_port_attr {
* If multiple requirements are not met, the ``EACCES`` error code takes
* precedence over ``EXDEV``.
*
* The following access right applies both to files and directories:
*
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
* character or block device.
*
* This access right applies to all `ioctl(2)` commands implemented by device
* drivers. However, the following common IOCTL commands continue to be
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
*
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
* * Some IOCTL commands which do not make sense when used with devices, but
* whose implementations are safe and return the right error codes
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
*
* This access right is available since the fifth version of the Landlock
* ABI.
*
* .. warning::
*
* It is currently not possible to restrict some file-related actions
* accessible through these syscall families: :manpage:`chdir(2)`,
* :manpage:`stat(2)`, :manpage:`flock(2)`, :manpage:`chmod(2)`,
* :manpage:`chown(2)`, :manpage:`setxattr(2)`, :manpage:`utime(2)`,
* :manpage:`ioctl(2)`, :manpage:`fcntl(2)`, :manpage:`access(2)`.
* :manpage:`fcntl(2)`, :manpage:`access(2)`.
* Future Landlock evolutions will enable to restrict them.
*/
/* clang-format off */
Expand All @@ -223,6 +244,7 @@ struct landlock_net_port_attr {
#define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12)
#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
#define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
#define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
/* clang-format on */

/**
Expand Down
18 changes: 13 additions & 5 deletions samples/landlock/sandboxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ static int parse_path(char *env_path, const char ***const path_list)
LANDLOCK_ACCESS_FS_EXECUTE | \
LANDLOCK_ACCESS_FS_WRITE_FILE | \
LANDLOCK_ACCESS_FS_READ_FILE | \
LANDLOCK_ACCESS_FS_TRUNCATE)
LANDLOCK_ACCESS_FS_TRUNCATE | \
LANDLOCK_ACCESS_FS_IOCTL_DEV)

/* clang-format on */

Expand Down Expand Up @@ -153,7 +154,7 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
const __u64 allowed_access)
{
int ret = 1;
char *env_port_name, *strport;
char *env_port_name, *env_port_name_next, *strport;
struct landlock_net_port_attr net_port = {
.allowed_access = allowed_access,
.port = 0,
Expand All @@ -165,7 +166,8 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
env_port_name = strdup(env_port_name);
unsetenv(env_var);

while ((strport = strsep(&env_port_name, ENV_DELIMITER))) {
env_port_name_next = env_port_name;
while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) {
net_port.port = atoi(strport);
if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
&net_port, 0)) {
Expand Down Expand Up @@ -201,11 +203,12 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
LANDLOCK_ACCESS_FS_MAKE_SYM | \
LANDLOCK_ACCESS_FS_REFER | \
LANDLOCK_ACCESS_FS_TRUNCATE)
LANDLOCK_ACCESS_FS_TRUNCATE | \
LANDLOCK_ACCESS_FS_IOCTL_DEV)

/* clang-format on */

#define LANDLOCK_ABI_LAST 4
#define LANDLOCK_ABI_LAST 5

int main(const int argc, char *const argv[], char *const *const envp)
{
Expand Down Expand Up @@ -319,6 +322,11 @@ int main(const int argc, char *const argv[], char *const *const envp)
ruleset_attr.handled_access_net &=
~(LANDLOCK_ACCESS_NET_BIND_TCP |
LANDLOCK_ACCESS_NET_CONNECT_TCP);
__attribute__((fallthrough));
case 4:
/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;

fprintf(stderr,
"Hint: You should update the running kernel "
"to leverage Landlock features "
Expand Down
Loading

0 comments on commit 2fc0e78

Please sign in to comment.