From aeecacc896988d84b948a79abcc0b6bc6cd3da52 Mon Sep 17 00:00:00 2001 From: Chris PeBenito <pebenito@ieee.org> Date: Sun, 18 Feb 2018 10:07:41 -0500 Subject: [PATCH] Conditional: Convert to direct sepol structure access. Add iterators. --- setools/policyrep/boolcond.pxi | 252 ++++++++++++++-------------- setools/policyrep/libpolicyrep.pyx | 18 -- setools/policyrep/selinuxpolicy.pxi | 6 +- setools/policyrep/terule.pxi | 4 +- setup.py | 1 - 5 files changed, 132 insertions(+), 149 deletions(-) diff --git a/setools/policyrep/boolcond.pxi b/setools/policyrep/boolcond.pxi index ec58baf..3a34d87 100644 --- a/setools/policyrep/boolcond.pxi +++ b/setools/policyrep/boolcond.pxi @@ -23,65 +23,8 @@ from collections import namedtuple truth_table_row = namedtuple("truth_table_row", ["values", "result"]) - -# -# Conditional expression factory functions -# cdef dict _cond_cache = {} -cdef inline Conditional conditional_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol): - """Factory function variant for iterating over Conditional objects.""" - return conditional_factory(policy, <const qpol_cond_t *> symbol.obj) - - -cdef inline Conditional conditional_factory(SELinuxPolicy policy, const qpol_cond_t *symbol): - """Factory function for creating Conditional objects.""" - try: - return _cond_cache[<uintptr_t>symbol] - except KeyError: - c = Conditional() - c.policy = policy - c.handle = symbol - _cond_cache[<uintptr_t>symbol] = c - return c - -# -# Conditional node factory functions -# -cdef inline object conditional_node_factory_iter(SELinuxPolicy policy, QpolIteratorItem item): - """Factory function variant for iterating over conditional node objects.""" - cdef const qpol_cond_expr_node_t *symbol = <const qpol_cond_expr_node_t *> item.obj - cdef uint32_t et - cdef qpol_bool_t *b - - # Determine if this node is a Boolean or an operator - if qpol_cond_expr_node_get_expr_type(policy.handle, symbol, &et): - ex = LowLevelPolicyError("Error reading conditional expression node type: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - - if (et == QPOL_COND_EXPR_BOOL): - if qpol_cond_expr_node_get_bool(policy.handle, symbol, &b): - ex = LowLevelPolicyError("Error reading boolean from conditional expression node: {}". - format(strerror(errno))) - ex.errno = errno - raise ex - - return Boolean.factory(policy, <sepol.cond_bool_datum_t *>b) - - else: - return conditional_op_factory(policy, symbol) - - -cdef inline ConditionalOperator conditional_op_factory(SELinuxPolicy policy, const qpol_cond_expr_node_t *symbol): - """Factory function for creating conditional node objects.""" - op = ConditionalOperator() - op.policy = policy - op.handle = symbol - return op - - # # Classes # @@ -120,7 +63,19 @@ cdef class Conditional(PolicySymbol): """A conditional policy block.""" - cdef const qpol_cond_t *handle + cdef sepol.cond_node_t *handle + + @staticmethod + cdef factory(SELinuxPolicy policy, sepol.cond_node_t *symbol): + """Factory function for creating Conditional objects.""" + try: + return _cond_cache[<uintptr_t>symbol] + except KeyError: + c = Conditional() + c.policy = policy + c.handle = symbol + _cond_cache[<uintptr_t>symbol] = c + return c def __contains__(self, other): for b in self.booleans: @@ -247,52 +202,18 @@ cdef class Conditional(PolicySymbol): def expression(self): """Iterator over The conditional expression.""" - cdef qpol_iterator_t *iter; - if qpol_cond_get_expr_node_iter(self.policy.handle, self.handle, &iter): - raise MemoryError - - return qpol_iterator_factory(self.policy, iter, conditional_node_factory_iter) + return ConditionalExprIterator.factory(self.policy, <sepol.cond_expr_t *>self.handle.expr) def false_rules(self): """An iterator over the rules in the false (else) block of the conditional.""" - cdef qpol_iterator_t *av_iter - cdef qpol_iterator_t *te_iter - - cdef uint32_t av_rule_types = QPOL_RULE_ALLOW | QPOL_RULE_AUDITALLOW | QPOL_RULE_DONTAUDIT \ - | QPOL_RULE_XPERMS_ALLOW | QPOL_RULE_XPERMS_AUDITALLOW | QPOL_RULE_XPERMS_DONTAUDIT - - cdef uint32_t te_rule_types = QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER - - if qpol_cond_get_av_false_iter(self.policy.handle, self.handle, av_rule_types, &av_iter): - raise MemoryError - - if qpol_cond_get_te_false_iter(self.policy.handle, self.handle, te_rule_types, &te_iter): - raise MemoryError - - return chain(qpol_iterator_factory(self.policy, av_iter, avrule_factory_iter), - qpol_iterator_factory(self.policy, te_iter, terule_factory_iter)) + pass def statement(self): raise NoStatement def true_rules(self): """An iterator over the rules in the true block of the conditional.""" - cdef qpol_iterator_t *av_iter - cdef qpol_iterator_t *te_iter - - cdef uint32_t av_rule_types = QPOL_RULE_ALLOW | QPOL_RULE_AUDITALLOW | QPOL_RULE_DONTAUDIT \ - | QPOL_RULE_XPERMS_ALLOW | QPOL_RULE_XPERMS_AUDITALLOW | QPOL_RULE_XPERMS_DONTAUDIT - - cdef uint32_t te_rule_types = QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER - - if qpol_cond_get_av_true_iter(self.policy.handle, self.handle, av_rule_types, &av_iter): - raise MemoryError - - if qpol_cond_get_te_true_iter(self.policy.handle, self.handle, te_rule_types, &te_iter): - raise MemoryError - - return chain(qpol_iterator_factory(self.policy, av_iter, avrule_factory_iter), - qpol_iterator_factory(self.policy, te_iter, terule_factory_iter)) + pass def truth_table(self): """ @@ -327,52 +248,48 @@ cdef class ConditionalOperator(PolicySymbol): """A conditional expression operator""" - cdef const qpol_cond_expr_node_t *handle + cdef sepol.cond_expr_t *handle _cond_expr_val_to_text = { - QPOL_COND_EXPR_NOT: "!", - QPOL_COND_EXPR_OR: "||", - QPOL_COND_EXPR_AND: "&&", - QPOL_COND_EXPR_XOR: "^", - QPOL_COND_EXPR_EQ: "==", - QPOL_COND_EXPR_NEQ: "!="} + sepol.COND_NOT: "!", + sepol.COND_OR: "||", + sepol.COND_AND: "&&", + sepol.COND_XOR: "^", + sepol.COND_EQ: "==", + sepol.COND_NEQ: "!="} _cond_expr_val_to_precedence = { - QPOL_COND_EXPR_NOT: 5, - QPOL_COND_EXPR_OR: 1, - QPOL_COND_EXPR_AND: 3, - QPOL_COND_EXPR_XOR: 2, - QPOL_COND_EXPR_EQ: 4, - QPOL_COND_EXPR_NEQ: 4} + sepol.COND_NOT: 5, + sepol.COND_OR: 1, + sepol.COND_AND: 3, + sepol.COND_XOR: 2, + sepol.COND_EQ: 4, + sepol.COND_NEQ: 4} + + @staticmethod + cdef factory(SELinuxPolicy policy, sepol.cond_expr_t *symbol): + """Factory function for conditional operators.""" + op = ConditionalOperator() + op.policy = policy + op.handle = symbol + return op def __str__(self): - return self._cond_expr_val_to_text[self._type] + return self._cond_expr_val_to_text[self.handle.expr_type] def _eq(self, ConditionalOperator other): """Low-level equality check (C pointers).""" return self.handle == other.handle - @property - def _type(self): - """The type of operator.""" - cdef uint32_t et - if qpol_cond_expr_node_get_expr_type(self.policy.handle, self.handle, &et): - ex = LowLevelPolicyError("Error reading conditional expression node type: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - - return et - @property def precedence(self): """The precedence of this operator.""" - return self._cond_expr_val_to_precedence[self._type] + return self._cond_expr_val_to_precedence[self.handle.expr_type] @property def unary(self): """T/F the operator is unary""" - return self._type == QPOL_COND_EXPR_NOT + return self.handle.expr_type == sepol.COND_NOT # @@ -394,3 +311,92 @@ cdef class BooleanHashtabIterator(HashtabIterator): def __next__(self): super().__next__() return Boolean.factory(self.policy, <sepol.cond_bool_datum_t *>self.curr.datum) + + +cdef class ConditionalIterator(PolicyIterator): + + """Conditionals iterator.""" + + cdef: + sepol.cond_node_t *head + sepol.cond_node_t *curr + + @staticmethod + cdef factory(SELinuxPolicy policy, sepol.cond_node_t *head): + """Constraint iterator factory.""" + c = ConditionalIterator() + c.policy = policy + c.head = head + c.reset() + return c + + def __next__(self): + if self.curr == NULL: + raise StopIteration + + item = Conditional.factory(self.policy, self.curr) + self.curr = self.curr.next + return item + + def __len__(self): + cdef: + sepol.cond_node_t *curr + size_t count = 0 + + curr = self.head + while curr != NULL: + count += 1 + curr = curr.next + + return count + + def reset(self): + """Reset the iterator back to the start.""" + self.curr = self.head + + +cdef class ConditionalExprIterator(PolicyIterator): + + """Conditional expression iterator.""" + + cdef: + sepol.cond_expr_t *head + sepol.cond_expr_t *curr + + @staticmethod + cdef factory(SELinuxPolicy policy, sepol.cond_expr_t *head): + """Conditional expression iterator factory.""" + e = ConditionalExprIterator() + e.policy = policy + e.head = head + e.reset() + return e + + def __next__(self): + if self.curr == NULL: + raise StopIteration + + if self.curr.expr_type == sepol.COND_BOOL: + item = Boolean.factory(self.policy, + self.policy.handle.p.p.bool_val_to_struct[self.curr.bool - 1]) + else: + item = ConditionalOperator.factory(self.policy, self.curr) + + self.curr = self.curr.next + return item + + def __len__(self): + cdef: + sepol.cond_expr_t *curr + size_t count = 0 + + curr = self.head + while curr != NULL: + count += 1 + curr = curr.next + + return count + + def reset(self): + """Reset the iterator back to the start.""" + self.curr = self.head diff --git a/setools/policyrep/libpolicyrep.pyx b/setools/policyrep/libpolicyrep.pyx index 5834d22..634f4a7 100644 --- a/setools/policyrep/libpolicyrep.pyx +++ b/setools/policyrep/libpolicyrep.pyx @@ -116,24 +116,6 @@ cdef extern from "include/qpol/cond_query.h": pass ctypedef struct qpol_cond_expr_node_t: pass - cdef int QPOL_COND_RULE_LIST - cdef int QPOL_COND_RULE_ENABLED - int qpol_policy_get_cond_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter) - int qpol_cond_get_expr_node_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, qpol_iterator_t ** iter) - int qpol_cond_get_av_true_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask, qpol_iterator_t ** iter) - int qpol_cond_get_te_true_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask, qpol_iterator_t ** iter) - int qpol_cond_get_av_false_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask, qpol_iterator_t ** iter) - int qpol_cond_get_te_false_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask, qpol_iterator_t ** iter) - int qpol_cond_eval(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t * is_true) - cdef int QPOL_COND_EXPR_BOOL - cdef int QPOL_COND_EXPR_NOT - cdef int QPOL_COND_EXPR_OR - cdef int QPOL_COND_EXPR_AND - cdef int QPOL_COND_EXPR_XOR - cdef int QPOL_COND_EXPR_EQ - cdef int QPOL_COND_EXPR_NEQ - int qpol_cond_expr_node_get_expr_type(const qpol_policy_t * policy, const qpol_cond_expr_node_t * node, uint32_t * expr_type) - int qpol_cond_expr_node_get_bool(const qpol_policy_t * policy, const qpol_cond_expr_node_t * node, qpol_bool_t ** cond_bool) cdef extern from "include/qpol/constraint_query.h": ctypedef struct qpol_constraint_t: diff --git a/setools/policyrep/selinuxpolicy.pxi b/setools/policyrep/selinuxpolicy.pxi index 9433261..39b2abb 100644 --- a/setools/policyrep/selinuxpolicy.pxi +++ b/setools/policyrep/selinuxpolicy.pxi @@ -589,11 +589,7 @@ cdef class SELinuxPolicy: # def conditionals(self): """Iterator over all conditional rule blocks.""" - cdef qpol_iterator_t *iter - if qpol_policy_get_cond_iter(self.handle, &iter): - raise MemoryError - - return qpol_iterator_factory(self, iter, conditional_factory_iter) + return ConditionalIterator.factory(self, self.handle.p.p.cond_list) def mlsrules(self): """Iterator over all MLS rules.""" diff --git a/setools/policyrep/terule.pxi b/setools/policyrep/terule.pxi index bf59255..8763a25 100644 --- a/setools/policyrep/terule.pxi +++ b/setools/policyrep/terule.pxi @@ -274,7 +274,7 @@ cdef class AVRule(PolicyRule): raise ex if c: - return conditional_factory(self.policy, c) + return Conditional.factory(self.policy, <sepol.cond_node_t *>c) else: raise RuleNotConditional @@ -567,7 +567,7 @@ cdef class TERule(PolicyRule): raise ex if c: - return conditional_factory(self.policy, c) + return Conditional.factory(self.policy, <sepol.cond_node_t *>c) else: raise RuleNotConditional diff --git a/setup.py b/setup.py index 4ba49f8..f6bbbb9 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,6 @@ else: ext_py_mods = [Extension('setools.policyrep.libpolicyrep', ['setools/policyrep/libpolicyrep.pyx', 'libqpol/avrule_query.c', - 'libqpol/cond_query.c', 'libqpol/iterator.c', 'libqpol/policy.c', 'libqpol/policy_extend.c',