diff --git a/Android.mk b/Android.mk index ccb66e5236711a200145cc598e1b4373be1edae9..c990d4ddbca61cb591ab4a67acd14e294a895bed 100644 --- a/Android.mk +++ b/Android.mk @@ -192,7 +192,8 @@ LOCAL_REQUIRED_MODULES += \ secilc \ nonplat_file_contexts \ plat_file_contexts \ - plat_sepolicy_vers.txt + plat_sepolicy_vers.txt \ + treble_sepolicy_tests # Include precompiled policy, unless told otherwise ifneq ($(PRODUCT_PRECOMPILED_SEPOLICY),false) @@ -1136,6 +1137,27 @@ nonplat_mac_perms_keys.tmp := all_nonplat_mac_perms_files := ################################## +ifeq ($(PRODUCT_FULL_TREBLE),true) +include $(CLEAR_VARS) +# For Treble builds run tests verifying that processes are properly labeled and +# permissions granted do not violate the treble model. +LOCAL_MODULE := treble_sepolicy_tests +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +treble_sepolicy_tests := $(intermediates)/treble_sepolicy_tests +$(treble_sepolicy_tests): PRIVATE_PLAT_FC := $(built_plat_fc) +$(treble_sepolicy_tests): PRIVATE_NONPLAT_FC := $(built_nonplat_fc) +$(treble_sepolicy_tests): PRIVATE_SEPOLICY := $(built_sepolicy) +$(treble_sepolicy_tests): $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py \ +$(built_plat_fc) $(built_nonplat_fc) $(built_sepolicy) + @mkdir -p $(dir $@) + $(hide) python $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py -l $(HOST_OUT)/lib64 -f $(PRIVATE_PLAT_FC) -f $(PRIVATE_NONPLAT_FC) -p $(PRIVATE_SEPOLICY) + $(hide) touch $@ +endif # ($(PRODUCT_FULL_TREBLE),true) +################################# add_nl := build_device_policy := diff --git a/tests/Android.bp b/tests/Android.bp index 87afab831a3a1a12966ca787048d003bc39d1e83..2c70f363f7adc9c2fa5b8ccf3f8e91b9a326faf2 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -5,3 +5,17 @@ cc_library_host_shared { cflags: ["-Wall", "-Werror",], export_include_dirs: ["include"], } + +cc_prebuilt_binary { + name: "policy.py", + srcs: ["policy.py"], + host_supported: true, + required: ["libsepolwrap"], +} + +cc_prebuilt_binary { + name: "treble_sepolicy_tests.py", + srcs: ["treble_sepolicy_tests.py"], + host_supported: true, + required: ["policy.py"], +} diff --git a/tests/policy.py b/tests/policy.py index 480faa23777e132d69381d016fe5f09af0e7d558..74a8ef70da7c4bc95f8e56e0f71ffa3ef850f10c 100644 --- a/tests/policy.py +++ b/tests/policy.py @@ -1,6 +1,7 @@ from ctypes import * import re import os +import sys class TERule: def __init__(self, rule): @@ -28,15 +29,17 @@ class Policy: # 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): - TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP, - create_string_buffer(Type), c_bool(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)) if (TypeIterP == None): sys.exit("Failed to initialize type iterator") buf = create_string_buffer(2048) while True: ret = self.__libsepolwrap.get_type(buf, c_int(2048), - self.__policydbP, TypeIterP) + c_void_p(self.__policydbP), c_void_p(TypeIterP)) if ret == 0: yield buf.value continue @@ -44,7 +47,7 @@ class Policy: break; # We should never get here. sys.exit("Failed to import policy") - self.__libsepolwrap.destroy_type_iter(TypeIterP) + self.__libsepolwrap.destroy_type_iter(c_void_p(TypeIterP)) # Return all TERules that match: # (any scontext) or (any tcontext) or (any tclass) or (any perms), @@ -79,7 +82,8 @@ class Policy: buf = create_string_buffer(2048) ret = 0 while True: - ret = self.__libsepolwrap.get_allow_rule(buf, c_int(2048), policydbP, avtabIterP) + ret = self.__libsepolwrap.get_allow_rule(buf, c_int(2048), + c_void_p(policydbP), c_void_p(avtabIterP)) if ret == 0: Rule = TERule(buf.value) self.__Rules.add(Rule) @@ -90,20 +94,29 @@ class Policy: sys.exit("Failed to import policy") def __InitTERules(self): - avtabIterP = self.__libsepolwrap.init_avtab(self.__policydbP) + init_avtab = self.__libsepolwrap.init_avtab + init_avtab.restype = c_void_p + avtabIterP = init_avtab(c_void_p(self.__policydbP)) if (avtabIterP == None): sys.exit("Failed to initialize avtab") self.__GetTERules(self.__policydbP, avtabIterP) - self.__libsepolwrap.destroy_avtab(avtabIterP) - avtabIterP = self.__libsepolwrap.init_cond_avtab(self.__policydbP) + 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)) if (avtabIterP == None): sys.exit("Failed to initialize conditional avtab") self.__GetTERules(self.__policydbP, avtabIterP) - self.__libsepolwrap.destroy_avtab(avtabIterP) + self.__libsepolwrap.destroy_avtab(c_void_p(avtabIterP)) # load ctypes-ified libsepol wrapper - def __InitLibsepolwrap(self): - self.__libsepolwrap = CDLL("libsepolwrap.so") + def __InitLibsepolwrap(self, LibPath): + if "linux" in sys.platform: + self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.so") + elif "darwin" in sys.platform: + self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.dylib") + else: + sys.exit("only Linux and Mac currrently supported") # load file_contexts def __InitFC(self, FcPaths): @@ -128,15 +141,17 @@ class Policy: # load policy def __InitPolicy(self, PolicyPath): - self.__policydbP = self.__libsepolwrap.load_policy(create_string_buffer(PolicyPath)) + load_policy = self.__libsepolwrap.load_policy + load_policy.restype = c_void_p + self.__policydbP = load_policy(create_string_buffer(PolicyPath)) if (self.__policydbP is None): sys.exit("Failed to load policy") - def __init__(self, PolicyPath, FcPaths): - self.__InitLibsepolwrap() + def __init__(self, PolicyPath, FcPaths, LibPath): + self.__InitLibsepolwrap(LibPath) self.__InitFC(FcPaths) self.__InitPolicy(PolicyPath) def __del__(self): if self.__policydbP is not None: - self.__libsepolwrap.destroy_policy(self.__policydbP) + self.__libsepolwrap.destroy_policy(c_void_p(self.__policydbP)) diff --git a/tests/treble.py b/tests/treble_sepolicy_tests.py similarity index 87% rename from tests/treble.py rename to tests/treble_sepolicy_tests.py index 901f7020997d919f87bc3c98797974b0fc3656f9..3d6a4805f537438519d4c90e6f0fa60bc5225a74 100644 --- a/tests/treble.py +++ b/tests/treble_sepolicy_tests.py @@ -5,6 +5,8 @@ import policy import re import sys +DEBUG=False + ''' Use file_contexts and policy to verify Treble requirements are not violated. @@ -47,18 +49,20 @@ class scontext: self.entrypoints = [] self.entrypointpaths = [] -def PrintScontext(domain, sctx): - print domain - print "\tcoredomain="+str(sctx.coredomain) - print "\tappdomain="+str(sctx.appdomain) - print "\tfromSystem="+str(sctx.fromSystem) - print "\tfromVendor="+str(sctx.fromVendor) - print "\tattributes="+str(sctx.attributes) - print "\tentrypoints="+str(sctx.entrypoints) - print "\tentrypointpaths=" - if sctx.entrypointpaths is not None: - for path in sctx.entrypointpaths: - print "\t\t"+str(path) +def PrintScontexts(): + for d in sorted(alldomains.keys()): + sctx = alldomains[d] + print d + print "\tcoredomain="+str(sctx.coredomain) + print "\tappdomain="+str(sctx.appdomain) + print "\tfromSystem="+str(sctx.fromSystem) + print "\tfromVendor="+str(sctx.fromVendor) + print "\tattributes="+str(sctx.attributes) + print "\tentrypoints="+str(sctx.entrypoints) + print "\tentrypointpaths=" + if sctx.entrypointpaths is not None: + for path in sctx.entrypointpaths: + print "\t\t"+str(path) alldomains = {} coredomains = set() @@ -150,7 +154,10 @@ def GetDomainEntrypoints(pol): # so skip the lookup. if x.tctx == "postinstall_file": continue - alldomains[x.sctx].entrypointpaths = pol.QueryFc(x.tctx) + entrypointpath = pol.QueryFc(x.tctx) + if not entrypointpath: + continue + alldomains[x.sctx].entrypointpaths.extend(entrypointpath) ### # Get attributes associated with each domain # @@ -227,11 +234,18 @@ if __name__ == '__main__': parser.add_option("-f", "--file_contexts", dest="file_contexts", metavar="FILE", action="extend", type="string") parser.add_option("-p", "--policy", dest="policy", metavar="FILE") + parser.add_option("-l", "--library-path", dest="libpath", metavar="FILE") parser.add_option("-t", "--test", dest="test", action="extend", help="Test options include "+str(Tests)) (options, args) = parser.parse_args() + if not options.libpath: + sys.exit("Must specify path to host libraries\n" + parser.usage) + if not os.path.exists(options.libpath): + sys.exit("Error: library-path " + options.libpath + " does not exist\n" + + parser.usage) + if not options.policy: sys.exit("Must specify monolithic policy file\n" + parser.usage) if not os.path.exists(options.policy): @@ -245,9 +259,12 @@ if __name__ == '__main__': sys.exit("Error: File_contexts file " + f + " does not exist\n" + parser.usage) - pol = policy.Policy(options.policy, options.file_contexts) + pol = policy.Policy(options.policy, options.file_contexts, options.libpath) setup(pol) + if DEBUG: + PrintScontexts() + results = "" # If an individual test is not specified, run all tests. if options.test is None or "CoredomainViolations" in options.tests: