All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks
@ 2026-07-06 23:50 Song Liu
  2026-07-06 23:50 ` [PATCH v6 1/8] lsm: Add " Song Liu
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

This series replaces the monolithic security_sb_mount() hook with
per-operation mount hooks, addressing two main issues:

1. TOCTOU: security_sb_mount() receives dev_name as a string, which
   LSMs like AppArmor and Tomoyo re-resolve via kern_path(). The new
   hooks pass pre-resolved struct path pointers where possible (bind
   mount, move mount), eliminating the double-resolution.

2. Conflation: security_sb_mount() handles bind, new mount, remount,
   move, propagation changes, and mount reconfiguration through a
   single hook, requiring LSMs to dispatch on flags internally. The
   new hooks are called at the operation level with appropriate
   context.

The new hooks are:
  mount_bind        - bind mount (pre-resolved source path)
  mount_new         - new filesystem mount (with fs_context)
  mount_remount     - filesystem remount (with fs_context)
  mount_reconfigure - mount flag reconfiguration (MS_REMOUNT|MS_BIND)
  mount_move        - move mount (pre-resolved paths)
  mount_change_type - propagation type changes

mount_new and mount_remount are called after parse_monolithic_mount_data(),
so LSMs have access to the fs_context with parsed mount options. They also
receive the original mount(2) flags and data pointer for LSMs (AppArmor,
Tomoyo) that need them for policy matching.

The series also replaces security_move_mount() with the new mount_move
hook, unifying the old mount(2) MS_MOVE path with the move_mount(2)
syscall path.

All existing LSM behaviors are preserved:
  AppArmor: same policy matching, TOCTOU fixed for bind/move
  SELinux:  same permission checks (FILE__MOUNTON, FILESYSTEM__REMOUNT)
  Landlock: same deny-all for sandboxed processes
  Tomoyo:   same policy matching, TOCTOU fixed for bind/move, unused
            data_page parameter removed


This work is inspired by earlier discussions:

[1] https://lore.kernel.org/bpf/20251127005011.1872209-1-song@kernel.org/
[2] https://lore.kernel.org/linux-security-module/20250708230504.3994335-1-song@kernel.org/

Changes v5 => v6:
1. Move security_mount_bind() and security_mount_move() under
   LOCK_MOUNT()/LOCK_MOUNT_MAYBE_BENEATH(). (Christian Brauner)
2. Rebase.

v5: https://lore.kernel.org/all/20260528182607.3150386-1-song@kernel.org/

Changes v4 => v5:
1. Restructure series: add new hooks in security/ first, then convert
   individual LSMs, then replace old hooks with new hooks in
   fs/namespace.c (single patch), then remove old hooks. This keeps
   all fs/namespace.c changes in one patch. (Christian Brauner)
2. Rebase.

v4: https://lore.kernel.org/linux-security-module/20260515200158.4081915-1-song@kernel.org/

Changes v3 => v4:
1. Move LSM_HOOK_INIT(move_mount, ...) removal from patch 7/7 to each
   per-LSM conversion patch (3/7, 4/7, 5/7). (Paul Moore)
2. Add kdoc comments to tomoyo mount hook functions and rename
   tomoyo_move_mount to tomoyo_mount_move in patch 6/7. (Tetsuo Handa)
3. Add Acked-by from Tetsuo Handa to patch 6/7.

v3: https://lore.kernel.org/linux-security-module/20260509015208.3853132-1-song@kernel.org/

Changes v2 => v3:
1. Rebase.
2. Move security_mount_move() call in vfs_move_mount() from patch 7/7
   to patch 1/7. (Paul Moore)

v2: https://lore.kernel.org/linux-security-module/20260430000315.918964-1-song@kernel.org/

Changes v1 => v2:
1. Rebase.
2. Add Reviewed-by and Tested-by from Stephen Smalley.

v1: https://lore.kernel.org/linux-security-module/20260318184400.3502908-1-song@kernel.org/

Song Liu (8):
  lsm: Add granular mount hooks
  apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount
  apparmor: Convert from sb_mount to granular mount hooks
  selinux: Convert from sb_mount to granular mount hooks
  landlock: Convert from sb_mount to granular mount hooks
  tomoyo: Convert from sb_mount to granular mount hooks
  vfs: Replace security_sb_mount/security_move_mount with granular hooks
  lsm: Remove security_sb_mount and security_move_mount

 fs/namespace.c                    |  77 ++++++++++++++----
 include/linux/lsm_hook_defs.h     |  16 +++-
 include/linux/security.h          |  60 +++++++++++---
 kernel/bpf/bpf_lsm.c              |   7 +-
 security/apparmor/include/mount.h |   5 +-
 security/apparmor/lsm.c           | 105 +++++++++++++++++-------
 security/apparmor/mount.c         |  37 ++-------
 security/landlock/fs.c            |  44 ++++++++--
 security/security.c               | 129 +++++++++++++++++++++++-------
 security/selinux/hooks.c          |  52 ++++++++----
 security/tomoyo/common.h          |   2 +-
 security/tomoyo/mount.c           |  31 ++++---
 security/tomoyo/tomoyo.c          | 111 ++++++++++++++++++++++---
 13 files changed, 508 insertions(+), 168 deletions(-)

--
2.53.0-Meta

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v6 1/8] lsm: Add granular mount hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:00   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount Song Liu
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Add the new granular mount hook declarations and implementations
to the LSM framework:

  mount_bind        - bind mount (pre-resolved source path)
  mount_new         - new filesystem mount (with fs_context)
  mount_remount     - filesystem remount (with fs_context)
  mount_reconfigure - mount flag reconfiguration (MS_REMOUNT|MS_BIND)
  mount_move        - move mount (pre-resolved source, target and top
                      paths; target == top unless MOVE_MOUNT_BENEATH)
  mount_change_type - propagation type changes

These hooks are added alongside the existing security_sb_mount() and
security_move_mount() hooks, which remain in place until all LSMs
are converted.

Code generated with the assistance of Claude, reviewed by human.

Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com> # for selinux only
Signed-off-by: Song Liu <song@kernel.org>
---
 include/linux/lsm_hook_defs.h |  12 ++++
 include/linux/security.h      |  52 +++++++++++++++++
 kernel/bpf/bpf_lsm.c          |   7 +++
 security/security.c           | 107 ++++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 65c9609ec207..06c904cb478e 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -81,6 +81,18 @@ LSM_HOOK(int, 0, sb_clone_mnt_opts, const struct super_block *oldsb,
 	 unsigned long *set_kern_flags)
 LSM_HOOK(int, 0, move_mount, const struct path *from_path,
 	 const struct path *to_path)
+LSM_HOOK(int, 0, mount_bind, const struct path *from, const struct path *to,
+	 bool recurse)
+LSM_HOOK(int, 0, mount_new, struct fs_context *fc, const struct path *mp,
+	 int mnt_flags, unsigned long flags, void *data)
+LSM_HOOK(int, 0, mount_remount, struct fs_context *fc,
+	 const struct path *mp, int mnt_flags, unsigned long flags,
+	 void *data)
+LSM_HOOK(int, 0, mount_reconfigure, const struct path *mp,
+	 unsigned int mnt_flags, unsigned long flags)
+LSM_HOOK(int, 0, mount_move, const struct path *from_path,
+	 const struct path *to_path, const struct path *top_path)
+LSM_HOOK(int, 0, mount_change_type, const struct path *mp, int ms_flags)
 LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
 	 int mode, const struct qstr *name, const char **xattr_name,
 	 struct lsm_context *cp)
diff --git a/include/linux/security.h b/include/linux/security.h
index 153e9043058f..5e207e38c004 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -386,6 +386,18 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				unsigned long kern_flags,
 				unsigned long *set_kern_flags);
 int security_move_mount(const struct path *from_path, const struct path *to_path);
+int security_mount_bind(const struct path *from, const struct path *to,
+			bool recurse);
+int security_mount_new(struct fs_context *fc, const struct path *mp,
+		       int mnt_flags, unsigned long flags, void *data);
+int security_mount_remount(struct fs_context *fc, const struct path *mp,
+			   int mnt_flags, unsigned long flags, void *data);
+int security_mount_reconfigure(const struct path *mp, unsigned int mnt_flags,
+			       unsigned long flags);
+int security_mount_move(const struct path *from_path,
+			const struct path *to_path,
+			const struct path *top_path);
+int security_mount_change_type(const struct path *mp, int ms_flags);
 int security_dentry_init_security(struct dentry *dentry, int mode,
 				  const struct qstr *name,
 				  const char **xattr_name,
@@ -854,6 +866,46 @@ static inline int security_move_mount(const struct path *from_path,
 	return 0;
 }
 
+static inline int security_mount_bind(const struct path *from,
+				      const struct path *to, bool recurse)
+{
+	return 0;
+}
+
+static inline int security_mount_new(struct fs_context *fc,
+				     const struct path *mp, int mnt_flags,
+				     unsigned long flags, void *data)
+{
+	return 0;
+}
+
+static inline int security_mount_remount(struct fs_context *fc,
+					 const struct path *mp, int mnt_flags,
+					 unsigned long flags, void *data)
+{
+	return 0;
+}
+
+static inline int security_mount_reconfigure(const struct path *mp,
+					     unsigned int mnt_flags,
+					     unsigned long flags)
+{
+	return 0;
+}
+
+static inline int security_mount_move(const struct path *from_path,
+				      const struct path *to_path,
+				      const struct path *top_path)
+{
+	return 0;
+}
+
+static inline int security_mount_change_type(const struct path *mp,
+					     int ms_flags)
+{
+	return 0;
+}
+
 static inline int security_path_notify(const struct path *path, u64 mask,
 				unsigned int obj_type)
 {
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index 1433809bb166..4b1ee9c67d6f 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -385,6 +385,13 @@ BTF_ID(func, bpf_lsm_task_setscheduler)
 BTF_ID(func, bpf_lsm_userns_create)
 BTF_ID(func, bpf_lsm_bdev_alloc_security)
 BTF_ID(func, bpf_lsm_bdev_setintegrity)
+BTF_ID(func, bpf_lsm_move_mount)
+BTF_ID(func, bpf_lsm_mount_bind)
+BTF_ID(func, bpf_lsm_mount_new)
+BTF_ID(func, bpf_lsm_mount_remount)
+BTF_ID(func, bpf_lsm_mount_reconfigure)
+BTF_ID(func, bpf_lsm_mount_move)
+BTF_ID(func, bpf_lsm_mount_change_type)
 BTF_SET_END(sleepable_lsm_hooks)
 
 BTF_SET_START(untrusted_lsm_hooks)
diff --git a/security/security.c b/security/security.c
index 71aea8fdf014..1ede060db3ca 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1182,6 +1182,113 @@ int security_move_mount(const struct path *from_path,
 	return call_int_hook(move_mount, from_path, to_path);
 }
 
+/**
+ * security_mount_bind() - Check permissions for a bind mount
+ * @from: source path
+ * @to: destination mount point
+ * @recurse: whether this is a recursive bind mount
+ *
+ * Check permission before a bind mount is performed. Called with the
+ * source path already resolved, eliminating TOCTOU issues with
+ * string-based dev_name in security_sb_mount().
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_bind(const struct path *from, const struct path *to,
+			bool recurse)
+{
+	return call_int_hook(mount_bind, from, to, recurse);
+}
+
+/**
+ * security_mount_new() - Check permissions for a new mount
+ * @fc: filesystem context with parsed options
+ * @mp: mount point path
+ * @mnt_flags: mount flags (MNT_*)
+ * @flags: original mount flags (MS_*, used by AppArmor/Tomoyo)
+ * @data: filesystem specific data (used by AppArmor)
+ *
+ * Check permission before a new filesystem is mounted. Called after
+ * mount options are parsed, providing access to the fs_context.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_new(struct fs_context *fc, const struct path *mp,
+		       int mnt_flags, unsigned long flags, void *data)
+{
+	return call_int_hook(mount_new, fc, mp, mnt_flags, flags, data);
+}
+
+/**
+ * security_mount_remount() - Check permissions for a remount
+ * @fc: filesystem context with parsed options
+ * @mp: mount point path
+ * @mnt_flags: mount flags (MNT_*)
+ * @flags: original mount flags (MS_*, used by AppArmor/Tomoyo)
+ * @data: filesystem specific data (used by AppArmor)
+ *
+ * Check permission before a filesystem is remounted. Called after
+ * mount options are parsed, providing access to the fs_context.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_remount(struct fs_context *fc, const struct path *mp,
+			   int mnt_flags, unsigned long flags, void *data)
+{
+	return call_int_hook(mount_remount, fc, mp, mnt_flags, flags, data);
+}
+
+/**
+ * security_mount_reconfigure() - Check permissions for mount reconfiguration
+ * @mp: mount point path
+ * @mnt_flags: new mount flags (MNT_*)
+ * @flags: original mount flags (MS_*, used by AppArmor/Tomoyo)
+ *
+ * Check permission before mount flags are reconfigured (MS_REMOUNT|MS_BIND).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_reconfigure(const struct path *mp, unsigned int mnt_flags,
+			       unsigned long flags)
+{
+	return call_int_hook(mount_reconfigure, mp, mnt_flags, flags);
+}
+
+/**
+ * security_mount_move() - Check permissions for moving a mount
+ * @from_path: source mount path
+ * @to_path: destination mount point path
+ * @top_path: mount that ends up on top at the destination
+ *
+ * Check permission before a mount is moved.  Called with the destination
+ * pinned under the namespace semaphore, so @to_path reflects the mount
+ * point that will actually be used.  For a plain move @top_path equals
+ * @to_path; for a MOVE_MOUNT_BENEATH move the source is inserted below
+ * @top_path, allowing a policy over the (source, target, top) triple.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_move(const struct path *from_path,
+			const struct path *to_path,
+			const struct path *top_path)
+{
+	return call_int_hook(mount_move, from_path, to_path, top_path);
+}
+
+/**
+ * security_mount_change_type() - Check permissions for propagation changes
+ * @mp: mount point path
+ * @ms_flags: propagation flags (MS_SHARED, MS_PRIVATE, etc.)
+ *
+ * Check permission before mount propagation type is changed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_mount_change_type(const struct path *mp, int ms_flags)
+{
+	return call_int_hook(mount_change_type, mp, ms_flags);
+}
+
 /**
  * security_path_notify() - Check if setting a watch is allowed
  * @path: file path
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
  2026-07-06 23:50 ` [PATCH v6 1/8] lsm: Add " Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:04   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks Song Liu
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

