summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Smalley <stephen.smalley.work@gmail.com>2020-08-19 16:45:41 +0300
committerPaul Moore <paul@paul-moore.com>2020-08-20 04:14:41 +0300
commit37ea433c66070fcef09c6d118492c36299eb72ba (patch)
treed3f5cbcd0fdd69e2ecfe1ce597b16b60751a1dd3
parent69ea651c40f7f08962d440a0486fd0212be74b73 (diff)
downloadlinux-37ea433c66070fcef09c6d118492c36299eb72ba.tar.xz
selinux: avoid dereferencing the policy prior to initialization
Certain SELinux security server functions (e.g. security_port_sid, called during bind) were not explicitly testing to see if SELinux has been initialized (i.e. initial policy loaded) and handling the no-policy-loaded case. In the past this happened to work because the policydb was statically allocated and could always be accessed, but with the recent encapsulation of policy state and conversion to dynamic allocation, we can no longer access the policy state prior to initialization. Add a test of !selinux_initialized(state) to all of the exported functions that were missing them and handle appropriately. Fixes: 461698026ffa ("selinux: encapsulate policy state, refactor policy load") Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org> Tested-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--security/selinux/ss/services.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d310910fb639..a48fc1b337ba 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2293,6 +2293,9 @@ size_t security_policydb_len(struct selinux_state *state)
{
size_t len;
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
len = state->ss->policy->policydb.len;
read_unlock(&state->ss->policy_rwlock);
@@ -2314,6 +2317,11 @@ int security_port_sid(struct selinux_state *state,
struct ocontext *c;
int rc = 0;
+ if (!selinux_initialized(state)) {
+ *out_sid = SECINITSID_PORT;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2359,6 +2367,11 @@ int security_ib_pkey_sid(struct selinux_state *state,
struct ocontext *c;
int rc = 0;
+ if (!selinux_initialized(state)) {
+ *out_sid = SECINITSID_UNLABELED;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2405,6 +2418,11 @@ int security_ib_endport_sid(struct selinux_state *state,
struct ocontext *c;
int rc = 0;
+ if (!selinux_initialized(state)) {
+ *out_sid = SECINITSID_UNLABELED;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2450,6 +2468,11 @@ int security_netif_sid(struct selinux_state *state,
int rc = 0;
struct ocontext *c;
+ if (!selinux_initialized(state)) {
+ *if_sid = SECINITSID_NETIF;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2513,6 +2536,11 @@ int security_node_sid(struct selinux_state *state,
int rc;
struct ocontext *c;
+ if (!selinux_initialized(state)) {
+ *out_sid = SECINITSID_NODE;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2780,6 +2808,11 @@ int security_genfs_sid(struct selinux_state *state,
{
int retval;
+ if (!selinux_initialized(state)) {
+ *sid = SECINITSID_UNLABELED;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
retval = __security_genfs_sid(state->ss->policy,
fstype, path, orig_sclass, sid);
@@ -2810,6 +2843,12 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
struct superblock_security_struct *sbsec = sb->s_security;
const char *fstype = sb->s_type->name;
+ if (!selinux_initialized(state)) {
+ sbsec->behavior = SECURITY_FS_USE_NONE;
+ sbsec->sid = SECINITSID_UNLABELED;
+ return 0;
+ }
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -2906,6 +2945,9 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
int rc;
u32 i, seqno = 0;
+ if (!selinux_initialized(state))
+ return -EINVAL;
+
/*
* NOTE: We do not need to take the policy read-lock
* around the code below because other policy-modifying
@@ -2982,6 +3024,9 @@ int security_get_bool_value(struct selinux_state *state,
int rc;
u32 len;
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -3161,6 +3206,9 @@ int security_net_peersid_resolve(struct selinux_state *state,
return 0;
}
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policy->policydb;
@@ -3307,6 +3355,9 @@ int security_get_reject_unknown(struct selinux_state *state)
{
int value;
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
value = state->ss->policy->policydb.reject_unknown;
read_unlock(&state->ss->policy_rwlock);
@@ -3317,6 +3368,9 @@ int security_get_allow_unknown(struct selinux_state *state)
{
int value;
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
value = state->ss->policy->policydb.allow_unknown;
read_unlock(&state->ss->policy_rwlock);
@@ -3338,6 +3392,9 @@ int security_policycap_supported(struct selinux_state *state,
{
int rc;
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
rc = ebitmap_get_bit(&state->ss->policy->policydb.policycaps, req_cap);
read_unlock(&state->ss->policy_rwlock);
@@ -3499,6 +3556,9 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
return -ENOENT;
}
+ if (!selinux_initialized(state))
+ return 0;
+
read_lock(&state->ss->policy_rwlock);
if (rule->au_seqno < state->ss->latest_granting) {