| /* |
| * Author: Karl MacMillan <kmacmillan@tresys.com> |
| * |
| * Copyright (C) 2006 Tresys Technology, LLC |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "test-deps.h" |
| #include "parse_util.h" |
| #include "helpers.h" |
| |
| #include <sepol/policydb/policydb.h> |
| #include <sepol/policydb/link.h> |
| |
| #include <stdlib.h> |
| |
| /* Tests for dependency checking / handling, specifically: |
| * |
| * 1 type in module global. |
| * 2 attribute in module global. |
| * 3 object class / perm in module global. |
| * 4 boolean in module global. |
| * 5 role in module global. |
| * |
| * 6 type in module optional. |
| * 7 attribute in module optional. |
| * 8 object class / perm in module optional. |
| * 9 boolean in module optional. |
| * 10 role in module optional. |
| * |
| * 11 type in base optional. |
| * 12 attribute in base optional. |
| * 13 object class / perm in base optional. |
| * 14 boolean in base optional. |
| * 15 role in base optional. |
| * |
| * Each of these tests are done with the dependency met and not |
| * met. Additionally, each of the required symbols is used in the |
| * scope it is required. |
| * |
| * In addition to the simple tests, we have test with more complex |
| * modules that test: |
| * |
| * 17 mutual dependencies between two modules. |
| * 18 circular dependency between three modules. |
| * 19 large number of dependencies in a module with a more complex base. |
| * 20 nested optionals with requires. |
| * |
| * Again, each of these tests is done with the requirements met and not |
| * met. |
| */ |
| |
| #include <sepol/debug.h> |
| #include <sepol/handle.h> |
| |
| #define BASE_MODREQ_TYPE_GLOBAL 0 |
| #define BASE_MODREQ_ATTR_GLOBAL 1 |
| #define BASE_MODREQ_OBJ_GLOBAL 2 |
| #define BASE_MODREQ_BOOL_GLOBAL 3 |
| #define BASE_MODREQ_ROLE_GLOBAL 4 |
| #define BASE_MODREQ_PERM_GLOBAL 5 |
| #define BASE_MODREQ_TYPE_OPT 6 |
| #define BASE_MODREQ_ATTR_OPT 7 |
| #define BASE_MODREQ_OBJ_OPT 8 |
| #define BASE_MODREQ_BOOL_OPT 9 |
| #define BASE_MODREQ_ROLE_OPT 10 |
| #define BASE_MODREQ_PERM_OPT 11 |
| #define NUM_BASES 12 |
| |
| static policydb_t bases_met[NUM_BASES]; |
| static policydb_t bases_notmet[NUM_BASES]; |
| |
| extern int mls; |
| |
| int deps_test_init(void) |
| { |
| int i; |
| |
| /* To test linking we need 1 base per link test and in |
| * order to load them in the init function we have |
| * to keep them all around. Not ideal, but it shouldn't |
| * matter too much. |
| */ |
| for (i = 0; i < NUM_BASES; i++) { |
| if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) |
| return -1; |
| } |
| |
| for (i = 0; i < NUM_BASES; i++) { |
| if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int deps_test_cleanup(void) |
| { |
| int i; |
| |
| for (i = 0; i < NUM_BASES; i++) { |
| policydb_destroy(&bases_met[i]); |
| } |
| |
| for (i = 0; i < NUM_BASES; i++) { |
| policydb_destroy(&bases_notmet[i]); |
| } |
| |
| return 0; |
| } |
| |
| /* This function performs testing of the dependency handles for module global |
| * symbols. It is capable of testing 2 scenarios - the dependencies are met |
| * and the dependencies are not met. |
| * |
| * Paramaters: |
| * req_met boolean indicating whether the base policy meets the |
| * requirements for the modules global block. |
| * b index of the base policy in the global bases_met array. |
| * |
| * policy name of the policy module to load for this test. |
| * decl_type name of the unique type found in the module's global |
| * section is to find that avrule_decl. |
| */ |
| static void do_deps_modreq_global(int req_met, int b, char *policy, char *decl_type) |
| { |
| policydb_t *base; |
| policydb_t mod; |
| policydb_t *mods[] = { &mod }; |
| avrule_decl_t *decl; |
| int ret, link_ret; |
| sepol_handle_t *h; |
| |
| /* suppress error reporting - this is because we know that we |
| * are going to get errors and don't want libsepol complaining |
| * about it constantly. */ |
| h = sepol_handle_create(); |
| CU_ASSERT_FATAL(h != NULL); |
| sepol_msg_set_callback(h, NULL, NULL); |
| |
| if (req_met) { |
| base = &bases_met[b]; |
| link_ret = 0; |
| } else { |
| base = &bases_notmet[b]; |
| link_ret = -3; |
| } |
| |
| CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); |
| |
| /* link the modules and check for the correct return value. |
| */ |
| ret = link_modules(h, base, mods, 1, 0); |
| CU_ASSERT_FATAL(ret == link_ret); |
| policydb_destroy(&mod); |
| |
| if (!req_met) |
| return; |
| |
| decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); |
| CU_ASSERT_FATAL(decl != NULL); |
| |
| CU_ASSERT(decl->enabled == 1); |
| } |
| |
| /* Test that symbol require statements in the global scope of a module |
| * work correctly. This will cover tests 1 - 5 (described above). |
| * |
| * Each of these policies will require as few symbols as possible to |
| * use the required symbol in addition requiring (for example, the type |
| * test also requires an object class for an allow rule). |
| */ |
| static void deps_modreq_global(void) |
| { |
| /* object classes */ |
| do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); |
| /* types */ |
| do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); |
| /* attributes */ |
| do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); |
| /* booleans */ |
| do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); |
| /* roles */ |
| do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); |
| do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); |
| do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); |
| } |
| |
| /* This function performs testing of the dependency handles for module optional |
| * symbols. It is capable of testing 2 scenarios - the dependencies are met |
| * and the dependencies are not met. |
| * |
| * Paramaters: |
| * req_met boolean indicating whether the base policy meets the |
| * requirements for the modules global block. |
| * b index of the base policy in the global bases_met array. |
| * |
| * policy name of the policy module to load for this test. |
| * decl_type name of the unique type found in the module's global |
| * section is to find that avrule_decl. |
| */ |
| static void do_deps_modreq_opt(int req_met, int ret_val, int b, char *policy, char *decl_type) |
| { |
| policydb_t *base; |
| policydb_t mod; |
| policydb_t *mods[] = { &mod }; |
| avrule_decl_t *decl; |
| int ret; |
| sepol_handle_t *h; |
| |
| /* suppress error reporting - this is because we know that we |
| * are going to get errors and don't want libsepol complaining |
| * about it constantly. */ |
| h = sepol_handle_create(); |
| CU_ASSERT_FATAL(h != NULL); |
| sepol_msg_set_callback(h, NULL, NULL); |
| |
| if (req_met) { |
| base = &bases_met[b]; |
| } else { |
| base = &bases_notmet[b]; |
| } |
| |
| CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); |
| |
| /* link the modules and check for the correct return value. |
| */ |
| ret = link_modules(h, base, mods, 1, 0); |
| CU_ASSERT_FATAL(ret == ret_val); |
| policydb_destroy(&mod); |
| if (ret_val < 0) |
| return; |
| |
| decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); |
| CU_ASSERT_FATAL(decl != NULL); |
| |
| if (req_met) { |
| CU_ASSERT(decl->enabled == 1); |
| } else { |
| CU_ASSERT(decl->enabled == 0); |
| } |
| } |
| |
| /* Test that symbol require statements in the global scope of a module |
| * work correctly. This will cover tests 6 - 10 (described above). |
| * |
| * Each of these policies will require as few symbols as possible to |
| * use the required symbol in addition requiring (for example, the type |
| * test also requires an object class for an allow rule). |
| */ |
| static void deps_modreq_opt(void) |
| { |
| /* object classes */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); |
| /* types */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); |
| /* attributes */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); |
| /* booleans */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); |
| /* roles */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); |
| /* permissions */ |
| do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); |
| do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); |
| } |
| |
| int deps_add_tests(CU_pSuite suite) |
| { |
| if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { |
| return CU_get_error(); |
| } |
| |
| if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { |
| return CU_get_error(); |
| } |
| |
| return 0; |
| } |