path_mount() already strips the magic number from flags before
calling security_sb_mount(), so this check in apparmor_sb_mount()
is a no-op. Remove it.

Code generated with the assistance of Claude, reviewed by human.

Signed-off-by: Song Liu <song@kernel.org>
---
 security/apparmor/lsm.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 88d12e89d115..71f30dd43f97 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -705,10 +705,6 @@ static int apparmor_sb_mount(const char *dev_name, const struct path *path,
 	int error = 0;
 	bool needput;
 
-	/* Discard magic */
-	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
-		flags &= ~MS_MGC_MSK;
-
 	flags &= ~AA_MS_IGNORE_MASK;
 
 	label = __begin_current_label_crit_section(&needput);
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
  2026-07-06 23:50 ` [PATCH v6 1/8] lsm: Add " Song Liu
  2026-07-06 23:50 ` [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:05   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 4/8] selinux: " Song Liu
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Replace AppArmor's monolithic apparmor_sb_mount() with granular
mount hooks.

Key changes:
- mount_bind: uses the pre-resolved struct path from VFS instead of
  re-resolving dev_name via kern_path(), eliminating a TOCTOU
  vulnerability. aa_bind_mount() now takes a struct path instead of
  a string for the source.
- mount_new, mount_remount: receive the original mount(2) flags and
  data parameters for policy matching via match_mnt_flags() and
  AA_MNT_CONT_MATCH data matching.
- mount_reconfigure: handles MS_REMOUNT|MS_BIND (mount attribute
  reconfiguration) which was previously handled as a remount.
- mount_move: wired to apparmor_move_mount(); its signature gains the
  new top_path argument (currently unused, reserved for
  MOVE_MOUNT_BENEATH policy).
- mount_change_type: propagation type changes.

aa_move_mount_old() is removed since move mounts now go through
security_mount_move() with pre-resolved struct path pointers for
both the old mount(2) and new move_mount(2) APIs.

Code generated with the assistance of Claude, reviewed by human.

Signed-off-by: Song Liu <song@kernel.org>
---
 security/apparmor/include/mount.h |   5 +-
 security/apparmor/lsm.c           | 103 +++++++++++++++++++++++-------
 security/apparmor/mount.c         |  37 ++---------
 3 files changed, 85 insertions(+), 60 deletions(-)

diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
index 46834f828179..088e2f938cc1 100644
--- a/security/apparmor/include/mount.h
+++ b/security/apparmor/include/mount.h
@@ -31,16 +31,13 @@ int aa_remount(const struct cred *subj_cred,
 
 int aa_bind_mount(const struct cred *subj_cred,
 		  struct aa_label *label, const struct path *path,
-		  const char *old_name, unsigned long flags);
+		  const struct path *old_path, bool recurse);
 
 
 int aa_mount_change_type(const struct cred *subj_cred,
 			 struct aa_label *label, const struct path *path,
 			 unsigned long flags);
 
-int aa_move_mount_old(const struct cred *subj_cred,
-		      struct aa_label *label, const struct path *path,
-		      const char *old_name);
 int aa_move_mount(const struct cred *subj_cred,
 		  struct aa_label *label, const struct path *from_path,
 		  const struct path *to_path);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 71f30dd43f97..d9d5822e4022 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/mount.h>
+#include <linux/fs_context.h>
 #include <linux/namei.h>
 #include <linux/ptrace.h>
 #include <linux/ctype.h>
@@ -698,41 +699,91 @@ static int apparmor_uring_sqpoll(void)
 }
 #endif /* CONFIG_IO_URING */
 
