From 8156e809b85f54e85d19aa5c0428d7282a0f5d5c Mon Sep 17 00:00:00 2001 From: Chris PeBenito Date: Tue, 7 Aug 2018 20:04:24 -0400 Subject: [PATCH] policyrep: Misc revisions to reduce Python interactions in Cython code. --- setools/policyrep/fscontext.pxi | 2 +- setools/policyrep/mlsrule.pxi | 10 +------ setools/policyrep/netcontext.pxi | 43 +++++++++++++++++++---------- setools/policyrep/rbacrule.pxi | 10 +------ setools/policyrep/role.pxi | 14 ++++++---- setools/policyrep/selinuxpolicy.pxi | 9 +++--- setools/policyrep/terule.pxi | 4 +-- setools/policyrep/typeattr.pxi | 4 +-- setools/policyrep/user.pxi | 13 +++++---- 9 files changed, 56 insertions(+), 53 deletions(-) diff --git a/setools/policyrep/fscontext.pxi b/setools/policyrep/fscontext.pxi index 16c9a0b..895e4f9 100644 --- a/setools/policyrep/fscontext.pxi +++ b/setools/policyrep/fscontext.pxi @@ -61,7 +61,7 @@ cdef class FSUse(Ocontext): return str(self) < str(other) -class GenfsFiletype(int): +cdef class GenfsFiletype(int): """ A genfscon file type. diff --git a/setools/policyrep/mlsrule.pxi b/setools/policyrep/mlsrule.pxi index 0b38eda..b58c38a 100644 --- a/setools/policyrep/mlsrule.pxi +++ b/setools/policyrep/mlsrule.pxi @@ -54,15 +54,7 @@ cdef class MLSRule(PolicyRule): return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default};".format(self) def __hash__(self): - try: - cond = self.conditional - cond_block = self.conditional_block - except RuleNotConditional: - cond = None - cond_block = None - - return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|{1}|{2}".format( - self, cond, cond_block)) + return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|None|None".format(self)) def __lt__(self, other): return str(self) < str(other) diff --git a/setools/policyrep/netcontext.pxi b/setools/policyrep/netcontext.pxi index 1676e63..0652db1 100644 --- a/setools/policyrep/netcontext.pxi +++ b/setools/policyrep/netcontext.pxi @@ -79,7 +79,12 @@ cdef class Nodecon(Ocontext): @staticmethod cdef inline Nodecon factory(SELinuxPolicy policy, sepol.ocontext_t *symbol, ip_version): """Factory function for creating Nodecon objects.""" - cdef Nodecon n = Nodecon.__new__(Nodecon) + cdef: + int CIDR = 0 + int i + uint32_t block + Nodecon n = Nodecon.__new__(Nodecon) + n.policy = policy n.key = symbol n.ip_version = ip_version @@ -96,28 +101,38 @@ cdef class Nodecon(Ocontext): if not n._mask: raise MemoryError - # convert network order to string - if ip_version == NodeconIPVersion.ipv4: - inet_ntop(AF_INET, &symbol.u.node.addr, n._addr, INET6_ADDRSTRLEN) - inet_ntop(AF_INET, &symbol.u.node.mask, n._mask, INET6_ADDRSTRLEN) - else: - inet_ntop(AF_INET6, &symbol.u.node6.addr, n._addr, INET6_ADDRSTRLEN) - inet_ntop(AF_INET6, &symbol.u.node6.mask, n._mask, INET6_ADDRSTRLEN) - # # Build network object # - CIDR = 0 # Python 3.4's IPv6Network constructor does not support # expanded netmasks, only CIDR numbers. Convert netmask # into CIDR. # This is Brian Kernighan's method for counting set bits. # If the netmask happens to be invalid, this will # not detect it. - int_mask = int(ip_address(n._mask)) - while int_mask: - int_mask &= int_mask - 1 - CIDR += 1 + if ip_version == NodeconIPVersion.ipv4: + # convert network order to string + inet_ntop(AF_INET, &symbol.u.node.addr, n._addr, INET6_ADDRSTRLEN) + inet_ntop(AF_INET, &symbol.u.node.mask, n._mask, INET6_ADDRSTRLEN) + + # count bits + block = symbol.u.node.mask + while block: + block &= block - 1 + CIDR += 1 + + else: # NodeconIPVersion.ipv6 + # convert network order to string + inet_ntop(AF_INET6, &symbol.u.node6.addr, n._addr, INET6_ADDRSTRLEN) + inet_ntop(AF_INET6, &symbol.u.node6.mask, n._mask, INET6_ADDRSTRLEN) + + # count bits + for i in range(4): + block = symbol.u.node6.mask[i] + while block: + block &= block - 1 + CIDR += 1 + net_with_mask = "{0}/{1}".format(n._addr, CIDR) try: diff --git a/setools/policyrep/rbacrule.pxi b/setools/policyrep/rbacrule.pxi index 5596e32..5cb7cda 100644 --- a/setools/policyrep/rbacrule.pxi +++ b/setools/policyrep/rbacrule.pxi @@ -112,15 +112,7 @@ cdef class RoleTransition(PolicyRule): return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default};".format(self) def __hash__(self): - try: - cond = self.conditional - cond_block = self.conditional_block - except RuleNotConditional: - cond = None - cond_block = None - - return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|{1}|{2}".format( - self, cond, cond_block)) + return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|None|None".format(self)) def __lt__(self, other): return str(self) < str(other) diff --git a/setools/policyrep/role.pxi b/setools/policyrep/role.pxi index feff22f..122c3c7 100644 --- a/setools/policyrep/role.pxi +++ b/setools/policyrep/role.pxi @@ -61,13 +61,15 @@ cdef class Role(PolicySymbol): return iter(self._types) def statement(self): - types = list(str(t) for t in self.types()) + cdef size_t count + types = list(str(t) for t in self._types) + count = len(types) stmt = "role {0}".format(self) - if types: - if (len(types) > 1): - stmt += " types {{ {0} }}".format(' '.join(types)) - else: - stmt += " types {0}".format(types[0]) + if count == 1: + stmt += " types {0}".format(types[0]) + else: + stmt += " types {{ {0} }}".format(' '.join(types)) + stmt += ";" return stmt diff --git a/setools/policyrep/selinuxpolicy.pxi b/setools/policyrep/selinuxpolicy.pxi index 1ab13d9..0c101ea 100644 --- a/setools/policyrep/selinuxpolicy.pxi +++ b/setools/policyrep/selinuxpolicy.pxi @@ -51,12 +51,15 @@ cdef class SELinuxPolicy: object constraint_counts object terule_counts - def __init__(self, policyfile=None): + def __cinit__(self, policyfile=None): """ Parameter: policyfile Path to a policy to open. """ + self.handle = NULL + self.cat_val_to_struct = NULL + self.level_val_to_struct = NULL self.log = logging.getLogger(__name__) if policyfile: @@ -67,10 +70,6 @@ cdef class SELinuxPolicy: except NameError: raise RuntimeError("Loading the running policy requires libselinux Python bindings") - def __cinit__(self): - self.handle = NULL - self.cat_val_to_struct = NULL - self.level_val_to_struct = NULL def __dealloc__(self): PyMem_Free(self.cat_val_to_struct) diff --git a/setools/policyrep/terule.pxi b/setools/policyrep/terule.pxi index 27ad198..360dab5 100644 --- a/setools/policyrep/terule.pxi +++ b/setools/policyrep/terule.pxi @@ -504,7 +504,7 @@ cdef class TERuleIterator(PolicyIterator): i.reset() return i - def _next_bucket(self): + cdef void _next_bucket(self): """Internal method for advancing to the next bucket.""" self.bucket += 1 if self.bucket < self.table.nslot: @@ -512,7 +512,7 @@ cdef class TERuleIterator(PolicyIterator): else: self.node = NULL - def _next_node(self): + cdef void _next_node(self): """Internal method for advancing to the next node.""" if self.node != NULL and self.node.next != NULL: self.node = self.node.next diff --git a/setools/policyrep/typeattr.pxi b/setools/policyrep/typeattr.pxi index 292b709..4e53a30 100644 --- a/setools/policyrep/typeattr.pxi +++ b/setools/policyrep/typeattr.pxi @@ -29,7 +29,7 @@ cdef dict _typeattr_cache = {} # # Type or attribute factory function # -cdef type_or_attr_factory(SELinuxPolicy policy, sepol.type_datum_t *symbol): +cdef inline BaseType 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 @@ -205,7 +205,7 @@ cdef class TypeAttribute(BaseType): # # Hash Table Iterator Classes # -cdef inline type_is_alias(sepol.type_datum_t *datum): +cdef inline bint 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 diff --git a/setools/policyrep/user.pxi b/setools/policyrep/user.pxi index 07805c6..2a6f07d 100644 --- a/setools/policyrep/user.pxi +++ b/setools/policyrep/user.pxi @@ -74,12 +74,15 @@ cdef class User(PolicySymbol): raise MLSDisabled def statement(self): - roles = list(str(r) for r in self.roles) - stmt = "user {0} roles ".format(self.name) - if len(roles) > 1: - stmt += "{{ {0} }}".format(' '.join(roles)) - else: + cdef: + list roles = list(str(r) for r in self.roles) + str stmt = "user {0} roles ".format(self.name) + size_t count = len(roles) + + if count == 1: stmt += roles[0] + else: + stmt += "{{ {0} }}".format(' '.join(roles)) if self._level: stmt += " level {0.mls_level} range {0.mls_range};".format(self)