From 1b8284444c088f5310879231bf3d62104bdaf324 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Wed, 21 Mar 2018 17:27:20 -0700 Subject: [PATCH] Assert types labeled in genfs_contexts have correct attributes Types in sysfs should have the sysfs_type attribute, types in debugfs and tracefs should have the debugfs_type attribute. TODO: Test that files in procfs have the proc_type attribute. TODO: Assert these tests in CTS. Bug: 74182216 Test: build - these are build-time tests. Change-Id: Icf0ff2a26c05f94da421ba23df0b92d8eef906bf --- tests/include/sepol_wrap.h | 3 ++ tests/policy.py | 51 +++++++++++++++++++++++++++++ tests/sepol_wrap.cpp | 67 ++++++++++++++++++++++++++++++++++++++ tests/sepolicy_tests.py | 10 ++++-- 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/tests/include/sepol_wrap.h b/tests/include/sepol_wrap.h index 2357421c7..0be2c1726 100644 --- a/tests/include/sepol_wrap.h +++ b/tests/include/sepol_wrap.h @@ -15,6 +15,9 @@ void destroy_expanded_avtab(void *avtab_iterp); int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp); void *init_type_iter(void *policydbp, const char *type, bool is_attr); void destroy_type_iter(void *type_iterp); +void *init_genfs_iter(void *policydbp); +int get_genfs(char *out, size_t max_size, void *policydbp, void *genfs_iterp); +void destroy_genfs_iter(void *genfs_iterp); #ifdef __cplusplus } diff --git a/tests/policy.py b/tests/policy.py index b51ebf237..90e387fb9 100644 --- a/tests/policy.py +++ b/tests/policy.py @@ -47,6 +47,7 @@ class Policy: __Rules = set() __FcDict = None __FcSorted = None + __GenfsDict = None __libsepolwrap = None __policydbP = None __BUFSIZE = 2048 @@ -66,6 +67,21 @@ class Policy: ret += " ".join(str(x) for x in sorted(violators)) + "\n" return ret + # Check that all types for "filesystem" have "attribute" associated with them + # for types labeled in genfs_contexts. + def AssertGenfsFilesystemTypesHaveAttr(self, Filesystem, Attr): + TypesPol = self.QueryTypeAttribute(Attr, True) + TypesGenfs = self.__GenfsDict[Filesystem] + violators = TypesGenfs.difference(TypesPol) + + ret = "" + if len(violators) > 0: + ret += "The following types in " + Filesystem + ret += " must be associated with the " + ret += "\"" + Attr + "\" attribute: " + ret += " ".join(str(x) for x in sorted(violators)) + "\n" + return ret + # 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 @@ -337,9 +353,43 @@ class Policy: 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] + # void *init_genfs_iter(void *policydbp) + lib.init_genfs_iter.restype = c_void_p + lib.init_genfs_iter.argtypes = [c_void_p] + # int get_genfs(char *out, size_t max_size, void *genfs_iterp); + lib.get_genfs.restype = c_int + lib.get_genfs.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p] + # void destroy_genfs_iter(void *genfs_iterp) + lib.destroy_genfs_iter.argtypes = [c_void_p] self.__libsepolwrap = lib + def __GenfsDictAdd(self, Dict, buf): + fs, path, context = buf.split(" ") + Type = context.split(":")[2] + if not fs in Dict: + Dict[fs] = {Type} + else: + Dict[fs].add(Type) + + def __InitGenfsCon(self): + self.__GenfsDict = {} + GenfsIterP = self.__libsepolwrap.init_genfs_iter(self.__policydbP) + if (GenfsIterP == None): + sys.exit("Failed to retreive genfs entries") + buf = create_string_buffer(self.__BUFSIZE) + while True: + ret = self.__libsepolwrap.get_genfs(buf, self.__BUFSIZE, + self.__policydbP, GenfsIterP) + if ret == 0: + self.__GenfsDictAdd(self.__GenfsDict, buf.value) + continue + if ret == 1: + self.__GenfsDictAdd(self.__GenfsDict, buf.value) + break; + # We should never get here. + sys.exit("Failed to get genfs entries") + self.__libsepolwrap.destroy_genfs_iter(GenfsIterP) # load file_contexts def __InitFC(self, FcPaths): @@ -376,6 +426,7 @@ class Policy: self.__InitLibsepolwrap(LibPath) self.__InitFC(FcPaths) self.__InitPolicy(PolicyPath) + self.__InitGenfsCon() def __del__(self): if self.__policydbP is not None: diff --git a/tests/sepol_wrap.cpp b/tests/sepol_wrap.cpp index d537b7e00..39b618b90 100644 --- a/tests/sepol_wrap.cpp +++ b/tests/sepol_wrap.cpp @@ -17,6 +17,73 @@ #include #include +struct genfs_iter { + genfs_t *genfs; + ocontext_t *ocon; +}; + +void *init_genfs_iter(void *policydbp) +{ + struct genfs_iter *out = (struct genfs_iter *) + calloc(1, sizeof(struct genfs_iter)); + + if (!out) { + std::cerr << "Failed to allocate genfs iterator" << std::endl; + return NULL; + } + + policydb_t *db = static_cast(policydbp); + + out->genfs = db->genfs; + out->ocon = db->genfs->head; + + return static_cast(out); +} + +/* + * print genfs path into *out buffer. + * + * Returns -1 on error. + * Returns 0 on successfully retrieving a genfs entry. + * Returns 1 on successfully retrieving the final genfs entry. + */ +int get_genfs(char *out, size_t max_size, void *policydbp, void *genfs_iterp) +{ + size_t len; + struct genfs_iter *i = static_cast(genfs_iterp); + policydb_t *db = static_cast(policydbp); + + len = snprintf(out, max_size, "%s %s %s:%s:%s:s0", + i->genfs->fstype, + i->ocon->u.name, + db->p_user_val_to_name[i->ocon->context->user-1], + db->p_role_val_to_name[i->ocon->context->role-1], + db->p_type_val_to_name[i->ocon->context->type-1]); + + if (len >= max_size) { + std::cerr << "genfs path exceeds buffer size." << std::endl; + return -1; + } + + i->ocon = i->ocon->next; + if (i->ocon == NULL) { + if (i->genfs->next != NULL) { + i->genfs = i->genfs->next; + i->ocon = i->genfs->head; + } else { + return 1; + } + } + + return 0; +} + +void destroy_genfs_iter(void *genfs_iterp) +{ + struct genfs_iter *genfs_i = static_cast(genfs_iterp); + free(genfs_i); +} + #define TYPE_ITER_LOOKUP 0 #define TYPE_ITER_ALLTYPES 1 #define TYPE_ITER_ALLATTRS 2 diff --git a/tests/sepolicy_tests.py b/tests/sepolicy_tests.py index 2cf4ae814..b09c60bc3 100644 --- a/tests/sepolicy_tests.py +++ b/tests/sepolicy_tests.py @@ -12,13 +12,17 @@ def TestDataTypeViolations(pol): return pol.AssertPathTypesHaveAttr(["/data/"], [], "data_file_type") def TestSysfsTypeViolations(pol): - return pol.AssertPathTypesHaveAttr(["/sys/"], ["/sys/kernel/debug/", + ret = pol.AssertGenfsFilesystemTypesHaveAttr("sysfs", "sysfs_type") + ret += pol.AssertPathTypesHaveAttr(["/sys/"], ["/sys/kernel/debug/", "/sys/kernel/tracing"], "sysfs_type") + return ret def TestDebugfsTypeViolations(pol): - # TODO: this should apply to genfs_context entries as well - return pol.AssertPathTypesHaveAttr(["/sys/kernel/debug/", + ret = pol.AssertGenfsFilesystemTypesHaveAttr("debugfs", "debugfs_type") + ret += pol.AssertGenfsFilesystemTypesHaveAttr("tracefs", "debugfs_type") + ret += pol.AssertPathTypesHaveAttr(["/sys/kernel/debug/", "/sys/kernel/tracing"], [], "debugfs_type") + return ret def TestVendorTypeViolations(pol): return pol.AssertPathTypesHaveAttr(["/vendor/"], [], "vendor_file_type")