-static int apparmor_sb_mount(const char *dev_name, const struct path *path,
-			     const char *type, unsigned long flags, void *data)
+static int apparmor_mount_bind(const struct path *from, const struct path *to,
+			       bool recurse)
 {
 	struct aa_label *label;
 	int error = 0;
 	bool needput;
 
-	flags &= ~AA_MS_IGNORE_MASK;
+	label = __begin_current_label_crit_section(&needput);
+	if (!unconfined(label))
+		error = aa_bind_mount(current_cred(), label, to, from,
+				      recurse);
+	__end_current_label_crit_section(label, needput);
 
+	return error;
+}
+
+static int apparmor_mount_new(struct fs_context *fc, const struct path *mp,
+			      int mnt_flags, unsigned long flags, void *data)
+{
+	struct aa_label *label;
+	int error = 0;
+	bool needput;
+
+	/* flags and data are from the original mount(2) call */
 	label = __begin_current_label_crit_section(&needput);
-	if (!unconfined(label)) {
-		if (flags & MS_REMOUNT)
-			error = aa_remount(current_cred(), label, path, flags,
-					   data);
-		else if (flags & MS_BIND)
-			error = aa_bind_mount(current_cred(), label, path,
-					      dev_name, flags);
-		else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
-				  MS_UNBINDABLE))
-			error = aa_mount_change_type(current_cred(), label,
-						     path, flags);
-		else if (flags & MS_MOVE)
-			error = aa_move_mount_old(current_cred(), label, path,
-						  dev_name);
-		else
-			error = aa_new_mount(current_cred(), label, dev_name,
-					     path, type, flags, data);
-	}
+	if (!unconfined(label))
+		error = aa_new_mount(current_cred(), label, fc->source,
+				     mp, fc->fs_type->name, flags, data);
+	__end_current_label_crit_section(label, needput);
+
+	return error;
+}
+
+static int apparmor_mount_remount(struct fs_context *fc, const struct path *mp,
+				  int mnt_flags, unsigned long flags,
+				  void *data)
+{
+	struct aa_label *label;
+	int error = 0;
+	bool needput;
+
+	/* flags and data are from the original mount(2) call */
+	label = __begin_current_label_crit_section(&needput);
+	if (!unconfined(label))
+		error = aa_remount(current_cred(), label, mp, flags, data);
+	__end_current_label_crit_section(label, needput);
+
+	return error;
+}
+
+static int apparmor_mount_reconfigure(const struct path *mp,
+				      unsigned int mnt_flags,
+				      unsigned long flags)
+{
+	struct aa_label *label;
+	int error = 0;
+	bool needput;
+
+	/* flags are from the original mount(2) call */
+	label = __begin_current_label_crit_section(&needput);
+	if (!unconfined(label))
+		error = aa_remount(current_cred(), label, mp, flags, NULL);
+	__end_current_label_crit_section(label, needput);
+
+	return error;
+}
+
+static int apparmor_mount_change_type(const struct path *mp, int ms_flags)
+{
+	struct aa_label *label;
+	int error = 0;
+	bool needput;
+
+	label = __begin_current_label_crit_section(&needput);
+	if (!unconfined(label))
+		error = aa_mount_change_type(current_cred(), label, mp,
+					     ms_flags);
 	__end_current_label_crit_section(label, needput);
 
 	return error;
 }
 
 static int apparmor_move_mount(const struct path *from_path,
-			       const struct path *to_path)
+			       const struct path *to_path,
+			       const struct path *top_path)
 {
 	struct aa_label *label;
 	int error = 0;
@@ -1669,8 +1720,12 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(capget, apparmor_capget),
 	LSM_HOOK_INIT(capable, apparmor_capable),
 
-	LSM_HOOK_INIT(move_mount, apparmor_move_mount),
-	LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
+	LSM_HOOK_INIT(mount_bind, apparmor_mount_bind),
+	LSM_HOOK_INIT(mount_new, apparmor_mount_new),
+	LSM_HOOK_INIT(mount_remount, apparmor_mount_remount),
+	LSM_HOOK_INIT(mount_reconfigure, apparmor_mount_reconfigure),
+	LSM_HOOK_INIT(mount_move, apparmor_move_mount),
+	LSM_HOOK_INIT(mount_change_type, apparmor_mount_change_type),
 	LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
 	LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
 
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
index 2f5d918832c1..1ea0d680437c 100644
--- a/security/apparmor/mount.c
+++ b/security/apparmor/mount.c
@@ -418,25 +418,17 @@ int aa_remount(const struct cred *subj_cred,
 }
 
 int aa_bind_mount(const struct cred *subj_cred,
-		  struct aa_label *label, const struct path *path,
-		  const char *dev_name, unsigned long flags)
+		       struct aa_label *label, const struct path *path,
+		       const struct path *old_path, bool recurse)
 {
 	struct aa_profile *profile;
 	char *buffer = NULL, *old_buffer = NULL;
-	struct path old_path;
+	unsigned long flags = MS_BIND | (recurse ? MS_REC : 0);
 	int error;
 
 	AA_BUG(!label);
 	AA_BUG(!path);
-
-	if (!dev_name || !*dev_name)
-		return -EINVAL;
-
-	flags &= MS_REC | MS_BIND;
-
-	error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
-	if (error)
-		return error;
+	AA_BUG(!old_path);
 
 	buffer = aa_get_buffer(false);
 	old_buffer = aa_get_buffer(false);
@@ -445,12 +437,11 @@ int aa_bind_mount(const struct cred *subj_cred,
 		goto out;
 
 	error = fn_for_each_confined(label, profile,
-			match_mnt(subj_cred, profile, path, buffer, &old_path,
+			match_mnt(subj_cred, profile, path, buffer, old_path,
 				  old_buffer, NULL, flags, NULL, false));
 out:
 	aa_put_buffer(buffer);
 	aa_put_buffer(old_buffer);
-	path_put(&old_path);
 
 	return error;
 }
@@ -514,24 +505,6 @@ int aa_move_mount(const struct cred *subj_cred,
 	return error;
 }
 
-int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label,
-		      const struct path *path, const char *orig_name)
-{
-	struct path old_path;
-	int error;
-
-	if (!orig_name || !*orig_name)
-		return -EINVAL;
-	error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
-	if (error)
-		return error;
-
-	error = aa_move_mount(subj_cred, label, &old_path, path);
-	path_put(&old_path);
-
-	return error;
-}
-
 int aa_new_mount(const struct cred *subj_cred, struct aa_label *label,
 		 const char *dev_name, const struct path *path,
 		 const char *type, unsigned long flags, void *data)
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 4/8] selinux: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
                   ` (2 preceding siblings ...)
  2026-07-06 23:50 ` [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:01   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 5/8] landlock: " Song Liu
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Replace selinux_mount() with granular mount hooks, preserving the
same permission checks:

- mount_bind, mount_new, mount_change_type: FILE__MOUNTON
- mount_remount, mount_reconfigure: FILESYSTEM__REMOUNT
- mount_move: FILE__MOUNTON (reuses selinux_move_mount)

The flags, data, and top_path parameters are unused by SELinux.

Code generated with the assistance of Claude, reviewed by human.

Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Song Liu <song@kernel.org>
---
 security/selinux/hooks.c | 52 ++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1a713d96206f..6cbe52375b5c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2802,23 +2802,42 @@ static int selinux_sb_statfs(struct dentry *dentry)
 	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
-static int selinux_mount(const char *dev_name,
-			 const struct path *path,
-			 const char *type,
-			 unsigned long flags,
-			 void *data)
+static int selinux_mount_bind(const struct path *from, const struct path *to,
+			      bool recurse)
 {
-	const struct cred *cred = current_cred();
+	return path_has_perm(current_cred(), to, FILE__MOUNTON);
+}
 
-	if (flags & MS_REMOUNT)
-		return superblock_has_perm(cred, path->dentry->d_sb,
-					   FILESYSTEM__REMOUNT, NULL);
-	else
-		return path_has_perm(cred, path, FILE__MOUNTON);
+static int selinux_mount_new(struct fs_context *fc, const struct path *mp,
+			     int mnt_flags, unsigned long flags, void *data)
+{
+	return path_has_perm(current_cred(), mp, FILE__MOUNTON);
+}
+
+static int selinux_mount_remount(struct fs_context *fc, const struct path *mp,
+				 int mnt_flags, unsigned long flags,
+				 void *data)
+{
+	return superblock_has_perm(current_cred(), fc->root->d_sb,
+				   FILESYSTEM__REMOUNT, NULL);
+}
+
+static int selinux_mount_reconfigure(const struct path *mp,
+				     unsigned int mnt_flags,
+				     unsigned long flags)
+{
+	return superblock_has_perm(current_cred(), mp->dentry->d_sb,
+				   FILESYSTEM__REMOUNT, NULL);
+}
+
+static int selinux_mount_change_type(const struct path *mp, int ms_flags)
+{
+	return path_has_perm(current_cred(), mp, FILE__MOUNTON);
 }
 
 static int selinux_move_mount(const struct path *from_path,
-			      const struct path *to_path)
+			      const struct path *to_path,
+			      const struct path *top_path)
 {
 	const struct cred *cred = current_cred();
 
@@ -7554,13 +7573,16 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
 	LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
 	LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
-	LSM_HOOK_INIT(sb_mount, selinux_mount),
+	LSM_HOOK_INIT(mount_bind, selinux_mount_bind),
+	LSM_HOOK_INIT(mount_new, selinux_mount_new),
+	LSM_HOOK_INIT(mount_remount, selinux_mount_remount),
+	LSM_HOOK_INIT(mount_reconfigure, selinux_mount_reconfigure),
+	LSM_HOOK_INIT(mount_change_type, selinux_mount_change_type),
+	LSM_HOOK_INIT(mount_move, selinux_move_mount),
 	LSM_HOOK_INIT(sb_umount, selinux_umount),
 	LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
 	LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
 
-	LSM_HOOK_INIT(move_mount, selinux_move_mount),
-
 	LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
 	LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
 
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 5/8] landlock: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
                   ` (3 preceding siblings ...)
  2026-07-06 23:50 ` [PATCH v6 4/8] selinux: " Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:04   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 6/8] tomoyo: " Song Liu
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Replace hook_sb_mount() with granular mount hooks. Landlock denies
all mount operations for sandboxed processes regardless of flags,
so all new hooks share a common hook_mount_deny() helper. The
mount_move hook reuses hook_move_mount() (its new top_path argument
is unused).

Code generated with the assistance of Claude, reviewed by human.

