]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
LSM: lift extracting and parsing LSM options into the caller of ->sb_remount()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 2 Dec 2018 04:06:57 +0000 (23:06 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Dec 2018 16:45:41 +0000 (11:45 -0500)
This paves the way for retaining the LSM options from a common filesystem
mount context during a mount parameter parsing phase to be instituted prior
to actual mount/reconfiguration actions.

Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namespace.c
include/linux/lsm_hooks.h
include/linux/security.h
security/security.c
security/selinux/hooks.c

index 08cffdad66659269690a83ca01f4694e9bbb388a..341793fbd3901d6eb202c4ac63dd6ab1b7185c63 100644 (file)
@@ -2299,6 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        int err;
        struct super_block *sb = path->mnt->mnt_sb;
        struct mount *mnt = real_mount(path->mnt);
+       struct security_mnt_opts opts;
 
        if (!check_mnt(mnt))
                return -EINVAL;
@@ -2309,7 +2310,23 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        if (!can_change_locked_flags(mnt, mnt_flags))
                return -EPERM;
 
-       err = security_sb_remount(sb, data);
+       security_init_mnt_opts(&opts);
+       if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) {
+               char *secdata = alloc_secdata();
+               if (!secdata)
+                       return -ENOMEM;
+               err = security_sb_copy_data(data, secdata);
+               if (err) {
+                       free_secdata(secdata);
+                       return err;
+               }
+               err = security_sb_parse_opts_str(secdata, &opts);
+               free_secdata(secdata);
+               if (err)
+                       return err;
+       }
+       err = security_sb_remount(sb, &opts);
+       security_free_mnt_opts(&opts);
        if (err)
                return err;
 
index c7f67341fd1dbb9054e1da74bf21a8cc25f36ca6..e1a12a1e2b321985545da5db2164b68553ab6139 100644 (file)
@@ -1462,7 +1462,8 @@ union security_list_options {
        int (*sb_alloc_security)(struct super_block *sb);
        void (*sb_free_security)(struct super_block *sb);
        int (*sb_copy_data)(char *orig, char *copy);
-       int (*sb_remount)(struct super_block *sb, void *data);
+       int (*sb_remount)(struct super_block *sb,
+                         struct security_mnt_opts *opts);
        int (*sb_kern_mount)(struct super_block *sb, int flags,
                             struct security_mnt_opts *opts);
        int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
index f2f88e41f35f9d1c863f9f58f4d56f0928198c74..4fc6d98bc7a6873da5da83290ab4fe41a9f0d580 100644 (file)
@@ -249,7 +249,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm);
 int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
-int security_sb_remount(struct super_block *sb, void *data);
+int security_sb_remount(struct super_block *sb, struct security_mnt_opts *opts);
 int security_sb_kern_mount(struct super_block *sb, int flags,
                           struct security_mnt_opts *opts);
 int security_sb_show_options(struct seq_file *m, struct super_block *sb);
@@ -561,7 +561,8 @@ static inline int security_sb_copy_data(char *orig, char *copy)
        return 0;
 }
 
-static inline int security_sb_remount(struct super_block *sb, void *data)
+static inline int security_sb_remount(struct super_block *sb,
+                                     struct security_mnt_opts *opts)
 {
        return 0;
 }
index b5fc8e1e849c643f79e08d504fbd248b8c57db10..3f50beb30fb1cccebd0da87328abbe21e1779548 100644 (file)
@@ -390,9 +390,10 @@ int security_sb_copy_data(char *orig, char *copy)
 }
 EXPORT_SYMBOL(security_sb_copy_data);
 
-int security_sb_remount(struct super_block *sb, void *data)
+int security_sb_remount(struct super_block *sb,
+                       struct security_mnt_opts *opts)
 {
-       return call_int_hook(sb_remount, 0, sb, data);
+       return call_int_hook(sb_remount, 0, sb, opts);
 }
 
 int security_sb_kern_mount(struct super_block *sb, int flags,
index ba229d4a64d396c486dcad982be538aabe048d69..ba3e2917bd24d358d8bd28e914b9cb3579bbc096 100644 (file)
@@ -2812,39 +2812,22 @@ static int selinux_sb_copy_data(char *orig, char *copy)
        return rc;
 }
 
-static int selinux_sb_remount(struct super_block *sb, void *data)
+static int selinux_sb_remount(struct super_block *sb,
+                             struct security_mnt_opts *opts)
 {
-       int rc, i, *flags;
-       struct security_mnt_opts opts;
-       char *secdata, **mount_options;
+       int i, *flags;
+       char **mount_options;
        struct superblock_security_struct *sbsec = sb->s_security;
 
        if (!(sbsec->flags & SE_SBINITIALIZED))
                return 0;
 
-       if (!data)
-               return 0;
-
-       if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
-               return 0;
-
-       security_init_mnt_opts(&opts);
-       secdata = alloc_secdata();
-       if (!secdata)
-               return -ENOMEM;
-       rc = selinux_sb_copy_data(data, secdata);
-       if (rc)
-               goto out_free_secdata;
-
-       rc = selinux_parse_opts_str(secdata, &opts);
-       if (rc)
-               goto out_free_secdata;
+       mount_options = opts->mnt_opts;
+       flags = opts->mnt_opts_flags;
 
-       mount_options = opts.mnt_opts;
-       flags = opts.mnt_opts_flags;
-
-       for (i = 0; i < opts.num_mnt_opts; i++) {
+       for (i = 0; i < opts->num_mnt_opts; i++) {
                u32 sid;
+               int rc;
 
                if (flags[i] == SBLABEL_MNT)
                        continue;
@@ -2855,9 +2838,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                        pr_warn("SELinux: security_context_str_to_sid"
                               "(%s) failed for (dev %s, type %s) errno=%d\n",
                               mount_options[i], sb->s_id, sb->s_type->name, rc);
-                       goto out_free_opts;
+                       return rc;
                }
-               rc = -EINVAL;
                switch (flags[i]) {
                case FSCONTEXT_MNT:
                        if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
@@ -2880,21 +2862,16 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                                goto out_bad_option;
                        break;
                default:
-                       goto out_free_opts;
+                       return -EINVAL;
                }
        }
+       return 0;
 
-       rc = 0;
-out_free_opts:
-       security_free_mnt_opts(&opts);
-out_free_secdata:
-       free_secdata(secdata);
-       return rc;
 out_bad_option:
        pr_warn("SELinux: unable to change security options "
               "during remount (dev %s, type=%s)\n", sb->s_id,
               sb->s_type->name);
-       goto out_free_opts;
+       return -EINVAL;
 }
 
 static int selinux_sb_kern_mount(struct super_block *sb, int flags,