Merge tag 'idmapped-mounts-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / security / selinux / hooks.c
index 9719dd1..ddd0977 100644 (file)
@@ -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)
 {
        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;
 
        if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
-               /* 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);
-                       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;
-               }
+               rc = sb_check_xattr_support(sb);
+               if (rc)
+                       return rc;
        }
 
        sbsec->flags |= SE_SBINITIALIZED;
@@ -554,7 +582,6 @@ static int sb_finish_set_opts(struct super_block *sb)
                spin_lock(&sbsec->isec_lock);
        }
        spin_unlock(&sbsec->isec_lock);
-out:
        return rc;
 }
 
@@ -1120,7 +1147,8 @@ static inline u16 inode_mode_to_security_class(umode_t mode)
 
 static inline int default_protocol_stream(int protocol)
 {
-       return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
+       return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP ||
+               protocol == IPPROTO_MPTCP);
 }
 
 static inline int default_protocol_dgram(int protocol)
@@ -2934,6 +2962,62 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
        return 0;
 }
 
+static int selinux_inode_init_security_anon(struct inode *inode,
+                                           const struct qstr *name,
+                                           const struct inode *context_inode)
+{
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
+       struct common_audit_data ad;
+       struct inode_security_struct *isec;
+       int rc;
+
+       if (unlikely(!selinux_initialized(&selinux_state)))
+               return 0;
+
+       isec = selinux_inode(inode);
+
+       /*
+        * We only get here once per ephemeral inode.  The inode has
+        * been initialized via inode_alloc_security but is otherwise
+        * untouched.
+        */
+
+       if (context_inode) {
+               struct inode_security_struct *context_isec =
+                       selinux_inode(context_inode);
+               if (context_isec->initialized != LABEL_INITIALIZED) {
+                       pr_err("SELinux:  context_inode is not initialized");
+                       return -EACCES;
+               }
+
+               isec->sclass = context_isec->sclass;
+               isec->sid = context_isec->sid;
+       } else {
+               isec->sclass = SECCLASS_ANON_INODE;
+               rc = security_transition_sid(
+                       &selinux_state, tsec->sid, tsec->sid,
+                       isec->sclass, name, &isec->sid);
+               if (rc)
+                       return rc;
+       }
+
+       isec->initialized = LABEL_INITIALIZED;
+       /*
+        * Now that we've initialized security, check whether we're
+        * allowed to actually create this type of anonymous inode.
+        */
+
+       ad.type = LSM_AUDIT_DATA_INODE;
+       ad.u.inode = inode;
+
+       return avc_has_perm(&selinux_state,
+                           tsec->sid,
+                           isec->sid,
+                           isec->sclass,
+                           FILE__CREATE,
+                           &ad);
+}
+
 static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        return may_create(dir, dentry, SECCLASS_FILE);
@@ -3417,6 +3501,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
 static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
 {
        const int len = sizeof(XATTR_NAME_SELINUX);
+
+       if (!selinux_initialized(&selinux_state))
+               return 0;
+
        if (buffer && len <= buffer_size)
                memcpy(buffer, XATTR_NAME_SELINUX, len);
        return len;
@@ -7005,6 +7093,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 
        LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
        LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
+       LSM_HOOK_INIT(inode_init_security_anon, selinux_inode_init_security_anon),
        LSM_HOOK_INIT(inode_create, selinux_inode_create),
        LSM_HOOK_INIT(inode_link, selinux_inode_link),
        LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),