Signed-off-by: Song Liu <song@kernel.org>
---
 security/landlock/fs.c | 44 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index f7e5e4ef9eac..0c56a3aa45ea 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1427,9 +1427,7 @@ static void log_fs_change_topology_dentry(
  * inherit these new constraints.  Anyway, for backward compatibility reasons,
  * a dedicated user space option would be required (e.g. as a ruleset flag).
  */
-static int hook_sb_mount(const char *const dev_name,
-			 const struct path *const path, const char *const type,
-			 const unsigned long flags, void *const data)
+static int hook_mount_deny(const struct path *const path)
 {
 	size_t handle_layer;
 	const struct landlock_cred_security *const subject =
@@ -1443,8 +1441,38 @@ static int hook_sb_mount(const char *const dev_name,
 	return -EPERM;
 }
 
+static int hook_mount_bind(const struct path *const from,
+			   const struct path *const to, bool recurse)
+{
+	return hook_mount_deny(to);
+}
+
+static int hook_mount_new(struct fs_context *fc, const struct path *const mp,
+			  int mnt_flags, unsigned long flags, void *data)
+{
+	return hook_mount_deny(mp);
+}
+
+static int hook_mount_remount(struct fs_context *fc, const struct path *mp,
+			      int mnt_flags, unsigned long flags, void *data)
+{
+	return hook_mount_deny(mp);
+}
+
+static int hook_mount_reconfigure(const struct path *const mp,
+				  unsigned int mnt_flags, unsigned long flags)
+{
+	return hook_mount_deny(mp);
+}
+
+static int hook_mount_change_type(const struct path *const mp, int ms_flags)
+{
+	return hook_mount_deny(mp);
+}
+
 static int hook_move_mount(const struct path *const from_path,
-			   const struct path *const to_path)
+			   const struct path *const to_path,
+			   const struct path *const top_path)
 {
 	size_t handle_layer;
 	const struct landlock_cred_security *const subject =
@@ -1981,8 +2009,12 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(inode_free_security_rcu, hook_inode_free_security_rcu),
 
 	LSM_HOOK_INIT(sb_delete, hook_sb_delete),
-	LSM_HOOK_INIT(sb_mount, hook_sb_mount),
-	LSM_HOOK_INIT(move_mount, hook_move_mount),
+	LSM_HOOK_INIT(mount_bind, hook_mount_bind),
+	LSM_HOOK_INIT(mount_new, hook_mount_new),
+	LSM_HOOK_INIT(mount_remount, hook_mount_remount),
+	LSM_HOOK_INIT(mount_reconfigure, hook_mount_reconfigure),
+	LSM_HOOK_INIT(mount_change_type, hook_mount_change_type),
+	LSM_HOOK_INIT(mount_move, hook_move_mount),
 	LSM_HOOK_INIT(sb_umount, hook_sb_umount),
 	LSM_HOOK_INIT(sb_remount, hook_sb_remount),
 	LSM_HOOK_INIT(sb_pivotroot, hook_sb_pivotroot),
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 6/8] tomoyo: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
                   ` (4 preceding siblings ...)
  2026-07-06 23:50 ` [PATCH v6 5/8] landlock: " Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:04   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks Song Liu
  2026-07-06 23:50 ` [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount Song Liu
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Replace tomoyo_sb_mount() with granular mount hooks. Each hook
reconstructs the MS_* flags expected by tomoyo_mount_permission()
using the original flags parameter where available.

Key changes:
- mount_bind: passes the pre-resolved source path to
  tomoyo_mount_acl() via a new dev_path parameter, instead of
  re-resolving dev_name via kern_path(). This eliminates a TOCTOU
  vulnerability.
- mount_new, mount_remount, mount_reconfigure: use the original
  mount(2) flags for policy matching.
- mount_move: passes pre-resolved paths for both source and
  destination; the new top_path argument is unused.
- mount_change_type: passes raw ms_flags directly.

Also removes the unused data_page parameter from
tomoyo_mount_permission().

Code generated with the assistance of Claude, reviewed by human.

Acked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Song Liu <song@kernel.org>
---
 security/tomoyo/common.h |   2 +-
 security/tomoyo/mount.c  |  31 +++++++----
 security/tomoyo/tomoyo.c | 111 +++++++++++++++++++++++++++++++++++----
 3 files changed, 123 insertions(+), 21 deletions(-)

diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index d098cf8aae61..9241034cfede 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -1013,7 +1013,7 @@ int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
 		      const unsigned int mode, unsigned int dev);
 int tomoyo_mount_permission(const char *dev_name, const struct path *path,
 			    const char *type, unsigned long flags,
-			    void *data_page);
+			    const struct path *dev_path);
 int tomoyo_open_control(const u8 type, struct file *file);
 int tomoyo_path2_perm(const u8 operation, const struct path *path1,
 		      const struct path *path2);
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index 322dfd188ada..82ffe7d02814 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -70,6 +70,7 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
  * @dir:      Pointer to "struct path".
  * @type:     Name of filesystem type.
  * @flags:    Mount options.
+ * @dev_path: Pre-resolved device/source path. Maybe NULL.
  *
  * Returns 0 on success, negative value otherwise.
  *
@@ -78,11 +79,11 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
 static int tomoyo_mount_acl(struct tomoyo_request_info *r,
 			    const char *dev_name,
 			    const struct path *dir, const char *type,
-			    unsigned long flags)
+			    unsigned long flags,
+			    const struct path *dev_path)
 	__must_hold_shared(&tomoyo_ss)
 {
 	struct tomoyo_obj_info obj = { };
-	struct path path;
 	struct file_system_type *fstype = NULL;
 	const char *requested_type = NULL;
 	const char *requested_dir_name = NULL;
@@ -134,13 +135,23 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r,
 			need_dev = 1;
 	}
 	if (need_dev) {
-		/* Get mount point or device file. */
-		if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
+		if (dev_path) {
+			/* Use pre-resolved path to avoid TOCTOU issues. */
+			obj.path1 = *dev_path;
+			path_get(&obj.path1);
+		} else if (!dev_name) {
 			error = -ENOENT;
 			goto out;
+		} else {
+			struct path path;
+
+			if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
+				error = -ENOENT;
+				goto out;
+			}
+			obj.path1 = path;
 		}
-		obj.path1 = path;
-		requested_dev_name = tomoyo_realpath_from_path(&path);
+		requested_dev_name = tomoyo_realpath_from_path(&obj.path1);
 		if (!requested_dev_name) {
 			error = -ENOENT;
 			goto out;
@@ -173,7 +184,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r,
 	if (fstype)
 		put_filesystem(fstype);
 	kfree(requested_type);
-	/* Drop refcount obtained by kern_path(). */
+	/* Drop refcount obtained by kern_path() or path_get(). */
 	if (obj.path1.dentry)
 		path_put(&obj.path1);
 	return error;
@@ -186,13 +197,13 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r,
  * @path:      Pointer to "struct path".
  * @type:      Name of filesystem type. Maybe NULL.
  * @flags:     Mount options.
- * @data_page: Optional data. Maybe NULL.
+ * @dev_path:  Pre-resolved device/source path. Maybe NULL.
  *
  * Returns 0 on success, negative value otherwise.
  */
 int tomoyo_mount_permission(const char *dev_name, const struct path *path,
 			    const char *type, unsigned long flags,
-			    void *data_page)
+			    const struct path *dev_path)
 {
 	struct tomoyo_request_info r;
 	int error;
@@ -236,7 +247,7 @@ int tomoyo_mount_permission(const char *dev_name, const struct path *path,
 	if (!type)
 		type = "<NULL>";
 	idx = tomoyo_read_lock();
-	error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
+	error = tomoyo_mount_acl(&r, dev_name, path, type, flags, dev_path);
 	tomoyo_read_unlock(idx);
 	return error;
 }
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index c66e02ed8ee3..eec3df35e28e 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -6,6 +6,8 @@
  */
 
 #include <linux/lsm_hooks.h>
+#include <linux/fs_context.h>
+#include <uapi/linux/mount.h>
 #include <uapi/linux/lsm.h>
 #include "common.h"
 
@@ -399,20 +401,104 @@ static int tomoyo_path_chroot(const struct path *path)
 }
 
 /**
- * tomoyo_sb_mount - Target for security_sb_mount().
+ * tomoyo_mount_bind - Target for security_mount_bind().
  *
- * @dev_name: Name of device file. Maybe NULL.
- * @path:     Pointer to "struct path".
- * @type:     Name of filesystem type. Maybe NULL.
- * @flags:    Mount options.
- * @data:     Optional data. Maybe NULL.
+ * @from:    Pointer to "struct path".
+ * @to:      Pointer to "struct path".
+ * @recurse: Whether recursive bind mount or not.
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_sb_mount(const char *dev_name, const struct path *path,
-			   const char *type, unsigned long flags, void *data)
+static int tomoyo_mount_bind(const struct path *from, const struct path *to,
+			     bool recurse)
 {
-	return tomoyo_mount_permission(dev_name, path, type, flags, data);
+	unsigned long flags = MS_BIND | (recurse ? MS_REC : 0);
+
+	return tomoyo_mount_permission(NULL, to, NULL, flags, from);
+}
+
+/**
+ * tomoyo_mount_new - Target for security_mount_new().
+ *
+ * @fc:        Pointer to "struct fs_context".
+ * @mp:        Pointer to "struct path".
+ * @mnt_flags: Mount options.
+ * @flags:     Original mount options.
+ * @data:      Optional data. Maybe NULL.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_mount_new(struct fs_context *fc, const struct path *mp,
+			    int mnt_flags, unsigned long flags, void *data)
+{
+	/* Use original MS_* flags for policy matching */
+	return tomoyo_mount_permission(fc->source, mp, fc->fs_type->name,
+				       flags, NULL);
+}
+
+/**
+ * tomoyo_mount_remount - Target for security_mount_remount().
+ *
+ * @fc:        Pointer to "struct fs_context".
+ * @mp:        Pointer to "struct path".
+ * @mnt_flags: Mount options.
+ * @flags:     Original mount options.
+ * @data:      Optional data. Maybe NULL.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_mount_remount(struct fs_context *fc, const struct path *mp,
+				int mnt_flags, unsigned long flags, void *data)
+{
+	/* Use original MS_* flags for policy matching */
+	return tomoyo_mount_permission(NULL, mp, NULL, flags, NULL);
+}
+
+/**
+ * tomoyo_mount_reconfigure - Target for security_mount_reconfigure().
+ *
+ * @mp:        Pointer to "struct path".
+ * @mnt_flags: Mount options.
+ * @flags:     Original mount options.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_mount_reconfigure(const struct path *mp,
+				    unsigned int mnt_flags,
+				    unsigned long flags)
+{
+	/* Use original MS_* flags for policy matching */
+	return tomoyo_mount_permission(NULL, mp, NULL, flags, NULL);
+}
+
+/**
+ * tomoyo_mount_change_type - Target for security_mount_change_type().
+ *
+ * @mp:       Pointer to "struct path".
+ * @ms_flags: Mount options.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_mount_change_type(const struct path *mp, int ms_flags)
+{
+	return tomoyo_mount_permission(NULL, mp, NULL, ms_flags, NULL);
+}
+
+/**
+ * tomoyo_mount_move - Target for security_mount_move().
+ *
+ * @from_path: Pointer to "struct path".
+ * @to_path:   Pointer to "struct path".
+ * @top_path:  Pointer to "struct path" of the mount ending up on top.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_mount_move(const struct path *from_path,
+			     const struct path *to_path,
+			     const struct path *top_path)
+{
+	return tomoyo_mount_permission(NULL, to_path, NULL, MS_MOVE,
+				       from_path);
 }
 
 /**
@@ -576,7 +662,12 @@ static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
 	LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
 	LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
-	LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount),
+	LSM_HOOK_INIT(mount_bind, tomoyo_mount_bind),
+	LSM_HOOK_INIT(mount_new, tomoyo_mount_new),
+	LSM_HOOK_INIT(mount_remount, tomoyo_mount_remount),
+	LSM_HOOK_INIT(mount_reconfigure, tomoyo_mount_reconfigure),
+	LSM_HOOK_INIT(mount_change_type, tomoyo_mount_change_type),
+	LSM_HOOK_INIT(mount_move, tomoyo_mount_move),
 	LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount),
 	LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot),
 	LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind),
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
                   ` (5 preceding siblings ...)
  2026-07-06 23:50 ` [PATCH v6 6/8] tomoyo: " Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  0:06   ` sashiko-bot
  2026-07-06 23:50 ` [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount Song Liu
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Replace the monolithic security_sb_mount() call in path_mount() and
the security_move_mount() call on the mount-move paths with the new
granular mount hooks:

- do_loopback(): call security_mount_bind()
- do_new_mount(): call security_mount_new()
- do_remount(): call security_mount_remount()
- do_reconfigure_mnt(): call security_mount_reconfigure()
- do_change_type(): call security_mount_change_type()
- do_move_mount(): call security_mount_move()
- do_set_group(): call security_mount_move()

The new hooks are called at the individual operation level with
appropriate context (resolved paths, fs_context), rather than at
the top of path_mount() with raw string arguments.

security_mount_bind() and security_mount_move() are called under the
namespace semaphore, after the mountpoint has been resolved and pinned
by LOCK_MOUNT(). This ensures the LSM inspects the mount that will
actually be used, instead of a mountpoint that could be overmounted
between the check and the operation. Placing the move hook in
do_move_mount() and do_set_group() also unifies the old mount(2)
MS_MOVE path (do_move_mount_old()) and the move_mount(2) path
(vfs_move_mount()) on a single call site.

For MOVE_MOUNT_BENEATH, security_mount_move() additionally receives the
mount that ends up on top, so an LSM can tell a plain move (target ==
top) apart from a mount-beneath operation.

Code generated with the assistance of Claude, reviewed by human.

Signed-off-by: Song Liu <song@kernel.org>
---
 fs/namespace.c | 77 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 61 insertions(+), 16 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 3d5cd5bf3b05..bc9401a2efac 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2893,6 +2893,10 @@ static int do_change_type(const struct path *path, int ms_flags)
 	if (!type)
 		return -EINVAL;
 
+	err = security_mount_change_type(path, ms_flags);
+	if (err)
+		return err;
+
 	guard(namespace_excl)();
 
 	err = may_change_propagation(mnt);
@@ -3003,6 +3007,7 @@ static int do_loopback(const struct path *path, const char *old_name,
 {
 	struct path old_path __free(path_put) = {};
 	struct mount *mnt = NULL;
+	struct path dest;
 	int err;
 
 	if (!old_name || !*old_name)
@@ -3021,6 +3026,17 @@ static int do_loopback(const struct path *path, const char *old_name,
 	if (!check_mnt(mp.parent))
 		return -EINVAL;
 
+	/*
+	 * Check permission against the mountpoint that was actually pinned
+	 * under the namespace semaphore, rather than the caller-supplied
+	 * @path which may have been overmounted before the lock was taken.
+	 */
+	dest.mnt = &mp.parent->mnt;
+	dest.dentry = mp.mp->m_dentry;
+	err = security_mount_bind(&old_path, &dest, recurse);
+	if (err)
+		return err;
+
 	mnt = __do_loopback(&old_path, recurse, CL_COPY_MNT_NS_FILE);
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
@@ -3335,7 +3351,8 @@ static void mnt_warn_timestamp_expiry(const struct path *mountpoint,
  * superblock it refers to.  This is triggered by specifying MS_REMOUNT|MS_BIND
  * to mount(2).
  */
-static int do_reconfigure_mnt(const struct path *path, unsigned int mnt_flags)
+static int do_reconfigure_mnt(const struct path *path, unsigned int mnt_flags,
+			      unsigned long flags)
 {
 	struct super_block *sb = path->mnt->mnt_sb;
 	struct mount *mnt = real_mount(path->mnt);
@@ -3350,6 +3367,10 @@ static int do_reconfigure_mnt(const struct path *path, unsigned int mnt_flags)
 	if (!can_change_locked_flags(mnt, mnt_flags))
 		return -EPERM;
 
+	ret = security_mount_reconfigure(path, mnt_flags, flags);
+	if (ret)
+		return ret;
+
 	/*
 	 * We're only checking whether the superblock is read-only not
 	 * changing it, so only take down_read(&sb->s_umount).
@@ -3373,7 +3394,7 @@ static int do_reconfigure_mnt(const struct path *path, unsigned int mnt_flags)
  * on it - tough luck.
  */
 static int do_remount(const struct path *path, int sb_flags,
-		      int mnt_flags, void *data)
+		      int mnt_flags, void *data, unsigned long flags)
 {
 	int err;
 	struct super_block *sb = path->mnt->mnt_sb;
@@ -3400,6 +3421,9 @@ static int do_remount(const struct path *path, int sb_flags,
 	fc->oldapi = true;
 
 	err = parse_monolithic_mount_data(fc, data);
+	if (!err)
+		err = security_mount_remount(fc, path, mnt_flags, flags,
+					    data);
 	if (!err) {
 		down_write(&sb->s_umount);
 		err = -EPERM;
@@ -3438,6 +3462,16 @@ static int do_set_group(const struct path *from_path, const struct path *to_path
 
 	guard(namespace_excl)();
 
+	/*
+	 * Setting a sharing group does not overmount anything, so the
+	 * source, target and top mount all refer to @to_path.  The check
+	 * runs under the namespace semaphore for the same reason as the
+	 * move case.
+	 */
+	err = security_mount_move(from_path, to_path, to_path);
+	if (err)
+		return err;
+
 	err = may_change_propagation(from);
 	if (err)
 		return err;
@@ -3634,6 +3668,7 @@ static int do_move_mount(const struct path *old_path,
 			 enum mnt_tree_flags_t flags)
 {
 	struct mount *old = real_mount(old_path->mnt);
+	struct path target, top;
 	int err;
 	bool beneath = flags & MNT_TREE_BENEATH;
 
@@ -3647,6 +3682,17 @@ static int do_move_mount(const struct path *old_path,
 	if (IS_ERR(mp.parent))
 		return PTR_ERR(mp.parent);
 
+	/*
+	 * The destination that was actually pinned under the namespace
+	 * semaphore.  For a plain move the source is attached on top of
+	 * @target, so @target is also the mount that ends up on top; for
+	 * MOVE_MOUNT_BENEATH the source is inserted below the existing top
+	 * mount, which is reported separately below.
+	 */
+	target.mnt = &mp.parent->mnt;
+	target.dentry = mp.mp->m_dentry;
+	top = target;
+
 	if (check_mnt(old)) {
 		/* if the source is in our namespace... */
 		/* ... it should be detachable from parent */
@@ -3687,8 +3733,14 @@ static int do_move_mount(const struct path *old_path,
 		err = can_move_mount_beneath(old, over, &mp);
 		if (err)
 			return err;
+		top.mnt = &over->mnt;
+		top.dentry = over->mnt.mnt_root;
 	}
 
+	err = security_mount_move(old_path, &target, &top);
+	if (err)
+		return err;
+
 	/*
 	 * Don't move a mount tree containing unbindable mounts to a destination
 	 * mount which is shared.
@@ -3793,7 +3845,7 @@ static int do_new_mount_fc(struct fs_context *fc, const struct path *mountpoint,
  */
 static int do_new_mount(const struct path *path, const char *fstype,
 			int sb_flags, int mnt_flags,
-			const char *name, void *data)
+			const char *name, void *data, unsigned long flags)
 {
 	struct file_system_type *type;
 	struct fs_context *fc;
@@ -3837,6 +3889,9 @@ static int do_new_mount(const struct path *path, const char *fstype,
 		err = parse_monolithic_mount_data(fc, data);
 	if (!err && !mount_capable(fc))
 		err = -EPERM;
+
+	if (!err)
+		err = security_mount_new(fc, path, mnt_flags, flags, data);
 	if (!err)
 		err = do_new_mount_fc(fc, path, mnt_flags);
 
@@ -4087,7 +4142,6 @@ int path_mount(const char *dev_name, const struct path *path,
 		const char *type_page, unsigned long flags, void *data_page)
 {
 	unsigned int mnt_flags = 0, sb_flags;
-	int ret;
 
 	/* Discard magic */
 	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
@@ -4100,9 +4154,6 @@ int path_mount(const char *dev_name, const struct path *path,
 	if (flags & MS_NOUSER)
 		return -EINVAL;
 
-	ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
-	if (ret)
-		return ret;
 	if (!may_mount())
 		return -EPERM;
 	if (flags & SB_MANDLOCK)
@@ -4148,9 +4199,9 @@ int path_mount(const char *dev_name, const struct path *path,
 			    SB_I_VERSION);
 
 	if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
-		return do_reconfigure_mnt(path, mnt_flags);
+		return do_reconfigure_mnt(path, mnt_flags, flags);
 	if (flags & MS_REMOUNT)
-		return do_remount(path, sb_flags, mnt_flags, data_page);
+		return do_remount(path, sb_flags, mnt_flags, data_page, flags);
 	if (flags & MS_BIND)
 		return do_loopback(path, dev_name, flags & MS_REC);
 	if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
@@ -4159,7 +4210,7 @@ int path_mount(const char *dev_name, const struct path *path,
 		return do_move_mount_old(path, dev_name);
 
 	return do_new_mount(path, type_page, sb_flags, mnt_flags, dev_name,
-			    data_page);
+			    data_page, flags);
 }
 
 int do_mount(const char *dev_name, const char __user *dir_name,
@@ -4554,12 +4605,6 @@ static inline int vfs_move_mount(const struct path *from_path,
 				 const struct path *to_path,
 				 enum mnt_tree_flags_t mflags)
 {
-	int ret;
-
-	ret = security_move_mount(from_path, to_path);
-	if (ret)
-		return ret;
-
 	if (mflags & MNT_TREE_PROPAGATION)
 		return do_set_group(from_path, to_path);
 
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount
  2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
                   ` (6 preceding siblings ...)
  2026-07-06 23:50 ` [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks Song Liu
@ 2026-07-06 23:50 ` Song Liu
  2026-07-07  2:08   ` sashiko-bot
  7 siblings, 1 reply; 17+ messages in thread
From: Song Liu @ 2026-07-06 23:50 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, selinux, apparmor
  Cc: paul, jmorris, serge, viro, brauner, jack, john.johansen,
	stephen.smalley.work, omosnace, mic, gnoack, takedakn,
	penguin-kernel, herton, kernel-team, Song Liu

Now that all LSMs have been converted to granular mount hooks and
fs/namespace.c calls the new hooks, remove the old hooks:

- security_sb_mount(): removed from lsm_hook_defs.h, security.h,
  security.c.
- security_move_mount(): removed from lsm_hook_defs.h, security.h,
  security.c, and bpf_lsm.c.

Code generated with the assistance of Claude, reviewed by human.

Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com> # for selinux only
Signed-off-by: Song Liu <song@kernel.org>
---
 include/linux/lsm_hook_defs.h |  4 ----
 include/linux/security.h      | 16 ---------------
 kernel/bpf/bpf_lsm.c          |  2 --
 security/security.c           | 38 -----------------------------------
 4 files changed, 60 deletions(-)

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 06c904cb478e..4015f6b579c3 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -69,8 +69,6 @@ LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts)
 LSM_HOOK(int, 0, sb_kern_mount, const struct super_block *sb)
 LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb)
 LSM_HOOK(int, 0, sb_statfs, struct dentry *dentry)
-LSM_HOOK(int, 0, sb_mount, const char *dev_name, const struct path *path,
-	 const char *type, unsigned long flags, void *data)
 LSM_HOOK(int, 0, sb_umount, struct vfsmount *mnt, int flags)
 LSM_HOOK(int, 0, sb_pivotroot, const struct path *old_path,
 	 const struct path *new_path)
@@ -79,8 +77,6 @@ LSM_HOOK(int, 0, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts,
 LSM_HOOK(int, 0, sb_clone_mnt_opts, const struct super_block *oldsb,
 	 struct super_block *newsb, unsigned long kern_flags,
 	 unsigned long *set_kern_flags)
-LSM_HOOK(int, 0, move_mount, const struct path *from_path,
-	 const struct path *to_path)
 LSM_HOOK(int, 0, mount_bind, const struct path *from, const struct path *to,
 	 bool recurse)
 LSM_HOOK(int, 0, mount_new, struct fs_context *fc, const struct path *mp,
diff --git a/include/linux/security.h b/include/linux/security.h
index 5e207e38c004..ff16831e8064 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -373,8 +373,6 @@ int security_sb_remount(struct super_block *sb, void *mnt_opts);
 int security_sb_kern_mount(const struct super_block *sb);
 int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
-int security_sb_mount(const char *dev_name, const struct path *path,
-		      const char *type, unsigned long flags, void *data);
 int security_sb_umount(struct vfsmount *mnt, int flags);
 int security_sb_pivotroot(const struct path *old_path, const struct path *new_path);
 int security_sb_set_mnt_opts(struct super_block *sb,
@@ -385,7 +383,6 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb,
 				unsigned long kern_flags,
 				unsigned long *set_kern_flags);
-int security_move_mount(const struct path *from_path, const struct path *to_path);
 int security_mount_bind(const struct path *from, const struct path *to,
 			bool recurse);
 int security_mount_new(struct fs_context *fc, const struct path *mp,
@@ -826,13 +823,6 @@ static inline int security_sb_statfs(struct dentry *dentry)
 	return 0;
 }
 
-static inline int security_sb_mount(const char *dev_name, const struct path *path,
-				    const char *type, unsigned long flags,
-				    void *data)
-{
-	return 0;
-}
-
 static inline int security_sb_umount(struct vfsmount *mnt, int flags)
 {
 	return 0;
@@ -860,12 +850,6 @@ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 	return 0;
 }
 
-static inline int security_move_mount(const struct path *from_path,
-				      const struct path *to_path)
-{
-	return 0;
-}
-
 static inline int security_mount_bind(const struct path *from,
 				      const struct path *to, bool recurse)
 {
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index 4b1ee9c67d6f..9cece66a0c49 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -353,7 +353,6 @@ BTF_ID(func, bpf_lsm_release_secctx)
 BTF_ID(func, bpf_lsm_sb_alloc_security)
 BTF_ID(func, bpf_lsm_sb_eat_lsm_opts)
 BTF_ID(func, bpf_lsm_sb_kern_mount)
-BTF_ID(func, bpf_lsm_sb_mount)
 BTF_ID(func, bpf_lsm_sb_remount)
 BTF_ID(func, bpf_lsm_sb_set_mnt_opts)
 BTF_ID(func, bpf_lsm_sb_show_options)
@@ -385,7 +384,6 @@ BTF_ID(func, bpf_lsm_task_setscheduler)
 BTF_ID(func, bpf_lsm_userns_create)
 BTF_ID(func, bpf_lsm_bdev_alloc_security)
 BTF_ID(func, bpf_lsm_bdev_setintegrity)
-BTF_ID(func, bpf_lsm_move_mount)
 BTF_ID(func, bpf_lsm_mount_bind)
 BTF_ID(func, bpf_lsm_mount_new)
 BTF_ID(func, bpf_lsm_mount_remount)
diff --git a/security/security.c b/security/security.c
index 1ede060db3ca..0456680738f2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1065,29 +1065,6 @@ int security_sb_statfs(struct dentry *dentry)
 	return call_int_hook(sb_statfs, dentry);
 }
 
-/**
- * security_sb_mount() - Check permission for mounting a filesystem
- * @dev_name: filesystem backing device
- * @path: mount point
- * @type: filesystem type
- * @flags: mount flags
- * @data: filesystem specific data
- *
- * Check permission before an object specified by @dev_name is mounted on the
- * mount point named by @nd.  For an ordinary mount, @dev_name identifies a
- * device if the file system type requires a device.  For a remount
- * (@flags & MS_REMOUNT), @dev_name is irrelevant.  For a loopback/bind mount
- * (@flags & MS_BIND), @dev_name identifies the	pathname of the object being
- * mounted.
- *
- * Return: Returns 0 if permission is granted.
- */
-int security_sb_mount(const char *dev_name, const struct path *path,
-		      const char *type, unsigned long flags, void *data)
-{
-	return call_int_hook(sb_mount, dev_name, path, type, flags, data);
-}
-
 /**
  * security_sb_umount() - Check permission for unmounting a filesystem
  * @mnt: mounted filesystem
@@ -1167,21 +1144,6 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 }
 EXPORT_SYMBOL(security_sb_clone_mnt_opts);
 
-/**
- * security_move_mount() - Check permissions for moving a mount
- * @from_path: source mount point
- * @to_path: destination mount point
- *
- * Check permission before a mount is moved.
- *
- * Return: Returns 0 if permission is granted.
- */
-int security_move_mount(const struct path *from_path,
-			const struct path *to_path)
-{
-	return call_int_hook(move_mount, from_path, to_path);
-}
-
 /**
  * security_mount_bind() - Check permissions for a bind mount
  * @from: source path
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 1/8] lsm: Add granular mount hooks
  2026-07-06 23:50 ` [PATCH v6 1/8] lsm: Add " Song Liu
@ 2026-07-07  0:00   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:00 UTC (permalink / raw)
  Cc: selinux

> Add the new granular mount hook declarations and implementations
> to the LSM framework:
> 
>   mount_bind        - bind mount (pre-resolved source path)
>   mount_new         - new filesystem mount (with fs_context)
>   mount_remount     - filesystem remount (with fs_context)
>   mount_reconfigure - mount flag reconfiguration (MS_REMOUNT|MS_BIND)
>   mount_move        - move mount (pre-resolved source, target and top
>                       paths; target == top unless MOVE_MOUNT_BENEATH)
>   mount_change_type - propagation type changes
> 
> These hooks are added alongside the existing security_sb_mount() and
> security_move_mount() hooks, which remain in place until all LSMs
> are converted.
> 
> Code generated with the assistance of Claude, reviewed by human.
> 
> Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com> # for selinux only
> Signed-off-by: Song Liu <song@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 4/8] selinux: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 ` [PATCH v6 4/8] selinux: " Song Liu
@ 2026-07-07  0:01   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:01 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] The patch series unregisters the `sb_mount` and `move_mount` LSM hooks in SELinux and AppArmor, replacing them with new granular hooks (`mount_bind`, `mount_new`, etc.). However, it completely fails to update the VFS layer (`fs/namespace.c`) to actually call these new `security_mount_*` wrappers. Because the VFS still calls the legacy `security_sb_mount()` and `security_move_mount()` functions, and the LSMs no longer provide handlers for them, the LSM framework silently defaults to returning 0 (success). This causes a total bypass of all mount permission checks for both SELinux and AppArmor.
--

--- Patch [4]: [PATCH v6 4/8] selinux: Convert from sb_mount to granular mount hooks ---
commit 55260dac718bdd3a6181cc49259e13a6867345fb
Author: Song Liu <song@kernel.org>

selinux: Convert from sb_mount to granular mount hooks

This commit replaces the monolithic selinux_mount hook with granular
mount hooks such as mount_bind, mount_new, and mount_remount. It removes
the legacy sb_mount and move_mount hooks from the selinux_hooks array.

> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 0f704380a8c81..85c168c204364 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c

[ ... ]

> @@ -7558,13 +7577,16 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
>  	LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
>  	LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
> -	LSM_HOOK_INIT(sb_mount, selinux_mount),
> +	LSM_HOOK_INIT(mount_bind, selinux_mount_bind),
> +	LSM_HOOK_INIT(mount_new, selinux_mount_new),
> +	LSM_HOOK_INIT(mount_remount, selinux_mount_remount),
> +	LSM_HOOK_INIT(mount_reconfigure, selinux_mount_reconfigure),
> +	LSM_HOOK_INIT(mount_change_type, selinux_mount_change_type),
> +	LSM_HOOK_INIT(mount_move, selinux_move_mount),
>  	LSM_HOOK_INIT(sb_umount, selinux_umount),
>  	LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
>  	LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
>  
> -	LSM_HOOK_INIT(move_mount, selinux_move_mount),
> -

[Severity: Critical]
Are there accompanying changes to the VFS layer in fs/namespace.c to actually
call these new security_mount_* wrappers?

If sb_mount and move_mount are unregistered here, but the VFS still calls the
legacy security_sb_mount() and security_move_mount(), will the LSM framework
silently default to returning 0 (success) because the handlers are gone?

Could this result in a complete bypass of all mount permission checks for
SELinux?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=4

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 6/8] tomoyo: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 ` [PATCH v6 6/8] tomoyo: " Song Liu
@ 2026-07-07  0:04   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:04 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] The patch series introduces a complete access control bypass for mount operations across all LSMs (Tomoyo, AppArmor, SELinux, Landlock).
--

