Sync internal master and AOSP sepolicy.
Bug: 37916906
Test: Builds 'n' boots.
Change-Id: Ia1d86264446ebecc1ca79f32f11354921bc77668
Merged-In: I208ec6a864127a059fb389417a9c6b259d7474cb
diff --git a/tests/policy.py b/tests/policy.py
index 74a8ef7..a0ddb90 100644
--- a/tests/policy.py
+++ b/tests/policy.py
@@ -3,6 +3,33 @@
import os
import sys
+###
+# Check whether the regex will match a file path starting with the provided
+# prefix
+#
+# Compares regex entries in file_contexts with a path prefix. Regex entries
+# are often more specific than this file prefix. For example, the regex could
+# be /system/bin/foo\.sh and the prefix could be /system. This function
+# loops over the regex removing characters from the end until
+# 1) there is a match - return True or 2) run out of characters - return
+# False.
+#
+def MatchPathPrefix(pathregex, prefix):
+ for i in range(len(pathregex), 0, -1):
+ try:
+ pattern = re.compile('^' + pathregex[0:i] + "$")
+ except:
+ continue
+ if pattern.match(prefix):
+ return True
+ return False
+
+def MatchPathPrefixes(pathregex, Prefixes):
+ for Prefix in Prefixes:
+ if MatchPathPrefix(pathregex, Prefix):
+ return True
+ return False
+
class TERule:
def __init__(self, rule):
data = rule.split(',')
@@ -14,10 +41,33 @@
self.rule = rule
class Policy:
- __Rules = None
+ __ExpandedRules = set()
+ __Rules = set()
__FcDict = None
__libsepolwrap = None
__policydbP = None
+ __BUFSIZE = 2048
+
+ # Check that path prefixes that match MatchPrefix, and do not Match
+ # DoNotMatchPrefix have the attribute Attr.
+ # For example assert that all types in /sys, and not in /sys/kernel/debugfs
+ # have the sysfs_type attribute.
+ def AssertPathTypesHaveAttr(self, MatchPrefix, DoNotMatchPrefix, Attr):
+ # Query policy for the types associated with Attr
+ TypesPol = self.QueryTypeAttribute(Attr, True)
+ # Search file_contexts to find paths/types that should be associated with
+ # Attr.
+ TypesFc = self.__GetTypesByFilePathPrefix(MatchPrefix, DoNotMatchPrefix)
+ violators = TypesFc.difference(TypesPol)
+
+ ret = ""
+ if len(violators) > 0:
+ ret += "The following types on "
+ ret += " ".join(str(x) for x in sorted(MatchPrefix))
+ ret += " must be associated with the "
+ ret += "\"" + Attr + "\" attribute: "
+ ret += " ".join(str(x) for x in sorted(violators)) + "\n"
+ return ret
# Return all file_contexts entries that map to the input Type.
def QueryFc(self, Type):
@@ -29,25 +79,68 @@
# Return all attributes associated with a type if IsAttr=False or
# all types associated with an attribute if IsAttr=True
def QueryTypeAttribute(self, Type, IsAttr):
- init_type_iter = self.__libsepolwrap.init_type_iter
- init_type_iter.restype = c_void_p
- TypeIterP = init_type_iter(c_void_p(self.__policydbP),
- create_string_buffer(Type), c_bool(IsAttr))
+ TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP,
+ create_string_buffer(Type), IsAttr)
if (TypeIterP == None):
sys.exit("Failed to initialize type iterator")
- buf = create_string_buffer(2048)
-
+ buf = create_string_buffer(self.__BUFSIZE)
+ TypeAttr = set()
while True:
- ret = self.__libsepolwrap.get_type(buf, c_int(2048),
- c_void_p(self.__policydbP), c_void_p(TypeIterP))
+ ret = self.__libsepolwrap.get_type(buf, self.__BUFSIZE,
+ self.__policydbP, TypeIterP)
if ret == 0:
- yield buf.value
+ TypeAttr.add(buf.value)
continue
if ret == 1:
break;
# We should never get here.
sys.exit("Failed to import policy")
- self.__libsepolwrap.destroy_type_iter(c_void_p(TypeIterP))
+ self.__libsepolwrap.destroy_type_iter(TypeIterP)
+ return TypeAttr
+
+ def __TERuleMatch(self, Rule, **kwargs):
+ # Match source type
+ if ("scontext" in kwargs and
+ len(kwargs['scontext']) > 0 and
+ Rule.sctx not in kwargs['scontext']):
+ return False
+ # Match target type
+ if ("tcontext" in kwargs and
+ len(kwargs['tcontext']) > 0 and
+ Rule.tctx not in kwargs['tcontext']):
+ return False
+ # Match target class
+ if ("tclass" in kwargs and
+ len(kwargs['tclass']) > 0 and
+ not bool(set([Rule.tclass]) & kwargs['tclass'])):
+ return False
+ # Match any perms
+ if ("perms" in kwargs and
+ len(kwargs['perms']) > 0 and
+ not bool(Rule.perms & kwargs['perms'])):
+ return False
+ return True
+
+ # resolve a type to its attributes or
+ # resolve an attribute to its types and attributes
+ # For example if scontext is the domain attribute, then we need to
+ # include all types with the domain attribute such as untrusted_app and
+ # priv_app and all the attributes of those types such as appdomain.
+ def ResolveTypeAttribute(self, Type):
+ types = self.GetAllTypes(False)
+ attributes = self.GetAllTypes(True)
+
+ if Type in types:
+ return self.QueryTypeAttribute(Type, False)
+ elif Type in attributes:
+ TypesAndAttributes = set()
+ Types = self.QueryTypeAttribute(Type, True)
+ TypesAndAttributes |= Types
+ for T in Types:
+ TypesAndAttributes |= self.QueryTypeAttribute(T, False)
+ return TypesAndAttributes
+ else:
+ return set()
# Return all TERules that match:
# (any scontext) or (any tcontext) or (any tclass) or (any perms),
@@ -58,35 +151,75 @@
# Will return any rule with:
# (tcontext="foo" or tcontext="bar") and ("entrypoint" in perms)
def QueryTERule(self, **kwargs):
- if self.__Rules is None:
+ if len(self.__Rules) == 0:
self.__InitTERules()
+
+ # add any matching types and attributes for scontext and tcontext
+ if ("scontext" in kwargs and len(kwargs['scontext']) > 0):
+ scontext = set()
+ for sctx in kwargs['scontext']:
+ scontext |= self.ResolveTypeAttribute(sctx)
+ kwargs['scontext'] = scontext
+ if ("tcontext" in kwargs and len(kwargs['tcontext']) > 0):
+ tcontext = set()
+ for tctx in kwargs['tcontext']:
+ tcontext |= self.ResolveTypeAttribute(tctx)
+ kwargs['tcontext'] = tcontext
for Rule in self.__Rules:
- # Match source type
- if "scontext" in kwargs and Rule.sctx not in kwargs['scontext']:
+ if self.__TERuleMatch(Rule, **kwargs):
+ yield Rule
+
+ # Same as QueryTERule but only using the expanded ruleset.
+ # i.e. all attributes have been expanded to their various types.
+ def QueryExpandedTERule(self, **kwargs):
+ if len(self.__ExpandedRules) == 0:
+ self.__InitExpandedTERules()
+ for Rule in self.__ExpandedRules:
+ if self.__TERuleMatch(Rule, **kwargs):
+ yield Rule
+
+ def GetAllTypes(self, isAttr):
+ TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP, None, isAttr)
+ if (TypeIterP == None):
+ sys.exit("Failed to initialize type iterator")
+ buf = create_string_buffer(self.__BUFSIZE)
+ AllTypes = set()
+ while True:
+ ret = self.__libsepolwrap.get_type(buf, self.__BUFSIZE,
+ self.__policydbP, TypeIterP)
+ if ret == 0:
+ AllTypes.add(buf.value)
continue
- # Match target type
- if "tcontext" in kwargs and Rule.tctx not in kwargs['tcontext']:
- continue
- # Match target class
- if "tclass" in kwargs and Rule.tclass not in kwargs['tclass']:
- continue
- # Match any perms
- if "perms" in kwargs and not bool(Rule.perms & set(kwargs['perms'])):
- continue
- yield Rule
+ if ret == 1:
+ break;
+ # We should never get here.
+ sys.exit("Failed to import policy")
+ self.__libsepolwrap.destroy_type_iter(TypeIterP)
+ return AllTypes
+
+ def __GetTypesByFilePathPrefix(self, MatchPrefixes, DoNotMatchPrefixes):
+ Types = set()
+ for Type in self.__FcDict:
+ for pathregex in self.__FcDict[Type]:
+ if not MatchPathPrefixes(pathregex, MatchPrefixes):
+ continue
+ if MatchPathPrefixes(pathregex, DoNotMatchPrefixes):
+ continue
+ Types.add(Type)
+ return Types
- def __GetTERules(self, policydbP, avtabIterP):
- if self.__Rules is None:
- self.__Rules = set()
- buf = create_string_buffer(2048)
+ def __GetTERules(self, policydbP, avtabIterP, Rules):
+ if Rules is None:
+ Rules = set()
+ buf = create_string_buffer(self.__BUFSIZE)
ret = 0
while True:
- ret = self.__libsepolwrap.get_allow_rule(buf, c_int(2048),
- c_void_p(policydbP), c_void_p(avtabIterP))
+ ret = self.__libsepolwrap.get_allow_rule(buf, self.__BUFSIZE,
+ policydbP, avtabIterP)
if ret == 0:
Rule = TERule(buf.value)
- self.__Rules.add(Rule)
+ Rules.add(Rule)
continue
if ret == 1:
break;
@@ -94,32 +227,78 @@
sys.exit("Failed to import policy")
def __InitTERules(self):
- init_avtab = self.__libsepolwrap.init_avtab
- init_avtab.restype = c_void_p
- avtabIterP = init_avtab(c_void_p(self.__policydbP))
+ avtabIterP = self.__libsepolwrap.init_avtab(self.__policydbP)
if (avtabIterP == None):
sys.exit("Failed to initialize avtab")
- self.__GetTERules(self.__policydbP, avtabIterP)
- self.__libsepolwrap.destroy_avtab(c_void_p(avtabIterP))
- init_cond_avtab = self.__libsepolwrap.init_cond_avtab
- init_cond_avtab.restype = c_void_p
- avtabIterP = init_cond_avtab(c_void_p(self.__policydbP))
+ self.__GetTERules(self.__policydbP, avtabIterP, self.__Rules)
+ self.__libsepolwrap.destroy_avtab(avtabIterP)
+ avtabIterP = self.__libsepolwrap.init_cond_avtab(self.__policydbP)
if (avtabIterP == None):
sys.exit("Failed to initialize conditional avtab")
- self.__GetTERules(self.__policydbP, avtabIterP)
- self.__libsepolwrap.destroy_avtab(c_void_p(avtabIterP))
+ self.__GetTERules(self.__policydbP, avtabIterP, self.__Rules)
+ self.__libsepolwrap.destroy_avtab(avtabIterP)
+
+ def __InitExpandedTERules(self):
+ avtabIterP = self.__libsepolwrap.init_expanded_avtab(self.__policydbP)
+ if (avtabIterP == None):
+ sys.exit("Failed to initialize avtab")
+ self.__GetTERules(self.__policydbP, avtabIterP, self.__ExpandedRules)
+ self.__libsepolwrap.destroy_expanded_avtab(avtabIterP)
+ avtabIterP = self.__libsepolwrap.init_expanded_cond_avtab(self.__policydbP)
+ if (avtabIterP == None):
+ sys.exit("Failed to initialize conditional avtab")
+ self.__GetTERules(self.__policydbP, avtabIterP, self.__ExpandedRules)
+ self.__libsepolwrap.destroy_expanded_avtab(avtabIterP)
# load ctypes-ified libsepol wrapper
def __InitLibsepolwrap(self, LibPath):
if "linux" in sys.platform:
- self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.so")
+ lib = CDLL(LibPath + "/libsepolwrap.so")
elif "darwin" in sys.platform:
- self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.dylib")
+ lib = CDLL(LibPath + "/libsepolwrap.dylib")
else:
sys.exit("only Linux and Mac currrently supported")
+ # int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp);
+ lib.get_allow_rule.restype = c_int
+ lib.get_allow_rule.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p];
+ # void *load_policy(const char *policy_path);
+ lib.load_policy.restype = c_void_p
+ lib.load_policy.argtypes = [c_char_p]
+ # void destroy_policy(void *policydbp);
+ lib.destroy_policy.argtypes = [c_void_p]
+ # void *init_expanded_avtab(void *policydbp);
+ lib.init_expanded_avtab.restype = c_void_p
+ lib.init_expanded_avtab.argtypes = [c_void_p]
+ # void *init_expanded_cond_avtab(void *policydbp);
+ lib.init_expanded_cond_avtab.restype = c_void_p
+ lib.init_expanded_cond_avtab.argtypes = [c_void_p]
+ # void destroy_expanded_avtab(void *avtab_iterp);
+ lib.destroy_expanded_avtab.argtypes = [c_void_p]
+ # void *init_avtab(void *policydbp);
+ lib.init_avtab.restype = c_void_p
+ lib.init_avtab.argtypes = [c_void_p]
+ # void *init_cond_avtab(void *policydbp);
+ lib.init_cond_avtab.restype = c_void_p
+ lib.init_cond_avtab.argtypes = [c_void_p]
+ # void destroy_avtab(void *avtab_iterp);
+ lib.destroy_avtab.argtypes = [c_void_p]
+ # int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp);
+ lib.get_type.restype = c_int
+ lib.get_type.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p]
+ # void *init_type_iter(void *policydbp, const char *type, bool is_attr);
+ lib.init_type_iter.restype = c_void_p
+ lib.init_type_iter.argtypes = [c_void_p, c_char_p, c_bool]
+ # void destroy_type_iter(void *type_iterp);
+ lib.destroy_type_iter.argtypes = [c_void_p]
+
+ self.__libsepolwrap = lib
+
+
# load file_contexts
def __InitFC(self, FcPaths):
+ if FcPaths is None:
+ return
fc = []
for path in FcPaths:
if not os.path.exists(path):
@@ -141,9 +320,8 @@
# load policy
def __InitPolicy(self, PolicyPath):
- load_policy = self.__libsepolwrap.load_policy
- load_policy.restype = c_void_p
- self.__policydbP = load_policy(create_string_buffer(PolicyPath))
+ cPolicyPath = create_string_buffer(PolicyPath)
+ self.__policydbP = self.__libsepolwrap.load_policy(cPolicyPath)
if (self.__policydbP is None):
sys.exit("Failed to load policy")
@@ -154,4 +332,4 @@
def __del__(self):
if self.__policydbP is not None:
- self.__libsepolwrap.destroy_policy(c_void_p(self.__policydbP))
+ self.__libsepolwrap.destroy_policy(self.__policydbP)