policyrep: Convert type and typeattrs to direct sepol structure access.

Add iterators.
This commit is contained in:
Chris PeBenito 2018-02-11 11:21:35 -05:00
parent 9eba422499
commit c45205c5b0
14 changed files with 326 additions and 827 deletions

View File

@ -1,95 +0,0 @@
/**
* @file
* Defines the public interface for searching and iterating over the permissive types.
*
* @author Steve Lawrence slawrence@tresys.com
*
* Copyright (C) 2006-2007 Tresys Technology, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <qpol/iterator.h>
#include <qpol/policy.h>
#include <qpol/permissive_query.h>
#include <sepol/policydb/policydb.h>
#include "qpol_internal.h"
#include "iterator_internal.h"
int qpol_permissive_get_name(const qpol_policy_t *policy, const qpol_permissive_t * datum, const char **name)
{
type_datum_t *internal_datum = NULL;
policydb_t *db = NULL;
if (policy == NULL || datum == NULL || name == NULL) {
if (name != NULL)
*name = NULL;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
internal_datum = (type_datum_t *)datum;
*name = db->p_type_val_to_name[internal_datum->s.value - 1];
return STATUS_SUCCESS;
}
int qpol_policy_get_permissive_iter(const qpol_policy_t *policy, qpol_iterator_t **iter)
{
int error = 0;
policydb_t *db;
ebitmap_state_t *state = NULL;
if (iter) {
*iter = NULL;
}
if (policy == NULL || iter == NULL) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
state = calloc(1, sizeof(ebitmap_state_t));
if (state == NULL) {
error = errno;
ERR(policy, "%s", strerror(ENOMEM));
errno = error;
return STATUS_ERR;
}
state->bmap = &(db->permissive_map);
state->cur = state->bmap->node ? state->bmap->node->startbit : 0;
if (qpol_iterator_create(policy, state, ebitmap_state_get_cur_permissive,
ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, iter)) {
free(state);
return STATUS_ERR;
}
if (state->bmap->node && !ebitmap_get_bit(state->bmap, state->cur))
ebitmap_state_next(*iter);
return STATUS_SUCCESS;
}

View File

@ -55,11 +55,12 @@ struct extend_bogus_alias_struct
static int extend_find_bogus_alias(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *args)
{
struct extend_bogus_alias_struct *e = (struct extend_bogus_alias_struct *)args;
/* within libqpol, qpol_type_t is the same a libsepol's type_datum_t */
qpol_type_t *qtype = (qpol_type_t *) datum;
type_datum_t *type = (type_datum_t *) datum;
unsigned char isalias;
qpol_type_get_isalias(e->q, qtype, &isalias);
unsigned char isalias = 0;
if ((type->primary == 0 && type->flavor == TYPE_TYPE) || type->flavor == TYPE_ALIAS)
isalias = 1;
return isalias && type->s.value == 0;
}
@ -97,11 +98,9 @@ static int qpol_policy_remove_bogus_aliases(qpol_policy_t * policy)
struct extend_bogus_alias_struct e = { policy, 0 };
hashtab_map_remove_on_error(db->p_types.table, extend_find_bogus_alias, extend_remove_bogus_alias, &e);
#ifdef SETOOLS_DEBUG
if (e.num_bogus_aliases > 0) {
WARN(policy, "%s", "This policy contained disabled aliases; they have been removed.");
}
#endif
return 0;
}
@ -518,9 +517,6 @@ int policy_extend(qpol_policy_t * policy)
goto err;
}
if (policy->options & QPOL_POLICY_OPTION_NO_RULES)
return STATUS_SUCCESS;
retv = qpol_policy_add_cond_rule_traceback(policy);
if (retv) {
error = errno;

View File

@ -1,468 +0,0 @@
/**
* @file
* Implementation of the interface for searching and iterating over types.
*
* @author Jeremy A. Mowery jmowery@tresys.com
* @author Jason Tang jtang@tresys.com
*
* Copyright (C) 2006-2008 Tresys Technology, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <qpol/iterator.h>
#include <qpol/policy.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/expand.h>
#include "iterator_internal.h"
#include <qpol/type_query.h>
#include "qpol_internal.h"
int qpol_policy_get_type_by_name(const qpol_policy_t * policy, const char *name, const qpol_type_t ** datum)
{
hashtab_datum_t internal_datum;
policydb_t *db;
if (policy == NULL || name == NULL || datum == NULL) {
if (datum != NULL)
*datum = NULL;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
internal_datum = hashtab_search(db->p_types.table, (hashtab_key_t)name);
if (internal_datum == NULL) {
*datum = NULL;
ERR(policy, "could not find datum for type %s", name);
errno = ENOENT;
return STATUS_ERR;
}
*datum = (qpol_type_t *) internal_datum;
return STATUS_SUCCESS;
}
int qpol_policy_get_type_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
{
policydb_t *db;
int error = 0;
hash_state_t *hs = NULL;
if (policy == NULL || iter == NULL) {
if (iter != NULL)
*iter = NULL;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
hs = calloc(1, sizeof(hash_state_t));
if (hs == NULL) {
error = errno;
ERR(policy, "%s", strerror(ENOMEM));
errno = error;
return STATUS_ERR;
}
hs->table = &db->p_types.table;
hs->node = (*(hs->table))->htable[0];
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur,
hash_state_next, hash_state_end, hash_state_size, free, iter)) {
free(hs);
return STATUS_ERR;
}
if (hs->node == NULL)
hash_state_next(*iter);
return STATUS_SUCCESS;
}
int qpol_type_get_value(const qpol_policy_t * policy, const qpol_type_t * datum, uint32_t * value)
{
type_datum_t *internal_datum;
if (policy == NULL || datum == NULL || value == NULL) {
if (value != NULL)
*value = 0;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
internal_datum = (type_datum_t *) datum;
if (internal_datum->flavor == TYPE_ALIAS) {
/* aliases that came from modules should use the value
* referenced to by that alias */
*value = internal_datum->primary;
} else {
*value = internal_datum->s.value;
}
return STATUS_SUCCESS;
}
/**
* Determine if a type_datum_t is an alias or a non-alias (primary
* type or an attribute). For aliases declared in base policies, they
* will have no primary value and a flavor of TYPE_TYPE. For aliases
* declared in modules, they have a flavor of TYPE_ALIAS; their
* primary value points to the new /linked/ type's value.
*
* @param datum Type datum to check.
*
* @return 1 if the datum is an alias, 0 if not.
*/
static int is_type_really_an_alias(const type_datum_t * datum)
{
if (datum->primary == 0 && datum->flavor == TYPE_TYPE) {
return 1;
}
if (datum->flavor == TYPE_ALIAS) {
return 1;
}
return 0;
}
int qpol_type_get_isalias(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *isalias)
{
type_datum_t *internal_datum;
if (policy == NULL || datum == NULL || isalias == NULL) {
if (isalias != NULL)
*isalias = 0;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
internal_datum = (type_datum_t *) datum;
*isalias = is_type_really_an_alias(internal_datum);
return STATUS_SUCCESS;
}
int qpol_type_get_isattr(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *isattr)
{
type_datum_t *internal_datum;
if (policy == NULL || datum == NULL || isattr == NULL) {
if (isattr != NULL)
*isattr = 0;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
internal_datum = (type_datum_t *) datum;
*isattr = (internal_datum->flavor == TYPE_ATTRIB ? 1 : 0);
return STATUS_SUCCESS;
}
int qpol_type_get_ispermissive(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *ispermissive)
{
if (policy == NULL || datum == NULL || ispermissive == NULL) {
if (ispermissive != NULL)
*ispermissive = 0;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
#ifdef HAVE_SEPOL_PERMISSIVE_TYPES
/* checking internal_datum->flags for permissive won't work,
because the type could be an alias. so instead, look up
its value within the permissive map */
uint32_t value;
if (qpol_type_get_value(policy, datum, &value) < 0) {
return STATUS_ERR;
}
policydb_t *p = &policy->p->p;
/* note that unlike other bitmaps, this one does not subtract
1 in the bitmap */
*ispermissive = ebitmap_get_bit(&p->permissive_map, value);
#else
*ispermissive = 0;
#endif
return STATUS_SUCCESS;
}
int qpol_type_get_type_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** types)
{
type_datum_t *internal_datum = NULL;
ebitmap_state_t *es = NULL;
int error = 0;
if (types != NULL)
*types = NULL;
if (policy == NULL || datum == NULL || types == NULL) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
internal_datum = (type_datum_t *) datum;
if (internal_datum->flavor != TYPE_ATTRIB) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_NODATA;
}
es = calloc(1, sizeof(ebitmap_state_t));
if (es == NULL) {
error = errno;
ERR(policy, "%s", strerror(ENOMEM));
errno = error;
return STATUS_ERR;
}
es->bmap = &(internal_datum->types);
es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_type,
ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, types)) {
free(es);
return STATUS_ERR;
}
if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
ebitmap_state_next(*types);
return STATUS_SUCCESS;
}
int qpol_type_get_attr_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** attrs)
{
type_datum_t *internal_datum = NULL;
ebitmap_state_t *es = NULL;
int error = 0;
if (attrs != NULL)
*attrs = NULL;
if (policy == NULL || datum == NULL || attrs == NULL) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
internal_datum = (type_datum_t *) datum;
if (internal_datum->flavor == TYPE_ATTRIB) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_NODATA;
}
es = calloc(1, sizeof(ebitmap_state_t));
if (es == NULL) {
error = errno;
ERR(policy, "%s", strerror(ENOMEM));
errno = error;
return STATUS_ERR;
}
es->bmap = &(internal_datum->types);
es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_type,
ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, attrs)) {
free(es);
return STATUS_ERR;
}
if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
ebitmap_state_next(*attrs);
return STATUS_SUCCESS;
}
int qpol_type_get_name(const qpol_policy_t * policy, const qpol_type_t * datum, const char **name)
{
type_datum_t *internal_datum = NULL;
policydb_t *db = NULL;
if (policy == NULL || datum == NULL || name == NULL) {
if (name != NULL)
*name = NULL;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
internal_datum = (type_datum_t *) datum;
*name = db->p_type_val_to_name[internal_datum->s.value - 1];
return STATUS_SUCCESS;
}
typedef struct type_alias_hash_state
{
unsigned int bucket;
hashtab_node_t *node;
hashtab_t *table;
uint32_t val;
} type_alias_hash_state_t;
/**
* For aliases that came from the base policy, their primary type is
* referenced by s.value. For aliases that came from modules, their
* primary type is referenced by the primary field.
*
* @param datum Alias whose primary value to get.
*
* @return The primary type's identifier.
*/
static uint32_t get_alias_primary(const type_datum_t * datum)
{
if (datum->flavor == TYPE_TYPE) {
return datum->s.value;
} else {
return datum->primary;
}
}
static int hash_state_next_type_alias(qpol_iterator_t * iter)
{
type_alias_hash_state_t *hs = NULL;
type_datum_t *datum = NULL;
if (iter == NULL) {
errno = EINVAL;
return STATUS_ERR;
}
hs = (type_alias_hash_state_t *) qpol_iterator_state(iter);
if (hs == NULL) {
errno = EINVAL;
return STATUS_ERR;
}
if (hs->bucket >= (*(hs->table))->size) {
errno = ERANGE;
return STATUS_ERR;
}
do {
hash_state_next(iter);
datum = hs->node ? (type_datum_t *) hs->node->datum : NULL;
} while (datum != NULL && (hs->val != get_alias_primary(datum) || !is_type_really_an_alias(datum)));
return STATUS_SUCCESS;
}
static void *hash_state_get_cur_alias(const qpol_iterator_t * iter)
{
type_alias_hash_state_t *hs = NULL;
if (iter == NULL) {
errno = EINVAL;
return NULL;
}
hs = (type_alias_hash_state_t *) qpol_iterator_state(iter);
if (hs == NULL) {
errno = EINVAL;
return NULL;
}
if (hs->bucket >= (*(hs->table))->size) {
errno = ERANGE;
return NULL;
}
return hs->node->key;
}
static size_t hash_alias_state_size(const qpol_iterator_t * iter)
{
type_alias_hash_state_t *hs = NULL;
type_datum_t *tmp_datum;
hashtab_node_t *tmp_node;
uint32_t tmp_bucket = 0;
size_t count = 0;
if (iter == NULL || qpol_iterator_state(iter) == NULL) {
errno = EINVAL;
return 0;
}
hs = (type_alias_hash_state_t *) qpol_iterator_state(iter);
for (tmp_bucket = 0; tmp_bucket < (*(hs->table))->size; tmp_bucket++) {
for (tmp_node = (*(hs->table))->htable[tmp_bucket]; tmp_node; tmp_node = tmp_node->next) {
tmp_datum = tmp_node ? tmp_node->datum : NULL;
if (tmp_datum) {
if (hs->val == get_alias_primary(tmp_datum) && is_type_really_an_alias(tmp_datum)) {
count++;
}
}
}
}
return count;
}
int qpol_type_get_alias_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** aliases)
{
type_datum_t *internal_datum = NULL;
policydb_t *db = NULL;
int error = 0;
type_alias_hash_state_t *hs = NULL;
if (policy == NULL || datum == NULL || aliases == NULL) {
if (aliases != NULL)
*aliases = NULL;
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
internal_datum = (type_datum_t *) datum;
hs = calloc(1, sizeof(type_alias_hash_state_t));
if (hs == NULL) {
error = errno;
ERR(policy, "%s", strerror(ENOMEM));
errno = error;
return STATUS_ERR;
}
hs->table = &db->p_types.table;
hs->node = (*(hs->table))->htable[0];
hs->val = get_alias_primary(internal_datum);
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur_alias,
hash_state_next_type_alias, hash_state_end, hash_alias_state_size, free, aliases)) {
free(hs);
return STATUS_ERR;
}
if (hs->node == NULL || hs->val != get_alias_primary((type_datum_t *) (hs->node->datum)) ||
!is_type_really_an_alias((type_datum_t *) hs->node->datum))
hash_state_next_type_alias(*aliases);
return STATUS_SUCCESS;
}