--- Patch [6]: [PATCH v6 6/8] tomoyo: Convert from sb_mount to granular mount hooks ---
commit b14cd8de9e00724d26864e133cbd2962345e3c1c
Author: Song Liu <song@kernel.org>

tomoyo: Convert from sb_mount to granular mount hooks

This patch replaces tomoyo_sb_mount() with granular mount hooks. Each hook
reconstructs the MS_* flags expected by tomoyo_mount_permission() to perform
security checks for bind mounts, new mounts, remounts, and other operations.

> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index c66e02ed8ee3b..eec3df35e28e5 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
[ ... ]
> @@ -576,7 +662,12 @@ static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
>  	LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
>  	LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
> -	LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount),
> +	LSM_HOOK_INIT(mount_bind, tomoyo_mount_bind),
> +	LSM_HOOK_INIT(mount_new, tomoyo_mount_new),
> +	LSM_HOOK_INIT(mount_remount, tomoyo_mount_remount),
> +	LSM_HOOK_INIT(mount_reconfigure, tomoyo_mount_reconfigure),
> +	LSM_HOOK_INIT(mount_change_type, tomoyo_mount_change_type),
> +	LSM_HOOK_INIT(mount_move, tomoyo_mount_move),
>  	LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount),

[Severity: Critical]
By removing the sb_mount hook here, does this introduce a regression where
mount access control policies are entirely bypassed during a git bisect?

