Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfs: account for selinux security context when deciding to share superblock

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>

authored by

Olga Kornievskaia and committed by
Paul Moore
ec1ade6a 8c6d76a3

+9
+3
fs/nfs/fs_context.c
··· 463 463 if (opt < 0) 464 464 return ctx->sloppy ? 1 : opt; 465 465 466 + if (fc->security) 467 + ctx->has_sec_mnt_opts = 1; 468 + 466 469 switch (opt) { 467 470 case Opt_source: 468 471 if (fc->source)
+1
fs/nfs/internal.h
··· 96 96 char *fscache_uniq; 97 97 unsigned short protofamily; 98 98 unsigned short mountfamily; 99 + bool has_sec_mnt_opts; 99 100 100 101 struct { 101 102 union {
+4
fs/nfs/super.c
··· 1077 1077 &sb->s_blocksize_bits); 1078 1078 1079 1079 nfs_super_set_maxbytes(sb, server->maxfilesize); 1080 + server->has_sec_mnt_opts = ctx->has_sec_mnt_opts; 1080 1081 } 1081 1082 1082 1083 static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, ··· 1193 1192 if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) 1194 1193 return 0; 1195 1194 if (!nfs_compare_userns(old, server)) 1195 + return 0; 1196 + if ((old->has_sec_mnt_opts || fc->security) && 1197 + security_sb_mnt_opts_compat(sb, fc->security)) 1196 1198 return 0; 1197 1199 return nfs_compare_mount_options(sb, server, fc); 1198 1200 }
+1
include/linux/nfs_fs_sb.h
··· 256 256 257 257 /* User namespace info */ 258 258 const struct cred *cred; 259 + bool has_sec_mnt_opts; 259 260 }; 260 261 261 262 /* Server capabilities */