summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2020-01-28 20:16:48 +0100
committerPaul Moore <paul@paul-moore.com>2020-02-10 10:49:01 -0500
commit7470d0d13fb680bb82b40f18831f7d4ee7a4bb62 (patch)
treed39d3d44ae8407d80d2751b83ee6680d7dc4f45c
parent06c2efe2cf3aa70abbdf97e88641abca2e707a15 (diff)
selinux: allow kernfs symlinks to inherit parent directory context
Currently symlinks on kernel filesystems, like sysfs, are labeled on creation with the parent filesystem root sid. Allow symlinks to inherit the parent directory context, so fine-grained kernfs labeling can be applied to symlinks too and checking contexts doesn't complain about them. For backward-compatibility this behavior is contained in a new policy capability: genfs_seclabel_symlinks Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--security/selinux/hooks.c4
-rw-r--r--security/selinux/include/security.h8
-rw-r--r--security/selinux/ss/services.c3
3 files changed, 13 insertions, 2 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d7762264f262..7c37cdb3aba0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1478,7 +1478,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
/* Default to the fs superblock SID. */
sid = sbsec->sid;
- if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
+ if ((sbsec->flags & SE_SBGENFS) &&
+ (!S_ISLNK(inode->i_mode) ||
+ selinux_policycap_genfs_seclabel_symlinks())) {
/* We must have a dentry to determine the label on
* procfs inodes */
if (opt_dentry) {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index f3a621058aba..d6036c018cf2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -79,6 +79,7 @@ enum {
POLICYDB_CAPABILITY_ALWAYSNETWORK,
POLICYDB_CAPABILITY_CGROUPSECLABEL,
POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
+ POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
@@ -213,6 +214,13 @@ static inline bool selinux_policycap_nnp_nosuid_transition(void)
return state->policycap[POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION];
}
+static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
+{
+ struct selinux_state *state = &selinux_state;
+
+ return state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS];
+}
+
int security_mls_enabled(struct selinux_state *state);
int security_load_policy(struct selinux_state *state,
void *data, size_t len);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 922b5e4a03e8..e310f8ee21a1 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -72,7 +72,8 @@ const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
"extended_socket_class",
"always_check_network",
"cgroup_seclabel",
- "nnp_nosuid_transition"
+ "nnp_nosuid_transition",
+ "genfs_seclabel_symlinks"
};
static struct selinux_ss selinux_ss;