Looking at path_mount() in fs/namespace.c, the VFS layer still relies on the
legacy security_sb_mount() wrapper which calls the sb_mount hook:

fs/namespace.c:path_mount() {
    ...
    ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
    if (ret)
        return ret;
    ...
}

If this patch is applied before the VFS layer is updated to invoke the new
security_mount_* hooks, wouldn't security_sb_mount() simply evaluate to 0
since the LSM no longer implements sb_mount? This seems to unconditionally
allow mounts that should be denied by policy.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=6

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount
  2026-07-06 23:50 ` [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount Song Liu
@ 2026-07-07  0:04   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:04 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] AppArmor's mount mediation contains a Time-of-Check to Time-of-Use (TOCTOU) vulnerability during mount operations (such as MS_BIND and MS_MOVE). It resolves user-supplied mount source paths via `kern_path()` for authorization. However, after authorization succeeds, VFS independently resolves the exact same string. An attacker can race this window to swap a symlink and mount unauthorized paths, entirely bypassing the MAC policy.
--

--- Patch [2]: [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount ---
commit eaca63dc76aaf43bda7315bdb224bbd33d80cf0e
Author: Song Liu <song@kernel.org>

apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount

This commit removes a redundant MS_MGC_MSK flag stripping check from
apparmor_sb_mount(), as path_mount() already handles it.

> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index 3491e9f601943..4415bca5889cf 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -705,10 +705,6 @@ static int apparmor_sb_mount(const char *dev_name, const struct path *path,
>  	int error = 0;
>  	bool needput;

[Severity: High]
This is a pre-existing issue, but does relying on the user-supplied dev_name
string here create a time-of-check to time-of-use vulnerability?

AppArmor's mount mediation resolves the untrusted user string dev_name via
kern_path() for authorization. For example:

security/apparmor/mount.c:aa_bind_mount() {
    ...
    error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
    ...
}

After authorization succeeds, the core mount code independently resolves the
exact same string again:

fs/namespace.c:do_loopback() {
    ...
    err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
    ...
}

Could an attacker race this window to swap a symlink and mount unauthorized
paths, bypassing the access policy?

> -	/* Discard magic */
> -	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
> -		flags &= ~MS_MGC_MSK;
> -
>  	flags &= ~AA_MS_IGNORE_MASK;
>  
>  	label = __begin_current_label_crit_section(&needput);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=2

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 5/8] landlock: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 ` [PATCH v6 5/8] landlock: " Song Liu
@ 2026-07-07  0:04   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:04 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Replacing the legacy `sb_mount` and `move_mount` LSM hooks with new granular mount hooks without updating the VFS callers completely drops Landlock's (as well as AppArmor's and SELinux's) mount sandbox protections.
--

