Linux Security Modules development
 help / color / mirror / Atom feed
From: "Günther Noack" <gnoack@google.com>
To: "Mickaël Salaün" <mic@digikod.net>,
	"Christian Brauner" <brauner@kernel.org>
Cc: 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>,
	"Günther Noack" <gnoack@google.com>
Subject: [PATCH v3 0/3] landlock: Restrict renameat2 with RENAME_WHITEOUT
Date: Wed, 10 Jun 2026 11:23:15 +0200	[thread overview]
Message-ID: <20260610092318.3868884-1-gnoack@google.com> (raw)

Hello!

As discussed in [1], the renameat2() syscall's RENAME_WHITEOUT flag allows
the creation of chardev directory entries with major=minor=0 as "whiteout
objects" in the location of the rename source file [2].

This functionality is available even without having any OverlayFS mounted
and can be invoked with the regular renameat2(2) syscall [3].

In V1 [5], it was discussed that whiteout objects are not the same as
character devices, and should therefore be guarded with a separate access
right.  We are therefore guarding the operation with the new access right
LANDLOCK_ACCESS_FS_MAKE_WHITEOUT now.

By introducing a new access right, that change is also exposed by
incrementing the ABI level and does not require a Landlock erratum.

Motivation
==========

The RENAME_WHITEOUT flag side-steps all of the existing Landlock access
rights, which are designed to restrict the creation of directory entries.
It is desirable to restrict that.

This patch set fixes that by adding a check in Landlock's path_rename hook.


[1] https://lore.kernel.org/all/adUBCQXrt7kmgqJT@google.com/
[2] https://docs.kernel.org/filesystems/overlayfs.html#whiteouts-and-opaque-directories
[3] https://man7.org/linux/man-pages/man2/renameat2.2.html#DESCRIPTION
[4] https://codesearch.debian.net/search?q=rename.*RENAME_WHITEOUT&literal=0
[5] https://lore.kernel.org/all/20260411090944.3131168-2-gnoack@google.com/


Changelog
=========

v3:
 - Do LANDLOCK_ACCESS_FS_MAKE_WHITEOUT check as part of
   current_check_refer_path().

v2:
 - Introduce LANDLOCK_ACCESS_FS_MAKE_WHITEOUT access right
   and guard it with that.
 - Bump ABI version
 - https://lore.kernel.org/all/20260513160552.4022649-1-gnoack@google.com/

v1:
 - initial version
   https://lore.kernel.org/all/20260411090944.3131168-2-gnoack@google.com/


Günther Noack (3):
  landlock: Require LANDLOCK_ACCESS_FS_MAKE_WHITEOUT for RENAME_WHITEOUT
  selftests/landlock: Add test for RENAME_WHITEOUT denial
  selftests/landlock: Test OverlayFS renames w/o
    LANDLOCK_ACCESS_FS_MAKE_WHITEOUT

 include/uapi/linux/landlock.h                |  3 ++
 security/landlock/audit.c                    |  1 +
 security/landlock/fs.c                       | 17 +++++--
 security/landlock/limits.h                   |  2 +-
 security/landlock/syscalls.c                 |  2 +-
 tools/testing/selftests/landlock/base_test.c |  4 +-
 tools/testing/selftests/landlock/fs_test.c   | 50 +++++++++++++++++++-
 7 files changed, 70 insertions(+), 9 deletions(-)

Range-diff against v2:
1:  1f2b7f49b927 ! 1:  4a8c3fb9e707 landlock: Require LANDLOCK_ACCESS_FS_MAKE_WHITEOUT for RENAME_WHITEOUT
    @@ security/landlock/audit.c: static const char *const fs_access_strings[] = {
      static_assert(ARRAY_SIZE(fs_access_strings) == LANDLOCK_NUM_ACCESS_FS);
     
      ## security/landlock/fs.c ##
    +@@ security/landlock/fs.c: 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
    +@@ security/landlock/fs.c: 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);
    +@@ security/landlock/fs.c: static int current_check_refer_path(struct dentry *const 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_WHITEOUT;
    ++
    + 	/* The mount points are the same for old and new paths, cf. EXDEV. */
    + 	if (old_dentry->d_parent == new_dir->dentry) {
    + 		/*
    +@@ security/landlock/fs.c: 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,
     @@ security/landlock/fs.c: static int hook_path_rename(const struct path *const old_dir,
    - 			    const unsigned int flags)
      {
      	/* old_dir refers to old_dentry->d_parent and new_dir->mnt */
    -+	if (flags & RENAME_WHITEOUT) {
    -+		int err;
    -+
    -+		/*
    -+		 * Rename with RENAME_WHITEOUT creates a whiteout object in the
    -+		 * old location, so we check the access right for creating that.
    -+		 *
    -+		 * See Documentation/filesystems/overlayfs.rst and renameat2(2).
    -+		 */
    -+		err = current_check_access_path(
    -+			old_dir, LANDLOCK_ACCESS_FS_MAKE_WHITEOUT);
    -+		if (err)
    -+			return err;
    -+	}
    -+
      	return current_check_refer_path(old_dentry, new_dir, new_dentry, true,
    - 					!!(flags & RENAME_EXCHANGE));
    +-					!!(flags & RENAME_EXCHANGE));
    ++					!!(flags & RENAME_EXCHANGE),
    ++					!!(flags & RENAME_WHITEOUT));
      }
    + 
    + static int hook_path_mkdir(const struct path *const dir,
     
      ## security/landlock/limits.h ##
     @@
2:  aa4e4aeb5884 = 2:  063646822083 selftests/landlock: Add test for RENAME_WHITEOUT denial
3:  6660d70a1eda = 3:  5d4606bc1e84 selftests/landlock: Test OverlayFS renames w/o LANDLOCK_ACCESS_FS_MAKE_WHITEOUT
-- 
2.54.0.1099.g489fc7bff1-goog


             reply	other threads:[~2026-06-10  9:23 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-10  9:23 Günther Noack [this message]
2026-06-10  9:23 ` [PATCH v3 1/3] landlock: Require LANDLOCK_ACCESS_FS_MAKE_WHITEOUT for RENAME_WHITEOUT Günther Noack
2026-06-10  9:23 ` [PATCH v3 2/3] selftests/landlock: Add test for RENAME_WHITEOUT denial Günther Noack
2026-06-10  9:23 ` [PATCH v3 3/3] selftests/landlock: Test OverlayFS renames w/o LANDLOCK_ACCESS_FS_MAKE_WHITEOUT 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=20260610092318.3868884-1-gnoack@google.com \
    --to=gnoack@google.com \
    --cc=amir73il@gmail.com \
    --cc=brauner@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --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