nfs: account for selinux security context when deciding to share superblock
authorOlga Kornievskaia <kolga@netapp.com>
Fri, 19 Feb 2021 22:22:33 +0000 (17:22 -0500)
committerPaul Moore <paul@paul-moore.com>
Mon, 22 Mar 2021 19:01:45 +0000 (15:01 -0400)
Keep track of whether or not there were LSM security context
options passed during mount (ie creation of the superblock).
Then, while deciding if the superblock can be shared for the new
mount, check if the newly passed in LSM security context options
are compatible with the existing superblock's ones by calling
security_sb_mnt_opts_compat().

Previously, with selinux enabled, NFS wasn't able to do the
following 2mounts:
mount -o vers=4.2,sec=sys,context=system_u:object_r:root_t:s0
<serverip>:/ /mnt
mount -o vers=4.2,sec=sys,context=system_u:object_r:swapfile_t:s0
<serverip>:/scratch /scratch

2nd mount would fail with "mount.nfs: an incorrect mount option was
specified" and var log messages would have:
"SElinux: mount invalid. Same superblock, different security
settings for.."

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
[PM: tweak subject line]
Signed-off-by: Paul Moore <paul@paul-moore.com>
fs/nfs/fs_context.c
fs/nfs/internal.h
fs/nfs/super.c
include/linux/nfs_fs_sb.h

index 971a9251c1d97c2c7bda911cead74d5a26654def..a06d213d76895f4c76699f728fea36a2919f9e98 100644 (file)
@@ -463,6 +463,9 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
        if (opt < 0)
                return ctx->sloppy ? 1 : opt;
 
+       if (fc->security)
+               ctx->has_sec_mnt_opts = 1;
+
        switch (opt) {
        case Opt_source:
                if (fc->source)
index 25fb43b69e5a45df09334d6cbf206c2f21687552..c3f57b423611358141749e5515e52627f33e3f82 100644 (file)
@@ -96,6 +96,7 @@ struct nfs_fs_context {
        char                    *fscache_uniq;
        unsigned short          protofamily;
        unsigned short          mountfamily;
+       bool                    has_sec_mnt_opts;
 
        struct {
                union {
index de83c61a67335a061f0cfc1c764c9e4a184705f3..4aaa1f5dd381efa10c347745ac8abd71acfd7569 100644 (file)
@@ -1077,6 +1077,7 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
                                                 &sb->s_blocksize_bits);
 
        nfs_super_set_maxbytes(sb, server->maxfilesize);
+       server->has_sec_mnt_opts = ctx->has_sec_mnt_opts;
 }
 
 static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b,
@@ -1193,6 +1194,9 @@ static int nfs_compare_super(struct super_block *sb, struct fs_context *fc)
                return 0;
        if (!nfs_compare_userns(old, server))
                return 0;
+       if ((old->has_sec_mnt_opts || fc->security) &&
+                       security_sb_mnt_opts_compat(sb, fc->security))
+               return 0;
        return nfs_compare_mount_options(sb, server, fc);
 }
 
index 6f76b32a0238fd06cf2fbbe209a94e0c41bba092..a28d71b45b5f0a5f32e8b213422803d17e771605 100644 (file)
@@ -256,6 +256,7 @@ struct nfs_server {
 
        /* User namespace info */
        const struct cred       *cred;
+       bool                    has_sec_mnt_opts;
 };
 
 /* Server capabilities */