View File

@ -84,7 +84,7 @@ cdef class Bounds(PolicySymbol):
if qpol_typebounds_get_parent_name(self.policy.handle, self.handle, &name):
raise RuntimeError("Could not get parent name")
return type_factory_lookup(self.policy, name, False)
return self.policy.lookup_type(name)
@property
def child(self):
@ -93,4 +93,4 @@ cdef class Bounds(PolicySymbol):
if qpol_typebounds_get_child_name(self.policy.handle, self.handle, &name):
raise RuntimeError("Could not get child name")
return type_factory_lookup(self.policy, name, False)
return self.policy.lookup_type(name)

View File

@ -450,7 +450,7 @@ cdef class ConstraintExprNode(PolicySymbol):
if self.symbol_type in self._role_syms:
names = frozenset(role_factory_lookup(self.policy, r) for r in name_iterator)
elif self.symbol_type in self._type_syms:
names = frozenset(type_or_attr_factory_lookup(self.policy, t, False)
names = frozenset(self.policy.lookup_type_or_attr(t)
for t in name_iterator)
else:
names = frozenset(user_factory_lookup(self.policy, u) for u in name_iterator)

View File

@ -63,11 +63,8 @@ cdef class Context(PolicySymbol):
@property
def type_(self):
"""The type portion of the context."""
cdef const qpol_type_t *t
if qpol_context_get_type(self.policy.handle, self.handle, &t):
raise RuntimeError("Could not get type from context")
return type_factory(self.policy, t, False)
cdef sepol.type_datum_t *t = self.policy.handle.p.p.type_val_to_struct[self.handle.type - 1]
return Type.factory(self.policy, t)
@property
def range_(self):

View File

@ -314,16 +314,6 @@ cdef extern from "include/qpol/terule_query.h":
cdef extern from "include/qpol/type_query.h":
ctypedef struct qpol_type_t:
pass
int qpol_policy_get_type_by_name(const qpol_policy_t * policy, const char *name, const qpol_type_t ** datum)
int qpol_policy_get_type_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
int qpol_type_get_value(const qpol_policy_t * policy, const qpol_type_t * datum, uint32_t * value)
int qpol_type_get_isalias(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *isalias)
int qpol_type_get_isattr(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *isattr)
int qpol_type_get_ispermissive(const qpol_policy_t * policy, const qpol_type_t * datum, unsigned char *ispermissive)
int qpol_type_get_type_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** types)
int qpol_type_get_attr_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** attrs)
int qpol_type_get_name(const qpol_policy_t * policy, const qpol_type_t * datum, const char **name)
int qpol_type_get_alias_iter(const qpol_policy_t * policy, const qpol_type_t * datum, qpol_iterator_t ** aliases)
cdef extern from "include/qpol/user_query.h":
ctypedef struct qpol_user_t:

