mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
Merge 60144b23c9 ("Merge tag 'selinux-pr-20210409' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux") into android-mainline
Steps on the way to 5.12-rc7 Signed-off-by Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ia4b9f3dfdd7f6b6a93b5348fe6fc343248b4b0b2
This commit is contained in:
commit
44ef0c2e4b
|
|
@ -109,7 +109,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
|
|||
struct avtab_node *prev, *cur, *newnode;
|
||||
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
|
||||
|
||||
if (!h)
|
||||
if (!h || !h->nslot)
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
|
|
@ -154,7 +154,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
|
|||
struct avtab_node *prev, *cur;
|
||||
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
|
||||
|
||||
if (!h)
|
||||
if (!h || !h->nslot)
|
||||
return NULL;
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
for (prev = NULL, cur = h->htable[hvalue];
|
||||
|
|
@ -184,7 +184,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
|
|||
struct avtab_node *cur;
|
||||
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
|
||||
|
||||
if (!h)
|
||||
if (!h || !h->nslot)
|
||||
return NULL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
|
|
@ -220,7 +220,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
|
|||
struct avtab_node *cur;
|
||||
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
|
||||
|
||||
if (!h)
|
||||
if (!h || !h->nslot)
|
||||
return NULL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
|
|
@ -295,6 +295,7 @@ void avtab_destroy(struct avtab *h)
|
|||
}
|
||||
kvfree(h->htable);
|
||||
h->htable = NULL;
|
||||
h->nel = 0;
|
||||
h->nslot = 0;
|
||||
h->mask = 0;
|
||||
}
|
||||
|
|
@ -303,88 +304,52 @@ void avtab_init(struct avtab *h)
|
|||
{
|
||||
h->htable = NULL;
|
||||
h->nel = 0;
|
||||
h->nslot = 0;
|
||||
h->mask = 0;
|
||||
}
|
||||
|
||||
int avtab_alloc(struct avtab *h, u32 nrules)
|
||||
static int avtab_alloc_common(struct avtab *h, u32 nslot)
|
||||
{
|
||||
u32 mask = 0;
|
||||
u32 shift = 0;
|
||||
u32 work = nrules;
|
||||
u32 nslot = 0;
|
||||
|
||||
if (nrules == 0)
|
||||
goto avtab_alloc_out;
|
||||
|
||||
while (work) {
|
||||
work = work >> 1;
|
||||
shift++;
|
||||
}
|
||||
if (shift > 2)
|
||||
shift = shift - 2;
|
||||
nslot = 1 << shift;
|
||||
if (nslot > MAX_AVTAB_HASH_BUCKETS)
|
||||
nslot = MAX_AVTAB_HASH_BUCKETS;
|
||||
mask = nslot - 1;
|
||||
if (!nslot)
|
||||
return 0;
|
||||
|
||||
h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL);
|
||||
if (!h->htable)
|
||||
return -ENOMEM;
|
||||
|
||||
avtab_alloc_out:
|
||||
h->nel = 0;
|
||||
h->nslot = nslot;
|
||||
h->mask = mask;
|
||||
pr_debug("SELinux: %d avtab hash slots, %d rules.\n",
|
||||
h->nslot, nrules);
|
||||
h->mask = nslot - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avtab_duplicate(struct avtab *new, struct avtab *orig)
|
||||
int avtab_alloc(struct avtab *h, u32 nrules)
|
||||
{
|
||||
int i;
|
||||
struct avtab_node *node, *tmp, *tail;
|
||||
int rc;
|
||||
u32 nslot = 0;
|
||||
|
||||
memset(new, 0, sizeof(*new));
|
||||
|
||||
new->htable = kvcalloc(orig->nslot, sizeof(void *), GFP_KERNEL);
|
||||
if (!new->htable)
|
||||
return -ENOMEM;
|
||||
new->nslot = orig->nslot;
|
||||
new->mask = orig->mask;
|
||||
|
||||
for (i = 0; i < orig->nslot; i++) {
|
||||
tail = NULL;
|
||||
for (node = orig->htable[i]; node; node = node->next) {
|
||||
tmp = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL);
|
||||
if (!tmp)
|
||||
goto error;
|
||||
tmp->key = node->key;
|
||||
if (tmp->key.specified & AVTAB_XPERMS) {
|
||||
tmp->datum.u.xperms =
|
||||
kmem_cache_zalloc(avtab_xperms_cachep,
|
||||
GFP_KERNEL);
|
||||
if (!tmp->datum.u.xperms) {
|
||||
kmem_cache_free(avtab_node_cachep, tmp);
|
||||
goto error;
|
||||
}
|
||||
tmp->datum.u.xperms = node->datum.u.xperms;
|
||||
} else
|
||||
tmp->datum.u.data = node->datum.u.data;
|
||||
|
||||
if (tail)
|
||||
tail->next = tmp;
|
||||
else
|
||||
new->htable[i] = tmp;
|
||||
|
||||
tail = tmp;
|
||||
new->nel++;
|
||||
if (nrules != 0) {
|
||||
u32 shift = 1;
|
||||
u32 work = nrules >> 3;
|
||||
while (work) {
|
||||
work >>= 1;
|
||||
shift++;
|
||||
}
|
||||
nslot = 1 << shift;
|
||||
if (nslot > MAX_AVTAB_HASH_BUCKETS)
|
||||
nslot = MAX_AVTAB_HASH_BUCKETS;
|
||||
|
||||
rc = avtab_alloc_common(h, nslot);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("SELinux: %d avtab hash slots, %d rules.\n", nslot, nrules);
|
||||
return 0;
|
||||
error:
|
||||
avtab_destroy(new);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig)
|
||||
{
|
||||
return avtab_alloc_common(new, orig->nslot);
|
||||
}
|
||||
|
||||
void avtab_hash_eval(struct avtab *h, char *tag)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ struct avtab {
|
|||
|
||||
void avtab_init(struct avtab *h);
|
||||
int avtab_alloc(struct avtab *, u32);
|
||||
int avtab_duplicate(struct avtab *new, struct avtab *orig);
|
||||
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
|
||||
struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
|
||||
void avtab_destroy(struct avtab *h);
|
||||
void avtab_hash_eval(struct avtab *h, char *tag);
|
||||
|
|
|
|||
|
|
@ -605,7 +605,6 @@ static int cond_dup_av_list(struct cond_av_list *new,
|
|||
struct cond_av_list *orig,
|
||||
struct avtab *avtab)
|
||||
{
|
||||
struct avtab_node *avnode;
|
||||
u32 i;
|
||||
|
||||
memset(new, 0, sizeof(*new));
|
||||
|
|
@ -615,10 +614,11 @@ static int cond_dup_av_list(struct cond_av_list *new,
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < orig->len; i++) {
|
||||
avnode = avtab_search_node(avtab, &orig->nodes[i]->key);
|
||||
if (WARN_ON(!avnode))
|
||||
return -EINVAL;
|
||||
new->nodes[i] = avnode;
|
||||
new->nodes[i] = avtab_insert_nonunique(avtab,
|
||||
&orig->nodes[i]->key,
|
||||
&orig->nodes[i]->datum);
|
||||
if (!new->nodes[i])
|
||||
return -ENOMEM;
|
||||
new->len++;
|
||||
}
|
||||
|
||||
|
|
@ -630,7 +630,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp,
|
|||
{
|
||||
int rc, i, j;
|
||||
|
||||
rc = avtab_duplicate(&newp->te_cond_avtab, &origp->te_cond_avtab);
|
||||
rc = avtab_alloc_dup(&newp->te_cond_avtab, &origp->te_cond_avtab);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1552,6 +1552,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
|
|||
if (!str)
|
||||
goto out;
|
||||
}
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -1565,6 +1566,15 @@ static int security_context_to_sid_core(struct selinux_state *state,
|
|||
} else if (rc)
|
||||
goto out_unlock;
|
||||
rc = sidtab_context_to_sid(sidtab, &context, sid);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
if (context.str) {
|
||||
str = context.str;
|
||||
context.str = NULL;
|
||||
}
|
||||
context_destroy(&context);
|
||||
goto retry;
|
||||
}
|
||||
context_destroy(&context);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
|
@ -1714,7 +1724,7 @@ static int security_compute_sid(struct selinux_state *state,
|
|||
struct selinux_policy *policy;
|
||||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
struct class_datum *cladatum = NULL;
|
||||
struct class_datum *cladatum;
|
||||
struct context *scontext, *tcontext, newcontext;
|
||||
struct sidtab_entry *sentry, *tentry;
|
||||
struct avtab_key avkey;
|
||||
|
|
@ -1736,6 +1746,8 @@ static int security_compute_sid(struct selinux_state *state,
|
|||
goto out;
|
||||
}
|
||||
|
||||
retry:
|
||||
cladatum = NULL;
|
||||
context_init(&newcontext);
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
@ -1880,6 +1892,11 @@ static int security_compute_sid(struct selinux_state *state,
|
|||
}
|
||||
/* Obtain the sid for the context. */
|
||||
rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
context_destroy(&newcontext);
|
||||
goto retry;
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
context_destroy(&newcontext);
|
||||
|
|
@ -2195,6 +2212,7 @@ void selinux_policy_commit(struct selinux_state *state,
|
|||
struct selinux_load_state *load_state)
|
||||
{
|
||||
struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
|
||||
unsigned long flags;
|
||||
u32 seqno;
|
||||
|
||||
oldpolicy = rcu_dereference_protected(state->policy,
|
||||
|
|
@ -2216,7 +2234,13 @@ void selinux_policy_commit(struct selinux_state *state,
|
|||
seqno = newpolicy->latest_granting;
|
||||
|
||||
/* Install the new policy. */
|
||||
rcu_assign_pointer(state->policy, newpolicy);
|
||||
if (oldpolicy) {
|
||||
sidtab_freeze_begin(oldpolicy->sidtab, &flags);
|
||||
rcu_assign_pointer(state->policy, newpolicy);
|
||||
sidtab_freeze_end(oldpolicy->sidtab, &flags);
|
||||
} else {
|
||||
rcu_assign_pointer(state->policy, newpolicy);
|
||||
}
|
||||
|
||||
/* Load the policycaps from the new policy */
|
||||
security_load_policycaps(state, newpolicy);
|
||||
|
|
@ -2360,13 +2384,15 @@ int security_port_sid(struct selinux_state *state,
|
|||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
struct ocontext *c;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if (!selinux_initialized(state)) {
|
||||
*out_sid = SECINITSID_PORT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2385,6 +2411,10 @@ int security_port_sid(struct selinux_state *state,
|
|||
if (!c->sid[0]) {
|
||||
rc = sidtab_context_to_sid(sidtab, &c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2411,13 +2441,15 @@ int security_ib_pkey_sid(struct selinux_state *state,
|
|||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
struct ocontext *c;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if (!selinux_initialized(state)) {
|
||||
*out_sid = SECINITSID_UNLABELED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2438,6 +2470,10 @@ int security_ib_pkey_sid(struct selinux_state *state,
|
|||
rc = sidtab_context_to_sid(sidtab,
|
||||
&c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2463,13 +2499,15 @@ int security_ib_endport_sid(struct selinux_state *state,
|
|||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
struct ocontext *c;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if (!selinux_initialized(state)) {
|
||||
*out_sid = SECINITSID_UNLABELED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2490,6 +2528,10 @@ int security_ib_endport_sid(struct selinux_state *state,
|
|||
if (!c->sid[0]) {
|
||||
rc = sidtab_context_to_sid(sidtab, &c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2513,7 +2555,7 @@ int security_netif_sid(struct selinux_state *state,
|
|||
struct selinux_policy *policy;
|
||||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct ocontext *c;
|
||||
|
||||
if (!selinux_initialized(state)) {
|
||||
|
|
@ -2521,6 +2563,8 @@ int security_netif_sid(struct selinux_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2537,10 +2581,18 @@ int security_netif_sid(struct selinux_state *state,
|
|||
if (!c->sid[0] || !c->sid[1]) {
|
||||
rc = sidtab_context_to_sid(sidtab, &c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = sidtab_context_to_sid(sidtab, &c->context[1],
|
||||
&c->sid[1]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2590,6 +2642,7 @@ int security_node_sid(struct selinux_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2638,6 +2691,10 @@ int security_node_sid(struct selinux_state *state,
|
|||
rc = sidtab_context_to_sid(sidtab,
|
||||
&c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2679,18 +2736,24 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
struct sidtab *sidtab;
|
||||
struct context *fromcon, usercon;
|
||||
u32 *mysids = NULL, *mysids2, sid;
|
||||
u32 mynel = 0, maxnel = SIDS_NEL;
|
||||
u32 i, j, mynel, maxnel = SIDS_NEL;
|
||||
struct user_datum *user;
|
||||
struct role_datum *role;
|
||||
struct ebitmap_node *rnode, *tnode;
|
||||
int rc = 0, i, j;
|
||||
int rc;
|
||||
|
||||
*sids = NULL;
|
||||
*nel = 0;
|
||||
|
||||
if (!selinux_initialized(state))
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL);
|
||||
if (!mysids)
|
||||
return -ENOMEM;
|
||||
|
||||
retry:
|
||||
mynel = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2710,11 +2773,6 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
|
||||
usercon.user = user->value;
|
||||
|
||||
rc = -ENOMEM;
|
||||
mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
|
||||
if (!mysids)
|
||||
goto out_unlock;
|
||||
|
||||
ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
|
||||
role = policydb->role_val_to_struct[i];
|
||||
usercon.role = i + 1;
|
||||
|
|
@ -2726,6 +2784,10 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
continue;
|
||||
|
||||
rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
if (mynel < maxnel) {
|
||||
|
|
@ -2748,14 +2810,14 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
rcu_read_unlock();
|
||||
if (rc || !mynel) {
|
||||
kfree(mysids);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = -ENOMEM;
|
||||
mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
|
||||
if (!mysids2) {
|
||||
kfree(mysids);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
for (i = 0, j = 0; i < mynel; i++) {
|
||||
struct av_decision dummy_avd;
|
||||
|
|
@ -2768,12 +2830,10 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
mysids2[j++] = mysids[i];
|
||||
cond_resched();
|
||||
}
|
||||
rc = 0;
|
||||
kfree(mysids);
|
||||
*sids = mysids2;
|
||||
*nel = j;
|
||||
out:
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2786,6 +2846,9 @@ int security_get_user_sids(struct selinux_state *state,
|
|||
* Obtain a SID to use for a file in a filesystem that
|
||||
* cannot support xattr or use a fixed labeling behavior like
|
||||
* transition SIDs or task SIDs.
|
||||
*
|
||||
* WARNING: This function may return -ESTALE, indicating that the caller
|
||||
* must retry the operation after re-acquiring the policy pointer!
|
||||
*/
|
||||
static inline int __security_genfs_sid(struct selinux_policy *policy,
|
||||
const char *fstype,
|
||||
|
|
@ -2864,11 +2927,13 @@ int security_genfs_sid(struct selinux_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
retval = __security_genfs_sid(policy,
|
||||
fstype, path, orig_sclass, sid);
|
||||
rcu_read_unlock();
|
||||
do {
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
retval = __security_genfs_sid(policy, fstype, path,
|
||||
orig_sclass, sid);
|
||||
rcu_read_unlock();
|
||||
} while (retval == -ESTALE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -2891,7 +2956,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
|
|||
struct selinux_policy *policy;
|
||||
struct policydb *policydb;
|
||||
struct sidtab *sidtab;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct ocontext *c;
|
||||
struct superblock_security_struct *sbsec = sb->s_security;
|
||||
const char *fstype = sb->s_type->name;
|
||||
|
|
@ -2902,6 +2967,8 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -2919,6 +2986,10 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
|
|||
if (!c->sid[0]) {
|
||||
rc = sidtab_context_to_sid(sidtab, &c->context[0],
|
||||
&c->sid[0]);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2926,6 +2997,10 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
|
|||
} else {
|
||||
rc = __security_genfs_sid(policy, fstype, "/",
|
||||
SECCLASS_DIR, &sbsec->sid);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc) {
|
||||
sbsec->behavior = SECURITY_FS_USE_NONE;
|
||||
rc = 0;
|
||||
|
|
@ -3135,12 +3210,13 @@ int security_sid_mls_copy(struct selinux_state *state,
|
|||
u32 len;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
if (!selinux_initialized(state)) {
|
||||
*new_sid = sid;
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
context_init(&newcon);
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
@ -3199,10 +3275,14 @@ int security_sid_mls_copy(struct selinux_state *state,
|
|||
}
|
||||
}
|
||||
rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
context_destroy(&newcon);
|
||||
goto retry;
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
context_destroy(&newcon);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -3795,6 +3875,8 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = 0;
|
||||
rcu_read_lock();
|
||||
policy = rcu_dereference(state->policy);
|
||||
policydb = &policy->policydb;
|
||||
|
|
@ -3821,23 +3903,24 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
|
|||
goto out;
|
||||
}
|
||||
rc = -EIDRM;
|
||||
if (!mls_context_isvalid(policydb, &ctx_new))
|
||||
goto out_free;
|
||||
if (!mls_context_isvalid(policydb, &ctx_new)) {
|
||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
|
||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||
if (rc == -ESTALE) {
|
||||
rcu_read_unlock();
|
||||
goto retry;
|
||||
}
|
||||
if (rc)
|
||||
goto out_free;
|
||||
goto out;
|
||||
|
||||
security_netlbl_cache_add(secattr, *sid);
|
||||
|
||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||
} else
|
||||
*sid = SECSID_NULL;
|
||||
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
out_free:
|
||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ int sidtab_init(struct sidtab *s)
|
|||
for (i = 0; i < SECINITSID_NUM; i++)
|
||||
s->isids[i].set = 0;
|
||||
|
||||
s->frozen = false;
|
||||
s->count = 0;
|
||||
s->convert = NULL;
|
||||
hash_init(s->context_to_sid);
|
||||
|
|
@ -281,6 +282,15 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
|
|||
if (*sid)
|
||||
goto out_unlock;
|
||||
|
||||
if (unlikely(s->frozen)) {
|
||||
/*
|
||||
* This sidtab is now frozen - tell the caller to abort and
|
||||
* get the new one.
|
||||
*/
|
||||
rc = -ESTALE;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
count = s->count;
|
||||
convert = s->convert;
|
||||
|
||||
|
|
@ -474,6 +484,17 @@ void sidtab_cancel_convert(struct sidtab *s)
|
|||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
|
||||
void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock)
|
||||
{
|
||||
spin_lock_irqsave(&s->lock, *flags);
|
||||
s->frozen = true;
|
||||
s->convert = NULL;
|
||||
}
|
||||
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock)
|
||||
{
|
||||
spin_unlock_irqrestore(&s->lock, *flags);
|
||||
}
|
||||
|
||||
static void sidtab_destroy_entry(struct sidtab_entry *entry)
|
||||
{
|
||||
context_destroy(&entry->context);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ struct sidtab {
|
|||
u32 count;
|
||||
/* access only under spinlock */
|
||||
struct sidtab_convert_params *convert;
|
||||
bool frozen;
|
||||
spinlock_t lock;
|
||||
|
||||
#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
|
||||
|
|
@ -125,6 +126,9 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params);
|
|||
|
||||
void sidtab_cancel_convert(struct sidtab *s);
|
||||
|
||||
void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock);
|
||||
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock);
|
||||
|
||||
int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid);
|
||||
|
||||
void sidtab_destroy(struct sidtab *s);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user