On Sat, May 23, 2020 at 9:56 PM Jonathan Lebon <jlebon@xxxxxxxxxx> wrote: > This patch does for `getxattr` what 3e3e24b4204 did for `setxattr`: it > allows querying the current SELinux label on disk before the policy is > loaded. > > One of the motivations described in that commit message also drives this > patch: for Fedora CoreOS (and eventually RHEL CoreOS), we want to be > able to move the root filesystem for example from xfs to ext4, on first > boot, at initrd time.[1] > > Because such an operation works at the filesystem level, we need to be > able to read the SELinux labels first from the original root, and apply > them to the files of the new root. Commit 3e3e24b4204 enabled the second > part of this process; this patch enables the first part. > > [1] https://github.com/coreos/fedora-coreos-tracker/issues/94 > > Signed-off-by: Jonathan Lebon <jlebon@xxxxxxxxxx> > --- > security/selinux/hooks.c | 55 ++++++++++++++++++++++++++++++++++++---- > 1 file changed, 50 insertions(+), 5 deletions(-) > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index 0b4e32161b7..3bbb9966697 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c <snip> > @@ -3333,10 +3354,34 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void > int error; > char *context = NULL; > struct inode_security_struct *isec; > + struct superblock_security_struct *sbsec; > > if (strcmp(name, XATTR_SELINUX_SUFFIX)) > return -EOPNOTSUPP; I might be missing something, but couldn't you achieve the same by simply adding something like this in here: if (!selinux_initialized(&selinux_state)) return -EOPNOTSUPP; (Or by adding it to the condition above.) Then you should hit this condition here and be all set: https://elixir.bootlin.com/linux/v5.7-rc7/source/fs/xattr.c#L337 > > + isec = inode_security(inode); > + sbsec = inode->i_sb->s_security; > + > + /* Just return the raw context if the policy isn't even loaded since we > + * have no way to validate it anyway. This is symmetrical with allowing > + * setxattr without a policy. */ > + if (!selinux_state.initialized) { > + /* See similar code in inode_doinit_with_dentry; for xattrs, > + * some filesystems really want a connected inode. If we don't > + * find one, just let fallback in case it corresponds to one of > + * the default sids. */ > + struct dentry *dentry = d_find_alias(inode); > + if (!dentry) > + dentry = d_find_any_alias(inode); > + > + if (dentry) { > + error = get_inode_raw_xattr_context(inode, dentry, > + &context, &size); > + dput(dentry); > + goto out; > + } > + } > + > /* > * If the caller has CAP_MAC_ADMIN, then get the raw context > * value even if it is not defined by current policy; otherwise, > @@ -3346,7 +3391,6 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void > * and lack of permission just means that we fall back to the > * in-core context value, not a denial. > */ > - isec = inode_security(inode); > if (has_cap_mac_admin(false)) > error = security_sid_to_context_force(&selinux_state, > isec->sid, &context, > @@ -3354,6 +3398,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void > else > error = security_sid_to_context(&selinux_state, isec->sid, > &context, &size); > +out: > if (error) > return error; > error = size; > -- > 2.25.4 > -- Ondrej Mosnacek Software Engineer, Platform Security - SELinux kernel, Red Hat, Inc.