16cd6a6acSopenharmony_ci/* 26cd6a6acSopenharmony_ci * Author: Karl MacMillan <kmacmillan@tresys.com> 36cd6a6acSopenharmony_ci * 46cd6a6acSopenharmony_ci * Copyright (C) 2006 Tresys Technology, LLC 56cd6a6acSopenharmony_ci * 66cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 76cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 86cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 96cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 106cd6a6acSopenharmony_ci * 116cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 126cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 136cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 146cd6a6acSopenharmony_ci * Lesser General Public License for more details. 156cd6a6acSopenharmony_ci * 166cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 176cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 186cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 196cd6a6acSopenharmony_ci */ 206cd6a6acSopenharmony_ci 216cd6a6acSopenharmony_ci#include "test-deps.h" 226cd6a6acSopenharmony_ci#include "parse_util.h" 236cd6a6acSopenharmony_ci#include "helpers.h" 246cd6a6acSopenharmony_ci 256cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 266cd6a6acSopenharmony_ci#include <sepol/policydb/link.h> 276cd6a6acSopenharmony_ci 286cd6a6acSopenharmony_ci#include <stdlib.h> 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci/* Tests for dependency checking / handling, specifically: 316cd6a6acSopenharmony_ci * 326cd6a6acSopenharmony_ci * 1 type in module global. 336cd6a6acSopenharmony_ci * 2 attribute in module global. 346cd6a6acSopenharmony_ci * 3 object class / perm in module global. 356cd6a6acSopenharmony_ci * 4 boolean in module global. 366cd6a6acSopenharmony_ci * 5 role in module global. 376cd6a6acSopenharmony_ci * 386cd6a6acSopenharmony_ci * 6 type in module optional. 396cd6a6acSopenharmony_ci * 7 attribute in module optional. 406cd6a6acSopenharmony_ci * 8 object class / perm in module optional. 416cd6a6acSopenharmony_ci * 9 boolean in module optional. 426cd6a6acSopenharmony_ci * 10 role in module optional. 436cd6a6acSopenharmony_ci * 446cd6a6acSopenharmony_ci * 11 type in base optional. 456cd6a6acSopenharmony_ci * 12 attribute in base optional. 466cd6a6acSopenharmony_ci * 13 object class / perm in base optional. 476cd6a6acSopenharmony_ci * 14 boolean in base optional. 486cd6a6acSopenharmony_ci * 15 role in base optional. 496cd6a6acSopenharmony_ci * 506cd6a6acSopenharmony_ci * Each of these tests are done with the dependency met and not 516cd6a6acSopenharmony_ci * met. Additionally, each of the required symbols is used in the 526cd6a6acSopenharmony_ci * scope it is required. 536cd6a6acSopenharmony_ci * 546cd6a6acSopenharmony_ci * In addition to the simple tests, we have test with more complex 556cd6a6acSopenharmony_ci * modules that test: 566cd6a6acSopenharmony_ci * 576cd6a6acSopenharmony_ci * 17 mutual dependencies between two modules. 586cd6a6acSopenharmony_ci * 18 circular dependency between three modules. 596cd6a6acSopenharmony_ci * 19 large number of dependencies in a module with a more complex base. 606cd6a6acSopenharmony_ci * 20 nested optionals with requires. 616cd6a6acSopenharmony_ci * 626cd6a6acSopenharmony_ci * Again, each of these tests is done with the requirements met and not 636cd6a6acSopenharmony_ci * met. 646cd6a6acSopenharmony_ci */ 656cd6a6acSopenharmony_ci 666cd6a6acSopenharmony_ci#include <sepol/debug.h> 676cd6a6acSopenharmony_ci#include <sepol/handle.h> 686cd6a6acSopenharmony_ci 696cd6a6acSopenharmony_ci#include "helpers.h" 706cd6a6acSopenharmony_ci 716cd6a6acSopenharmony_ci#define BASE_MODREQ_TYPE_GLOBAL 0 726cd6a6acSopenharmony_ci#define BASE_MODREQ_ATTR_GLOBAL 1 736cd6a6acSopenharmony_ci#define BASE_MODREQ_OBJ_GLOBAL 2 746cd6a6acSopenharmony_ci#define BASE_MODREQ_BOOL_GLOBAL 3 756cd6a6acSopenharmony_ci#define BASE_MODREQ_ROLE_GLOBAL 4 766cd6a6acSopenharmony_ci#define BASE_MODREQ_PERM_GLOBAL 5 776cd6a6acSopenharmony_ci#define BASE_MODREQ_TYPE_OPT 6 786cd6a6acSopenharmony_ci#define BASE_MODREQ_ATTR_OPT 7 796cd6a6acSopenharmony_ci#define BASE_MODREQ_OBJ_OPT 8 806cd6a6acSopenharmony_ci#define BASE_MODREQ_BOOL_OPT 9 816cd6a6acSopenharmony_ci#define BASE_MODREQ_ROLE_OPT 10 826cd6a6acSopenharmony_ci#define BASE_MODREQ_PERM_OPT 11 836cd6a6acSopenharmony_ci#define NUM_BASES 12 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_cistatic policydb_t bases_met[NUM_BASES]; 866cd6a6acSopenharmony_cistatic policydb_t bases_notmet[NUM_BASES]; 876cd6a6acSopenharmony_ci 886cd6a6acSopenharmony_ciextern int mls; 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ciint deps_test_init(void) 916cd6a6acSopenharmony_ci{ 926cd6a6acSopenharmony_ci int i; 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci /* To test linking we need 1 base per link test and in 956cd6a6acSopenharmony_ci * order to load them in the init function we have 966cd6a6acSopenharmony_ci * to keep them all around. Not ideal, but it shouldn't 976cd6a6acSopenharmony_ci * matter too much. 986cd6a6acSopenharmony_ci */ 996cd6a6acSopenharmony_ci for (i = 0; i < NUM_BASES; i++) { 1006cd6a6acSopenharmony_ci if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) 1016cd6a6acSopenharmony_ci return -1; 1026cd6a6acSopenharmony_ci } 1036cd6a6acSopenharmony_ci 1046cd6a6acSopenharmony_ci for (i = 0; i < NUM_BASES; i++) { 1056cd6a6acSopenharmony_ci if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) 1066cd6a6acSopenharmony_ci return -1; 1076cd6a6acSopenharmony_ci } 1086cd6a6acSopenharmony_ci 1096cd6a6acSopenharmony_ci return 0; 1106cd6a6acSopenharmony_ci} 1116cd6a6acSopenharmony_ci 1126cd6a6acSopenharmony_ciint deps_test_cleanup(void) 1136cd6a6acSopenharmony_ci{ 1146cd6a6acSopenharmony_ci int i; 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ci for (i = 0; i < NUM_BASES; i++) { 1176cd6a6acSopenharmony_ci policydb_destroy(&bases_met[i]); 1186cd6a6acSopenharmony_ci } 1196cd6a6acSopenharmony_ci 1206cd6a6acSopenharmony_ci for (i = 0; i < NUM_BASES; i++) { 1216cd6a6acSopenharmony_ci policydb_destroy(&bases_notmet[i]); 1226cd6a6acSopenharmony_ci } 1236cd6a6acSopenharmony_ci 1246cd6a6acSopenharmony_ci return 0; 1256cd6a6acSopenharmony_ci} 1266cd6a6acSopenharmony_ci 1276cd6a6acSopenharmony_ci/* This function performs testing of the dependency handles for module global 1286cd6a6acSopenharmony_ci * symbols. It is capable of testing 2 scenarios - the dependencies are met 1296cd6a6acSopenharmony_ci * and the dependencies are not met. 1306cd6a6acSopenharmony_ci * 1316cd6a6acSopenharmony_ci * Parameters: 1326cd6a6acSopenharmony_ci * req_met boolean indicating whether the base policy meets the 1336cd6a6acSopenharmony_ci * requirements for the modules global block. 1346cd6a6acSopenharmony_ci * b index of the base policy in the global bases_met array. 1356cd6a6acSopenharmony_ci * 1366cd6a6acSopenharmony_ci * policy name of the policy module to load for this test. 1376cd6a6acSopenharmony_ci * decl_type name of the unique type found in the module's global 1386cd6a6acSopenharmony_ci * section is to find that avrule_decl. 1396cd6a6acSopenharmony_ci */ 1406cd6a6acSopenharmony_cistatic void do_deps_modreq_global(int req_met, int b, const char *policy, const char *decl_type) 1416cd6a6acSopenharmony_ci{ 1426cd6a6acSopenharmony_ci policydb_t *base; 1436cd6a6acSopenharmony_ci policydb_t mod; 1446cd6a6acSopenharmony_ci policydb_t *mods[] = { &mod }; 1456cd6a6acSopenharmony_ci avrule_decl_t *decl; 1466cd6a6acSopenharmony_ci int ret, link_ret; 1476cd6a6acSopenharmony_ci sepol_handle_t *h; 1486cd6a6acSopenharmony_ci 1496cd6a6acSopenharmony_ci /* suppress error reporting - this is because we know that we 1506cd6a6acSopenharmony_ci * are going to get errors and don't want libsepol complaining 1516cd6a6acSopenharmony_ci * about it constantly. */ 1526cd6a6acSopenharmony_ci h = sepol_handle_create(); 1536cd6a6acSopenharmony_ci CU_ASSERT_FATAL(h != NULL); 1546cd6a6acSopenharmony_ci sepol_msg_set_callback(h, NULL, NULL); 1556cd6a6acSopenharmony_ci 1566cd6a6acSopenharmony_ci if (req_met) { 1576cd6a6acSopenharmony_ci base = &bases_met[b]; 1586cd6a6acSopenharmony_ci link_ret = 0; 1596cd6a6acSopenharmony_ci } else { 1606cd6a6acSopenharmony_ci base = &bases_notmet[b]; 1616cd6a6acSopenharmony_ci link_ret = -3; 1626cd6a6acSopenharmony_ci } 1636cd6a6acSopenharmony_ci 1646cd6a6acSopenharmony_ci CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 1656cd6a6acSopenharmony_ci 1666cd6a6acSopenharmony_ci /* link the modules and check for the correct return value. 1676cd6a6acSopenharmony_ci */ 1686cd6a6acSopenharmony_ci ret = link_modules(h, base, mods, 1, 0); 1696cd6a6acSopenharmony_ci CU_ASSERT_FATAL(ret == link_ret); 1706cd6a6acSopenharmony_ci policydb_destroy(&mod); 1716cd6a6acSopenharmony_ci sepol_handle_destroy(h); 1726cd6a6acSopenharmony_ci 1736cd6a6acSopenharmony_ci if (!req_met) 1746cd6a6acSopenharmony_ci return; 1756cd6a6acSopenharmony_ci 1766cd6a6acSopenharmony_ci decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 1776cd6a6acSopenharmony_ci CU_ASSERT_FATAL(decl != NULL); 1786cd6a6acSopenharmony_ci 1796cd6a6acSopenharmony_ci CU_ASSERT(decl->enabled == 1); 1806cd6a6acSopenharmony_ci} 1816cd6a6acSopenharmony_ci 1826cd6a6acSopenharmony_ci/* Test that symbol require statements in the global scope of a module 1836cd6a6acSopenharmony_ci * work correctly. This will cover tests 1 - 5 (described above). 1846cd6a6acSopenharmony_ci * 1856cd6a6acSopenharmony_ci * Each of these policies will require as few symbols as possible to 1866cd6a6acSopenharmony_ci * use the required symbol in addition requiring (for example, the type 1876cd6a6acSopenharmony_ci * test also requires an object class for an allow rule). 1886cd6a6acSopenharmony_ci */ 1896cd6a6acSopenharmony_cistatic void deps_modreq_global(void) 1906cd6a6acSopenharmony_ci{ 1916cd6a6acSopenharmony_ci /* object classes */ 1926cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 1936cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 1946cd6a6acSopenharmony_ci /* types */ 1956cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 1966cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 1976cd6a6acSopenharmony_ci /* attributes */ 1986cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 1996cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 2006cd6a6acSopenharmony_ci /* booleans */ 2016cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 2026cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 2036cd6a6acSopenharmony_ci /* roles */ 2046cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 2056cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 2066cd6a6acSopenharmony_ci do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 2076cd6a6acSopenharmony_ci do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 2086cd6a6acSopenharmony_ci} 2096cd6a6acSopenharmony_ci 2106cd6a6acSopenharmony_ci/* This function performs testing of the dependency handles for module optional 2116cd6a6acSopenharmony_ci * symbols. It is capable of testing 2 scenarios - the dependencies are met 2126cd6a6acSopenharmony_ci * and the dependencies are not met. 2136cd6a6acSopenharmony_ci * 2146cd6a6acSopenharmony_ci * Parameters: 2156cd6a6acSopenharmony_ci * req_met boolean indicating whether the base policy meets the 2166cd6a6acSopenharmony_ci * requirements for the modules global block. 2176cd6a6acSopenharmony_ci * b index of the base policy in the global bases_met array. 2186cd6a6acSopenharmony_ci * 2196cd6a6acSopenharmony_ci * policy name of the policy module to load for this test. 2206cd6a6acSopenharmony_ci * decl_type name of the unique type found in the module's global 2216cd6a6acSopenharmony_ci * section is to find that avrule_decl. 2226cd6a6acSopenharmony_ci */ 2236cd6a6acSopenharmony_cistatic void do_deps_modreq_opt(int req_met, int ret_val, int b, const char *policy, const char *decl_type) 2246cd6a6acSopenharmony_ci{ 2256cd6a6acSopenharmony_ci policydb_t *base; 2266cd6a6acSopenharmony_ci policydb_t mod; 2276cd6a6acSopenharmony_ci policydb_t *mods[] = { &mod }; 2286cd6a6acSopenharmony_ci avrule_decl_t *decl; 2296cd6a6acSopenharmony_ci int ret; 2306cd6a6acSopenharmony_ci sepol_handle_t *h; 2316cd6a6acSopenharmony_ci 2326cd6a6acSopenharmony_ci /* suppress error reporting - this is because we know that we 2336cd6a6acSopenharmony_ci * are going to get errors and don't want libsepol complaining 2346cd6a6acSopenharmony_ci * about it constantly. */ 2356cd6a6acSopenharmony_ci h = sepol_handle_create(); 2366cd6a6acSopenharmony_ci CU_ASSERT_FATAL(h != NULL); 2376cd6a6acSopenharmony_ci sepol_msg_set_callback(h, NULL, NULL); 2386cd6a6acSopenharmony_ci 2396cd6a6acSopenharmony_ci if (req_met) { 2406cd6a6acSopenharmony_ci base = &bases_met[b]; 2416cd6a6acSopenharmony_ci } else { 2426cd6a6acSopenharmony_ci base = &bases_notmet[b]; 2436cd6a6acSopenharmony_ci } 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 2466cd6a6acSopenharmony_ci 2476cd6a6acSopenharmony_ci /* link the modules and check for the correct return value. 2486cd6a6acSopenharmony_ci */ 2496cd6a6acSopenharmony_ci ret = link_modules(h, base, mods, 1, 0); 2506cd6a6acSopenharmony_ci CU_ASSERT_FATAL(ret == ret_val); 2516cd6a6acSopenharmony_ci policydb_destroy(&mod); 2526cd6a6acSopenharmony_ci sepol_handle_destroy(h); 2536cd6a6acSopenharmony_ci if (ret_val < 0) 2546cd6a6acSopenharmony_ci return; 2556cd6a6acSopenharmony_ci 2566cd6a6acSopenharmony_ci decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 2576cd6a6acSopenharmony_ci CU_ASSERT_FATAL(decl != NULL); 2586cd6a6acSopenharmony_ci 2596cd6a6acSopenharmony_ci if (req_met) { 2606cd6a6acSopenharmony_ci CU_ASSERT(decl->enabled == 1); 2616cd6a6acSopenharmony_ci } else { 2626cd6a6acSopenharmony_ci CU_ASSERT(decl->enabled == 0); 2636cd6a6acSopenharmony_ci } 2646cd6a6acSopenharmony_ci} 2656cd6a6acSopenharmony_ci 2666cd6a6acSopenharmony_ci/* Test that symbol require statements in the global scope of a module 2676cd6a6acSopenharmony_ci * work correctly. This will cover tests 6 - 10 (described above). 2686cd6a6acSopenharmony_ci * 2696cd6a6acSopenharmony_ci * Each of these policies will require as few symbols as possible to 2706cd6a6acSopenharmony_ci * use the required symbol in addition requiring (for example, the type 2716cd6a6acSopenharmony_ci * test also requires an object class for an allow rule). 2726cd6a6acSopenharmony_ci */ 2736cd6a6acSopenharmony_cistatic void deps_modreq_opt(void) 2746cd6a6acSopenharmony_ci{ 2756cd6a6acSopenharmony_ci /* object classes */ 2766cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 2776cd6a6acSopenharmony_ci do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 2786cd6a6acSopenharmony_ci /* types */ 2796cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 2806cd6a6acSopenharmony_ci do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 2816cd6a6acSopenharmony_ci /* attributes */ 2826cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 2836cd6a6acSopenharmony_ci do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 2846cd6a6acSopenharmony_ci /* booleans */ 2856cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 2866cd6a6acSopenharmony_ci do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 2876cd6a6acSopenharmony_ci /* roles */ 2886cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 2896cd6a6acSopenharmony_ci do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 2906cd6a6acSopenharmony_ci /* permissions */ 2916cd6a6acSopenharmony_ci do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 2926cd6a6acSopenharmony_ci do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 2936cd6a6acSopenharmony_ci} 2946cd6a6acSopenharmony_ci 2956cd6a6acSopenharmony_ciint deps_add_tests(CU_pSuite suite) 2966cd6a6acSopenharmony_ci{ 2976cd6a6acSopenharmony_ci if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { 2986cd6a6acSopenharmony_ci return CU_get_error(); 2996cd6a6acSopenharmony_ci } 3006cd6a6acSopenharmony_ci 3016cd6a6acSopenharmony_ci if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { 3026cd6a6acSopenharmony_ci return CU_get_error(); 3036cd6a6acSopenharmony_ci } 3046cd6a6acSopenharmony_ci 3056cd6a6acSopenharmony_ci return 0; 3066cd6a6acSopenharmony_ci} 307