--- Patch [5]: [PATCH v6 5/8] landlock: Convert from sb_mount to granular mount hooks ---
commit aefe12302c757bd8116e65f91a6c6d4886925d19
Author: Song Liu <song@kernel.org>

landlock: Convert from sb_mount to granular mount hooks

This commit replaces Landlock's legacy sb_mount and move_mount hooks
with granular mount hooks (mount_bind, mount_new, etc.). The new hooks
are wired to a common helper that denies all mount operations for
sandboxed processes.

> diff --git a/security/landlock/fs.c b/security/landlock/fs.c
> index c1ecfe2390326..4e6712f972f0a 100644
> --- a/security/landlock/fs.c
> +++ b/security/landlock/fs.c

[ ... ]

> @@ -1950,8 +1978,12 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(inode_free_security_rcu, hook_inode_free_security_rcu),
>  
>  	LSM_HOOK_INIT(sb_delete, hook_sb_delete),
> -	LSM_HOOK_INIT(sb_mount, hook_sb_mount),
> -	LSM_HOOK_INIT(move_mount, hook_move_mount),
> +	LSM_HOOK_INIT(mount_bind, hook_mount_bind),
> +	LSM_HOOK_INIT(mount_new, hook_mount_new),
> +	LSM_HOOK_INIT(mount_remount, hook_mount_remount),
> +	LSM_HOOK_INIT(mount_reconfigure, hook_mount_reconfigure),
> +	LSM_HOOK_INIT(mount_change_type, hook_mount_change_type),
> +	LSM_HOOK_INIT(mount_move, hook_move_mount),

[Severity: Critical]
Does this conversion inadvertently bypass Landlock's mount protections?

Looking at path_mount() in fs/namespace.c, the VFS still relies on the legacy
security_sb_mount() API:

fs/namespace.c:path_mount() {
    ...
    ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
    ...
}

And this wrapper strictly evaluates the legacy sb_mount hook list:

security/security.c:security_sb_mount() {
    return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}

Similarly, vfs_move_mount() in fs/namespace.c still calls the legacy
security_move_mount() API.

