1 /* 2 * Author: Karl MacMillan <kmacmillan (at) tresys.com> 3 * 4 * Copyright (C) 2006 Tresys Technology, LLC 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "test-deps.h" 22 #include "parse_util.h" 23 #include "helpers.h" 24 25 #include <sepol/policydb/policydb.h> 26 #include <sepol/policydb/link.h> 27 28 #include <stdlib.h> 29 30 /* Tests for dependency checking / handling, specifically: 31 * 32 * 1 type in module global. 33 * 2 attribute in module global. 34 * 3 object class / perm in module global. 35 * 4 boolean in module global. 36 * 5 role in module global. 37 * 38 * 6 type in module optional. 39 * 7 attribute in module optional. 40 * 8 object class / perm in module optional. 41 * 9 boolean in module optional. 42 * 10 role in module optional. 43 * 44 * 11 type in base optional. 45 * 12 attribute in base optional. 46 * 13 object class / perm in base optional. 47 * 14 boolean in base optional. 48 * 15 role in base optional. 49 * 50 * Each of these tests are done with the dependency met and not 51 * met. Additionally, each of the required symbols is used in the 52 * scope it is required. 53 * 54 * In addition to the simple tests, we have test with more complex 55 * modules that test: 56 * 57 * 17 mutual dependencies between two modules. 58 * 18 circular dependency between three modules. 59 * 19 large number of dependencies in a module with a more complex base. 60 * 20 nested optionals with requires. 61 * 62 * Again, each of these tests is done with the requirements met and not 63 * met. 64 */ 65 66 #include <sepol/debug.h> 67 #include <sepol/handle.h> 68 69 #define BASE_MODREQ_TYPE_GLOBAL 0 70 #define BASE_MODREQ_ATTR_GLOBAL 1 71 #define BASE_MODREQ_OBJ_GLOBAL 2 72 #define BASE_MODREQ_BOOL_GLOBAL 3 73 #define BASE_MODREQ_ROLE_GLOBAL 4 74 #define BASE_MODREQ_PERM_GLOBAL 5 75 #define BASE_MODREQ_TYPE_OPT 6 76 #define BASE_MODREQ_ATTR_OPT 7 77 #define BASE_MODREQ_OBJ_OPT 8 78 #define BASE_MODREQ_BOOL_OPT 9 79 #define BASE_MODREQ_ROLE_OPT 10 80 #define BASE_MODREQ_PERM_OPT 11 81 #define NUM_BASES 12 82 83 static policydb_t bases_met[NUM_BASES]; 84 static policydb_t bases_notmet[NUM_BASES]; 85 86 extern int mls; 87 88 int deps_test_init(void) 89 { 90 int i; 91 92 /* To test linking we need 1 base per link test and in 93 * order to load them in the init function we have 94 * to keep them all around. Not ideal, but it shouldn't 95 * matter too much. 96 */ 97 for (i = 0; i < NUM_BASES; i++) { 98 if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) 99 return -1; 100 } 101 102 for (i = 0; i < NUM_BASES; i++) { 103 if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) 104 return -1; 105 } 106 107 return 0; 108 } 109 110 int deps_test_cleanup(void) 111 { 112 int i; 113 114 for (i = 0; i < NUM_BASES; i++) { 115 policydb_destroy(&bases_met[i]); 116 } 117 118 for (i = 0; i < NUM_BASES; i++) { 119 policydb_destroy(&bases_notmet[i]); 120 } 121 122 return 0; 123 } 124 125 /* This function performs testing of the dependency handles for module global 126 * symbols. It is capable of testing 2 scenarios - the dependencies are met 127 * and the dependencies are not met. 128 * 129 * Paramaters: 130 * req_met boolean indicating whether the base policy meets the 131 * requirements for the modules global block. 132 * b index of the base policy in the global bases_met array. 133 * 134 * policy name of the policy module to load for this test. 135 * decl_type name of the unique type found in the module's global 136 * section is to find that avrule_decl. 137 */ 138 static void do_deps_modreq_global(int req_met, int b, char *policy, char *decl_type) 139 { 140 policydb_t *base; 141 policydb_t mod; 142 policydb_t *mods[] = { &mod }; 143 avrule_decl_t *decl; 144 int ret, link_ret; 145 sepol_handle_t *h; 146 147 /* suppress error reporting - this is because we know that we 148 * are going to get errors and don't want libsepol complaining 149 * about it constantly. */ 150 h = sepol_handle_create(); 151 CU_ASSERT_FATAL(h != NULL); 152 sepol_msg_set_callback(h, NULL, NULL); 153 154 if (req_met) { 155 base = &bases_met[b]; 156 link_ret = 0; 157 } else { 158 base = &bases_notmet[b]; 159 link_ret = -3; 160 } 161 162 CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 163 164 /* link the modules and check for the correct return value. 165 */ 166 ret = link_modules(h, base, mods, 1, 0); 167 CU_ASSERT_FATAL(ret == link_ret); 168 policydb_destroy(&mod); 169 170 if (!req_met) 171 return; 172 173 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 174 CU_ASSERT_FATAL(decl != NULL); 175 176 CU_ASSERT(decl->enabled == 1); 177 } 178 179 /* Test that symbol require statements in the global scope of a module 180 * work correctly. This will cover tests 1 - 5 (described above). 181 * 182 * Each of these policies will require as few symbols as possible to 183 * use the required symbol in addition requiring (for example, the type 184 * test also requires an object class for an allow rule). 185 */ 186 static void deps_modreq_global(void) 187 { 188 /* object classes */ 189 do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 190 do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 191 /* types */ 192 do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 193 do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 194 /* attributes */ 195 do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 196 do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 197 /* booleans */ 198 do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 199 do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 200 /* roles */ 201 do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 202 do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 203 do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 204 do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 205 } 206 207 /* This function performs testing of the dependency handles for module optional 208 * symbols. It is capable of testing 2 scenarios - the dependencies are met 209 * and the dependencies are not met. 210 * 211 * Paramaters: 212 * req_met boolean indicating whether the base policy meets the 213 * requirements for the modules global block. 214 * b index of the base policy in the global bases_met array. 215 * 216 * policy name of the policy module to load for this test. 217 * decl_type name of the unique type found in the module's global 218 * section is to find that avrule_decl. 219 */ 220 static void do_deps_modreq_opt(int req_met, int ret_val, int b, char *policy, char *decl_type) 221 { 222 policydb_t *base; 223 policydb_t mod; 224 policydb_t *mods[] = { &mod }; 225 avrule_decl_t *decl; 226 int ret; 227 sepol_handle_t *h; 228 229 /* suppress error reporting - this is because we know that we 230 * are going to get errors and don't want libsepol complaining 231 * about it constantly. */ 232 h = sepol_handle_create(); 233 CU_ASSERT_FATAL(h != NULL); 234 sepol_msg_set_callback(h, NULL, NULL); 235 236 if (req_met) { 237 base = &bases_met[b]; 238 } else { 239 base = &bases_notmet[b]; 240 } 241 242 CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 243 244 /* link the modules and check for the correct return value. 245 */ 246 ret = link_modules(h, base, mods, 1, 0); 247 CU_ASSERT_FATAL(ret == ret_val); 248 policydb_destroy(&mod); 249 if (ret_val < 0) 250 return; 251 252 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 253 CU_ASSERT_FATAL(decl != NULL); 254 255 if (req_met) { 256 CU_ASSERT(decl->enabled == 1); 257 } else { 258 CU_ASSERT(decl->enabled == 0); 259 } 260 } 261 262 /* Test that symbol require statements in the global scope of a module 263 * work correctly. This will cover tests 6 - 10 (described above). 264 * 265 * Each of these policies will require as few symbols as possible to 266 * use the required symbol in addition requiring (for example, the type 267 * test also requires an object class for an allow rule). 268 */ 269 static void deps_modreq_opt(void) 270 { 271 /* object classes */ 272 do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 273 do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 274 /* types */ 275 do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 276 do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 277 /* attributes */ 278 do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 279 do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 280 /* booleans */ 281 do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 282 do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 283 /* roles */ 284 do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 285 do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 286 /* permissions */ 287 do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 288 do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 289 } 290 291 int deps_add_tests(CU_pSuite suite) 292 { 293 if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { 294 return CU_get_error(); 295 } 296 297 if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { 298 return CU_get_error(); 299 } 300 301 return 0; 302 } 303