Replace the monolithic security_sb_mount() call in path_mount() and
security_move_mount() in vfs_move_mount() 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_move_mount_old(): call security_mount_move()
- do_change_type(): call security_mount_change_type()
- vfs_move_mount(): replace security_move_mount() with
  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.

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

Reviewed-by: Stephen Smalley <[email protected]>
Tested-by: Stephen Smalley <[email protected]> # for selinux only
Signed-off-by: Song Liu <[email protected]>
---
 fs/namespace.c | 41 ++++++++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index fe919abd2f01..43f22c5e2bf4 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2888,6 +2888,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);
@@ -3006,6 +3010,10 @@ static int do_loopback(const struct path *path, const 
char *old_name,
        if (err)
                return err;
 
+       err = security_mount_bind(&old_path, path, recurse);
+       if (err)
+               return err;
+
        if (mnt_ns_loop(old_path.dentry))
                return -EINVAL;
 
@@ -3328,7 +3336,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);
@@ -3343,6 +3352,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).
@@ -3366,7 +3379,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;
@@ -3393,6 +3406,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;
@@ -3708,6 +3724,10 @@ static int do_move_mount_old(const struct path *path, 
const char *old_name)
        if (err)
                return err;
 
+       err = security_mount_move(&old_path, path);
+       if (err)
+               return err;
+
        return do_move_mount(&old_path, path, 0);
 }
 
@@ -3786,7 +3806,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;
@@ -3830,6 +3850,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);
 
@@ -4080,7 +4103,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)
@@ -4093,9 +4115,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)
@@ -4141,9 +4160,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))
@@ -4152,7 +4171,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,
@@ -4545,7 +4564,7 @@ static inline int vfs_move_mount(const struct path 
*from_path,
 {
        int ret;
 
-       ret = security_move_mount(from_path, to_path);
+       ret = security_mount_move(from_path, to_path);
        if (ret)
                return ret;
 
-- 
2.53.0-Meta


Reply via email to