1/* 2 * Author: Karl MacMillan <kmacmillan@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#include "helpers.h" 70 71#define BASE_MODREQ_TYPE_GLOBAL 0 72#define BASE_MODREQ_ATTR_GLOBAL 1 73#define BASE_MODREQ_OBJ_GLOBAL 2 74#define BASE_MODREQ_BOOL_GLOBAL 3 75#define BASE_MODREQ_ROLE_GLOBAL 4 76#define BASE_MODREQ_PERM_GLOBAL 5 77#define BASE_MODREQ_TYPE_OPT 6 78#define BASE_MODREQ_ATTR_OPT 7 79#define BASE_MODREQ_OBJ_OPT 8 80#define BASE_MODREQ_BOOL_OPT 9 81#define BASE_MODREQ_ROLE_OPT 10 82#define BASE_MODREQ_PERM_OPT 11 83#define NUM_BASES 12 84 85static policydb_t bases_met[NUM_BASES]; 86static policydb_t bases_notmet[NUM_BASES]; 87 88extern int mls; 89 90int deps_test_init(void) 91{ 92 int i; 93 94 /* To test linking we need 1 base per link test and in 95 * order to load them in the init function we have 96 * to keep them all around. Not ideal, but it shouldn't 97 * matter too much. 98 */ 99 for (i = 0; i < NUM_BASES; i++) { 100 if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) 101 return -1; 102 } 103 104 for (i = 0; i < NUM_BASES; i++) { 105 if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) 106 return -1; 107 } 108 109 return 0; 110} 111 112int deps_test_cleanup(void) 113{ 114 int i; 115 116 for (i = 0; i < NUM_BASES; i++) { 117 policydb_destroy(&bases_met[i]); 118 } 119 120 for (i = 0; i < NUM_BASES; i++) { 121 policydb_destroy(&bases_notmet[i]); 122 } 123 124 return 0; 125} 126 127/* This function performs testing of the dependency handles for module global 128 * symbols. It is capable of testing 2 scenarios - the dependencies are met 129 * and the dependencies are not met. 130 * 131 * Parameters: 132 * req_met boolean indicating whether the base policy meets the 133 * requirements for the modules global block. 134 * b index of the base policy in the global bases_met array. 135 * 136 * policy name of the policy module to load for this test. 137 * decl_type name of the unique type found in the module's global 138 * section is to find that avrule_decl. 139 */ 140static void do_deps_modreq_global(int req_met, int b, const char *policy, const char *decl_type) 141{ 142 policydb_t *base; 143 policydb_t mod; 144 policydb_t *mods[] = { &mod }; 145 avrule_decl_t *decl; 146 int ret, link_ret; 147 sepol_handle_t *h; 148 149 /* suppress error reporting - this is because we know that we 150 * are going to get errors and don't want libsepol complaining 151 * about it constantly. */ 152 h = sepol_handle_create(); 153 CU_ASSERT_FATAL(h != NULL); 154 sepol_msg_set_callback(h, NULL, NULL); 155 156 if (req_met) { 157 base = &bases_met[b]; 158 link_ret = 0; 159 } else { 160 base = &bases_notmet[b]; 161 link_ret = -3; 162 } 163 164 CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 165 166 /* link the modules and check for the correct return value. 167 */ 168 ret = link_modules(h, base, mods, 1, 0); 169 CU_ASSERT_FATAL(ret == link_ret); 170 policydb_destroy(&mod); 171 sepol_handle_destroy(h); 172 173 if (!req_met) 174 return; 175 176 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 177 CU_ASSERT_FATAL(decl != NULL); 178 179 CU_ASSERT(decl->enabled == 1); 180} 181 182/* Test that symbol require statements in the global scope of a module 183 * work correctly. This will cover tests 1 - 5 (described above). 184 * 185 * Each of these policies will require as few symbols as possible to 186 * use the required symbol in addition requiring (for example, the type 187 * test also requires an object class for an allow rule). 188 */ 189static void deps_modreq_global(void) 190{ 191 /* object classes */ 192 do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 193 do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 194 /* types */ 195 do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 196 do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 197 /* attributes */ 198 do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 199 do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 200 /* booleans */ 201 do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 202 do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 203 /* roles */ 204 do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 205 do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 206 do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 207 do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 208} 209 210/* This function performs testing of the dependency handles for module optional 211 * symbols. It is capable of testing 2 scenarios - the dependencies are met 212 * and the dependencies are not met. 213 * 214 * Parameters: 215 * req_met boolean indicating whether the base policy meets the 216 * requirements for the modules global block. 217 * b index of the base policy in the global bases_met array. 218 * 219 * policy name of the policy module to load for this test. 220 * decl_type name of the unique type found in the module's global 221 * section is to find that avrule_decl. 222 */ 223static void do_deps_modreq_opt(int req_met, int ret_val, int b, const char *policy, const char *decl_type) 224{ 225 policydb_t *base; 226 policydb_t mod; 227 policydb_t *mods[] = { &mod }; 228 avrule_decl_t *decl; 229 int ret; 230 sepol_handle_t *h; 231 232 /* suppress error reporting - this is because we know that we 233 * are going to get errors and don't want libsepol complaining 234 * about it constantly. */ 235 h = sepol_handle_create(); 236 CU_ASSERT_FATAL(h != NULL); 237 sepol_msg_set_callback(h, NULL, NULL); 238 239 if (req_met) { 240 base = &bases_met[b]; 241 } else { 242 base = &bases_notmet[b]; 243 } 244 245 CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 246 247 /* link the modules and check for the correct return value. 248 */ 249 ret = link_modules(h, base, mods, 1, 0); 250 CU_ASSERT_FATAL(ret == ret_val); 251 policydb_destroy(&mod); 252 sepol_handle_destroy(h); 253 if (ret_val < 0) 254 return; 255 256 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 257 CU_ASSERT_FATAL(decl != NULL); 258 259 if (req_met) { 260 CU_ASSERT(decl->enabled == 1); 261 } else { 262 CU_ASSERT(decl->enabled == 0); 263 } 264} 265 266/* Test that symbol require statements in the global scope of a module 267 * work correctly. This will cover tests 6 - 10 (described above). 268 * 269 * Each of these policies will require as few symbols as possible to 270 * use the required symbol in addition requiring (for example, the type 271 * test also requires an object class for an allow rule). 272 */ 273static void deps_modreq_opt(void) 274{ 275 /* object classes */ 276 do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 277 do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 278 /* types */ 279 do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 280 do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 281 /* attributes */ 282 do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 283 do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 284 /* booleans */ 285 do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 286 do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 287 /* roles */ 288 do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 289 do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 290 /* permissions */ 291 do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 292 do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 293} 294 295int deps_add_tests(CU_pSuite suite) 296{ 297 if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { 298 return CU_get_error(); 299 } 300 301 if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { 302 return CU_get_error(); 303 } 304 305 return 0; 306} 307