[PATCH v3] nfs: Fix automount superblock LSM init problem, preventing sb sharing

Paul Moore paul at paul-moore.com
Tue Aug 16 03:25:44 UTC 2022


On Thu, Aug 11, 2022 at 8:28 AM Ondrej Mosnacek <omosnace at redhat.com> wrote:
> On Fri, Aug 5, 2022 at 3:36 PM David Howells <dhowells at redhat.com> wrote:
> > When NFS superblocks are created by automounting, their LSM parameters
> > aren't set in the fs_context struct prior to sget_fc() being called,
> > leading to failure to match existing superblocks.
> >
> > Fix this by adding a new LSM hook to load fc->security for submount
> > creation when alloc_fs_context() is creating the fs_context for it.
> >
> > However, this uncovers a further bug: nfs_get_root() initialises the
> > superblock security manually by calling security_sb_set_mnt_opts() or
> > security_sb_clone_mnt_opts() - but then vfs_get_tree() calls
> > security_sb_set_mnt_opts(), which can lead to SELinux, at least,
> > complaining.
> >
> > Fix that by adding a flag to the fs_context that suppresses the
> > security_sb_set_mnt_opts() call in vfs_get_tree().  This can be set by NFS
> > when it sets the LSM context on the new superblock.
> >
> > The first bug leads to messages like the following appearing in dmesg:
> >
> >         NFS: Cache volume key already in use (nfs,4.2,2,108,106a8c0,1,,,,100000,100000,2ee,3a98,1d4c,3a98,1)
> >
> > Changes
> > =======
> > ver #2)
> >  - Made LSM parameter extraction dependent on fc->purpose ==
> >    FS_CONTEXT_FOR_SUBMOUNT.  Shouldn't happen on FOR_RECONFIGURE.
> >
> > ver #2)
> >  - Added Smack support
> >  - Made LSM parameter extraction dependent on reference != NULL.
> >
> > Signed-off-by: David Howells <dhowells at redhat.com>
> > Fixes: 9bc61ab18b1d ("vfs: Introduce fs_context, switch vfs_kern_mount() to it.")
> > Fixes: 779df6a5480f ("NFS: Ensure security label is set for root inode)
> > cc: Trond Myklebust <trond.myklebust at hammerspace.com>
> > cc: Anna Schumaker <anna at kernel.org>
> > cc: Alexander Viro <viro at zeniv.linux.org.uk>
> > cc: Scott Mayhew <smayhew at redhat.com>
> > cc: Jeff Layton <jlayton at kernel.org>
> > cc: Paul Moore <paul at paul-moore.com>
> > cc: Casey Schaufler <casey at schaufler-ca.com>
> > cc: linux-nfs at vger.kernel.org
> > cc: selinux at vger.kernel.org
> > cc: linux-security-module at vger.kernel.org
> > cc: linux-fsdevel at vger.kernel.org
> > ---
> >
> >  fs/fs_context.c               |    4 +++
> >  fs/nfs/getroot.c              |    1 +
> >  fs/super.c                    |   10 ++++---
> >  include/linux/fs_context.h    |    1 +
> >  include/linux/lsm_hook_defs.h |    1 +
> >  include/linux/lsm_hooks.h     |    6 +++-
> >  include/linux/security.h      |    6 ++++
> >  security/security.c           |    5 +++
> >  security/selinux/hooks.c      |   29 +++++++++++++++++++
> >  security/smack/smack_lsm.c    |   61 +++++++++++++++++++++++++++++++++++++++++
> >  10 files changed, 119 insertions(+), 5 deletions(-)
>
> <snip>
>
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 1bbd53321d13..ddeaff4f3bb1 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2768,6 +2768,34 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
> >                                    FILESYSTEM__UNMOUNT, NULL);
> >  }
> >
> > +static int selinux_fs_context_init(struct fs_context *fc,
> > +                                  struct dentry *reference)
> > +{
> > +       const struct superblock_security_struct *sbsec;
> > +       const struct inode_security_struct *root_isec;
> > +       struct selinux_mnt_opts *opts;
> > +
> > +       if (fc->purpose == FS_CONTEXT_FOR_SUBMOUNT) {
> > +               opts = kzalloc(sizeof(*opts), GFP_KERNEL);
> > +               if (!opts)
> > +                       return -ENOMEM;
> > +
> > +               root_isec = backing_inode_security(reference->d_sb->s_root);
> > +               sbsec = selinux_superblock(reference->d_sb);
> > +               if (sbsec->flags & FSCONTEXT_MNT)
> > +                       opts->fscontext_sid     = sbsec->sid;
> > +               if (sbsec->flags & CONTEXT_MNT)
> > +                       opts->context_sid       = sbsec->mntpoint_sid;
> > +               if (sbsec->flags & ROOTCONTEXT_MNT)
> > +                       opts->rootcontext_sid   = root_isec->sid;
>
> I wonder if this part is correct... The rootcontext=... mount option
> relates to the root inode of the mount where it is specified - i.e. in
> case of NFS only to the toplevel inode of the initial mount. Setting
> the same context on the root inode of submounts, which AFAIK are
> supposed to be transparent to the user, doesn't seem correct to me -
> i.e. it should just be left unset for the automatically created
> submounts.

Like Ondrej, I'm not going to say I'm very comfortable with some of
the VFS corner cases, but this is an interesting case ... as far as I
can tell, the submount has a superblock and is treated like a normal
filesystem mount with the one exception that it is mounted
automatically so that users might not be aware it is a separate mount.

I guess my question is this: for inodes inside the superblock, does
their superblock pointer point to the submount's superblock, or the
parent filesystem's superblock?

-- 
paul-moore.com



More information about the Linux-security-module-archive mailing list