From patchwork Fri Feb 9 17:06:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551634 Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33D49745ED for ; Fri, 9 Feb 2024 17:06:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498383; cv=none; b=sGvGFI3/b6CJygSd9jcN+4dZnyGbUY0Jpq96K1RfjYBTEYnNKqF7XuRolupFvOd6A3sX/prbGxJljx7CdhME66W8L58wKbNqQUYnmwl2QlK2TBqMA5j9SVswj0PQFcA9HIxnsmiipku4s05k7LVlEeHNTcs2a4wgLR+i0JE40xE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498383; c=relaxed/simple; bh=X1diXY+DYKrMWa5Z7a4F9dAoaifyZNERvchyXwVO+UY=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=LEGrNGjoVq3p99oTP3kTMGJA+coG43Zw0LgTW1m1IqMkdR6zhutFrYEsXY6fgXc717WbVxfjRXMcNhxHJq4CKMsX9qYKpoM8khPA9KFHTVOCZ5wMEuBOVS9aaGfF0+mxaIzSxFEeo8qX8MEaA1mE/ZjxJjDb/XAK5bZ2vF5jk7I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=wNDpK04C; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wNDpK04C" Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dc74800c869so1760278276.2 for ; Fri, 09 Feb 2024 09:06:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498380; x=1708103180; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=Hkbuo6BwnabPk1udt6nxLTjNAj3su/byHyS9EixaHCg=; b=wNDpK04CVku3RtRioMczGjLRCHW1LaAgPkPpaCjTUke0om8Mwd/gl4Wgq+WX5Hw1GF KCFYpq7ogEnM9t+xzI2pXS1ULcll3DOSHx6jCFGb3XwB3CZoR+yfZUxsN7vKukY/OQFn jY90J3KQz7Kh6TN3EYvu/YJ1VcTH3NA2sC1L+sf2lFjgropglYusw8AaZWRDiGOTCG6U xPuZhe20aK2XBwXXs2uYJWyufFzENAOStZ+O2t2UgiFYJv2rT94bVngT/rj4HDawHFtF uAUWbzI7db8qw+s1Jh6lerTr34Rh46kTWFy0tJH22BgdrfWD9fBxffKP0OeixsByEKF3 WNow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498380; x=1708103180; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=Hkbuo6BwnabPk1udt6nxLTjNAj3su/byHyS9EixaHCg=; b=Ck56YSGXJiYcUfbAhKat4m7+Bjfb36ioXlX9esfBmK8BslsEFGQvoWWK4pokn4pcWa bQDOiD6cVJ0YV85nNHyWnEozSj+u3dWtQ0Z0vGpuke5jH7H/zLC1KKfhqXFJusoYy1yj v+5lbHqYdH0KJHPwYJ+4bxL46r4dVk7vlmGdSPq/BzIBVcov/RecO2GYtIGyX6rhr0YX UwzWATrGcUyhZWpYSAmzddMjpV1F6uaOUFdx1sZ7Q08AZyRTBX+D8lx95X2zCTzssnTo tvKS7h8v2zsXENol/A7g84M2oo4r4Xmz7+r5OLdalcvO5w7T8QglhBmB9mQOXcfb94i8 WwEA== X-Gm-Message-State: AOJu0Yxh51FwTDe3uA0Db0UTkkZ1DT/b7mRyyQxwB7mqaBcYCBkac7ia RFjGmOwJw4WTlJH7AjtFabzpz0TUoVD9gSAIH4KIkVh2kVA5nK/sOyonGtBZqZBrwr7NU+3+Pr9 QDw== X-Google-Smtp-Source: AGHT+IGPcRY6hKjecmGfhMVTqgjSfDuVwuV+HGr+ABQS64Er+yZK8GTz4uKiUnab3iPw4yyn5I3feTI6P4U= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6902:2283:b0:dc2:5525:f6b with SMTP id dn3-20020a056902228300b00dc255250f6bmr457667ybb.7.1707498380274; Fri, 09 Feb 2024 09:06:20 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:05 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-2-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 1/8] landlock: Add IOCTL access right From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Introduces the LANDLOCK_ACCESS_FS_IOCTL access right and increments the Landlock ABI version to 5. Like the truncate right, these rights are associated with a file descriptor at the time of open(2), and get respected even when the file descriptor is used outside of the thread which it was originally opened in. A newly enabled Landlock policy therefore does not apply to file descriptors which are already open. If the LANDLOCK_ACCESS_FS_IOCTL right is handled, only a small number of safe IOCTL commands will be permitted on newly opened files. The permitted IOCTLs can be configured through the ruleset in limited ways now. (See documentation for details.) Specifically, when LANDLOCK_ACCESS_FS_IOCTL is handled, granting this right on a file or directory will *not* permit to do all IOCTL commands, but only influence the IOCTL commands which are not already handled through other access rights. The intent is to keep the groups of IOCTL commands more fine-grained. Noteworthy scenarios which require special attention: TTY devices are often passed into a process from the parent process, and so a newly enabled Landlock policy does not retroactively apply to them automatically. In the past, TTY devices have often supported IOCTL commands like TIOCSTI and some TIOCLINUX subcommands, which were letting callers control the TTY input buffer (and simulate keypresses). This should be restricted to CAP_SYS_ADMIN programs on modern kernels though. Some legitimate file system features, like setting up fscrypt, are exposed as IOCTL commands on regular files and directories -- users of Landlock are advised to double check that the sandboxed process does not need to invoke these IOCTLs. Known limitations: The LANDLOCK_ACCESS_FS_IOCTL access right is a coarse-grained control over IOCTL commands. Future work will enable a more fine-grained access control for IOCTLs. In the meantime, Landlock users may use path-based restrictions in combination with their knowledge about the file system layout to control what IOCTLs can be done. Mounting file systems with the nodev option can help to distinguish regular files and devices, and give guarantees about the affected files, which Landlock alone can not give yet. Signed-off-by: Günther Noack --- include/uapi/linux/landlock.h | 55 ++++- security/landlock/fs.c | 227 ++++++++++++++++++- security/landlock/fs.h | 3 + security/landlock/limits.h | 11 +- security/landlock/ruleset.h | 2 +- security/landlock/syscalls.c | 19 +- tools/testing/selftests/landlock/base_test.c | 2 +- tools/testing/selftests/landlock/fs_test.c | 5 +- 8 files changed, 302 insertions(+), 22 deletions(-) diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 25c8d7677539..16d7d72804f8 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -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 @@ -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 @@ -198,13 +199,50 @@ 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: Invoke :manpage:`ioctl(2)` commands on an opened + * file or directory. + * + * This access right applies to all :manpage:`ioctl(2)` commands, except of + * ``FIOCLEX``, ``FIONCLEX``, ``FIONBIO`` and ``FIOASYNC``. These commands + * continue to be invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL + * access right. + * + * When certain other access rights are handled in the ruleset, in addition to + * %LANDLOCK_ACCESS_FS_IOCTL, granting these access rights will unlock access + * to additional groups of IOCTL commands, on the affected files: + * + * * %LANDLOCK_ACCESS_FS_READ_FILE and %LANDLOCK_ACCESS_FS_WRITE_FILE unlock + * access to ``FIOQSIZE``, ``FIONREAD``, ``FIGETBSZ``, ``FS_IOC_FIEMAP``, + * ``FIBMAP``, ``FIDEDUPERANGE``, ``FICLONE``, ``FICLONERANGE``, + * ``FS_IOC_RESVSP``, ``FS_IOC_RESVSP64``, ``FS_IOC_UNRESVSP``, + * ``FS_IOC_UNRESVSP64``, ``FS_IOC_ZERO_RANGE``. + * + * * %LANDLOCK_ACCESS_FS_READ_DIR unlocks access to ``FIOQSIZE``, + * ``FIONREAD``, ``FIGETBSZ``. + * + * When these access rights are handled in the ruleset, the availability of + * the affected IOCTL commands is not governed by %LANDLOCK_ACCESS_FS_IOCTL + * any more, but by the respective access right. + * + * All other IOCTL commands are not handled specially, and are governed by + * %LANDLOCK_ACCESS_FS_IOCTL. This includes %FS_IOC_GETFLAGS and + * %FS_IOC_SETFLAGS for manipulating inode flags (:manpage:`ioctl_iflags(2)`), + * %FS_IOC_FSFETXATTR and %FS_IOC_FSSETXATTR for manipulating extended + * attributes, as well as %FIFREEZE and %FITHAW for freezing and thawing file + * systems. + * + * 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 */ @@ -223,6 +261,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 (1ULL << 15) /* clang-format on */ /** diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 73997e63734f..84efea3f7c0f 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -7,6 +7,7 @@ * Copyright © 2021-2022 Microsoft Corporation */ +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include #include "common.h" @@ -84,6 +87,186 @@ static const struct landlock_object_underops landlock_fs_underops = { .release = release_inode }; +/* IOCTL helpers */ + +/* + * These are synthetic access rights, which are only used within the kernel, but + * not exposed to callers in userspace. The mapping between these access rights + * and IOCTL commands is defined in the get_required_ioctl_access() helper function. + */ +#define LANDLOCK_ACCESS_FS_IOCTL_RW (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 1) +#define LANDLOCK_ACCESS_FS_IOCTL_RW_FILE (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 2) + +/* ioctl_groups - all synthetic access rights for IOCTL command groups */ +/* clang-format off */ +#define IOCTL_GROUPS ( \ + LANDLOCK_ACCESS_FS_IOCTL_RW | \ + LANDLOCK_ACCESS_FS_IOCTL_RW_FILE) +/* clang-format on */ + +static_assert((IOCTL_GROUPS & LANDLOCK_MASK_ACCESS_FS) == IOCTL_GROUPS); + +/** + * get_required_ioctl_access(): Determine required IOCTL access rights. + * + * @cmd: The IOCTL command that is supposed to be run. + * + * Any new IOCTL commands that are implemented in fs/ioctl.c's do_vfs_ioctl() + * should be considered for inclusion here. + * + * Returns: The access rights that must be granted on an opened file in order to + * use the given @cmd. + */ +static __attribute_const__ access_mask_t +get_required_ioctl_access(const unsigned int cmd) +{ + switch (cmd) { + case FIOCLEX: + case FIONCLEX: + case FIONBIO: + case FIOASYNC: + /* + * FIOCLEX, FIONCLEX, FIONBIO and FIOASYNC manipulate the FD's + * close-on-exec and the file's buffered-IO and async flags. + * These operations are also available through fcntl(2), and are + * unconditionally permitted in Landlock. + */ + return 0; + case FIONREAD: + case FIOQSIZE: + case FIGETBSZ: + /* + * FIONREAD returns the number of bytes available for reading. + * FIONREAD returns the number of immediately readable bytes for + * a file. + * + * FIOQSIZE queries the size of a file or directory. + * + * FIGETBSZ queries the file system's block size for a file or + * directory. + * + * These IOCTL commands are permitted for files which are opened + * with LANDLOCK_ACCESS_FS_READ_DIR, + * LANDLOCK_ACCESS_FS_READ_FILE, or + * LANDLOCK_ACCESS_FS_WRITE_FILE. + */ + return LANDLOCK_ACCESS_FS_IOCTL_RW; + case FS_IOC_FIEMAP: + case FIBMAP: + /* + * FS_IOC_FIEMAP and FIBMAP query information about the + * allocation of blocks within a file. They are permitted for + * files which are opened with LANDLOCK_ACCESS_FS_READ_FILE or + * LANDLOCK_ACCESS_FS_WRITE_FILE. + */ + fallthrough; + case FIDEDUPERANGE: + case FICLONE: + case FICLONERANGE: + /* + * FIDEDUPERANGE, FICLONE and FICLONERANGE make files share + * their underlying storage ("reflink") between source and + * destination FDs, on file systems which support that. + * + * The underlying implementations are already checking whether + * the involved files are opened with the appropriate read/write + * modes. We rely on this being implemented correctly. + * + * These IOCTLs are permitted for files which are opened with + * LANDLOCK_ACCESS_FS_READ_FILE or + * LANDLOCK_ACCESS_FS_WRITE_FILE. + */ + fallthrough; + case FS_IOC_RESVSP: + case FS_IOC_RESVSP64: + case FS_IOC_UNRESVSP: + case FS_IOC_UNRESVSP64: + case FS_IOC_ZERO_RANGE: + /* + * These IOCTLs reserve space, or create holes like + * fallocate(2). We rely on the implementations checking the + * files' read/write modes. + * + * These IOCTLs are permitted for files which are opened with + * LANDLOCK_ACCESS_FS_READ_FILE or + * LANDLOCK_ACCESS_FS_WRITE_FILE. + */ + return LANDLOCK_ACCESS_FS_IOCTL_RW_FILE; + default: + /* + * Other commands are guarded by the catch-all access right. + */ + return LANDLOCK_ACCESS_FS_IOCTL; + } +} + +/** + * expand_ioctl() - Return the dst flags from either the src flag or the + * %LANDLOCK_ACCESS_FS_IOCTL flag, depending on whether the + * %LANDLOCK_ACCESS_FS_IOCTL and src access rights are handled or not. + * + * @handled: Handled access rights. + * @access: The access mask to copy values from. + * @src: A single access right to copy from in @access. + * @dst: One or more access rights to copy to. + * + * Returns: @dst, or 0. + */ +static __attribute_const__ access_mask_t +expand_ioctl(const access_mask_t handled, const access_mask_t access, + const access_mask_t src, const access_mask_t dst) +{ + access_mask_t copy_from; + + if (!(handled & LANDLOCK_ACCESS_FS_IOCTL)) + return 0; + + copy_from = (handled & src) ? src : LANDLOCK_ACCESS_FS_IOCTL; + if (access & copy_from) + return dst; + + return 0; +} + +/** + * landlock_expand_access_fs() - Returns @access with the synthetic IOCTL group + * flags enabled if necessary. + * + * @handled: Handled FS access rights. + * @access: FS access rights to expand. + * + * Returns: @access expanded by the necessary flags for the synthetic IOCTL + * access rights. + */ +static __attribute_const__ access_mask_t landlock_expand_access_fs( + const access_mask_t handled, const access_mask_t access) +{ + return access | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_WRITE_FILE, + LANDLOCK_ACCESS_FS_IOCTL_RW | + LANDLOCK_ACCESS_FS_IOCTL_RW_FILE) | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_READ_FILE, + LANDLOCK_ACCESS_FS_IOCTL_RW | + LANDLOCK_ACCESS_FS_IOCTL_RW_FILE) | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_READ_DIR, + LANDLOCK_ACCESS_FS_IOCTL_RW); +} + +/** + * landlock_expand_handled_access_fs() - add synthetic IOCTL access rights to an + * access mask of handled accesses. + * + * @handled: The handled accesses of a ruleset that is being created. + * + * Returns: @handled, with the bits for the synthetic IOCTL access rights set, + * if %LANDLOCK_ACCESS_FS_IOCTL is handled. + */ +__attribute_const__ access_mask_t +landlock_expand_handled_access_fs(const access_mask_t handled) +{ + return landlock_expand_access_fs(handled, handled); +} + /* Ruleset management */ static struct landlock_object *get_inode_object(struct inode *const inode) @@ -148,7 +331,8 @@ static struct landlock_object *get_inode_object(struct inode *const inode) 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) /* clang-format on */ /* @@ -158,6 +342,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, const struct path *const path, access_mask_t access_rights) { + access_mask_t handled; int err; struct landlock_id id = { .type = LANDLOCK_KEY_INODE, @@ -170,9 +355,11 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, if (WARN_ON_ONCE(ruleset->num_layers != 1)) return -EINVAL; + handled = landlock_get_fs_access_mask(ruleset, 0); + /* Expands the synthetic IOCTL groups. */ + access_rights |= landlock_expand_access_fs(handled, access_rights); /* Transforms relative access rights to absolute ones. */ - access_rights |= LANDLOCK_MASK_ACCESS_FS & - ~landlock_get_fs_access_mask(ruleset, 0); + access_rights |= LANDLOCK_MASK_ACCESS_FS & ~handled; id.key.object = get_inode_object(d_backing_inode(path->dentry)); if (IS_ERR(id.key.object)) return PTR_ERR(id.key.object); @@ -1333,7 +1520,9 @@ static int hook_file_open(struct file *const file) { layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; access_mask_t open_access_request, full_access_request, allowed_access; - const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE; + const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE | + LANDLOCK_ACCESS_FS_IOCTL | + IOCTL_GROUPS; const struct landlock_ruleset *const dom = get_current_fs_domain(); if (!dom) @@ -1375,6 +1564,16 @@ static int hook_file_open(struct file *const file) } } + /* + * Named pipes should be treated just like anonymous pipes. + * Therefore, we permit all IOCTLs on them. + */ + if (S_ISFIFO(file_inode(file)->i_mode)) { + allowed_access |= LANDLOCK_ACCESS_FS_IOCTL | + LANDLOCK_ACCESS_FS_IOCTL_RW | + LANDLOCK_ACCESS_FS_IOCTL_RW_FILE; + } + /* * For operations on already opened files (i.e. ftruncate()), it is the * access rights at the time of open() which decide whether the @@ -1406,6 +1605,25 @@ static int hook_file_truncate(struct file *const file) return -EACCES; } +static int hook_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + const access_mask_t required_access = get_required_ioctl_access(cmd); + const access_mask_t allowed_access = + landlock_file(file)->allowed_access; + + /* + * It is the access rights at the time of opening the file which + * determine whether IOCTL can be used on the opened file later. + * + * The access right is attached to the opened file in hook_file_open(). + */ + if ((allowed_access & required_access) == required_access) + return 0; + + return -EACCES; +} + static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_free_security, hook_inode_free_security), @@ -1428,6 +1646,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(file_alloc_security, hook_file_alloc_security), LSM_HOOK_INIT(file_open, hook_file_open), LSM_HOOK_INIT(file_truncate, hook_file_truncate), + LSM_HOOK_INIT(file_ioctl, hook_file_ioctl), }; __init void landlock_add_fs_hooks(void) diff --git a/security/landlock/fs.h b/security/landlock/fs.h index 488e4813680a..086576b8386b 100644 --- a/security/landlock/fs.h +++ b/security/landlock/fs.h @@ -92,4 +92,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, const struct path *const path, access_mask_t access_hierarchy); +__attribute_const__ access_mask_t +landlock_expand_handled_access_fs(const access_mask_t handled); + #endif /* _SECURITY_LANDLOCK_FS_H */ diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 93c9c6f91556..ecbdc8bbf906 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -18,7 +18,16 @@ #define LANDLOCK_MAX_NUM_LAYERS 16 #define LANDLOCK_MAX_NUM_RULES U32_MAX -#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_TRUNCATE +/* + * For file system access rights, Landlock distinguishes between the publicly + * visible access rights (1 to LANDLOCK_LAST_PUBLIC_ACCESS_FS) and the private + * ones which are not exposed to userspace (LANDLOCK_LAST_PUBLIC_ACCESS_FS + 1 + * to LANDLOCK_LAST_ACCESS_FS). The private access rights are defined in fs.c. + */ +#define LANDLOCK_LAST_PUBLIC_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL +#define LANDLOCK_MASK_PUBLIC_ACCESS_FS ((LANDLOCK_LAST_PUBLIC_ACCESS_FS << 1) - 1) + +#define LANDLOCK_LAST_ACCESS_FS (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 2) #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) #define LANDLOCK_SHIFT_ACCESS_FS 0 diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h index c7f1526784fd..5a28ea8e1c3d 100644 --- a/security/landlock/ruleset.h +++ b/security/landlock/ruleset.h @@ -30,7 +30,7 @@ LANDLOCK_ACCESS_FS_REFER) /* clang-format on */ -typedef u16 access_mask_t; +typedef u32 access_mask_t; /* Makes sure all filesystem access rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); /* Makes sure all network access rights can be stored. */ diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 898358f57fa0..f0bc50003b46 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -137,7 +137,7 @@ static const struct file_operations ruleset_fops = { .write = fop_dummy_write, }; -#define LANDLOCK_ABI_VERSION 4 +#define LANDLOCK_ABI_VERSION 5 /** * sys_landlock_create_ruleset - Create a new ruleset @@ -192,8 +192,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset, return err; /* Checks content (and 32-bits cast). */ - if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_ACCESS_FS) != - LANDLOCK_MASK_ACCESS_FS) + if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_PUBLIC_ACCESS_FS) != + LANDLOCK_MASK_PUBLIC_ACCESS_FS) return -EINVAL; /* Checks network content (and 32-bits cast). */ @@ -201,6 +201,10 @@ SYSCALL_DEFINE3(landlock_create_ruleset, LANDLOCK_MASK_ACCESS_NET) return -EINVAL; + /* Expands synthetic IOCTL groups. */ + ruleset_attr.handled_access_fs = landlock_expand_handled_access_fs( + ruleset_attr.handled_access_fs); + /* Checks arguments and transforms to kernel struct. */ ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs, ruleset_attr.handled_access_net); @@ -309,8 +313,13 @@ static int add_rule_path_beneath(struct landlock_ruleset *const ruleset, if (!path_beneath_attr.allowed_access) return -ENOMSG; - /* Checks that allowed_access matches the @ruleset constraints. */ - mask = landlock_get_raw_fs_access_mask(ruleset, 0); + /* + * Checks that allowed_access matches the @ruleset constraints and only + * consists of publicly visible access rights (as opposed to synthetic + * ones). + */ + mask = landlock_get_raw_fs_access_mask(ruleset, 0) & + LANDLOCK_MASK_PUBLIC_ACCESS_FS; if ((path_beneath_attr.allowed_access | mask) != mask) return -EINVAL; diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 646f778dfb1e..d292b419ccba 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -75,7 +75,7 @@ TEST(abi_version) const struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE, }; - ASSERT_EQ(4, landlock_create_ruleset(NULL, 0, + ASSERT_EQ(5, landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)); ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 2d6d9b43d958..3203f4a5bc85 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -527,9 +527,10 @@ TEST_F_FORK(layout1, inval) 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) -#define ACCESS_LAST LANDLOCK_ACCESS_FS_TRUNCATE +#define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL #define ACCESS_ALL ( \ ACCESS_FILE | \ From patchwork Fri Feb 9 17:06:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551635 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8FB22E632 for ; Fri, 9 Feb 2024 17:06:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498386; cv=none; b=F8rEVueYnEykF1hNXygG3zYmp2/dkPXXlh80jaF2ex5rZRERIh4TAjDrgWeQHsHjAx2NQ2gUeAwdMuvkLTH0j72bGFzcTeXP9o/ZDm/wBfxPEJRex1EZ1n2VGaWU6TfHQO+GDdO9A9QdoaKfpGksGw83ukZ04LzQWW4XXYBq/5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498386; c=relaxed/simple; bh=pgXtTW831ZCa5Q1K21oQWfrSPXWxTFd8H3OjAYMuwjA=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=NqiDZcrVvyo8ma3q4y6tv/fTzXcOtXSpiJCt4RrViEcmPsnMb2z4fBj3/MP9GmlGgjs3NBu4I09cVJveSz8qpSKtswx6n3TzU8DK3HkVursBO0iITGNcnx0Ti/8TYzCHTaBbdDfV+I9wf1Y8Oc3IqFTkaamI98dfldzlQFUEIjA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TZE2xuwn; arc=none smtp.client-ip=209.85.208.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TZE2xuwn" Received: by mail-ed1-f74.google.com with SMTP id 4fb4d7f45d1cf-560127ce17fso707875a12.0 for ; Fri, 09 Feb 2024 09:06:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498383; x=1708103183; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=ZWceuWdFUB2p61QT2dRG6Wq/C3P9HIbEdoSnPoZ0Bb0=; b=TZE2xuwnzo9qNAEYQYr72tHeuDACPJcN0NwdSTPUJ0l1XGQfSYQ0Q1NJnlxc0XqU36 wKl6JrT/sAGypjuKBLbIn0EDBv7mAle2yb3G7mlq7swxSgVzhYyPDjk+98sj8p21zA5Q Ek+6Ze4KAWaONyXN0zajI2XGKpHtnAlU1td2R/bYEB2O8sp0LfZAh6jGsaByWYR1ho75 qLp/XUcsGlUEi0koJY8R2n/NukM2g9zfXrBtquTN1Lv+uU+Y5X2GV7s3Gm15Mu3hg2PK JrkUBQr8izdx3fwSqMdAcDKdwyS0Uf1qsxZPNY36J+bLwD11HcRAuDFzws2E+2CgACiB U0Tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498383; x=1708103183; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ZWceuWdFUB2p61QT2dRG6Wq/C3P9HIbEdoSnPoZ0Bb0=; b=qlSv7ttjW1OFR2YQn7QGOC//HaMKmFojgPAG67LM2DKyb3B3T1MuWo505CDFENDSUf TX51fWuvHS6e1pgeJ5DpO5oCUsSJyylNn8/IiiUZfHQ3n00Uee2AdOAoTmS60JEE7UOP 92uqp+IcwA7jNP8tYg2BrbTo87MIOK16jFiabDuQRaoGwEPtZVYAAGAq1C5nTnLZhYCE S6oDYk9EWzbBfKiX4xzpG8UAIAW1zwuzwrqi2QglQH7wtpOvG9D4o3VXp9BmURHN8xGc EYoyJsmRQpvXIN/yC5iIbGWpU8Ae03CAf+s7mlNkNJ+URxLQrDww4Acnw3grFdags62O HsdA== X-Gm-Message-State: AOJu0Yxbd0wCG+s344s+nz0yRCwhyYcMEY2LvcY43y2JpZY89H1t7MiZ ooTvtqDq6yI1U3y2bkYWUJNHwM7+M1uiqbDNnmwlOWo/DgjPMqS3Ud3+2tzRKJmQqkuCo45tB/O dcw== X-Google-Smtp-Source: AGHT+IHaiaOhKUPbOA5Nox92k2d5qWgKBE3k8Rcqe2AhHnovtDLCmsYap3nsfmDwEeQjLTkpM2cdXGh3sWs= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:4496:b0:560:9958:1010 with SMTP id er22-20020a056402449600b0056099581010mr7567edb.7.1707498382970; Fri, 09 Feb 2024 09:06:22 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:06 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-3-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 2/8] selftests/landlock: Test IOCTL support From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Exercises Landlock's IOCTL feature in different combinations of handling and permitting the rights LANDLOCK_ACCESS_FS_IOCTL, LANDLOCK_ACCESS_FS_READ_FILE, LANDLOCK_ACCESS_FS_WRITE_FILE and LANDLOCK_ACCESS_FS_READ_DIR, and in different combinations of using files and directories. Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 379 ++++++++++++++++++++- 1 file changed, 376 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 3203f4a5bc85..6ff1026c26c2 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -23,6 +23,12 @@ #include #include +/* + * Intentionally included last to work around header conflict. + * See https://sourceware.org/glibc/wiki/Synchronizing_Headers. + */ +#include + #include "common.h" #ifndef renameat2 @@ -735,6 +741,9 @@ static int create_ruleset(struct __test_metadata *const _metadata, } for (i = 0; rules[i].path; i++) { + if (!rules[i].access) + continue; + add_path_beneath(_metadata, ruleset_fd, rules[i].access, rules[i].path); } @@ -3443,7 +3452,7 @@ TEST_F_FORK(layout1, truncate_unhandled) LANDLOCK_ACCESS_FS_WRITE_FILE; int ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, handled, rules); ASSERT_LE(0, ruleset_fd); @@ -3526,7 +3535,7 @@ TEST_F_FORK(layout1, truncate) LANDLOCK_ACCESS_FS_TRUNCATE; int ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, handled, rules); ASSERT_LE(0, ruleset_fd); @@ -3752,7 +3761,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate) }; int fd, ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, variant->handled, rules); ASSERT_LE(0, ruleset_fd); enforce_ruleset(_metadata, ruleset_fd); @@ -3829,6 +3838,16 @@ TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes) ASSERT_EQ(0, close(socket_fds[1])); } +/* Invokes the FS_IOC_GETFLAGS IOCTL and returns its errno or 0. */ +static int test_fs_ioc_getflags_ioctl(int fd) +{ + uint32_t flags; + + if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0) + return errno; + return 0; +} + TEST(memfd_ftruncate) { int fd; @@ -3845,6 +3864,360 @@ TEST(memfd_ftruncate) ASSERT_EQ(0, close(fd)); } +/* clang-format off */ +FIXTURE(ioctl) {}; +/* clang-format on */ + +FIXTURE_SETUP(ioctl) +{ + prepare_layout(_metadata); + create_file(_metadata, file1_s1d1); +} + +FIXTURE_TEARDOWN(ioctl) +{ + EXPECT_EQ(0, remove_path(file1_s1d1)); + cleanup_layout(_metadata); +} + +FIXTURE_VARIANT(ioctl) +{ + const __u64 handled; + const __u64 allowed; + const mode_t open_mode; + /* + * These are the expected IOCTL results for a representative IOCTL from + * each of the IOCTL groups. We only distinguish the 0 and EACCES + * results here, and treat other errors as 0. + */ + const int expected_fioqsize_result; /* RW */ + const int expected_fibmap_result; /* RW_FILE */ + const int expected_fionread_result; /* special */ +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_none) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_IOCTL, + .allowed = 0, + .open_mode = O_RDWR, + /* + * If LANDLOCK_ACCESS_FS_IOCTL is handled, but nothing else is + * explicitly handled, almost all IOCTL commands will be governed by the + * LANDLOCK_ACCESS_FS_IOCTL right. Files can be opened, but IOCTLs are + * disallowed. + */ + .expected_fioqsize_result = EACCES, + .expected_fibmap_result = EACCES, + .expected_fionread_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_i) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, unhandled) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_EXECUTE, + .allowed = LANDLOCK_ACCESS_FS_EXECUTE, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwd_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_READ_DIR, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + /* If LANDLOCK_ACCESS_FS_IOCTL is not handled, all IOCTLs work. */ + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwd_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_READ_DIR, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + /* If LANDLOCK_ACCESS_FS_IOCTL is not handled, all IOCTLs work. */ + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_ri_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_wi_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_di_allowed_d) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_DIR, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = EACCES, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_rw) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_ri) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_wi) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, +}; + +static int test_fioqsize_ioctl(int fd) +{ + size_t sz; + + if (ioctl(fd, FIOQSIZE, &sz) < 0) + return errno; + return 0; +} + +static int test_fibmap_ioctl(int fd) +{ + int blk = 0; + + /* + * We only want to distinguish here whether Landlock already caught it, + * so we treat anything but EACCESS as success. (It commonly returns + * EPERM when missing CAP_SYS_RAWIO.) + */ + if (ioctl(fd, FIBMAP, &blk) < 0 && errno == EACCES) + return errno; + return 0; +} + +static int test_fionread_ioctl(int fd) +{ + size_t sz = 0; + + if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES) + return errno; + return 0; +} + +TEST_F_FORK(ioctl, handle_dir_access_file) +{ + const int flag = 0; + const struct rule rules[] = { + { + .path = dir_s1d1, + .access = variant->allowed, + }, + {}, + }; + int file_fd, ruleset_fd; + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + file_fd = open(file1_s1d1, variant->open_mode); + ASSERT_LE(0, file_fd); + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(file_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(file_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(file_fd)); +} + +TEST_F_FORK(ioctl, handle_dir_access_dir) +{ + const char *const path = dir_s1d1; + const int flag = 0; + const struct rule rules[] = { + { + .path = path, + .access = variant->allowed, + }, + {}, + }; + int dir_fd, ruleset_fd; + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * Ignore variant->open_mode for this test, as we intend to open a + * directory. If the directory can not be opened, the variant is + * infeasible to test with an opened directory. + */ + dir_fd = open(path, O_RDONLY); + if (dir_fd < 0) + return; + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(dir_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(dir_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(dir_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(dir_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(dir_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(dir_fd)); +} + +TEST_F_FORK(ioctl, handle_file_access_file) +{ + const char *const path = file1_s1d1; + const int flag = 0; + const struct rule rules[] = { + { + .path = path, + .access = variant->allowed, + }, + {}, + }; + int file_fd, ruleset_fd; + + if (variant->allowed & LANDLOCK_ACCESS_FS_READ_DIR) { + SKIP(return, "LANDLOCK_ACCESS_FS_READ_DIR " + "can not be granted on files"); + } + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + file_fd = open(path, variant->open_mode); + ASSERT_LE(0, file_fd); + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(file_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(file_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(file_fd)); +} + /* clang-format off */ FIXTURE(layout1_bind) {}; /* clang-format on */ From patchwork Fri Feb 9 17:06:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551636 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA81C7E595 for ; Fri, 9 Feb 2024 17:06:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498389; cv=none; b=tu+9amg5lzVcknylfBFvK0zZ33mE3PyF8/xYx7/6Bi4KUuni08aJ4zcXHVj3mOQCzWsFCQ69Sk6iv2h/DkcqVUG9HcbAkkXGBiPkHaftq+G0UuQd4zG2120qWzAC5Z1OixWqDMikibqtjVUaqbwkXFhEwlkhXjNrlnSYi48IDyY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498389; c=relaxed/simple; bh=qnVVQyk96V+29yOrH9p87U8Q4CRd3DD7DhbdDzGIkLk=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=kGs8MZ196sbIkUcmGzkEQzMufxYRRvGwRNfC8lCCBapsOqNAUsmPdxzGpaCtbSJgYi6Cn73Vxe0nurmVqW3EHDPmeFLPMeZ0/e3ZGX6pDJPEVonFX+G0zUpquvnkql7tzAVirsEWJMUQ+RSV+PsurNcRZNR3QrPVtt0LdSi5VPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CFTi9fAZ; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CFTi9fAZ" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-55ffcfed2ffso2555343a12.0 for ; Fri, 09 Feb 2024 09:06:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498386; x=1708103186; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=gbIxtpk2chw6jsiB6rCOoopjh/LiZGd5/fSxW0kPD1E=; b=CFTi9fAZ8SfLI02MxJyk2PoEZ1CFkiRFXgoqA+U3JhaQZJMWpJ3mfAwd2sYB8QARsf 7eDBBYx/u4ki/8BhujqImLSWaRrGU/5VSkk8mypef5vPcAgQqQafjqNziXNhkrTM0FZ0 0QGDzNPmZMzVRzNp/tAF5yyDBKh/D5isYuEb0iMTogVzytyBhM+Pn95mpUVJL9L4/9wf q0lrXVX0d6acl2uTw+mNsiWe/u6f4E/zTa+F8LajeeWqikjXUfeYAxxryITH6EaJ91x5 9NIPVLS1o6MzTUMJXzCBQfqVrabcG59xDhvV57NeflBo6X6qzWFTF+kGLaf1WiQxJAY+ PVlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498386; x=1708103186; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=gbIxtpk2chw6jsiB6rCOoopjh/LiZGd5/fSxW0kPD1E=; b=UBllnf4rGCgyhO3r7c6Us6KTmlDa72fJRQhzVdknGlLAvG8hQNjt+l+P0tzK0dATff nKU8B+mWJUOs5zU2kookRh+FVphM8liarDnFXbwHYarizOmNKItDP4DjsZ0Hf2Gf1LDP rxQmIHlc6LpIvaEzAL309M6TJxx2srJdIKFmNxoAFl9y2omo7YhyDvVUoAokdO9SBs/d B+XtTBiL6hCN7qNmj0cc54/80Uuf5G7F/rS8fJfj2PM1hLeEyCfp7g8Wysl0Lb42y0rC HZa1i55I1ulKkfpOgNYdG46phyAwC5Kz6lqAp1B2ILhHxswfjLFb9TEzGjtrpHfkgWF4 Z18g== X-Forwarded-Encrypted: i=1; AJvYcCW4p3K63paph3RL0/7RbbuxQITLUB0B+qZ9xQNM6vpwWbfSbQmw+/V7BYaklrbuPIZogq0YhklQMnEsBOi3DkoGNqMESaqV6tq2fidBEw== X-Gm-Message-State: AOJu0Ywc+MBm2b1SGm7Jze4UZNvJIri+zB6v7Elta2AxH6wOOdQUG5Uz lTn1w4DLTdoZNgS1u2H68/xjVUpwDjoOGFjYuSXW/3liaj+Exw7HLgtCAVPwvZ3nuqmsLZXDaFn rmQ== X-Google-Smtp-Source: AGHT+IEkXTF2JnkhhOCozajRd1N6fTjDERadCVkYE3Gcr63l6dmKM2d5Wmn7khHsRaEPtLo/oxdM9j/9THQ= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:400f:b0:560:aa2e:676f with SMTP id d15-20020a056402400f00b00560aa2e676fmr5547eda.3.1707498386021; Fri, 09 Feb 2024 09:06:26 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:07 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-4-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 3/8] selftests/landlock: Test IOCTL with memfds From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Because the LANDLOCK_ACCESS_FS_IOCTL right is associated with the opened file during open(2), IOCTLs are supposed to work with files which are opened by means other than open(2). Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 36 ++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 6ff1026c26c2..aa4e5524b22f 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3848,20 +3848,38 @@ static int test_fs_ioc_getflags_ioctl(int fd) return 0; } -TEST(memfd_ftruncate) +TEST(memfd_ftruncate_and_ioctl) { - int fd; - - fd = memfd_create("name", MFD_CLOEXEC); - ASSERT_LE(0, fd); + const struct landlock_ruleset_attr attr = { + .handled_access_fs = ACCESS_ALL, + }; + int ruleset_fd, fd, i; /* - * Checks that ftruncate is permitted on file descriptors that are - * created in ways other than open(2). + * We exercise the same test both with and without Landlock enabled, to + * ensure that it behaves the same in both cases. */ - EXPECT_EQ(0, test_ftruncate(fd)); + for (i = 0; i < 2; i++) { + /* Creates a new memfd. */ + fd = memfd_create("name", MFD_CLOEXEC); + ASSERT_LE(0, fd); - ASSERT_EQ(0, close(fd)); + /* + * Checks that operations associated with the opened file + * (ftruncate, ioctl) are permitted on file descriptors that are + * created in ways other than open(2). + */ + EXPECT_EQ(0, test_ftruncate(fd)); + EXPECT_EQ(0, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + } } /* clang-format off */ From patchwork Fri Feb 9 17:06:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551637 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 395D97EF00 for ; Fri, 9 Feb 2024 17:06:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498391; cv=none; b=Mf/7drfgkz4v5yW3xLCexpPZKlIq2rGz1zx4VIJwAGpDdgmM9uWu6w4KjhIDZzYCEEb1n6I54eWaK5fagaCO6tM70ZqTEPV7GP9IWNkvv8xzlpNrU70Ze/KNn4fvv0tcEcwDtji9fK/XLL4ZUBmuN4Zw1uQrm3JulC92bV1R2NU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498391; c=relaxed/simple; bh=yH1ybo8pFyJV4FaWc4tCKu5kwI86vylombstdw6W6Dc=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=QF0G/CvahmvkTODS7vJHlMkwmY7F/MNajinul1doT0TKmxMPPrdTZlKh2bYOA/tAHAdSLaJjmW8qylV/WJjx7dm2JjolbIxutZTVfoaosd4A173ecc4O4enQcUp+6NvwGUjBW9viU6KocGW3jvhPFOjUWG1Q9gpbBDyF+B2dS2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Sakv5ezT; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Sakv5ezT" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-560129c6ca4so656297a12.2 for ; Fri, 09 Feb 2024 09:06:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498388; x=1708103188; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=SUXvZkpipzzisPEeIj9GHmgj+gz6GS2fMiTzN8+mL+I=; b=Sakv5ezT1UP4bucZjLV3xEFF7kmhCpEm3eBU3pKmqorLdMu2EjU4L8UerSfmb/fu/g z+Z229sWiN235holIE5uQC91e3+3aJCL5SItemUYpzivkcozWlKcC0IIdEam6O27iCbY 7n9p81r+eSg62x4afqMeoyThGH71EJh0x14wPJjLmU9bjqjAqKJuxD/hJpH3uP+SZIP7 AI4Ur8L5UaQJGWPopr/kGe4j1w8O7HKhEPEjFwdgdZs8i6SH1jXFJUMjMnI7SUCqKY2C MRq8Lu3mQVh1W+DH3YgJXSAcpqbeqQo8lRe1M1scQBZXrtTdM/g6ATlGtLV63dioK5hy r3Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498388; x=1708103188; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=SUXvZkpipzzisPEeIj9GHmgj+gz6GS2fMiTzN8+mL+I=; b=F8dUdMt454VRy8HfSwIVrqzuX6u448/eJP6+U0VrDGva4UaH/msjCPPGbRrYhmI0ng zIUnh8smlkVessVPQwQgTp/e9SdKi+9M/f6aYePEjvEHOixJnOiyHMT7tXvd7EV24prH uo8hYtbvSoreWQhNrWBOEcM3FJProuoMW8Tg4kHq9wB1crWpul43tGdUIOka4UpwgSl9 IFwRzbGtrKhMtE47skG3EJTIbbkck5tgF63OFJyK0cFN5/aXcubXMw9IjdqIyYPzYC9x xm+lHNdjuu2Ux92XnB7WNpUFqnL3fp9xVWdi0oBB/U+J9GTH18wOST+DpWMWAafMIJoc kFlA== X-Forwarded-Encrypted: i=1; AJvYcCV3kcqzPV7FRDAulw9CQhP4fBzF/UaekhnqCed1SLdF4/8KrxDgHddAfc1x+0rpx97ZmjvKIvsmCTPIFnZjbS9OOAyrkLVNFViUQlilXA== X-Gm-Message-State: AOJu0YxO3kO2seapDCAEzOhtP8kIBorTA+T2urZr4rz3jfdzcr9D+Oz4 CfPnHze5KazpBpU2NxKU/S0Ta/WYeUcc/tV/EH9vSd36ufAwkK5R++bZ8BS18W2TAeEZylKgnz1 4iw== X-Google-Smtp-Source: AGHT+IG12HwYRRpWchg7kE9xdw7gYJFKi0josGqIpnNVO8tOlBQ2dNQlzewAsPpX+SK21xfN7LDdgd0OMOE= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:4022:b0:560:e01b:6a4c with SMTP id d34-20020a056402402200b00560e01b6a4cmr7995eda.2.1707498388494; Fri, 09 Feb 2024 09:06:28 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:08 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-5-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 4/8] selftests/landlock: Test ioctl(2) and ftruncate(2) with open(O_PATH) From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " ioctl(2) and ftruncate(2) operations on files opened with O_PATH should always return EBADF, independent of the LANDLOCK_ACCESS_FS_TRUNCATE and LANDLOCK_ACCESS_FS_IOCTL access rights in that file hierarchy. Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index aa4e5524b22f..9e9b828a898b 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3882,6 +3882,46 @@ TEST(memfd_ftruncate_and_ioctl) } } +TEST_F_FORK(layout1, o_path_ftruncate_and_ioctl) +{ + const struct landlock_ruleset_attr attr = { + .handled_access_fs = ACCESS_ALL, + }; + int ruleset_fd, fd; + + /* + * Checks that for files opened with O_PATH, both ioctl(2) and + * ftruncate(2) yield EBADF, as it is documented in open(2) for the + * O_PATH flag. + */ + fd = open(dir_s1d1, O_PATH | O_CLOEXEC); + ASSERT_LE(0, fd); + + EXPECT_EQ(EBADF, test_ftruncate(fd)); + EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * Checks that after enabling Landlock, + * - the file can still be opened with O_PATH + * - both ioctl and truncate still yield EBADF (not EACCES). + */ + fd = open(dir_s1d1, O_PATH | O_CLOEXEC); + ASSERT_LE(0, fd); + + EXPECT_EQ(EBADF, test_ftruncate(fd)); + EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); +} + /* clang-format off */ FIXTURE(ioctl) {}; /* clang-format on */ From patchwork Fri Feb 9 17:06:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551638 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AF177E595 for ; Fri, 9 Feb 2024 17:06:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498394; cv=none; b=nkjYmwd1qxM3eOuB9IIVJLTvT4tgpObMGnsKZvgyVvP6rzvGKNmSJkjsWSTnkzM+DxdCf8zbLUkLvtvTLYF1bhtR4lWDUMFkw8RioCGrrD5pkzcwApQUbgh/qkmoNLT34VzjUk9mC6Lla5RNyGj9QncEr4sAYt+An3z8sdblwjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498394; c=relaxed/simple; bh=ir+nhOodQJZaUi3t0QMO4b+HzJCAUJIFK8BFQmc/sIE=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=TtOLWsNoOXwVKxe1r7cJI6j2PgrKjwBHvMhmJLYtY/ljVNM0GL/0KbaZWa2YbOWKJ2BS/TJbBp9VrdJjdQOCsbgsZxUNBhWKYaXGK0GcLL/xTezoqx1QsY96w8H6ql9PhABNNvo90B9TxlvMPTuV235TuJEJkL4/ei8mIHpVKlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=HVzjXZqF; arc=none smtp.client-ip=209.85.208.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="HVzjXZqF" Received: by mail-ed1-f74.google.com with SMTP id 4fb4d7f45d1cf-5615647dfb7so153933a12.3 for ; Fri, 09 Feb 2024 09:06:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498391; x=1708103191; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=x8bXTZKOf2uP7frXW3XX6UWjY33n1Dc79uBumdx0Eb8=; b=HVzjXZqF5vNEJFOAdPupnEgIN1JSVCm7uSgGM8p4tEYXT9SBRryO+8x6XKp+5ewl7S i/XjzEwwbntWq4qLOlIepHzZNtr1UuKJ19yfg3k2Uz69JaGWbfb88gMrK4lZyDFatRW4 5alamRHVYD77uQ6NgXipgZHc2zBvP+/BxenAe593rjhijWb6SZeUb0+zLzOId4oKt/iv QaCiW3UxqwZYduagxIdZzptXW6vKjiKt3ZEqSCBnzToHhyAEMLlJHZHg+ZmyQK5XjXJU y2dEqNsUwhpLnnGN3ESu+C/GFhnoAebxwmQ/fVYuvWhafXGSLxUVRuebfdhMef9qe/Ra JMdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498391; x=1708103191; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=x8bXTZKOf2uP7frXW3XX6UWjY33n1Dc79uBumdx0Eb8=; b=nxxWwQuABmfRzMq2mwt+kggbywYZDvrhECaFF/4zxT9wIpFN10Tq77HWcHu6VJCY7/ Ft54hXJU+AkLbNdkSFa1d+z2X6MRr1riAfGy9U92Z86gnyJkwbFBJK5FzZO7gPokGj3J iaA8pJRRJ/UbuxCMij9tY1B/yZeicnhuojcaa4gUVLMfGazTqeqlVAQ4Dmos8AHpAsyE CSSjR/MTYbwxKoi9MzikRoa6ovAMrc2pHf8priYuqt8F3z/906HBfnbPsZyJoDQ1AxEY ELGVQXbCvzab20NuIZbDNglzhDU5jMKAYMu7AlWP3aLxsR3MzXO9FxLtc03KAoSxH2Tk cHiA== X-Gm-Message-State: AOJu0YxKDfFod6vFGcJftLyOuK0NGGIjUsDCtlBZCJe0Uhyd4jU7E8nT iVXzykIGXVdfQNUnMUUsBxBdHeedQ7V+agvqjc6BWttvtpoykBJHh9RnSg6KHUlzVBurooDqNFE 7YA== X-Google-Smtp-Source: AGHT+IF10vz63m02uAW14nmsz+sX2yfpf+Cs1KrtSmnw3SCKnw6/XlxHkgRXgdVE9Z2EFKf37IgfUOygyog= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:f08:b0:560:98a2:93e2 with SMTP id i8-20020a0564020f0800b0056098a293e2mr10505eda.0.1707498390946; Fri, 09 Feb 2024 09:06:30 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:09 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-6-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 5/8] selftests/landlock: Test IOCTLs on named pipes From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Named pipes should behave like pipes created with pipe(2), so we don't want to restrict IOCTLs on them. Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 70 +++++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 9e9b828a898b..ae8b8b412828 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3922,6 +3922,67 @@ TEST_F_FORK(layout1, o_path_ftruncate_and_ioctl) ASSERT_EQ(0, close(fd)); } +static int test_fionread_ioctl(int fd) +{ + size_t sz = 0; + + if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES) + return errno; + return 0; +} + +/* + * For named pipes, the same rules should apply as for anonymous pipes. + * + * That means, if the pipe is opened, we should permit the IOCTLs which are + * implemented by pipefifo_fops (fs/pipe.c), even if they were otherwise + * forbidden by Landlock policy. + */ +TEST_F_FORK(layout1, named_pipe_ioctl) +{ + pid_t child_pid; + int fd, ruleset_fd; + const char *const path = file1_s1d1; + const struct landlock_ruleset_attr attr = { + .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL, + }; + + ASSERT_EQ(0, unlink(path)); + ASSERT_EQ(0, mkfifo(path, 0600)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* The child process opens the pipe for writing. */ + child_pid = fork(); + ASSERT_NE(-1, child_pid); + if (child_pid == 0) { + fd = open(path, O_WRONLY); + close(fd); + exit(0); + } + + fd = open(path, O_RDONLY); + ASSERT_LE(0, fd); + + /* FIONREAD is implemented by pipefifo_fops. */ + EXPECT_EQ(0, test_fionread_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); + ASSERT_EQ(0, unlink(path)); + + /* Under the same conditions, FIONREAD on a regular file fails. */ + fd = open(file2_s1d1, O_RDONLY); + ASSERT_LE(0, fd); + EXPECT_EQ(EACCES, test_fionread_ioctl(fd)); + ASSERT_EQ(0, close(fd)); + + ASSERT_EQ(child_pid, waitpid(child_pid, NULL, 0)); +} + /* clang-format off */ FIXTURE(ioctl) {}; /* clang-format on */ @@ -4134,15 +4195,6 @@ static int test_fibmap_ioctl(int fd) return 0; } -static int test_fionread_ioctl(int fd) -{ - size_t sz = 0; - - if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES) - return errno; - return 0; -} - TEST_F_FORK(ioctl, handle_dir_access_file) { const int flag = 0; From patchwork Fri Feb 9 17:06:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551639 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 523557E595 for ; Fri, 9 Feb 2024 17:06:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498397; cv=none; b=XDnQdglzU2190OluJk0wr3TKY5RAFYjx9qqL1U6v8STv9KGyr74K0+JiASQ8uTyhwdw5xJQ0FgQyfTIYTJgUPAkFiKlkgiL4JXhGu6/Wku4D7Lezcny7Gibo+AFbdLf49ro42K78Rrs2mg/SNX+q28+VOwSNqMOS3mia1qHle0E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498397; c=relaxed/simple; bh=ZOMMoEDQ5xIGIh13zw5bCfNnxE82fCIe2LgtgMyom98=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=axmgL6Iumr9SlIRvplrxV1KdF/kCZJbjX0sPjlnbfPluA8cfeum6D8asmOeZvOCtz+i3DPde3m5fNALvr71mTjrIcdooE47Ur+3Csls6zEnYmXAjRJ2a71EQlQLozSWDlrIp9b4ZD8D/KT882JasDWAsdby9WaVOA2Jh0OgOydM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=wvYgzuwv; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wvYgzuwv" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-5589ce327e2so1005725a12.2 for ; Fri, 09 Feb 2024 09:06:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498393; x=1708103193; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=o+kC6dT4IyBTfeBcHN42EnhFy5ZpJ2/rUmLiDKj8ztc=; b=wvYgzuwv0BVe4kqj49qaEVMDC8Rw0A+H/B/1rN+utWgvAOy4ycvKUt6lT33qUK1iMi w1pHzgAV7J9175qCvgVMwtbVQYyZO48Dgqa8B4LvDSq2DiTeVa8Tj1Gcje1RFkx5cKcy i+vO9T7vAYBhJqXdSIQvT3GbGiNjaDHCzCVYFTqija7gnGheALk+c550ziiTT5vAIWlc 4iIpGzcllFqfkzYnFGy+XMvfnKopglsyEv/c4r/2mtZtOFNbC6eDT4FlFkPCQLVv8dWA NKRzFFVKflOnk668cy4pXz0aaqRfg6SmHs2Ra2kS4tqcVljxZUdP/HsQPZnytURI4wVN /C4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498393; x=1708103193; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=o+kC6dT4IyBTfeBcHN42EnhFy5ZpJ2/rUmLiDKj8ztc=; b=Fc7lHnxAmO5padSs+IPJv047ZDv5aJboX+8/CvBBqgFBqyYgFiYY/v+kmO02zWQlnj k7uT3P/33PPyfLcwBXA756bgiKOXRQQxpP0RPNhNSK8T6iQMJwXhTW02zXDg9n/6+b/v CTvSL+NyLEDQ5P6COVgtJqHp73qpeqX1ua5uc9qLglmfTpMprFq7FwKz/NC0r/cnkMlW nVuYjT63ogBaJZ7JfoXFSEOsqQoBuvAdAoAVHrt3zpMKQ75h0kR5Oz2GLUVRbM8goPYp RyefxY9yjxT8gzbPvLbW2J0plK/rClssFv5ygpg82Zj/q0HRLeZmXfGPXPyeL1SFFLgl bF0Q== X-Forwarded-Encrypted: i=1; AJvYcCUAyYPBNK+OEGLCsNeDex7XtbTUFPXFzJvKGqUz/+reKEAcPp5xuvD5FSAZK/8WFjRcSBz+FNqFnBBoikRYsriJ1KpMaV1/4DtHsgE1Jw== X-Gm-Message-State: AOJu0YzAQjy3bEa542L2ROA+xQfiF87PJGhHI5AFUcFs3Ehx9++hLF2H ES556dWoKabMVUuxBj/7TXN4wOjlMc+4YAHwbA8SNiFDIzU91Gi97fZgwS5D06KPmHt63N9N8Sb WZQ== X-Google-Smtp-Source: AGHT+IE+S3vXTRJstlGpyHPrIzXl4dpZ7xz7gmneKPNSqhlpVLJgSelFzxDYg6Ih094UIcOnll2O2YPkRo8= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:4009:b0:560:b996:189d with SMTP id d9-20020a056402400900b00560b996189dmr10674eda.2.1707498393599; Fri, 09 Feb 2024 09:06:33 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:10 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-7-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 6/8] selftests/landlock: Check IOCTL restrictions for named UNIX domain sockets From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index ae8b8b412828..59b57ff6915b 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -18,8 +18,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -3983,6 +3985,57 @@ TEST_F_FORK(layout1, named_pipe_ioctl) ASSERT_EQ(child_pid, waitpid(child_pid, NULL, 0)); } +/* For named UNIX domain sockets, no IOCTL restrictions apply. */ +TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) +{ + const char *const path = file1_s1d1; + int srv_fd, cli_fd, ruleset_fd; + socklen_t size; + struct sockaddr_un srv_un, cli_un; + const struct landlock_ruleset_attr attr = { + .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL, + }; + + /* Sets up a server */ + srv_un.sun_family = AF_UNIX; + strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path)); + + ASSERT_EQ(0, unlink(path)); + ASSERT_LE(0, (srv_fd = socket(AF_UNIX, SOCK_STREAM, 0))); + + size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path); + ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size)); + ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Sets up a client connection to it */ + cli_un.sun_family = AF_UNIX; + snprintf(cli_un.sun_path, sizeof(cli_un.sun_path), "%s%ld", path, + (long)getpid()); + + ASSERT_LE(0, (cli_fd = socket(AF_UNIX, SOCK_STREAM, 0))); + + size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path); + ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size)); + + bzero(&cli_un, sizeof(cli_un)); + cli_un.sun_family = AF_UNIX; + strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path)); + size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path); + + ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size)); + + /* FIONREAD and other IOCTLs should not be forbidden. */ + EXPECT_EQ(0, test_fionread_ioctl(cli_fd)); + + ASSERT_EQ(0, close(cli_fd)); +} + /* clang-format off */ FIXTURE(ioctl) {}; /* clang-format on */ From patchwork Fri Feb 9 17:06:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551640 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28CFB7E595 for ; Fri, 9 Feb 2024 17:06:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498399; cv=none; b=IV5zahfHiDw6crv5TMAxuNMEdarvC9+32OZEdTulca1CFwyQqH8rR+aMl1D2Dhfeum+HHO2xQbHEDAoPEUvSjBqjaC+ywV3/XKgNg3GKIDiFR/lOFUIhp7t99cPVOQdpDOEaxRH30AZqR7c1Ira9L/fjA3Tz39mTywySj4M0zsM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498399; c=relaxed/simple; bh=kIEptzQde7cesZNFjMOm2MmmN9Ek6A0D6Wd9L3b44iE=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=IrEXeNP9QXHjgvF9vIsCm3hBpc/K8EB75Ztab+mLo4Uzi5LRUdN2KDmYMuEnTtwdv2W/67Tl8PeRfdWDacK617TpRlcI95AtiS5TPnu+8Zk7ITsHYmuxlAEctlK9ywKI5cGkE9FM2VeUkV9H91nLAXQKfmV+TxL5bKA8LmSRYN4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qvWr5Mdw; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qvWr5Mdw" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-5611e1da4c6so822675a12.1 for ; Fri, 09 Feb 2024 09:06:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498396; x=1708103196; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=es+e+wQNjnyIvSqYUyube9Brelr1LLu1DXJz4rbQGc8=; b=qvWr5MdwO1Ma+dQRtPBOw4tXF8RyyuWm+fH4CS0yD9gL3bZa6ehoeGQdy4J4NyBrDj +pYjHhRYyUrdcrO1uzRmJbWIp5jXYDGaxaJ6R/7yhYnaN670I23eeYNXYPsA7bTAmIwP AsRAWjSraIOismKjO1xA3aa2wlH5q/auXMtV+vJz6hr3FiX+dLbGAy7b16oW8e9xQXSf yK3/21imzWmy2MvS1hgp4YbRqd7PgRQeUeaE7zWlsQsKlfHSb/o6/CNShsQbjsoQu5/C qEJab4eIy1N+Igv9pMp4yPbEgJL5a712XmrWbUyJpRoO5TliV/Kx5N0mHokRkmRoyxDo N0/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498396; x=1708103196; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=es+e+wQNjnyIvSqYUyube9Brelr1LLu1DXJz4rbQGc8=; b=L8olMqATnCajsF7x+6qxMzzhzaPV0L/2/Z6Kqw5AezB+hClSMouQzvswyqNmi6lWyN Q4KwQ8wKi8NILZwh/TvOYfSVY/l6I54Od146Gxfr4ucJd6l9l8ng7RNyTf2crJQCvPVJ GiFbnkz1sAL7VSSQcr5sRIESQQZdca3yp5YP3QZ9OikOfRbqOMpbC2h9loVd3OrRItl9 C/0WWDA8ChQbeDlBAqJKofoYICZxSRnea5MGmVDedph1R7GYDIsHPzo9DKzr3iE6+5lG 0qJ+NT8DmvRCKRMvunoT09MxHFNLFB6G7pO0F8tiag45PGrS+kvRO4YQ3qbMu7KlGpR/ qCag== X-Forwarded-Encrypted: i=1; AJvYcCW9SXdNMcBwYcti1HUgA/vQZMOAu/qtBziYk54I5/LiwzVhZQ6pyKd4Uq1C4C6wr3F5PMs1RPQkNYQ6gY+n6YQB50oVKMykk14NcsAVFw== X-Gm-Message-State: AOJu0YxkoCvgBKZWxG2tRSQMnVjGh58avAsQW+Q2xSog6Pc9AmiS2yzE r3gMDkBBVJCDAs84aSGB8H1sPJbVTkQH6k3RJrpgU0vksmoSJqPxzA6jd5xBlJE4iuBQDA7IaaS tIQ== X-Google-Smtp-Source: AGHT+IFB+/pCN9oyiGtqBzLpOTRwTMJGgBLKeYT+4cNG8iiYDpmKYYsqMea+WwU2IoCoNg5kd4GNsf+JBRY= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:6402:3718:b0:560:ab40:e6bd with SMTP id ek24-20020a056402371800b00560ab40e6bdmr9105edb.1.1707498396254; Fri, 09 Feb 2024 09:06:36 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:11 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-8-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 7/8] samples/landlock: Add support for LANDLOCK_ACCESS_FS_IOCTL From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Add ioctl support to the Landlock sample tool. The ioctl right is grouped with the read-write rights in the sample tool, as some ioctl requests provide features that mutate state. Signed-off-by: Günther Noack --- samples/landlock/sandboxer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index 08596c0ef070..d7323e5526be 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -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) /* clang-format on */ @@ -199,11 +200,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) /* 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) { @@ -317,6 +319,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 for ABI < 5 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL; + fprintf(stderr, "Hint: You should update the running kernel " "to leverage Landlock features " From patchwork Fri Feb 9 17:06:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13551641 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D98680BFB for ; Fri, 9 Feb 2024 17:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498402; cv=none; b=R/LPN92cTxZEWzLjx104GH+Jz/t9oxwFY0IU4rPcFGp2EXdZzYcgJHG0DVVH6VAIRTvLyKjObF6/8z7IPW5lI6qTimV7bwt/yUKGs3Nc3yx6+2nuTQBXSiY50fMhykIdic4LYk7k5EICdH+6BqisxXJk55dhI3/9cDavx92uvMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707498402; c=relaxed/simple; bh=kk2+83Jnk/yTpdhOZPYnQFVonl0BESaWR3BPYChIpGo=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Cc:Content-Type; b=K5TrSr+6NR1W/bzXlesjeR1Is/u02bAvbyG+9cXWfoPjIvf9CPvnW9oJXE4ey1ilAB5gB9tmbS2SfLQ6kYBl7vN3RCbMo8h4vGDPYdPpLKysSCt8NM5QlVqLSN6c/4JsImUhtOiiA0PTTsGhJZCJ0ExWSdHtNxB5aWTRCKkXFvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=PUrBSFKu; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--gnoack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="PUrBSFKu" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-604b6d55dfcso13125347b3.1 for ; Fri, 09 Feb 2024 09:06:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707498399; x=1708103199; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=yNvcTp+W25e9LmdR8XoSXV4JuupjrHIFCzjVXEdIKbc=; b=PUrBSFKuoDNUzGb2QRQ6Vxibw3JSbbzRioqrjWO+2tnMkuwnVuoLz+WZsIB+uOklJq GyD5Kn7bNGsY9X1z/mMpPYAp/12u5A+RDYiRYfhcf8cminIKLCypJR2E2qFUGvHPWHL1 hJ8PULr3WoUGz3Bl0HxJ6lvR+5vVEqCJI1+q7rvCeYBhNyfWTA7+umpGLzc1CmxFGLV8 1lbadfzX5GpD8c8l0wEXslbDchSaLaLxYwUAd4YRbjMCNwGJ+NmfZoGjqIy+uBGnSJKN Xkw12tqVq6iMT5XYad7j22dgKTk9OunRk3XnVKeo3QE6AJbE+ww4jB5RhYC9oXkKa/UJ elDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707498399; x=1708103199; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=yNvcTp+W25e9LmdR8XoSXV4JuupjrHIFCzjVXEdIKbc=; b=BVrQqiySmcd3NrsC1YaRRXo8W1FyzNgjZtG9pwehs9uiXBEpyA7ZyUYjH7MCqVz+oc OtcHEbpnLUOkBp0YmjQij69w+I4mvax/r0u44pdHorfHi5rTkdDTBTy6xMUWy6ySBpTC MB+94+3EGNlDCkg6E1WjaTcuzIIk0xZJBvWeI/BgT3MVFizm59MHlmdhmd7aiNbYe3sW pyIM+tCFfMiShI8IEH2lvH2iEy+yn6B/oEDxsCHqc+JDY5o581M33rGdmC16ACAs4HhP ZXMKB+7MAkH8qq3v8XbgDwtPRyulxL8o+AThZst3razYq9B1DjEdsMCAOUng8FnUpnnB V1BQ== X-Forwarded-Encrypted: i=1; AJvYcCWG3Dvo7R7wKc7zrHKU/f6MqyZFvyfPU3LY1jW114Tbq8+w22/LImdmWnzhVBpb9I8Eecbh5bW5WR618ApkMaQMbWwxS6G7L//RuAxCtQ== X-Gm-Message-State: AOJu0YwOlv2bZTO8orErUDLenpKrbJFxgdYKT41cR8HY0/AFu9gAmFk0 4s63qn83owqV+D9ciidcUXoBkr22DLBDQBNS//iHmIStJWMPx7quqnRlWw6j9MJmqM3pyrhzl97 pJA== X-Google-Smtp-Source: AGHT+IGi9LtbBw+CYZHCewjY6wNoK4x/xLKkQhRbDBfeUYmSqdt1T/96Qoe2cp4khXbra13QRVoQehLvfQE= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:3162:977f:c07:bcd8]) (user=gnoack job=sendgmr) by 2002:a05:690c:4284:b0:604:982c:3c26 with SMTP id gj4-20020a05690c428400b00604982c3c26mr292358ywb.3.1707498399274; Fri, 09 Feb 2024 09:06:39 -0800 (PST) Date: Fri, 9 Feb 2024 18:06:12 +0100 In-Reply-To: <20240209170612.1638517-1-gnoack@google.com> Message-Id: <20240209170612.1638517-9-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209170612.1638517-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Subject: [PATCH v9 8/8] landlock: Document IOCTL support From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Arnd Bergmann , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " In the paragraph above the fallback logic, use the shorter phrasing from the landlock(7) man page. Signed-off-by: Günther Noack --- Documentation/userspace-api/landlock.rst | 121 ++++++++++++++++++++--- 1 file changed, 106 insertions(+), 15 deletions(-) diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst index 2e3822677061..a6e55912139b 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -75,7 +75,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, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP, @@ -84,10 +85,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 @@ -113,6 +114,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 for ABI < 5 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL; } This enables to create an inclusive ruleset that will contain our rules. @@ -224,6 +229,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, @@ -317,18 +323,72 @@ 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`` 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. + +Restricting IOCTL commands +-------------------------- + +When the ``LANDLOCK_ACCESS_FS_IOCTL`` right is handled, Landlock will restrict +the invocation of IOCTL commands. However, to *allow* these IOCTL commands +again, some of these IOCTL commands are then granted through other, preexisting +access rights. + +For example, consider a program which handles ``LANDLOCK_ACCESS_FS_IOCTL`` and +``LANDLOCK_ACCESS_FS_READ_FILE``. The program *allows* +``LANDLOCK_ACCESS_FS_READ_FILE`` on a file ``foo.log``. + +By virtue of granting this access on the ``foo.log`` file, it is now possible to +use common and harmless IOCTL commands which are useful when reading files, such +as ``FIONREAD``. + +When both ``LANDLOCK_ACCESS_FS_IOCTL`` and other access rights are +handled in the ruleset, these other access rights may start governing +the use of individual IOCTL commands instead of +``LANDLOCK_ACCESS_FS_IOCTL``. For instance, if both +``LANDLOCK_ACCESS_FS_IOCTL`` and ``LANDLOCK_ACCESS_FS_READ_FILE`` are +handled, allowing ``LANDLOCK_ACCESS_FS_READ_FILE`` will make it +possible to use ``FIONREAD`` and other IOCTL commands. + +The following table illustrates how IOCTL attempts for ``FIONREAD`` are +filtered, depending on how a Landlock ruleset handles and allows the +``LANDLOCK_ACCESS_FS_IOCTL`` and ``LANDLOCK_ACCESS_FS_READ_FILE`` rights: + ++-------------------------+--------------+--------------+--------------+ +| | ``FS_IOCTL`` | ``FS_IOCTL`` | ``FS_IOCTL`` | +| | not handled | handled and | handled and | +| | | allowed | not allowed | ++-------------------------+--------------+--------------+--------------+ +| ``FS_READ_FILE`` | allow | allow | deny | +| not handled | | | | ++-------------------------+ +--------------+--------------+ +| ``FS_READ_FILE`` | | allow | +| handled and allowed | | | ++-------------------------+ +-----------------------------+ +| ``FS_READ_FILE`` | | deny | +| handled and not allowed | | | ++-------------------------+--------------+-----------------------------+ + +The full list of IOCTL commands and the access rights which affect them is +documented below. Compatibility ============= @@ -457,6 +517,27 @@ 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`` right restricts the use of :manpage:`ioctl(2)`, +but it only applies to newly opened 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. It is therefore recommended to close inherited TTY file descriptors, +or to reopen them from ``/proc/self/fd/*`` without the +``LANDLOCK_ACCESS_FS_IOCTL`` right, if possible. The :manpage:`isatty(3)` +function checks whether a given file descriptor is a TTY. + +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`` right on files where it is really harmless. In +cases where you can control the mounts, the ``nodev`` mount option can help to +rule out that device files can be accessed. + Previous limitations ==================== @@ -494,6 +575,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`` access right. + .. _kernel_support: Kernel support