diff --git a/Android.mk b/Android.mk index 8ec1ebf2b5d65f973edd82067a5974f835235ba6..0503b55444096021e296d374636ffb47a05e4ae7 100644 --- a/Android.mk +++ b/Android.mk @@ -1155,30 +1155,121 @@ LOCAL_MODULE_TAGS := tests include $(BUILD_SYSTEM)/base_rules.mk -# 26.0_compat - the current plat_sepolicy.cil built -# with the compatibility file targeting the 26.0 -# SELinux release. +# 26.0_plat - the platform policy shipped as part of the 26.0 release. This is +# built to enable us to determine the diff between the current policy and the +# 26.0 policy, which will be used in tests to make sure that compatibility has +# been maintained by our mapping files. +26.0_PLAT_PUBLIC_POLICY := $(LOCAL_PATH)/prebuilts/api/26.0/public +26.0_PLAT_PRIVATE_POLICY := $(LOCAL_PATH)/prebuilts/api/26.0/private +26.0_plat_policy.conf := $(intermediates)/26.0_plat_policy.conf +$(26.0_plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS) +$(26.0_plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS) +$(26.0_plat_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch) +$(26.0_plat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan) +$(26.0_plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(26.0_plat_policy.conf): PRIVATE_FULL_TREBLE := true +$(26.0_plat_policy.conf): $(call build_policy, $(sepolicy_build_files), \ +$(26.0_PLAT_PUBLIC_POLICY) $(26.0_PLAT_PRIVATE_POLICY)) + $(transform-policy-to-conf) + $(hide) sed '/dontaudit/d' $@ > $@.dontaudit + +built_26.0_plat_sepolicy := $(intermediates)/built_26.0_plat_sepolicy +$(built_26.0_plat_sepolicy): PRIVATE_ADDITIONAL_CIL_FILES := \ + $(call build_policy, technical_debt.cil , $(26.0_PLAT_PRIVATE_POLICY)) +$(built_26.0_plat_sepolicy): $(26.0_plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \ + $(HOST_OUT_EXECUTABLES)/secilc \ + $(call build_policy, technical_debt.cil, $(26.0_PLAT_PRIVATE_POLICY)) + @mkdir -p $(dir $@) + $(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \ + $(POLICYVERS) -o $@ $< + $(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@ + $(hide) $(HOST_OUT_EXECUTABLES)/secilc -M true -G -c $(POLICYVERS) $@ -o $@ -f /dev/null + +26.0_plat_policy.conf := + + +# 26.0_compat - the current plat_sepolicy.cil built with the compatibility file +# targeting the 26.0 SELinux release. This ensures that our policy will build +# when used on a device that has non-platform policy targetting the 26.0 release. 26.0_compat := $(intermediates)/26.0_compat -26.0_mapping_cil := $(LOCAL_PATH)/prebuilts/api/26.0/26.0.cil +26.0_mapping.cil := $(LOCAL_PATH)/prebuilts/api/26.0/26.0.cil +26.0_mapping.ignore.cil := $(LOCAL_PATH)/prebuilts/api/26.0/26.0.ignore.cil 26.0_nonplat := $(LOCAL_PATH)/prebuilts/api/26.0/nonplat_sepolicy.cil $(26.0_compat): PRIVATE_CIL_FILES := \ -$(built_plat_cil) $(26.0_mapping_cil) $(26.0_nonplat) +$(built_plat_cil) $(26.0_mapping.cil) $(26.0_nonplat) $(26.0_compat): $(HOST_OUT_EXECUTABLES)/secilc \ -$(built_plat_cil) $(26.0_mapping_cil) $(26.0_nonplat) +$(built_plat_cil) $(26.0_mapping.cil) $(26.0_nonplat) $(hide) $(HOST_OUT_EXECUTABLES)/secilc -M true -G -N -c $(POLICYVERS) \ $(PRIVATE_CIL_FILES) -o $@ -f /dev/null +# 26.0_mapping.combined.cil - a combination of the mapping file used when +# combining the current platform policy with nonplatform policy based on the +# 26.0 policy release and also a special ignored file that exists purely for +# these tests. +26.0_mapping.combined.cil := $(intermediates)/26.0_mapping.combined.cil +$(26.0_mapping.combined.cil): $(26.0_mapping.cil) $(26.0_mapping.ignore.cil) + mkdir -p $(dir $@) + cat $^ > $@ + +# plat_sepolicy - the current platform policy only, built into a policy binary. +# TODO - this currently excludes partner extensions, but support should be added +# to enable partners to add their own compatibility mapping +BASE_PLAT_PUBLIC_POLICY := $(filter-out $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR), $(PLAT_PUBLIC_POLICY)) +BASE_PLAT_PRIVATE_POLICY := $(filter-out $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR), $(PLAT_PRIVATE_POLICY)) +base_plat_policy.conf := $(intermediates)/base_plat_policy.conf +$(base_plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS) +$(base_plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS) +$(base_plat_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch) +$(base_plat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan) +$(base_plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(base_plat_policy.conf): PRIVATE_FULL_TREBLE := true +$(base_plat_policy.conf): $(call build_policy, $(sepolicy_build_files), \ +$(BASE_PLAT_PUBLIC_POLICY) $(BASE_PLAT_PRIVATE_POLICY)) + $(transform-policy-to-conf) + $(hide) sed '/dontaudit/d' $@ > $@.dontaudit + +built_plat_sepolicy := $(intermediates)/built_plat_sepolicy +$(built_plat_sepolicy): PRIVATE_ADDITIONAL_CIL_FILES := \ + $(call build_policy, $(sepolicy_build_cil_workaround_files), $(BASE_PLAT_PRIVATE_POLICY)) +$(built_plat_sepolicy): $(base_plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \ +$(HOST_OUT_EXECUTABLES)/secilc \ +$(call build_policy, $(sepolicy_build_cil_workaround_files), $(BASE_PLAT_PRIVATE_POLICY)) + @mkdir -p $(dir $@) + $(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \ + $(POLICYVERS) -o $@ $< + $(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@ + $(hide) $(HOST_OUT_EXECUTABLES)/secilc -M true -G -c $(POLICYVERS) $@ -o $@ -f /dev/null + 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): PRIVATE_SEPOLICY_OLD := $(built_26.0_plat_sepolicy) +$(treble_sepolicy_tests): PRIVATE_COMBINED_MAPPING := $(26.0_mapping.combined.cil) +$(treble_sepolicy_tests): PRIVATE_PLAT_SEPOLICY := $(built_plat_sepolicy) $(treble_sepolicy_tests): $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py \ -$(built_plat_fc) $(built_nonplat_fc) $(built_sepolicy) $(26.0_compat) +$(built_plat_fc) $(built_nonplat_fc) $(built_sepolicy) $(built_plat_sepolicy) \ +$(built_26.0_plat_sepolicy) $(26.0_compat) $(26.0_mapping.combined.cil) @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) python $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py -l \ + $(HOST_OUT)/lib64 -f $(PRIVATE_PLAT_FC) -f $(PRIVATE_NONPLAT_FC) \ + -b $(PRIVATE_PLAT_SEPOLICY) -m $(PRIVATE_COMBINED_MAPPING) \ + -o $(PRIVATE_SEPOLICY_OLD) -p $(PRIVATE_SEPOLICY) $(hide) touch $@ +26.0_PLAT_PUBLIC_POLICY := +26.0_PLAT_PRIVATE_POLICY := 26.0_compat := +26.0_mapping.cil := +26.0_mapping.combined.cil := +26.0_mapping.ignore.cil := +26.0_nonplat := +BASE_PLAT_PUBLIC_POLICY := +BASE_PLAT_PRIVATE_POLICY := +base_plat_policy.conf := +built_26.0_plat_sepolicy := +plat_sepolicy := + endif # ($(PRODUCT_FULL_TREBLE),true) ################################# diff --git a/tests/Android.bp b/tests/Android.bp index e875497d5d22054105b9debbba4a86733de07f8c..19aca9ccd6b4ff060487c375d0dd9bcd0b70559c 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -6,6 +6,12 @@ cc_library_host_shared { export_include_dirs: ["include"], } +cc_prebuilt_binary { + name: "mini_parser.py", + srcs: ["mini_parser.py"], + host_supported: true, +} + cc_prebuilt_binary { name: "policy.py", srcs: ["policy.py"], @@ -17,7 +23,7 @@ cc_prebuilt_binary { name: "treble_sepolicy_tests.py", srcs: ["treble_sepolicy_tests.py"], host_supported: true, - required: ["policy.py"], + required: ["mini_parser.py", "policy.py"], } cc_prebuilt_binary { diff --git a/tests/mini_parser.py b/tests/mini_parser.py new file mode 100644 index 0000000000000000000000000000000000000000..57b3d59f82cd628b3a48a8b16c70aaf171267a6a --- /dev/null +++ b/tests/mini_parser.py @@ -0,0 +1,100 @@ +from os.path import basename +import re +import sys + +# A very limited parser whose job is to process the compatibility mapping +# files and retrieve type and attribute information until proper support is +# built into libsepol + +# get the text in the next matching parens + +class MiniCilParser: + types = set() # types declared in mapping + pubtypes = set() + typeattributes = set() # attributes declared in mapping + typeattributesets = {} # sets defined in mapping + rTypeattributesets = {} # reverse mapping of above sets + apiLevel = None + + def _getNextStmt(self, infile): + parens = 0 + s = "" + c = infile.read(1) + # get to first statement + while c and c != "(": + c = infile.read(1) + + parens += 1 + c = infile.read(1) + while c and parens != 0: + s += c + c = infile.read(1) + if c == ';': + # comment, get rid of rest of the line + while c != '\n': + c = infile.read(1) + elif c == '(': + parens += 1 + elif c == ')': + parens -= 1 + return s + + def _parseType(self, stmt): + m = re.match(r"type\s+(.+)", stmt) + self.types.update(set(m.group(1))) + return + + def _parseTypeattribute(self, stmt): + m = re.match(r"typeattribute\s+(.+)", stmt) + self.typeattributes.update(set(m.group(1))) + return + + def _parseTypeattributeset(self, stmt): + m = re.match(r"typeattributeset\s+(.+?)\s+\((.+?)\)", stmt, flags = re.M |re.S) + ta = m.group(1) + # this isn't proper expression parsing, but will do for our + # current use + tas = m.group(2).split() + + if self.typeattributesets.get(ta) is None: + self.typeattributesets[ta] = set() + self.typeattributesets[ta].update(set(tas)) + for t in tas: + if self.rTypeattributesets.get(t) is None: + self.rTypeattributesets[t] = set() + self.rTypeattributesets[t].update(set(ta)) + + # check to see if this typeattributeset is a versioned public type + pub = re.match(r"(\w+)_\d+_\d+", ta) + if pub is not None: + self.pubtypes.update(set(pub.group(1))) + return + + def _parseStmt(self, stmt): + if re.match(r"type\s+.+", stmt): + self._parseType(stmt) + elif re.match(r"typeattribute\s+.+", stmt): + self._parseTypeattribute(stmt) + elif re.match(r"typeattributeset\s+.+", stmt): + self._parseTypeattributeset(stmt) + else: + m = re.match(r"(\w+)\s+.+", stmt) + ret = "Warning: Unknown statement type (" + m.group(1) + ") in " + ret += "mapping file, perhaps consider adding support for it in " + ret += "system/sepolicy/tests/mini_parser.py!\n" + print ret + return + + def __init__(self, policyFile): + with open(policyFile, 'r') as infile: + s = self._getNextStmt(infile) + while s: + self._parseStmt(s) + s = self._getNextStmt(infile) + fn = basename(policyFile) + m = re.match(r"(\d+\.\d+).+\.cil", fn) + self.apiLevel = m.group(1) + +if __name__ == '__main__': + f = sys.argv[1] + p = MiniCilParser(f) diff --git a/tests/policy.py b/tests/policy.py index b70b836d0c8df3cfc9e1a2c16bb3b67969ee79bf..15a537ec39bcb00b08fd2925965401b25c6ca162 100644 --- a/tests/policy.py +++ b/tests/policy.py @@ -123,6 +123,26 @@ class Policy: continue yield Rule + + def GetAllTypes(self): + TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP, None, False) + 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 + 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: @@ -203,6 +223,8 @@ class Policy: # load file_contexts def __InitFC(self, FcPaths): + if FcPaths is None: + return fc = [] for path in FcPaths: if not os.path.exists(path): diff --git a/tests/sepol_wrap.cpp b/tests/sepol_wrap.cpp index a12d4383df986b13b56972ccea8d9dcd1ee660ee..cd5336795e49315aed9ad690060a634af75e75da 100644 --- a/tests/sepol_wrap.cpp +++ b/tests/sepol_wrap.cpp @@ -17,8 +17,11 @@ #include <android-base/strings.h> #include <sepol_wrap.h> - +#define TYPE_ITER_LOOKUP 0 +#define TYPE_ITER_ALLTYPES 1 +#define TYPE_ITER_ALLATTRS 2 struct type_iter { + unsigned int alltypes; type_datum *d; ebitmap_node *n; unsigned int length; @@ -36,23 +39,33 @@ void *init_type_iter(void *policydbp, const char *type, bool is_attr) return NULL; } - out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type)); - if (is_attr && out->d->flavor != TYPE_ATTRIB) { - std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl; - free(out); - return NULL; - } else if (!is_attr && out->d->flavor !=TYPE_TYPE) { - std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl; - free(out); - return NULL; - } - - if (is_attr) { - out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n); - out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]); + if (type == NULL) { + out->length = db->p_types.nprim; + out->bit = 0; + if (is_attr) + out->alltypes = TYPE_ITER_ALLATTRS; + else + out->alltypes = TYPE_ITER_ALLTYPES; } else { - out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n); - out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]); + out->alltypes = TYPE_ITER_LOOKUP; + out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type)); + if (is_attr && out->d->flavor != TYPE_ATTRIB) { + std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl; + free(out); + return NULL; + } else if (!is_attr && out->d->flavor !=TYPE_TYPE) { + std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl; + free(out); + return NULL; + } + + if (is_attr) { + out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n); + out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]); + } else { + out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n); + out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]); + } } return static_cast<void *>(out); @@ -65,7 +78,7 @@ void destroy_type_iter(void *type_iterp) } /* - * print allow rule into *out buffer. + * print type into *out buffer. * * Returns -1 on error. * Returns 0 on successfully reading an avtab entry. @@ -77,20 +90,28 @@ int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp) policydb_t *db = static_cast<policydb_t *>(policydbp); struct type_iter *i = static_cast<struct type_iter *>(type_iterp); - for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) { - if (!ebitmap_node_get_bit(i->n, i->bit)) { - continue; - } - len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]); - if (len >= max_size) { - std::cerr << "type name exceeds buffer size." << std::endl; - return -1; + if (!i->alltypes) { + for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) { + if (!ebitmap_node_get_bit(i->n, i->bit)) { + continue; + } + break; } - i->bit = ebitmap_next(&i->n, i->bit); - return 0; } - - return 1; + if (i->bit >= i->length) + return 1; + while ((i->alltypes == TYPE_ITER_ALLATTRS + && db->type_val_to_struct[i->bit]->flavor != TYPE_ATTRIB) + || (i->alltypes == TYPE_ITER_ALLTYPES + && db->type_val_to_struct[i->bit]->flavor != TYPE_TYPE)) + i->bit++; + len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]); + if (len >= max_size) { + std::cerr << "type name exceeds buffer size." << std::endl; + return -1; + } + i->alltypes ? i->bit++ : i->bit = ebitmap_next(&i->n, i->bit); + return 0; } void *load_policy(const char *policy_path) diff --git a/tests/treble_sepolicy_tests.py b/tests/treble_sepolicy_tests.py index b358a14e12cb96a9c2bd19659ddf98b5212393db..7584cab5a6adcbddcf3fba265de20138820f63a0 100644 --- a/tests/treble_sepolicy_tests.py +++ b/tests/treble_sepolicy_tests.py @@ -1,6 +1,7 @@ from optparse import OptionParser from optparse import Option, OptionValueError import os +import mini_parser import policy from policy import MatchPathPrefix import re @@ -70,6 +71,11 @@ coredomains = set() appdomains = set() vendordomains = set() +# compat vars +alltypes = set() +oldalltypes = set() +compatMapping = None + def GetAllDomains(pol): global alldomains for result in pol.QueryTypeAttribute("domain", True): @@ -87,7 +93,6 @@ def GetAppDomains(): alldomains[d].appdomain = True appdomains.add(d) - def GetCoreDomains(): global alldomains global coredomains @@ -147,6 +152,12 @@ def GetAttributes(pol): for result in pol.QueryTypeAttribute(domain, False): alldomains[domain].attributes.add(result) +def GetAllTypes(pol, oldpol): + global alltypes + global oldalltypes + alltypes = pol.GetAllTypes() + oldalltypes = oldpol.GetAllTypes() + def setup(pol): GetAllDomains(pol) GetAttributes(pol) @@ -154,6 +165,13 @@ def setup(pol): GetAppDomains() GetCoreDomains() +# setup for the policy compatibility tests +def compatSetup(pol, oldpol, mapping): + global compatMapping + + GetAllTypes(pol, oldpol) + compatMapping = mapping + ############################################################# # Tests ############################################################# @@ -189,6 +207,30 @@ def TestCoredomainViolations(): return ret ### +# Make sure that any new type introduced in the new policy that was not present +# in the old policy has been recorded in the mapping file. +def TestNoUnmappedNewTypes(): + global alltypes + global oldalltypes + newt = alltypes - oldalltypes + ret = "" + violators = [] + + for n in newt: + if compatMapping.rTypeattributesets.get(n) is None: + violators.append(n) + + if len(violators) > 0: + ret += "SELinux: The following types were found added to the policy " + ret += "without an entry into the compatibility mapping file(s) found " + ret += "in prebuilts/api/" + compatMapping.apiLevel + "/\n" + ret += " ".join(str(x) for x in sorted(violators)) + "\n" + return ret + +def TestTrebleCompatMapping(): + ret = TestNoUnmappedNewTypes() + return ret +### # extend OptionParser to allow the same option flag to be used multiple times. # This is used to allow multiple file_contexts files and tests to be # specified. @@ -205,17 +247,23 @@ class MultipleOption(Option): else: Option.take_action(self, action, dest, opt, value, values, parser) -Tests = ["CoredomainViolations"] +Tests = {"CoredomainViolations": TestCoredomainViolations, + "TrebleCompatMapping": TestTrebleCompatMapping } if __name__ == '__main__': usage = "treble_sepolicy_tests.py -f nonplat_file_contexts -f " - usage +="plat_file_contexts -p policy [--test test] [--help]" + usage +="plat_file_contexts -p curr_policy -b base_policy -o old_policy " + usage +="-m mapping file [--test test] [--help]" parser = OptionParser(option_class=MultipleOption, usage=usage) + parser.add_option("-b", "--basepolicy", dest="basepolicy", metavar="FILE") 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("-m", "--mapping", dest="mapping", metavar="FILE") + parser.add_option("-o", "--oldpolicy", dest="oldpolicy", metavar="FILE") + parser.add_option("-p", "--policy", dest="policy", metavar="FILE") parser.add_option("-t", "--test", dest="tests", action="extend", + help="Test options include "+str(Tests)) (options, args) = parser.parse_args() @@ -225,9 +273,14 @@ if __name__ == '__main__': if not os.path.exists(options.libpath): sys.exit("Error: library-path " + options.libpath + " does not exist\n" + parser.usage) - + if not options.basepolicy: + sys.exit("Must specify the current platform-only policy file\n" + parser.usage) + if not options.mapping: + sys.exit("Must specify a compatibility mapping file\n" + parser.usage) + if not options.oldpolicy: + sys.exit("Must specify the previous monolithic policy file\n" + parser.usage) if not options.policy: - sys.exit("Must specify monolithic policy file\n" + parser.usage) + sys.exit("Must specify current monolithic policy file\n" + parser.usage) if not os.path.exists(options.policy): sys.exit("Error: policy file " + options.policy + " does not exist\n" + parser.usage) @@ -241,17 +294,30 @@ if __name__ == '__main__': pol = policy.Policy(options.policy, options.file_contexts, options.libpath) setup(pol) + basepol = policy.Policy(options.basepolicy, None, options.libpath) + oldpol = policy.Policy(options.oldpolicy, None, options.libpath) + mapping = mini_parser.MiniCilParser(options.mapping) + compatSetup(basepol, oldpol, mapping) if DEBUG: PrintScontexts() results = "" # If an individual test is not specified, run all tests. - if ( options.tests is None - or ("CoredomainViolations" in options.tests and len(options.tests) == 1)): - results += TestCoredomainViolations() + if options.tests is None: + for t in Tests.values(): + results += t() else: - sys.exit("Error: unknown test(s): " + str(options.tests)) + for tn in options.tests: + t = Tests.get(tn) + if t: + results += t() + else: + err = "Error: unknown test: " + tn + "\n" + err += "Available tests:\n" + for tn in Tests.keys(): + err += tn + "\n" + sys.exit(err) if len(results) > 0: sys.exit(results)