Constraint/Validatetrans: Refactor to load attributes on construction.

This commit is contained in:
Chris PeBenito 2018-08-08 15:38:04 -04:00
parent d0012dacaa
commit ded09017d6
2 changed files with 103 additions and 97 deletions

View File

@ -39,6 +39,11 @@ cdef class BaseConstraint(PolicySymbol):
sepol.constraint_node_t *handle sepol.constraint_node_t *handle
readonly object ruletype readonly object ruletype
readonly object tclass readonly object tclass
list _postfix_expression
list _infix_expression
readonly frozenset users
readonly frozenset roles
readonly frozenset types
def __str__(self): def __str__(self):
raise NotImplementedError raise NotImplementedError
@ -65,60 +70,63 @@ cdef class BaseConstraint(PolicySymbol):
Return: list Return: list
""" """
_precedence = { if self._infix_expression is None:
"not": 4, _precedence = {
"and": 2, "not": 4,
"or": 1, "and": 2,
"==": 3, "or": 1,
"!=": 3, "==": 3,
"dom": 3, "!=": 3,
"domby": 3, "dom": 3,
"incomp": 3} "domby": 3,
"incomp": 3}
_max_precedence = 4 _max_precedence = 4
_operands = ["u1", "u2", "u3", _operands = ["u1", "u2", "u3",
"r1", "r2", "r3", "r1", "r2", "r3",
"t1", "t2", "t3", "t1", "t2", "t3",
"l1", "l2", "l1", "l2",
"h1", "h2"] "h1", "h2"]
# qpol representation is in postfix notation. This code # sepol representation is in postfix notation. This code
# converts it to infix notation. Parentheses are added # converts it to infix notation. Parentheses are added
# to ensure correct expressions, though they may end up # to ensure correct expressions, though they may end up
# being overused. Set previous operator at start to the # being overused. Set previous operator at start to the
# highest precedence (op) so if there is a single binary # highest precedence (op) so if there is a single binary
# operator, no parentheses are output # operator, no parentheses are output
stack = [] stack = []
prev_op_precedence = _max_precedence prev_op_precedence = _max_precedence
for op in self.postfix_expression(): for op in self.postfix_expression():
if isinstance(op, frozenset) or op in _operands: if isinstance(op, frozenset) or op in _operands:
# operands # operands
stack.append(op) stack.append(op)
else:
# operators
if op == "not":
# unary operator
operator = op
operand = stack.pop()
op_precedence = _precedence[op]
stack.append([operator, "(", operand, ")"])
else: else:
# binary operators # operators
operand2 = stack.pop() if op == "not":
operand1 = stack.pop() # unary operator
operator = op operator = op
operand = stack.pop()
# if previous operator is of higher precedence op_precedence = _precedence[op]
# no parentheses are needed. stack.append([operator, "(", operand, ")"])
if _precedence[op] < prev_op_precedence:
stack.append([operand1, operator, operand2])
else: else:
stack.append(["(", operand1, operator, operand2, ")"]) # binary operators
operand2 = stack.pop()
operand1 = stack.pop()
operator = op
prev_op_precedence = _precedence[op] # if previous operator is of higher precedence
# no parentheses are needed.
if _precedence[op] < prev_op_precedence:
stack.append([operand1, operator, operand2])
else:
stack.append(["(", operand1, operator, operand2, ")"])
return self._flatten_expression(stack) prev_op_precedence = _precedence[op]
self._infix_expression = self._flatten_expression(stack)
return self._infix_expression
def postfix_expression(self): def postfix_expression(self):
""" """
@ -126,41 +134,7 @@ cdef class BaseConstraint(PolicySymbol):
Return: list Return: list
""" """
expression = [] return self._postfix_expression
for expr_node in ConstraintExprIterator.factory(self.policy, self.handle.expr):
expression.extend(expr_node())
return expression
@property
def roles(self):
"""The roles used in the expression."""
roles = set()
for expr_node in ConstraintExprIterator.factory(self.policy, self.handle.expr):
if expr_node.roles:
roles.update(expr_node.names)
return roles
@property
def types(self):
"""The types and type attributes used in the expression."""
types = set()
for expr_node in ConstraintExprIterator.factory(self.policy, self.handle.expr):
if expr_node.types:
types.update(expr_node.names)
return types
@property
def users(self):
"""The users used in the expression."""
users = set()
for expr_node in ConstraintExprIterator.factory(self.policy, self.handle.expr):
if expr_node.users:
users.update(expr_node.names)
return users
# #
# Internal functions # Internal functions
@ -198,20 +172,41 @@ cdef class Constraint(BaseConstraint):
"""A constraint rule (constrain/mlsconstrain).""" """A constraint rule (constrain/mlsconstrain)."""
cdef readonly frozenset perms
@staticmethod @staticmethod
cdef factory(SELinuxPolicy policy, ObjClass tclass, sepol.constraint_node_t *symbol): cdef factory(SELinuxPolicy policy, ObjClass tclass, sepol.constraint_node_t *symbol):
"""Factory function for creating Constraint objects.""" """Factory function for creating Constraint objects."""
c = Constraint() cdef:
Constraint c = Constraint.__new__(Constraint)
list users = []
list roles = []
list types = []
c.policy = policy c.policy = policy
c.handle = symbol c.handle = symbol
c.tclass = tclass c.tclass = tclass
c.perms = frozenset(PermissionVectorIterator.factory(policy, tclass, symbol.permissions))
c.ruletype = ConstraintRuletype.constrain
c._postfix_expression = []
for expr_node in ConstraintExprIterator.factory(policy, symbol.expr): for expr_node in ConstraintExprIterator.factory(policy, symbol.expr):
if expr_node.mls: if expr_node.mls:
c.ruletype = ConstraintRuletype.mlsconstrain c.ruletype = ConstraintRuletype.mlsconstrain
break
else: if expr_node.types:
c.ruletype = ConstraintRuletype.constrain types.extend(expr_node.names)
elif expr_node.roles:
roles.extend(expr_node.names)
elif expr_node.users:
users.extend(expr_node.names)
c._postfix_expression.extend(expr_node())
c.users = frozenset(users)
c.roles = frozenset(roles)
c.types = frozenset(types)
return c return c
@ -229,12 +224,6 @@ cdef class Constraint(BaseConstraint):
return rule_string return rule_string
@property
def perms(self):
"""The constraint's permission set."""
return set(p for p in PermissionVectorIterator.factory(self.policy, self.tclass,
self.handle.permissions))
cdef class Validatetrans(BaseConstraint): cdef class Validatetrans(BaseConstraint):
@ -243,17 +232,34 @@ cdef class Validatetrans(BaseConstraint):
@staticmethod @staticmethod
cdef factory(SELinuxPolicy policy, ObjClass tclass, sepol.constraint_node_t *symbol): cdef factory(SELinuxPolicy policy, ObjClass tclass, sepol.constraint_node_t *symbol):
"""Factory function for creating Validatetrans objects.""" """Factory function for creating Validatetrans objects."""
v = Validatetrans() cdef:
Validatetrans v = Validatetrans.__new__(Validatetrans)
list users = []
list roles = []
list types = []
v.policy = policy v.policy = policy
v.handle = symbol v.handle = symbol
v.tclass = tclass v.tclass = tclass
v.ruletype = ConstraintRuletype.validatetrans
v._postfix_expression = []
for expr_node in ConstraintExprIterator.factory(policy, symbol.expr): for expr_node in ConstraintExprIterator.factory(policy, symbol.expr):
if expr_node.mls: if expr_node.mls:
v.ruletype = ConstraintRuletype.mlsvalidatetrans v.ruletype = ConstraintRuletype.mlsvalidatetrans
break
else: if expr_node.types:
v.ruletype = ConstraintRuletype.validatetrans types.extend(expr_node.names)
elif expr_node.roles:
roles.extend(expr_node.names)
elif expr_node.users:
users.extend(expr_node.names)
v._postfix_expression.extend(expr_node())
v.users = frozenset(users)
v.roles = frozenset(roles)
v.types = frozenset(types)
return v return v

View File

@ -94,9 +94,9 @@ cdef class Type(BaseType):
return _type_cache[<uintptr_t>symbol] return _type_cache[<uintptr_t>symbol]
except KeyError: except KeyError:
t = Type.__new__(Type) t = Type.__new__(Type)
_type_cache[<uintptr_t>symbol] = t
t.policy = policy t.policy = policy
t.handle = symbol t.handle = symbol
_type_cache[<uintptr_t>symbol] = t
t.value = symbol.s.value t.value = symbol.s.value
t.name = policy.type_value_to_name(symbol.s.value - 1) t.name = policy.type_value_to_name(symbol.s.value - 1)
t.ispermissive = <bint>symbol.flags & sepol.TYPE_FLAGS_PERMISSIVE t.ispermissive = <bint>symbol.flags & sepol.TYPE_FLAGS_PERMISSIVE