View File

@ -83,26 +83,12 @@ cdef class MLSRule(PolicyRule):
@property
def source(self):
"""The rule's source type/attribute."""
cdef const qpol_type_t *t
if qpol_range_trans_get_source_type(self.policy.handle, self.handle, &t):
ex = LowLevelPolicyError("Error reading source type/attr for range_transition rule: {}".
format(strerror(errno)))
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, self.policy.handle.p.p.type_val_to_struct[self.handle.source_type - 1])
@property
def target(self):
"""The rule's target type/attribute."""
cdef const qpol_type_t *t
if qpol_range_trans_get_target_type(self.policy.handle, self.handle, &t):
ex = LowLevelPolicyError("Error reading target type/attr for range_transition rule: {}".
format(strerror(errno)))
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, self.policy.handle.p.p.type_val_to_struct[self.handle.target_type - 1])
@property
def tclass(self):

View File

@ -183,7 +183,7 @@ cdef class RoleTransition(PolicyRule):
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, <sepol.type_datum_t *>t)
@property
def tclass(self):

View File

@ -395,7 +395,7 @@ cdef class SELinuxPolicy:
@property
def type_attribute_count(self):
"""The number of (type) attributes."""
return sum(1 for _ in self.typeattributes())
return len(self.typeattributes())
@property
def type_change_count(self):
@ -406,7 +406,7 @@ cdef class SELinuxPolicy:
@property
def type_count(self):
"""The number of types."""
return sum(1 for _ in self.types())
return len(self.types())
@property
def type_member_count(self):
@ -501,15 +501,27 @@ cdef class SELinuxPolicy:
def lookup_type(self, name):
"""Look up a type by name."""
return type_factory_lookup(self, name, True)
for t in self.types():
if t == name:
return t
raise InvalidType("{0} is not a valid type".format(name))
def lookup_type_or_attr(self, name):
"""Look up a type or type attribute by name."""
return type_or_attr_factory_lookup(self, name, True)
for t in chain(self.types(), self.typeattributes()):
if t == name:
return t
raise InvalidType("{0} is not a valid type attribute".format(name))
def lookup_typeattr(self, name):
"""Look up a type attribute by name."""
return attribute_factory_lookup(self, name)
for t in self.typeattributes():
if t == name:
return t
raise InvalidType("{0} is not a valid type attribute".format(name))
def lookup_user(self, name):
"""Look up a user by name."""
@ -572,19 +584,11 @@ cdef class SELinuxPolicy:
def types(self):
"""Iterator over all types."""
cdef qpol_iterator_t *iter
if qpol_policy_get_type_iter(self.handle, &iter):
raise MemoryError
return qpol_iterator_factory(self, iter, type_factory_iter, ValueError)
return TypeHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_TYPES].table)
def typeattributes(self):
"""Iterator over all (type) attributes."""
cdef qpol_iterator_t *iter
if qpol_policy_get_type_iter(self.handle, &iter):
raise MemoryError
return qpol_iterator_factory(self, iter, attribute_factory_iter, ValueError)
return TypeAttributeHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_TYPES].table)
def users(self):
"""Iterator which yields all roles."""

