selinux: wrap cgroup seclabel support with its own policy capability
authorStephen Smalley <sds@tycho.nsa.gov>
Tue, 28 Feb 2017 15:35:56 +0000 (10:35 -0500)
committerJames Morris <james.l.morris@oracle.com>
Wed, 1 Mar 2017 23:27:40 +0000 (10:27 +1100)
commit 1ea0ce40690dff38935538e8dab7b12683ded0d3 ("selinux: allow
changing labels for cgroupfs") broke the Android init program,
which looks up security contexts whenever creating directories
and attempts to assign them via setfscreatecon().
When creating subdirectories in cgroup mounts, this would previously
be ignored since cgroup did not support userspace setting of security
contexts.  However, after the commit, SELinux would attempt to honor
the requested context on cgroup directories and fail due to permission
denial.  Avoid breaking existing userspace/policy by wrapping this change
with a conditional on a new cgroup_seclabel policy capability.  This
preserves existing behavior until/unless a new policy explicitly enables
this capability.

Reported-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/services.c

index 9a8f12f8d5b7ffce41259a104d928308296fdf12..0a4b4b040e0ab0e2ea954744b4d3d023481896d1 100644 (file)
@@ -480,12 +480,13 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
                sbsec->behavior == SECURITY_FS_USE_NATIVE ||
                /* Special handling. Genfs but also in-core setxattr handler */
                !strcmp(sb->s_type->name, "sysfs") ||
-               !strcmp(sb->s_type->name, "cgroup") ||
-               !strcmp(sb->s_type->name, "cgroup2") ||
                !strcmp(sb->s_type->name, "pstore") ||
                !strcmp(sb->s_type->name, "debugfs") ||
                !strcmp(sb->s_type->name, "tracefs") ||
-               !strcmp(sb->s_type->name, "rootfs");
+               !strcmp(sb->s_type->name, "rootfs") ||
+               (selinux_policycap_cgroupseclabel &&
+                (!strcmp(sb->s_type->name, "cgroup") ||
+                 !strcmp(sb->s_type->name, "cgroup2")));
 }
 
 static int sb_finish_set_opts(struct super_block *sb)
index beaa14b8b6cf570993c1b9ee210232fb03a6a1e4..f979c35e037ec44f6f7ee98dfa1fec93bf8190de 100644 (file)
@@ -71,6 +71,7 @@ enum {
        POLICYDB_CAPABILITY_OPENPERM,
        POLICYDB_CAPABILITY_EXTSOCKCLASS,
        POLICYDB_CAPABILITY_ALWAYSNETWORK,
+       POLICYDB_CAPABILITY_CGROUPSECLABEL,
        __POLICYDB_CAPABILITY_MAX
 };
 #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
@@ -79,6 +80,7 @@ extern int selinux_policycap_netpeer;
 extern int selinux_policycap_openperm;
 extern int selinux_policycap_extsockclass;
 extern int selinux_policycap_alwaysnetwork;
+extern int selinux_policycap_cgroupseclabel;
 
 /*
  * type_datum properties
index c9e8a9898ce48111af344584534c19f9cdc483a9..cb3fd98fb05ae7df77b2ad20bf640d38b5133123 100644 (file)
@@ -46,7 +46,8 @@ static char *policycap_names[] = {
        "network_peer_controls",
        "open_perms",
        "extended_socket_class",
-       "always_check_network"
+       "always_check_network",
+       "cgroup_seclabel"
 };
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
index a70fcee9824ba301cf0b367fd1a701a62a8c87b8..b4aa491a0a23d8e025f00fde82b317952816773f 100644 (file)
@@ -74,6 +74,7 @@ int selinux_policycap_netpeer;
 int selinux_policycap_openperm;
 int selinux_policycap_extsockclass;
 int selinux_policycap_alwaysnetwork;
+int selinux_policycap_cgroupseclabel;
 
 static DEFINE_RWLOCK(policy_rwlock);
 
@@ -1993,6 +1994,9 @@ static void security_load_policycaps(void)
                                          POLICYDB_CAPABILITY_EXTSOCKCLASS);
        selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
                                                  POLICYDB_CAPABILITY_ALWAYSNETWORK);
+       selinux_policycap_cgroupseclabel =
+               ebitmap_get_bit(&policydb.policycaps,
+                               POLICYDB_CAPABILITY_CGROUPSECLABEL);
 }
 
 static int security_preserve_bools(struct policydb *p);