forked from Minki/linux
selinux: fall back to SECURITY_FS_USE_GENFS if no xattr support
When a superblock is assigned the SECURITY_FS_USE_XATTR behavior by the policy yet it lacks xattr support, try to fall back to genfs rather than rejecting the mount. If a genfscon rule is found for the filesystem, then change the behavior to SECURITY_FS_USE_GENFS, otherwise reject the mount as before. A similar fallback is already done in security_fs_use() if no behavior specification is found for the given filesystem. This is needed e.g. for virtiofs, which may or may not support xattrs depending on the backing host filesystem. Example: # seinfo --genfs | grep ' ramfs' genfscon ramfs / system_u:object_r:ramfs_t:s0 # echo '(fsuse xattr ramfs (system_u object_r fs_t ((s0) (s0))))' >ramfs_xattr.cil # semodule -i ramfs_xattr.cil # mount -t ramfs none /mnt Before: mount: /mnt: mount(2) system call failed: Operation not supported. After: (mount succeeds) # ls -Zd /mnt system_u:object_r:ramfs_t:s0 /mnt See also: https://lore.kernel.org/selinux/20210105142148.GA3200@redhat.com/T/ https://github.com/fedora-selinux/selinux-policy/pull/478 Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
e0de8a9aeb
commit
08abe46b2c
@ -484,6 +484,55 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sb_check_xattr_support(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct superblock_security_struct *sbsec = sb->s_security;
|
||||||
|
struct dentry *root = sb->s_root;
|
||||||
|
struct inode *root_inode = d_backing_inode(root);
|
||||||
|
u32 sid;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that the xattr handler exists and that no
|
||||||
|
* error other than -ENODATA is returned by getxattr on
|
||||||
|
* the root directory. -ENODATA is ok, as this may be
|
||||||
|
* the first boot of the SELinux kernel before we have
|
||||||
|
* assigned xattr values to the filesystem.
|
||||||
|
*/
|
||||||
|
if (!(root_inode->i_opflags & IOP_XATTR)) {
|
||||||
|
pr_warn("SELinux: (dev %s, type %s) has no xattr support\n",
|
||||||
|
sb->s_id, sb->s_type->name);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
|
||||||
|
if (rc < 0 && rc != -ENODATA) {
|
||||||
|
if (rc == -EOPNOTSUPP) {
|
||||||
|
pr_warn("SELinux: (dev %s, type %s) has no security xattr handler\n",
|
||||||
|
sb->s_id, sb->s_type->name);
|
||||||
|
goto fallback;
|
||||||
|
} else {
|
||||||
|
pr_warn("SELinux: (dev %s, type %s) getxattr errno %d\n",
|
||||||
|
sb->s_id, sb->s_type->name, -rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fallback:
|
||||||
|
/* No xattr support - try to fallback to genfs if possible. */
|
||||||
|
rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/",
|
||||||
|
SECCLASS_DIR, &sid);
|
||||||
|
if (rc)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
pr_warn("SELinux: (dev %s, type %s) falling back to genfs\n",
|
||||||
|
sb->s_id, sb->s_type->name);
|
||||||
|
sbsec->behavior = SECURITY_FS_USE_GENFS;
|
||||||
|
sbsec->sid = sid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sb_finish_set_opts(struct super_block *sb)
|
static int sb_finish_set_opts(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct superblock_security_struct *sbsec = sb->s_security;
|
struct superblock_security_struct *sbsec = sb->s_security;
|
||||||
@ -492,30 +541,9 @@ static int sb_finish_set_opts(struct super_block *sb)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
|
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
|
||||||
/* Make sure that the xattr handler exists and that no
|
rc = sb_check_xattr_support(sb);
|
||||||
error other than -ENODATA is returned by getxattr on
|
if (rc)
|
||||||
the root directory. -ENODATA is ok, as this may be
|
return rc;
|
||||||
the first boot of the SELinux kernel before we have
|
|
||||||
assigned xattr values to the filesystem. */
|
|
||||||
if (!(root_inode->i_opflags & IOP_XATTR)) {
|
|
||||||
pr_warn("SELinux: (dev %s, type %s) has no "
|
|
||||||
"xattr support\n", sb->s_id, sb->s_type->name);
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
|
|
||||||
if (rc < 0 && rc != -ENODATA) {
|
|
||||||
if (rc == -EOPNOTSUPP)
|
|
||||||
pr_warn("SELinux: (dev %s, type "
|
|
||||||
"%s) has no security xattr handler\n",
|
|
||||||
sb->s_id, sb->s_type->name);
|
|
||||||
else
|
|
||||||
pr_warn("SELinux: (dev %s, type "
|
|
||||||
"%s) getxattr errno %d\n", sb->s_id,
|
|
||||||
sb->s_type->name, -rc);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sbsec->flags |= SE_SBINITIALIZED;
|
sbsec->flags |= SE_SBINITIALIZED;
|
||||||
@ -554,7 +582,6 @@ static int sb_finish_set_opts(struct super_block *sb)
|
|||||||
spin_lock(&sbsec->isec_lock);
|
spin_lock(&sbsec->isec_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&sbsec->isec_lock);
|
spin_unlock(&sbsec->isec_lock);
|
||||||
out:
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user