summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/ss/services.c403
-rw-r--r--security/selinux/ss/services.h10
2 files changed, 221 insertions, 192 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 676550103fac..137d9396742a 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -238,9 +238,15 @@ static void map_decision(struct selinux_map *map,
int security_mls_enabled(struct selinux_state *state)
{
- struct policydb *p = &state->ss->policydb;
+ int mls_enabled;
- return p->mls_enabled;
+ if (!selinux_initialized(state))
+ return 0;
+
+ read_lock(&state->ss->policy_rwlock);
+ mls_enabled = state->ss->policy->policydb.mls_enabled;
+ read_unlock(&state->ss->policy_rwlock);
+ return mls_enabled;
}
/*
@@ -716,8 +722,8 @@ static int security_validtrans_handle_fail(struct selinux_state *state,
struct sidtab_entry *tentry,
u16 tclass)
{
- struct policydb *p = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *p = &state->ss->policy->policydb;
+ struct sidtab *sidtab = &state->ss->policy->sidtab;
char *o = NULL, *n = NULL, *t = NULL;
u32 olen, nlen, tlen;
@@ -761,11 +767,11 @@ static int security_compute_validatetrans(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
if (!user)
- tclass = unmap_class(&state->ss->map, orig_tclass);
+ tclass = unmap_class(&state->ss->policy->map, orig_tclass);
else
tclass = orig_tclass;
@@ -862,8 +868,8 @@ int security_bounded_transition(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
rc = -EINVAL;
old_entry = sidtab_search_entry(sidtab, old_sid);
@@ -1019,8 +1025,8 @@ void security_compute_xperms_decision(struct selinux_state *state,
if (!selinux_initialized(state))
goto allow;
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
@@ -1036,7 +1042,7 @@ void security_compute_xperms_decision(struct selinux_state *state,
goto out;
}
- tclass = unmap_class(&state->ss->map, orig_tclass);
+ tclass = unmap_class(&state->ss->policy->map, orig_tclass);
if (unlikely(orig_tclass && !tclass)) {
if (policydb->allow_unknown)
goto allow;
@@ -1104,8 +1110,8 @@ void security_compute_av(struct selinux_state *state,
if (!selinux_initialized(state))
goto allow;
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
@@ -1125,7 +1131,7 @@ void security_compute_av(struct selinux_state *state,
goto out;
}
- tclass = unmap_class(&state->ss->map, orig_tclass);
+ tclass = unmap_class(&state->ss->policy->map, orig_tclass);
if (unlikely(orig_tclass && !tclass)) {
if (policydb->allow_unknown)
goto allow;
@@ -1133,7 +1139,7 @@ void security_compute_av(struct selinux_state *state,
}
context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
xperms);
- map_decision(&state->ss->map, orig_tclass, avd,
+ map_decision(&state->ss->policy->map, orig_tclass, avd,
policydb->allow_unknown);
out:
read_unlock(&state->ss->policy_rwlock);
@@ -1158,8 +1164,8 @@ void security_compute_av_user(struct selinux_state *state,
if (!selinux_initialized(state))
goto allow;
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
@@ -1282,7 +1288,7 @@ int security_sidtab_hash_stats(struct selinux_state *state, char *page)
}
read_lock(&state->ss->policy_rwlock);
- rc = sidtab_hash_stats(state->ss->sidtab, page);
+ rc = sidtab_hash_stats(&state->ss->policy->sidtab, page);
read_unlock(&state->ss->policy_rwlock);
return rc;
@@ -1330,8 +1336,8 @@ static int security_sid_to_context_core(struct selinux_state *state,
return -EINVAL;
}
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
if (force)
entry = sidtab_search_entry_force(sidtab, sid);
@@ -1524,8 +1530,8 @@ static int security_context_to_sid_core(struct selinux_state *state,
goto out;
}
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
rc = string_to_context_struct(policydb, sidtab, scontext2,
&context, def_sid);
if (rc == -EINVAL && force) {
@@ -1612,8 +1618,8 @@ static int compute_sid_handle_invalid_context(
u16 tclass,
struct context *newcontext)
{
- struct policydb *policydb = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *policydb = &state->ss->policy->policydb;
+ struct sidtab *sidtab = &state->ss->policy->sidtab;
char *s = NULL, *t = NULL, *n = NULL;
u32 slen, tlen, nlen;
struct audit_buffer *ab;
@@ -1709,16 +1715,16 @@ static int security_compute_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
if (kern) {
- tclass = unmap_class(&state->ss->map, orig_tclass);
+ tclass = unmap_class(&state->ss->policy->map, orig_tclass);
sock = security_is_socket_class(orig_tclass);
} else {
tclass = orig_tclass;
- sock = security_is_socket_class(map_class(&state->ss->map,
+ sock = security_is_socket_class(map_class(&state->ss->policy->map,
tclass));
}
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
sentry = sidtab_search_entry(sidtab, ssid);
if (!sentry) {
@@ -1935,7 +1941,7 @@ static inline int convert_context_handle_invalid_context(
struct selinux_state *state,
struct context *context)
{
- struct policydb *policydb = &state->ss->policydb;
+ struct policydb *policydb = &state->ss->policy->policydb;
char *s;
u32 len;
@@ -2088,10 +2094,14 @@ bad:
static void security_load_policycaps(struct selinux_state *state)
{
- struct policydb *p = &state->ss->policydb;
+ struct policydb *p;
unsigned int i;
struct ebitmap_node *node;
+ read_lock(&state->ss->policy_rwlock);
+
+ p = &state->ss->policy->policydb;
+
for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
@@ -2105,11 +2115,76 @@ static void security_load_policycaps(struct selinux_state *state)
pr_info("SELinux: unknown policy capability %u\n",
i);
}
+
+ read_unlock(&state->ss->policy_rwlock);
}
static int security_preserve_bools(struct selinux_state *state,
struct policydb *newpolicydb);
+static void selinux_policy_free(struct selinux_policy *policy)
+{
+ if (!policy)
+ return;
+
+ policydb_destroy(&policy->policydb);
+ sidtab_destroy(&policy->sidtab);
+ kfree(policy->map.mapping);
+ kfree(policy);
+}
+
+static void selinux_policy_commit(struct selinux_state *state,
+ struct selinux_policy *newpolicy)
+{
+ struct selinux_policy *oldpolicy;
+ u32 seqno;
+
+ /*
+ * NOTE: We do not need to take the policy read-lock
+ * around the code below because other policy-modifying
+ * operations are already excluded by selinuxfs via
+ * fsi->mutex.
+ */
+
+ /* If switching between different policy types, log MLS status */
+ oldpolicy = state->ss->policy;
+ if (oldpolicy) {
+ if (oldpolicy->policydb.mls_enabled && !newpolicy->policydb.mls_enabled)
+ pr_info("SELinux: Disabling MLS support...\n");
+ else if (!oldpolicy->policydb.mls_enabled && newpolicy->policydb.mls_enabled)
+ pr_info("SELinux: Enabling MLS support...\n");
+ }
+
+ /* Install the new policy. */
+ write_lock_irq(&state->ss->policy_rwlock);
+ state->ss->policy = newpolicy;
+ seqno = ++state->ss->latest_granting;
+ write_unlock_irq(&state->ss->policy_rwlock);
+
+ /* Load the policycaps from the new policy */
+ security_load_policycaps(state);
+
+ if (!selinux_initialized(state)) {
+ /*
+ * After first policy load, the security server is
+ * marked as initialized and ready to handle requests and
+ * any objects created prior to policy load are then labeled.
+ */
+ selinux_mark_initialized(state);
+ selinux_complete_init();
+ }
+
+ /* Free the old policy */
+ selinux_policy_free(oldpolicy);
+
+ /* Flush external caches and notify userspace of policy load */
+ avc_ss_reset(state->avc, seqno);
+ selnl_notify_policyload(seqno);
+ selinux_status_update_policyload(state, seqno);
+ selinux_netlbl_cache_invalidate();
+ selinux_xfrm_notify_policyload();
+}
+
/**
* security_load_policy - Load a security policy configuration.
* @data: binary policy data
@@ -2122,112 +2197,64 @@ static int security_preserve_bools(struct selinux_state *state,
*/
int security_load_policy(struct selinux_state *state, void *data, size_t len)
{
- struct policydb *policydb;
- struct sidtab *oldsidtab, *newsidtab;
- struct policydb *oldpolicydb, *newpolicydb;
- struct selinux_mapping *oldmapping;
- struct selinux_map newmap;
+ struct selinux_policy *newpolicy;
struct sidtab_convert_params convert_params;
struct convert_context_args args;
- u32 seqno;
int rc = 0;
struct policy_file file = { data, len }, *fp = &file;
- policydb = &state->ss->policydb;
-
- newsidtab = kmalloc(sizeof(*newsidtab), GFP_KERNEL);
- if (!newsidtab)
+ newpolicy = kzalloc(sizeof(*newpolicy), GFP_KERNEL);
+ if (!newpolicy)
return -ENOMEM;
- if (!selinux_initialized(state)) {
- rc = policydb_read(policydb, fp);
- if (rc) {
- kfree(newsidtab);
- return rc;
- }
-
- policydb->len = len;
- rc = selinux_set_mapping(policydb, secclass_map,
- &state->ss->map);
- if (rc) {
- kfree(newsidtab);
- policydb_destroy(policydb);
- return rc;
- }
-
- rc = policydb_load_isids(policydb, newsidtab);
- if (rc) {
- kfree(newsidtab);
- policydb_destroy(policydb);
- return rc;
- }
-
- state->ss->sidtab = newsidtab;
- security_load_policycaps(state);
- selinux_mark_initialized(state);
- seqno = ++state->ss->latest_granting;
- selinux_complete_init();
- avc_ss_reset(state->avc, seqno);
- selnl_notify_policyload(seqno);
- selinux_status_update_policyload(state, seqno);
- selinux_netlbl_cache_invalidate();
- selinux_xfrm_notify_policyload();
- return 0;
- }
+ rc = policydb_read(&newpolicy->policydb, fp);
+ if (rc)
+ goto err;
- oldpolicydb = kcalloc(2, sizeof(*oldpolicydb), GFP_KERNEL);
- if (!oldpolicydb) {
- kfree(newsidtab);
- return -ENOMEM;
- }
- newpolicydb = oldpolicydb + 1;
+ newpolicy->policydb.len = len;
+ rc = selinux_set_mapping(&newpolicy->policydb, secclass_map,
+ &newpolicy->map);
+ if (rc)
+ goto err;
- rc = policydb_read(newpolicydb, fp);
+ rc = policydb_load_isids(&newpolicy->policydb, &newpolicy->sidtab);
if (rc) {
- kfree(newsidtab);
- goto out;
+ pr_err("SELinux: unable to load the initial SIDs\n");
+ goto err;
}
- newpolicydb->len = len;
- /* If switching between different policy types, log MLS status */
- if (policydb->mls_enabled && !newpolicydb->mls_enabled)
- pr_info("SELinux: Disabling MLS support...\n");
- else if (!policydb->mls_enabled && newpolicydb->mls_enabled)
- pr_info("SELinux: Enabling MLS support...\n");
- rc = policydb_load_isids(newpolicydb, newsidtab);
- if (rc) {
- pr_err("SELinux: unable to load the initial SIDs\n");
- policydb_destroy(newpolicydb);
- kfree(newsidtab);
- goto out;
+ if (!selinux_initialized(state)) {
+ /* First policy load, so no need to preserve state from old policy */
+ selinux_policy_commit(state, newpolicy);
+ return 0;
}
- rc = selinux_set_mapping(newpolicydb, secclass_map, &newmap);
- if (rc)
- goto err;
-
- rc = security_preserve_bools(state, newpolicydb);
+ /* Preserve active boolean values from the old policy */
+ rc = security_preserve_bools(state, &newpolicy->policydb);
if (rc) {
pr_err("SELinux: unable to preserve booleans\n");
goto err;
}
- oldsidtab = state->ss->sidtab;
-
/*
* Convert the internal representations of contexts
* in the new SID table.
+ *
+ * NOTE: We do not need to take the policy read-lock
+ * around the code below because other policy-modifying
+ * operations are already excluded by selinuxfs via
+ * fsi->mutex.
*/
args.state = state;
- args.oldp = policydb;
- args.newp = newpolicydb;
+ args.oldp = &state->ss->policy->policydb;
+ args.newp = &newpolicy->policydb;
convert_params.func = convert_context;
convert_params.args = &args;
- convert_params.target = newsidtab;
+ convert_params.target = &newpolicy->sidtab;
- rc = sidtab_convert(oldsidtab, &convert_params);
+ rc = sidtab_convert(&state->ss->policy->sidtab, &convert_params);
if (rc) {
pr_err("SELinux: unable to convert the internal"
" representation of contexts in the new SID"
@@ -2235,53 +2262,19 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
goto err;
}
- /* Save the old policydb and SID table to free later. */
- memcpy(oldpolicydb, policydb, sizeof(*policydb));
-
- /* Install the new policydb and SID table. */
- write_lock_irq(&state->ss->policy_rwlock);
- memcpy(policydb, newpolicydb, sizeof(*policydb));
- state->ss->sidtab = newsidtab;
- security_load_policycaps(state);
- oldmapping = state->ss->map.mapping;
- state->ss->map.mapping = newmap.mapping;
- state->ss->map.size = newmap.size;
- seqno = ++state->ss->latest_granting;
- write_unlock_irq(&state->ss->policy_rwlock);
-
- /* Free the old policydb and SID table. */
- policydb_destroy(oldpolicydb);
- sidtab_destroy(oldsidtab);
- kfree(oldsidtab);
- kfree(oldmapping);
-
- avc_ss_reset(state->avc, seqno);
- selnl_notify_policyload(seqno);
- selinux_status_update_policyload(state, seqno);
- selinux_netlbl_cache_invalidate();
- selinux_xfrm_notify_policyload();
-
- rc = 0;
- goto out;
-
+ selinux_policy_commit(state, newpolicy);
+ return 0;
err:
- kfree(newmap.mapping);
- sidtab_destroy(newsidtab);
- kfree(newsidtab);
- policydb_destroy(newpolicydb);
-
-out:
- kfree(oldpolicydb);
+ selinux_policy_free(newpolicy);
return rc;
}
size_t security_policydb_len(struct selinux_state *state)
{
- struct policydb *p = &state->ss->policydb;
size_t len;
read_lock(&state->ss->policy_rwlock);
- len = p->len;
+ len = state->ss->policy->policydb.len;
read_unlock(&state->ss->policy_rwlock);
return len;
@@ -2303,8 +2296,8 @@ int security_port_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
c = policydb->ocontexts[OCON_PORT];
while (c) {
@@ -2348,8 +2341,8 @@ int security_ib_pkey_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
c = policydb->ocontexts[OCON_IBPKEY];
while (c) {
@@ -2394,8 +2387,8 @@ int security_ib_endport_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
c = policydb->ocontexts[OCON_IBENDPORT];
while (c) {
@@ -2439,8 +2432,8 @@ int security_netif_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
c = policydb->ocontexts[OCON_NETIF];
while (c) {
@@ -2502,8 +2495,8 @@ int security_node_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
switch (domain) {
case AF_INET: {
@@ -2602,8 +2595,8 @@ int security_get_user_sids(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
context_init(&usercon);
@@ -2704,8 +2697,8 @@ static inline int __security_genfs_sid(struct selinux_state *state,
u16 orig_sclass,
u32 *sid)
{
- struct policydb *policydb = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *policydb = &state->ss->policy->policydb;
+ struct sidtab *sidtab = &state->ss->policy->sidtab;
int len;
u16 sclass;
struct genfs *genfs;
@@ -2715,7 +2708,7 @@ static inline int __security_genfs_sid(struct selinux_state *state,
while (path[0] == '/' && path[1] == '/')
path++;
- sclass = unmap_class(&state->ss->map, orig_sclass);
+ sclass = unmap_class(&state->ss->policy->map, orig_sclass);
*sid = SECINITSID_UNLABELED;
for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
@@ -2790,8 +2783,8 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
- sidtab = state->ss->sidtab;
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
c = policydb->ocontexts[OCON_FSUSE];
while (c) {
@@ -2841,7 +2834,7 @@ int security_get_bools(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
+ policydb = &state->ss->policy->policydb;
*names = NULL;
*values = NULL;
@@ -2896,7 +2889,7 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
write_lock_irq(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
+ policydb = &state->ss->policy->policydb;
rc = -EFAULT;
lenp = policydb->p_bools.nprim;
@@ -2944,7 +2937,7 @@ int security_get_bool_value(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
- policydb = &state->ss->policydb;
+ policydb = &state->ss->policy->policydb;
rc = -EFAULT;
len = policydb->p_bools.nprim;
@@ -2992,8 +2985,8 @@ out:
int security_sid_mls_copy(struct selinux_state *state,
u32 sid, u32 mls_sid, u32 *new_sid)
{
- struct policydb *policydb = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *context1;
struct context *context2;
struct context newcon;
@@ -3002,7 +2995,7 @@ int security_sid_mls_copy(struct selinux_state *state,
int rc;
rc = 0;
- if (!selinux_initialized(state) || !policydb->mls_enabled) {
+ if (!selinux_initialized(state)) {
*new_sid = sid;
goto out;
}
@@ -3011,6 +3004,14 @@ int security_sid_mls_copy(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
+
+ if (!policydb->mls_enabled) {
+ *new_sid = sid;
+ goto out_unlock;
+ }
+
rc = -EINVAL;
context1 = sidtab_search(sidtab, sid);
if (!context1) {
@@ -3088,8 +3089,8 @@ int security_net_peersid_resolve(struct selinux_state *state,
u32 xfrm_sid,
u32 *peer_sid)
{
- struct policydb *policydb = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *policydb;
+ struct sidtab *sidtab;
int rc;
struct context *nlbl_ctx;
struct context *xfrm_ctx;
@@ -3111,15 +3112,20 @@ int security_net_peersid_resolve(struct selinux_state *state,
return 0;
}
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
+
/*
* We don't need to check initialized here since the only way both
* nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
* security server was initialized and state->initialized was true.
*/
- if (!policydb->mls_enabled)
- return 0;
-
- read_lock(&state->ss->policy_rwlock);
+ if (!policydb->mls_enabled) {
+ rc = 0;
+ goto out;
+ }
rc = -EINVAL;
nlbl_ctx = sidtab_search(sidtab, nlbl_sid);
@@ -3166,7 +3172,7 @@ static int get_classes_callback(void *k, void *d, void *args)
int security_get_classes(struct selinux_state *state,
char ***classes, int *nclasses)
{
- struct policydb *policydb = &state->ss->policydb;
+ struct policydb *policydb;
int rc;
if (!selinux_initialized(state)) {
@@ -3177,6 +3183,8 @@ int security_get_classes(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+
rc = -ENOMEM;
*nclasses = policydb->p_classes.nprim;
*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
@@ -3213,12 +3221,14 @@ static int get_permissions_callback(void *k, void *d, void *args)
int security_get_permissions(struct selinux_state *state,
char *class, char ***perms, int *nperms)
{
- struct policydb *policydb = &state->ss->policydb;
+ struct policydb *policydb;
int rc, i;
struct class_datum *match;
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+
rc = -EINVAL;
match = symtab_search(&policydb->p_classes, class);
if (!match) {
@@ -3259,12 +3269,22 @@ err:
int security_get_reject_unknown(struct selinux_state *state)
{
- return state->ss->policydb.reject_unknown;
+ int value;
+
+ read_lock(&state->ss->policy_rwlock);
+ value = state->ss->policy->policydb.reject_unknown;
+ read_unlock(&state->ss->policy_rwlock);
+ return value;
}
int security_get_allow_unknown(struct selinux_state *state)
{
- return state->ss->policydb.allow_unknown;
+ int value;
+
+ read_lock(&state->ss->policy_rwlock);
+ value = state->ss->policy->policydb.allow_unknown;
+ read_unlock(&state->ss->policy_rwlock);
+ return value;
}
/**
@@ -3280,11 +3300,10 @@ int security_get_allow_unknown(struct selinux_state *state)
int security_policycap_supported(struct selinux_state *state,
unsigned int req_cap)
{
- struct policydb *policydb = &state->ss->policydb;
int rc;
read_lock(&state->ss->policy_rwlock);
- rc = ebitmap_get_bit(&policydb->policycaps, req_cap);
+ rc = ebitmap_get_bit(&state->ss->policy->policydb.policycaps, req_cap);
read_unlock(&state->ss->policy_rwlock);
return rc;
@@ -3308,7 +3327,7 @@ void selinux_audit_rule_free(void *vrule)
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
{
struct selinux_state *state = &selinux_state;
- struct policydb *policydb = &state->ss->policydb;
+ struct policydb *policydb;
struct selinux_audit_rule *tmprule;
struct role_datum *roledatum;
struct type_datum *typedatum;
@@ -3353,6 +3372,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+
tmprule->au_seqno = state->ss->latest_granting;
switch (field) {
@@ -3449,7 +3470,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
goto out;
}
- ctxt = sidtab_search(state->ss->sidtab, sid);
+ ctxt = sidtab_search(&state->ss->policy->sidtab, sid);
if (unlikely(!ctxt)) {
WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
sid);
@@ -3611,8 +3632,8 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
struct netlbl_lsm_secattr *secattr,
u32 *sid)
{
- struct policydb *policydb = &state->ss->policydb;
- struct sidtab *sidtab = state->ss->sidtab;
+ struct policydb *policydb;
+ struct sidtab *sidtab;
int rc;
struct context *ctx;
struct context ctx_new;
@@ -3624,6 +3645,9 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+ sidtab = &state->ss->policy->sidtab;
+
if (secattr->flags & NETLBL_SECATTR_CACHE)
*sid = *(u32 *)secattr->cache->data;
else if (secattr->flags & NETLBL_SECATTR_SECID)
@@ -3680,7 +3704,7 @@ out:
int security_netlbl_sid_to_secattr(struct selinux_state *state,
u32 sid, struct netlbl_lsm_secattr *secattr)
{
- struct policydb *policydb = &state->ss->policydb;
+ struct policydb *policydb;
int rc;
struct context *ctx;
@@ -3689,8 +3713,10 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policy->policydb;
+
rc = -ENOENT;
- ctx = sidtab_search(state->ss->sidtab, sid);
+ ctx = sidtab_search(&state->ss->policy->sidtab, sid);
if (ctx == NULL)
goto out;
@@ -3719,7 +3745,6 @@ out:
int security_read_policy(struct selinux_state *state,
void **data, size_t *len)
{
- struct policydb *policydb = &state->ss->policydb;
int rc;
struct policy_file fp;
@@ -3736,7 +3761,7 @@ int security_read_policy(struct selinux_state *state,
fp.len = *len;
read_lock(&state->ss->policy_rwlock);
- rc = policydb_write(policydb, &fp);
+ rc = policydb_write(&state->ss->policy->policydb, &fp);
read_unlock(&state->ss->policy_rwlock);
if (rc)
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index a06f3d835216..c36933c1c363 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -22,12 +22,16 @@ struct selinux_map {
u16 size; /* array size of mapping */
};
-struct selinux_ss {
- struct sidtab *sidtab;
+struct selinux_policy {
+ struct sidtab sidtab;
struct policydb policydb;
+ struct selinux_map map;
+};
+
+struct selinux_ss {
rwlock_t policy_rwlock;
u32 latest_granting;
- struct selinux_map map;
+ struct selinux_policy *policy;
} __randomize_layout;
void services_compute_xperms_drivers(struct extended_perms *xperms,