Because this patch removes sb_mount and move_mount from landlock_hooks, won't
these VFS calls find an empty hook list for Landlock and unconditionally return
0 (success), allowing unprivileged sandboxed processes to perform unauthorized
mounts?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=5

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks
  2026-07-06 23:50 ` [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks Song Liu
@ 2026-07-07  0:05   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:05 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] The patch completely disables AppArmor mount mediation by replacing active LSM hooks (`sb_mount` and `move_mount`) with new granular hooks (`mount_bind`, `mount_new`, `mount_remount`, `mount_move`, etc.) that are never invoked by the VFS.
- [High] The new granular mount hooks fail to strip `AA_MS_IGNORE_MASK` internal kernel flags before policy matching, causing legitimate mounts to be denied if the hooks were active.
--

--- Patch [3]: [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks ---
commit 6ef64d51cf68e28f54ba97e3ee56be6a9183f162
Author: Song Liu <song@kernel.org>

apparmor: Convert from sb_mount to granular mount hooks

Replace AppArmor's monolithic apparmor_sb_mount() with granular mount hooks.
Key changes include updating bind, new, remount, reconfigure, move, and
change_type mount handling.

> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index 4415bca5889cf..cfd7f0f757734 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -698,41 +699,91 @@ static int apparmor_uring_sqpoll(void)
>  }
>  #endif /* CONFIG_IO_URING */
>  
> -static int apparmor_sb_mount(const char *dev_name, const struct path *path,
> -			     const char *type, unsigned long flags, void *data)
> -{
> -	struct aa_label *label;
> -	int error = 0;
> -	bool needput;
> -
> -	flags &= ~AA_MS_IGNORE_MASK;

[ ... ]

> +static int apparmor_mount_new(struct fs_context *fc, const struct path *mp,
> +			      int mnt_flags, unsigned long flags, void *data)
> +{
> +	struct aa_label *label;
> +	int error = 0;
> +	bool needput;
> +
> +	/* flags and data are from the original mount(2) call */
> +	label = __begin_current_label_crit_section(&needput);
> +	if (!unconfined(label))
> +		error = aa_new_mount(current_cred(), label, fc->source,
> +				     mp, fc->fs_type->name, flags, data);

[Severity: High]
Does this pass raw flags to aa_new_mount() without stripping internal kernel
flags? 

The old apparmor_sb_mount() explicitly performed:

    flags &= ~AA_MS_IGNORE_MASK;

Could passing raw flags cause legitimate mounts to be denied if internal bits
fail policy evaluation?

> +	__end_current_label_crit_section(label, needput);
> +
> +	return error;
> +}
> +
> +static int apparmor_mount_remount(struct fs_context *fc, const struct path *mp,
> +				  int mnt_flags, unsigned long flags,
> +				  void *data)
> +{
> +	struct aa_label *label;
> +	int error = 0;
> +	bool needput;
> +
> +	/* flags and data are from the original mount(2) call */
> +	label = __begin_current_label_crit_section(&needput);
> +	if (!unconfined(label))
> +		error = aa_remount(current_cred(), label, mp, flags, data);

[Severity: High]
Similarly, should AA_MS_IGNORE_MASK be stripped from flags here before
passing them to aa_remount()?

> +	__end_current_label_crit_section(label, needput);
> +
> +	return error;
> +}

[ ... ]

> @@ -1655,8 +1706,12 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(capget, apparmor_capget),
>  	LSM_HOOK_INIT(capable, apparmor_capable),
>  
> -	LSM_HOOK_INIT(move_mount, apparmor_move_mount),
> -	LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
> +	LSM_HOOK_INIT(mount_bind, apparmor_mount_bind),
> +	LSM_HOOK_INIT(mount_new, apparmor_mount_new),
> +	LSM_HOOK_INIT(mount_remount, apparmor_mount_remount),
> +	LSM_HOOK_INIT(mount_reconfigure, apparmor_mount_reconfigure),
> +	LSM_HOOK_INIT(mount_move, apparmor_move_mount),
> +	LSM_HOOK_INIT(mount_change_type, apparmor_mount_change_type),
>  	LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
>  	LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),

[Severity: Critical]
Are these new hooks being invoked by the VFS?

This patch removes the active sb_mount and move_mount hooks, replacing them
with granular hooks like mount_new and mount_bind. However, the VFS doesn't
appear to have been updated to call these new security hooks (e.g.,
security_mount_new() is never called in fs/namespace.c).

Could this completely disable AppArmor mount mediation, allowing userspace
to perform arbitrary mount operations regardless of the AppArmor profile?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=3

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks
  2026-07-06 23:50 ` [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks Song Liu
@ 2026-07-07  0:06   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  0:06 UTC (permalink / raw)
  Cc: selinux

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Critical] The `data` buffer containing mount options is truncated before being evaluated by LSM hooks due to in-place modification.

Pre-existing issues:
- [High] Time-of-Check to Time-of-Use (TOCTOU) race condition in `security_mount_new()` allows mount restriction bypass via concurrent overmounting.
--

--- Patch [7]: [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks ---
commit db44b5a9ddea0d89351b2678afb54e9fc292fef1
Author: Song Liu <song@kernel.org>

vfs: Replace security_sb_mount/security_move_mount with granular hooks

This commit replaces the monolithic security_sb_mount() and
security_move_mount() calls with new granular mount hooks at the individual
operation level. The new hooks receive appropriate context like resolved paths
and fs_context rather than raw string arguments. It also checks permissions
against pinned mountpoints for bind and move operations to avoid overmount
races.

> diff --git a/fs/namespace.c b/fs/namespace.c
> index 341ddd353b3a8..fef435c93e50e 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c

[ ... ]

> @@ -3396,6 +3417,9 @@ static int do_remount(const struct path *path, int sb_flags,
>  	fc->oldapi = true;
>  
>  	err = parse_monolithic_mount_data(fc, data);
> +	if (!err)
> +		err = security_mount_remount(fc, path, mnt_flags, flags,
> +					    data);

[Severity: Critical]
Does passing the data buffer to security_mount_remount() after calling
parse_monolithic_mount_data() result in the LSM seeing a truncated options
string?

The generic_parse_monolithic() parser uses strsep() and strchr() to mutate
the data string in-place, replacing commas and equal signs with null bytes.

When the buffer is subsequently passed to security_mount_remount(), will an
LSM (like AppArmor) only evaluate the first mount option, while the kernel
processes all options?

Could this allow an attacker to bypass mount option policies by placing
allowed options first, followed by restricted options?

>  	if (!err) {
>  		down_write(&sb->s_umount);
>  		err = -EPERM;

[ ... ]

> @@ -3833,6 +3885,9 @@ static int do_new_mount(const struct path *path, const char *fstype,
>  		err = parse_monolithic_mount_data(fc, data);
>  	if (!err && !mount_capable(fc))
>  		err = -EPERM;
> +
> +	if (!err)
> +		err = security_mount_new(fc, path, mnt_flags, flags, data);

[Severity: Critical]
Does passing the data buffer to security_mount_new() after calling
parse_monolithic_mount_data() also result in the LSM seeing a truncated
options string?

Similar to do_remount(), the string is modified in-place before the LSM hook,
potentially allowing mount restriction policies to be bypassed.

>  	if (!err)
>  		err = do_new_mount_fc(fc, path, mnt_flags);

[Severity: High]
This is a pre-existing issue, but does evaluating the unlocked path here open
a Time-of-Check to Time-of-Use (TOCTOU) race condition?

The security_mount_new() hook evaluates the caller-supplied path before
do_new_mount_fc() calls LOCK_MOUNT().

Could an attacker concurrently bind-mount a shared mount over the path
immediately after the LSM check?

When do_new_mount_fc() executes LOCK_MOUNT(), it would follow the new
overmount. The filesystem would then be grafted onto the shared mount and
propagate to restricted peers, bypassing the LSM's denial of mounting onto
those peers.

Can security_mount_new() be moved to run after the mountpoint is locked,
similar to how the TOCTOU protection was applied for bind and move mounts
in this commit?

>  
>  	put_fs_context(fc);
>  	return err;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=7

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount
  2026-07-06 23:50 ` [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount Song Liu
@ 2026-07-07  2:08   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-07  2:08 UTC (permalink / raw)
  Cc: selinux

> Now that all LSMs have been converted to granular mount hooks and
> fs/namespace.c calls the new hooks, remove the old hooks:
> 
> - security_sb_mount(): removed from lsm_hook_defs.h, security.h,
>   security.c.
> - security_move_mount(): removed from lsm_hook_defs.h, security.h,
>   security.c, and bpf_lsm.c.
> 
> Code generated with the assistance of Claude, reviewed by human.
> 
> Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com> # for selinux only
> Signed-off-by: Song Liu <song@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706235053.4104951-1-song@kernel.org?part=8


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-07-07  2:08 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 23:50 [PATCH v6 0/8] lsm: Replace security_sb_mount with granular mount hooks Song Liu
2026-07-06 23:50 ` [PATCH v6 1/8] lsm: Add " Song Liu
2026-07-07  0:00   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 2/8] apparmor: Remove redundant MS_MGC_MSK stripping in apparmor_sb_mount Song Liu
2026-07-07  0:04   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 3/8] apparmor: Convert from sb_mount to granular mount hooks Song Liu
2026-07-07  0:05   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 4/8] selinux: " Song Liu
2026-07-07  0:01   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 5/8] landlock: " Song Liu
2026-07-07  0:04   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 6/8] tomoyo: " Song Liu
2026-07-07  0:04   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 7/8] vfs: Replace security_sb_mount/security_move_mount with granular hooks Song Liu
2026-07-07  0:06   ` sashiko-bot
2026-07-06 23:50 ` [PATCH v6 8/8] lsm: Remove security_sb_mount and security_move_mount Song Liu
2026-07-07  2:08   ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.