View File

@ -406,8 +406,12 @@ cdef extern from "<sepol/policydb/policydb.h>":
#
# type_set_t
#
cdef int TYPE_TYPE
cdef int TYPE_ATTRIB
cdef int TYPE_ALIAS
cdef int TYPE_STAR
cdef int TYPE_COMP
cdef int TYPE_FLAGS_PERMISSIVE
cdef struct type_set:
ebitmap_t types

View File

@ -240,7 +240,7 @@ cdef class AVRule(PolicyRule):
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, <sepol.type_datum_t *> t)
@property
def target(self):
@ -252,7 +252,7 @@ cdef class AVRule(PolicyRule):
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, <sepol.type_datum_t *> t)
@property
def tclass(self):
@ -526,7 +526,7 @@ cdef class TERule(PolicyRule):
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, <sepol.type_datum_t *>t)
@property
def target(self):
@ -538,7 +538,7 @@ cdef class TERule(PolicyRule):
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, <sepol.type_datum_t *>t)
@property
def tclass(self):
@ -560,7 +560,7 @@ cdef class TERule(PolicyRule):
ex.errno = errno
raise ex
return type_factory(self.policy, t, False)
return Type.factory(self.policy, <sepol.type_datum_t *>t)
@property
def filename(self):
@ -691,26 +691,12 @@ cdef class FileNameTERule(PolicyRule):
@property
def source(self):
"""The rule's source type/attribute."""
cdef const qpol_type_t *t
if qpol_filename_trans_get_source_type(self.policy.handle, self.handle, &t):
ex = LowLevelPolicyError("Error reading source type/attr for TE rule: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, self.policy.handle.p.p.type_val_to_struct[self.handle.stype - 1])
@property
def target(self):
"""The rule's target type/attribute."""
cdef const qpol_type_t *t
if qpol_filename_trans_get_target_type(self.policy.handle, self.handle, &t):
ex = LowLevelPolicyError("Error reading target type/attr for TE rule: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
return type_or_attr_factory(self.policy, t)
return type_or_attr_factory(self.policy, self.policy.handle.p.p.type_val_to_struct[self.handle.ttype - 1])
@property
def tclass(self):
@ -725,14 +711,15 @@ cdef class FileNameTERule(PolicyRule):
@property
def default(self):
"""The rule's default type."""
cdef const qpol_type_t *t
if qpol_filename_trans_get_default_type(self.policy.handle, self.handle, &t):
ex = LowLevelPolicyError("Error reading default type for TE rule: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
cdef sepol.filename_trans_datum_t *datum
datum = <sepol.filename_trans_datum_t *> hashtab_search(
self.policy.handle.p.p.filename_trans, <sepol.hashtab_key_t> self.handle)
return type_factory(self.policy, t, False)
if datum == NULL:
raise LowLevelPolicyError("Error reading default type for TE rule.")
return Type.factory(self.policy,
<sepol.type_datum_t *> self.policy.handle.p.p.type_val_to_struct[datum.otype - 1])
@property
def filename(self):

View File

@ -17,157 +17,26 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
import warnings
#
# Type factory functions
# Cache objects
#
cdef dict _type_cache = {}
cdef inline Type type_factory_lookup(SELinuxPolicy policy, str name, deref):
"""Factory function variant for constructing Type objects by name."""
cdef const qpol_type_t *symbol
if qpol_policy_get_type_by_name(policy.handle, name.encode(), &symbol):
raise InvalidType("{0} is not a valid type".format(name))
return type_factory(policy, symbol, deref)
cdef inline Type type_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
"""Factory function variant for iterating over Type objects."""
return type_factory(policy, <const qpol_type_t *> symbol.obj, False)
cdef inline Type type_factory(SELinuxPolicy policy, const qpol_type_t *symbol, deref):
"""Factory function for creating Type objects."""
cdef unsigned char isattr
cdef unsigned char isalias
cdef const char *name
if qpol_type_get_isattr(policy.handle, symbol, &isattr):
ex = LowLevelPolicyError("Error determining if type is an attribute: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
if isattr:
if qpol_type_get_name(policy.handle, symbol, &name):
raise ValueError("The specified type is an attribute.")
raise ValueError("{0} is an attribute".format(name))
if qpol_type_get_isalias(policy.handle, symbol, &isalias):
ex = LowLevelPolicyError("Error determining if type is an alias: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
if isalias and not deref:
if qpol_type_get_name(policy.handle, symbol, &name):
raise ValueError("The specified type is an alias.")
raise ValueError("{0} is an alias".format(name))
try:
return _type_cache[<uintptr_t>symbol]
except KeyError:
t = Type()
t.policy = policy
t.handle = symbol
_type_cache[<uintptr_t>symbol] = t
return t
#
# Attribute factory functions
#
cdef dict _typeattr_cache = {}
cdef inline TypeAttribute attribute_factory_lookup(SELinuxPolicy policy, str name):
"""Factory function variant for constructing TypeAttribute objects by name."""
cdef const qpol_type_t *symbol
if qpol_policy_get_type_by_name(policy.handle, name.encode(), &symbol):
raise InvalidType("{0} is not a valid attribute".format(name))
return attribute_factory(policy, symbol)
cdef inline TypeAttribute attribute_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
"""Factory function variant for iterating over TypeAttribute objects."""
return attribute_factory(policy, <const qpol_type_t *> symbol.obj)
cdef inline TypeAttribute attribute_factory(SELinuxPolicy policy, const qpol_type_t *symbol):
"""Factory function for creating TypeAttribute objects."""
cdef unsigned char isattr
cdef const char *name
if qpol_type_get_isattr(policy.handle, symbol, &isattr):
ex = LowLevelPolicyError("Error determining if type is an attribute: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
if not isattr:
if qpol_type_get_name(policy.handle, symbol, &name):
raise ValueError("The symbol is a type.")
raise ValueError("{0} is a type".format(name))
try:
return _typeattr_cache[<uintptr_t>symbol]
except KeyError:
a = TypeAttribute()
a.policy = policy
a.handle = symbol
_typeattr_cache[<uintptr_t>symbol] = a
return a
#
# Type or Attribute factory functions
# Type or attribute factory function
#
cdef inline BaseType type_or_attr_factory_lookup(SELinuxPolicy policy, str name, deref):
"""Factory function variant for constructing Type objects by name."""
cdef const qpol_type_t *symbol
cdef unsigned char isalias
if qpol_policy_get_type_by_name(policy.handle, name.encode(), &symbol):
raise InvalidType("{0} is not a valid type or type attribute".format(name))
if qpol_type_get_isalias(policy.handle, symbol, &isalias):
ex = LowLevelPolicyError("Error determining if type is an alias: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
if isalias and not deref:
raise ValueError("{0} is an alias.".format(name))
return type_or_attr_factory(policy, symbol)
cdef inline BaseType type_or_attr_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
"""Factory function variant for iterating over Type or TypeAttribute objects."""
return type_or_attr_factory(policy, <const qpol_type_t *> symbol.obj)
cdef inline BaseType type_or_attr_factory(SELinuxPolicy policy, const qpol_type_t *symbol):
cdef type_or_attr_factory(SELinuxPolicy policy, sepol.type_datum_t *symbol):
"""Factory function for creating type or attribute objects."""
cdef sepol.type_datum_t *handle
cdef unsigned char i
if qpol_type_get_isattr(policy.handle, symbol, &i):
ex = LowLevelPolicyError("Error determining if type is an attribute: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
if i:
return attribute_factory(policy, symbol)
if symbol.flavor == sepol.TYPE_ATTRIB:
return TypeAttribute.factory(policy, symbol)
else:
return type_factory(policy, symbol, False)
return Type.factory(policy, symbol)
#
@ -177,17 +46,10 @@ cdef class BaseType(PolicySymbol):
"""Type/attribute base class."""
cdef const qpol_type_t *handle
cdef sepol.type_datum_t *handle
def __str__(self):
cdef const char *name
if qpol_type_get_name(self.policy.handle, self.handle, &name):
ex = LowLevelPolicyError("Error reading type name: {}".format(strerror(errno)))
ex.errno = errno
raise ex
return intern(name)
return intern(self.policy.handle.p.p.sym_val_to_name[sepol.SYM_TYPES][self.handle.s.value - 1])
def _eq(self, BaseType other):
"""Low-level equality check (C pointers)."""
@ -214,9 +76,25 @@ cdef class Type(BaseType):
"""A type."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.type_datum_t *symbol):
"""Factory function for creating Type objects."""
if symbol.flavor != sepol.TYPE_TYPE:
raise ValueError("{0} is not a type".format(
policy.handle.p.p.sym_val_to_name[sepol.SYM_TYPES][symbol.s.value - 1]))
try:
return _type_cache[<uintptr_t>symbol]
except KeyError:
t = Type()
t.policy = policy
t.handle = symbol
_type_cache[<uintptr_t>symbol] = t
return t
def __deepcopy__(self, memo):
# shallow copy as all of the members are immutable
newobj = type_factory(self.policy, self.handle, False)
newobj = Type.factory(self.policy, self.handle)
memo[id(self)] = newobj
return newobj
@ -231,19 +109,12 @@ cdef class Type(BaseType):
return <bytes>(<char *>self.handle)
cdef _unpickle(self, bytes handle):
memcpy(&self.handle, <char *>handle, sizeof(qpol_type_t*))
memcpy(&self.handle, <char *>handle, sizeof(sepol.type_datum_t*))
@property
def ispermissive(self):
"""(T/F) the type is permissive."""
cdef unsigned char i
if qpol_type_get_ispermissive(self.policy.handle, self.handle, &i):
ex = LowLevelPolicyError("Error determining if type is permissive: {}".format(
strerror(errno)))
ex.errno = errno
raise ex
return bool(i)
return <bint> ebitmap_get_bit(&self.policy.handle.p.p.permissive_map, self.handle.s.value)
def expand(self):
"""Generator that expands this into its member types."""
@ -251,21 +122,11 @@ cdef class Type(BaseType):
def attributes(self):
"""Generator that yields all attributes for this type."""
cdef qpol_iterator_t *iter
if qpol_type_get_attr_iter(self.policy.handle, self.handle, &iter) < 0:
ex = LowLevelPolicyError("Error reading type attributes: {}".format(strerror(errno)))
ex.errno = errno
raise ex
return qpol_iterator_factory(self.policy, iter, attribute_factory_iter)
return TypeAttributeEbitmapIterator.factory(self.policy, &self.handle.types)
def aliases(self):
"""Generator that yields all aliases for this type."""
cdef qpol_iterator_t *iter
if qpol_type_get_alias_iter(self.policy.handle, self.handle, &iter):
raise MemoryError
return qpol_iterator_factory(self.policy, iter, string_factory_iter)
return TypeAliasHashtabIterator.factory(self.policy, &self.policy.handle.p.p.symtab[sepol.SYM_TYPES].table, self)
def statement(self):
attrs = list(self.attributes())
@ -286,6 +147,22 @@ cdef class TypeAttribute(BaseType):
"""A type attribute."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.type_datum_t *symbol):
"""Factory function for creating TypeAttribute objects."""
if symbol.flavor != sepol.TYPE_ATTRIB:
raise ValueError("{0} is not an attribute".format(
policy.handle.p.p.sym_val_to_name[sepol.SYM_TYPES][symbol.s.value - 1]))
try:
return _typeattr_cache[<uintptr_t>symbol]
except KeyError:
t = TypeAttribute()
t.policy = policy
t.handle = symbol
_typeattr_cache[<uintptr_t>symbol] = t
return t
def __contains__(self, other):
for type_ in self.expand():
if other == type_:
@ -295,11 +172,7 @@ cdef class TypeAttribute(BaseType):
def expand(self):
"""Generator that expands this attribute into its member types."""
cdef qpol_iterator_t *iter
if qpol_type_get_type_iter(self.policy.handle, self.handle, &iter) < 0:
raise MemoryError
return qpol_iterator_factory(self.policy, iter, type_factory_iter)
return TypeEbitmapIterator.factory(self.policy, &self.handle.types)
def attributes(self):
"""Generator that yields all attributes for this type."""
@ -316,3 +189,230 @@ cdef class TypeAttribute(BaseType):
def statement(self):
return "attribute {0};".format(self)
#
# Hash Table Iterator Classes
#
cdef inline type_is_alias(sepol.type_datum_t *datum):
"""Determine if the type datum is an alias."""
return (datum.primary == 0 and datum.flavor == sepol.TYPE_TYPE) \
or datum.flavor == sepol.TYPE_ALIAS
cdef class TypeHashtabIterator(HashtabIterator):
"""Iterate over types in the policy."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
"""Factory function for creating Role iterators."""
i = TypeHashtabIterator()
i.policy = policy
i.table = table
i.reset()
return i
def __next__(self):
cdef sepol.type_datum_t *datum
super().__next__()
datum = <sepol.type_datum_t *> self.curr.datum
while datum.flavor != sepol.TYPE_TYPE or type_is_alias(datum):
super().__next__()
datum = <sepol.type_datum_t *> self.curr.datum
return Type.factory(self.policy, datum)
def __len__(self):
cdef sepol.type_datum_t *datum
cdef sepol.hashtab_node_t *node
cdef uint32_t bucket = 0
cdef size_t count = 0
while bucket < self.table[0].size:
node = self.table[0].htable[bucket]
while node != NULL:
datum = <sepol.type_datum_t *>node.datum if node else NULL
if datum != NULL and datum.flavor == sepol.TYPE_TYPE and not type_is_alias(datum):
count += 1
node = node.next
bucket += 1
return count
def reset(self):
super().reset()
# advance over any attributes or aliases
while (<sepol.type_datum_t *> self.node.datum).flavor != sepol.TYPE_TYPE:
self._next_node()
cdef class TypeAttributeHashtabIterator(HashtabIterator):
"""Iterate over type attributes in the policy."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
"""Factory function for creating Role iterators."""
i = TypeAttributeHashtabIterator()
i.policy = policy
i.table = table
i.reset()
return i
def __next__(self):
super().__next__()
while (<sepol.type_datum_t *> self.curr.datum).flavor != sepol.TYPE_ATTRIB:
super().__next__()
return TypeAttribute.factory(self.policy, <sepol.type_datum_t *> self.curr.datum)
def __len__(self):
cdef sepol.type_datum_t *datum
cdef sepol.hashtab_node_t *node
cdef uint32_t bucket = 0
cdef size_t count = 0
while bucket < self.table[0].size:
node = self.table[0].htable[bucket]
while node != NULL:
datum = <sepol.type_datum_t *>node.datum if node else NULL
if datum != NULL and datum.flavor == sepol.TYPE_ATTRIB:
count += 1
node = node.next
bucket += 1
return count
def reset(self):
super().reset()
# advance over any attributes or aliases
while (<sepol.type_datum_t *> self.node.datum).flavor != sepol.TYPE_ATTRIB:
self._next_node()
cdef class TypeAliasHashtabIterator(HashtabIterator):
"""Iterate over type aliases in the policy."""
cdef uint32_t primary
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table, Type primary):
"""Factory function for creating type alias iterators."""
i = TypeAliasHashtabIterator()
i.policy = policy
i.table = table
i.primary = primary.handle.s.value
i.reset()
return i
def __next__(self):
super().__next__()
datum = <sepol.type_datum_t *> self.curr.datum if self.curr else NULL
while datum != NULL and (not type_is_alias(datum) or datum.s.value != self.primary):
super().__next__()
datum = <sepol.type_datum_t *> self.curr.datum if self.curr else NULL
return intern(self.curr.key)
def __len__(self):
cdef sepol.type_datum_t *datum
cdef sepol.hashtab_node_t *node
cdef uint32_t bucket = 0
cdef size_t count = 0
while bucket < self.table[0].size:
node = self.table[0].htable[bucket]
while node != NULL:
datum = <sepol.type_datum_t *>node.datum if node else NULL
if datum != NULL and self.primary == datum.s.value and type_is_alias(datum):
count += 1
node = node.next
bucket += 1
return count
def reset(self):
super().reset()
cdef sepol.type_datum_t *datum = <sepol.type_datum_t *> self.node.datum if self.node else NULL
# advance over any attributes or aliases
while datum != NULL and (not type_is_alias(datum) and self.primary != datum.s.value):
self._next_node()
if self.node == NULL or self.bucket >= self.table[0].size:
break
datum = <sepol.type_datum_t *> self.node.datum if self.node else NULL
#
# Ebitmap Iterator Classes
#
cdef class TypeEbitmapIterator(EbitmapIterator):
"""Iterate over a type ebitmap."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.ebitmap_t *symbol):
"""Factory function for creating TypeEbitmapIterator."""
i = TypeEbitmapIterator()
i.policy = policy
i.bmap = symbol
i.reset()
return i
@staticmethod
cdef factory_from_set(SELinuxPolicy policy, sepol.type_set_t *symbol):
"""Factory function for creating TypeEbitmapIterator from a type set."""
if symbol.flags:
warnings.warn("* or ~ in the type set; this is not implemented in SETools.")
if symbol.negset.node != NULL:
warnings.warn("Negations in the type set; this is not implemented in SETools.")
return TypeEbitmapIterator.factory(policy, &symbol.types)
def __next__(self):
super().__next__()
return Type.factory(self.policy, self.policy.handle.p.p.type_val_to_struct[self.bit])
cdef class TypeAttributeEbitmapIterator(EbitmapIterator):
"""Iterate over a type attribute ebitmap."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.ebitmap_t *bmap):
"""Factory function for creating TypeAttributeEbitmapIterator."""
i = TypeAttributeEbitmapIterator()
i.policy = policy
i.bmap = bmap
i.reset()
return i
@staticmethod
cdef factory_from_set(SELinuxPolicy policy, sepol.type_set_t *symbol):
"""Factory function for creating TypeAttributeEbitmapIterator from a type set."""
if symbol.flags:
warnings.warn("* or ~ in the type set; this is not implemented in SETools.")
if symbol.negset.node != NULL:
warnings.warn("Negations in the type set; this is not implemented in SETools.")
return TypeAttributeEbitmapIterator.factory(policy, &symbol.types)
def __next__(self):
super().__next__()
return TypeAttribute.factory(self.policy,
self.policy.handle.p.p.type_val_to_struct[self.bit])

View File

@ -76,13 +76,11 @@ ext_py_mods = [Extension('setools.policyrep.libpolicyrep',
'libqpol/ftrule_query.c',
'libqpol/iterator.c',
'libqpol/mlsrule_query.c',
'libqpol/permissive_query.c',
'libqpol/policy.c',
'libqpol/policy_extend.c',
'libqpol/rbacrule_query.c',
'libqpol/role_query.c',
'libqpol/terule_query.c',
'libqpol/type_query.c',
'libqpol/user_query.c'],
include_dirs=include_dirs,
extra_compile_args=['-Werror', '-Wextra',