From: "Mickaël Salaün" <mic@digikod.net>
To: "Günther Noack" <gnoack@google.com>
Cc: Christian Brauner <brauner@kernel.org>,
linux-security-module@vger.kernel.org,
Paul Moore <paul@paul-moore.com>,
Amir Goldstein <amir73il@gmail.com>,
Miklos Szeredi <miklos@szeredi.hu>,
Serge Hallyn <serge@hallyn.com>,
Stephen Smalley <stephen.smalley.work@gmail.com>
Subject: Re: [PATCH v4 2/5] landlock: Require LANDLOCK_ACCESS_FS_MAKE_REG for whiteout creation
Date: Fri, 31 Jul 2026 13:07:57 +0200 [thread overview]
Message-ID: <20260731.eiNi7aik6cah@digikod.net> (raw)
In-Reply-To: <20260724161004.2360749-3-gnoack@google.com>
On Fri, Jul 24, 2026 at 06:10:01PM +0200, Günther Noack wrote:
> Whiteout files are used in the upper layer of an Overlayfs to indicate
> that the file with this name does not exist in the unified view, even
> if it is present in one of the lower layer file systems.
>
> For userspace implementations of Overlay file systems (fuse-overlayfs),
We should name OverlayFS consistently.
> whiteout files can be created from userspace as well:
>
> * mknod(2) with S_IFCHR and makedev(0, 0)
> * renameat2(2) with RENAME_WHITEOUT,
> creating the whiteout in the old place of the moved file.
>
> This commit guards whiteout creation in both of these cases with
> LANDLOCK_ACCESS_FS_MAKE_REG. Whiteout files are *not* considered
> character devices and are not bound to a driver.
>
> Before this commit, renameat2(2) with RENAME_WHITEOUT would create a
> directory entry even when all LANDLOCK_ACCESS_FS_MAKE_* rights are
> denied.
>
> This does not affect normal renames within layered OverlayFS mounts:
> When doing a regular rename() on a mounted fuse-overlayfs, it is the
> fuse-overlayfs daemon that exercises renameat2() with RENAME_WHITEOUT,
> and only the Landlock domain of that daemon is checked there.
>
> This also adds a Landlock erratum for that case.
>
> Suggested-by: Christian Brauner <brauner@kernel.org>
> Suggested-by: Mickaël Salaün <mic@digikod.net>
> Fixes: cb2c7d1a1776 ("landlock: Support filesystem access-control")
> Signed-off-by: Günther Noack <gnoack@google.com>
> ---
> include/uapi/linux/landlock.h | 1 +
> security/landlock/errata/abi-1.h | 26 ++++++++++++++++++++++++++
> security/landlock/fs.c | 31 ++++++++++++++++++++++++-------
> 3 files changed, 51 insertions(+), 7 deletions(-)
>
> diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> index 7ffe2ef127ee..9c1102ebf06e 100644
> --- a/include/uapi/linux/landlock.h
> +++ b/include/uapi/linux/landlock.h
> @@ -351,6 +351,7 @@ struct landlock_net_port_attr {
> * device.
> * - %LANDLOCK_ACCESS_FS_MAKE_DIR: Create (or rename) a directory.
> * - %LANDLOCK_ACCESS_FS_MAKE_REG: Create (or rename or link) a regular file.
> + * This also guards the creation of whiteout objects as used in OverlayFS.
> * - %LANDLOCK_ACCESS_FS_MAKE_SOCK: Create (or rename or link) a UNIX domain
> * socket.
> * - %LANDLOCK_ACCESS_FS_MAKE_FIFO: Create (or rename or link) a named pipe.
> diff --git a/security/landlock/errata/abi-1.h b/security/landlock/errata/abi-1.h
> index 3f099555f059..ee43bf53f6e2 100644
> --- a/security/landlock/errata/abi-1.h
> +++ b/security/landlock/errata/abi-1.h
> @@ -22,3 +22,29 @@
> * from their original mount points.
> */
> LANDLOCK_ERRATUM(3)
> +
> +/**
> + * DOC: erratum_4
> + *
> + * Erratum 4: Creation of whiteout objects
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * This fix addresses an issue through which it was possible to create whiteout
> + * objects, even when all file creation is restricted using Landlock.
> + *
> + * With this fix, the creation of whiteout objects is now guarded using
> + * ``LANDLOCK_ACCESS_FS_MAKE_REG``, both when it is done through
> + * :manpage:`renameat2(2)` with `RENAME_WHITEOUT`, and when it is done through
> + * :manpage:`mknod(2)` with ``S_IFCHR`` and ``makedev(0, 0)`` (which previously
> + * required ``LANDLOCK_ACCESS_FS_MAKE_CHAR``).
> + *
> + * Whiteout objects are special file types used in OverlayFS to mark the absence
> + * of a file in an upper file system, even when the lower (often read-only) file
> + * system does have a file with the same name.
> + *
> + * Impact:
> + *
> + * Without this fix, it was possible to create whiteout files from userspace
> + * using :manpage:`renameat2(2)` with the ``RENAME_WHITEOUT`` flag.
The errata should focus on the change of access rights which are needed
(and could potentially break some use cases), not to talk about the
RENAME_WHITEOUT (bypass) fix. Most fixes don't get a Landlock errata
bit. The impact should then be explicit that this is for sandboxed
programs such as fuse-overlayfs.
This patch does two things:
- fix the RENAME_WHITEOUT creating a whitout without being controlled
(no errata, just a fix),
- and repurpose the MAKE_REG to control whitetout creation instead of
relying on MAKE_CHAR (which needs an errata because it could break
legitimate use cases/policies).
> + */
> +LANDLOCK_ERRATUM(4)
> diff --git a/security/landlock/fs.c b/security/landlock/fs.c
> index f7e5e4ef9eac..570f9ff21344 100644
> --- a/security/landlock/fs.c
> +++ b/security/landlock/fs.c
> @@ -983,7 +983,8 @@ static int current_check_access_path(const struct path *const path,
> return -EACCES;
> }
#include <linux/kdev_t.h>
>
> -static __attribute_const__ access_mask_t get_mode_access(const umode_t mode)
> +static __attribute_const__ access_mask_t get_mode_access(const umode_t mode,
> + const unsigned int dev)
const dev_t dev
> {
> switch (mode & S_IFMT) {
> case S_IFLNK:
> @@ -991,6 +992,9 @@ static __attribute_const__ access_mask_t get_mode_access(const umode_t mode)
> case S_IFDIR:
> return LANDLOCK_ACCESS_FS_MAKE_DIR;
> case S_IFCHR:
> + /* Whiteout objects are guarded with MAKE_REG. */
> + if (dev == WHITEOUT_DEV)
This kind of work by luck, but dev should really be dev_t.
> + return LANDLOCK_ACCESS_FS_MAKE_REG;
> return LANDLOCK_ACCESS_FS_MAKE_CHAR;
> case S_IFBLK:
> return LANDLOCK_ACCESS_FS_MAKE_BLOCK;
> @@ -1093,6 +1097,7 @@ static bool collect_domain_accesses(const struct landlock_ruleset *const domain,
> * @new_dentry: Destination file or directory.
> * @removable: Sets to true if it is a rename operation.
> * @exchange: Sets to true if it is a rename operation with RENAME_EXCHANGE.
> + * @whiteout: Sets to true if it is a rename operation with RENAME_WHITEOUT.
> *
> * Because of its unprivileged constraints, Landlock relies on file hierarchies
> * (and not only inodes) to tie access rights to files. Being able to link or
> @@ -1140,7 +1145,8 @@ static bool collect_domain_accesses(const struct landlock_ruleset *const domain,
> static int current_check_refer_path(struct dentry *const old_dentry,
> const struct path *const new_dir,
> struct dentry *const new_dentry,
> - const bool removable, const bool exchange)
> + const bool removable, const bool exchange,
> + const bool whiteout)
> {
> const struct landlock_cred_security *const subject =
> landlock_get_applicable_subject(current_cred(), any_fs, NULL);
> @@ -1160,17 +1166,27 @@ static int current_check_refer_path(struct dentry *const old_dentry,
> if (unlikely(d_is_negative(new_dentry)))
> return -ENOENT;
> access_request_parent1 =
> - get_mode_access(d_backing_inode(new_dentry)->i_mode);
> + get_mode_access(d_backing_inode(new_dentry)->i_mode,
> + d_backing_inode(new_dentry)->i_rdev);
A new small get_dentry_access(dentry) helper would simplify these calls.
> } else {
> access_request_parent1 = 0;
> }
> access_request_parent2 =
> - get_mode_access(d_backing_inode(old_dentry)->i_mode);
> + get_mode_access(d_backing_inode(old_dentry)->i_mode,
> + d_backing_inode(old_dentry)->i_rdev);
> if (removable) {
> access_request_parent1 |= maybe_remove(old_dentry);
> access_request_parent2 |= maybe_remove(new_dentry);
> }
>
> + /*
> + * In case of renameat2(2) with RENAME_WHITEOUT, a whiteout object is
> + * created in the source location, so we require an additional access
> + * right there.
> + */
> + if (whiteout)
> + access_request_parent1 |= LANDLOCK_ACCESS_FS_MAKE_REG;
I'm wondering if this would be cleaner (see OverlayFS code):
access_request_parent1 |= get_mode_access(S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
> +
> /* The mount points are the same for old and new paths, cf. EXDEV. */
> if (old_dentry->d_parent == new_dir->dentry) {
> /*
> @@ -1520,7 +1536,7 @@ static int hook_path_link(struct dentry *const old_dentry,
> struct dentry *const new_dentry)
> {
> return current_check_refer_path(old_dentry, new_dir, new_dentry, false,
> - false);
> + false, false);
> }
>
> static int hook_path_rename(const struct path *const old_dir,
> @@ -1531,7 +1547,8 @@ static int hook_path_rename(const struct path *const old_dir,
> {
> /* old_dir refers to old_dentry->d_parent and new_dir->mnt */
> return current_check_refer_path(old_dentry, new_dir, new_dentry, true,
> - !!(flags & RENAME_EXCHANGE));
> + !!(flags & RENAME_EXCHANGE),
> + !!(flags & RENAME_WHITEOUT));
> }
>
> static int hook_path_mkdir(const struct path *const dir,
> @@ -1544,7 +1561,7 @@ static int hook_path_mknod(const struct path *const dir,
> struct dentry *const dentry, const umode_t mode,
> const unsigned int dev)
> {
> - return current_check_access_path(dir, get_mode_access(mode));
> + return current_check_access_path(dir, get_mode_access(mode, dev));
return current_check_access_path(dir, get_mode_access(mode, new_decode_dev(dev)));
> }
>
> static int hook_path_symlink(const struct path *const dir,
> --
> 2.55.0.229.g6434b31f56-goog
>
>
next prev parent reply other threads:[~2026-07-31 11:08 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 16:09 [PATCH v4 0/5] landlock: Restrict whiteout object creation Günther Noack
2026-07-24 16:10 ` [PATCH v4 1/5] selftests/landlock: Use an actual chardev for MAKE_CHAR audit test Günther Noack
2026-07-24 16:10 ` [PATCH v4 2/5] landlock: Require LANDLOCK_ACCESS_FS_MAKE_REG for whiteout creation Günther Noack
2026-07-31 11:07 ` Mickaël Salaün [this message]
2026-07-31 13:13 ` Günther Noack
2026-07-31 14:21 ` Günther Noack
2026-07-31 15:14 ` Mickaël Salaün
2026-07-31 13:13 ` Mickaël Salaün
2026-07-31 14:05 ` Günther Noack
2026-07-24 16:10 ` [PATCH v4 3/5] selftests/landlock: Add tests for whiteout object creation Günther Noack
2026-07-31 13:22 ` Mickaël Salaün
2026-07-31 14:18 ` Günther Noack
2026-07-24 16:10 ` [PATCH v4 4/5] selftests/landlock: Test whiteout object behaviour in OverlayFS renames Günther Noack
2026-07-31 13:43 ` Mickaël Salaün
2026-07-24 16:10 ` [PATCH v4 5/5] landlock: Link the erratum documentation for whiteout objects Günther Noack
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260731.eiNi7aik6cah@digikod.net \
--to=mic@digikod.net \
--cc=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=gnoack@google.com \
--cc=linux-security-module@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=paul@paul-moore.com \
--cc=serge@hallyn.com \
--cc=stephen.smalley.work@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox