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#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 83static policydb_t bases_met[NUM_BASES]; 84static policydb_t bases_notmet[NUM_BASES]; 85 86extern int mls; 87 88int 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 110int 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 */ 138static void do_deps_modreq_global(int req_met, int b, const char *policy, const 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 sepol_handle_destroy(h); 170 171 if (!req_met) 172 return; 173 174 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 175 CU_ASSERT_FATAL(decl != NULL); 176 177 CU_ASSERT(decl->enabled == 1); 178} 179 180/* Test that symbol require statements in the global scope of a module 181 * work correctly. This will cover tests 1 - 5 (described above). 182 * 183 * Each of these policies will require as few symbols as possible to 184 * use the required symbol in addition requiring (for example, the type 185 * test also requires an object class for an allow rule). 186 */ 187static void deps_modreq_global(void) 188{ 189 /* object classes */ 190 do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 191 do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); 192 /* types */ 193 do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 194 do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); 195 /* attributes */ 196 do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 197 do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); 198 /* booleans */ 199 do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 200 do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); 201 /* roles */ 202 do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 203 do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); 204 do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 205 do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); 206} 207 208/* This function performs testing of the dependency handles for module optional 209 * symbols. It is capable of testing 2 scenarios - the dependencies are met 210 * and the dependencies are not met. 211 * 212 * Paramaters: 213 * req_met boolean indicating whether the base policy meets the 214 * requirements for the modules global block. 215 * b index of the base policy in the global bases_met array. 216 * 217 * policy name of the policy module to load for this test. 218 * decl_type name of the unique type found in the module's global 219 * section is to find that avrule_decl. 220 */ 221static void do_deps_modreq_opt(int req_met, int ret_val, int b, const char *policy, const char *decl_type) 222{ 223 policydb_t *base; 224 policydb_t mod; 225 policydb_t *mods[] = { &mod }; 226 avrule_decl_t *decl; 227 int ret; 228 sepol_handle_t *h; 229 230 /* suppress error reporting - this is because we know that we 231 * are going to get errors and don't want libsepol complaining 232 * about it constantly. */ 233 h = sepol_handle_create(); 234 CU_ASSERT_FATAL(h != NULL); 235 sepol_msg_set_callback(h, NULL, NULL); 236 237 if (req_met) { 238 base = &bases_met[b]; 239 } else { 240 base = &bases_notmet[b]; 241 } 242 243 CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); 244 245 /* link the modules and check for the correct return value. 246 */ 247 ret = link_modules(h, base, mods, 1, 0); 248 CU_ASSERT_FATAL(ret == ret_val); 249 policydb_destroy(&mod); 250 sepol_handle_destroy(h); 251 if (ret_val < 0) 252 return; 253 254 decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); 255 CU_ASSERT_FATAL(decl != NULL); 256 257 if (req_met) { 258 CU_ASSERT(decl->enabled == 1); 259 } else { 260 CU_ASSERT(decl->enabled == 0); 261 } 262} 263 264/* Test that symbol require statements in the global scope of a module 265 * work correctly. This will cover tests 6 - 10 (described above). 266 * 267 * Each of these policies will require as few symbols as possible to 268 * use the required symbol in addition requiring (for example, the type 269 * test also requires an object class for an allow rule). 270 */ 271static void deps_modreq_opt(void) 272{ 273 /* object classes */ 274 do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 275 do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); 276 /* types */ 277 do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 278 do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); 279 /* attributes */ 280 do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 281 do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); 282 /* booleans */ 283 do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 284 do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); 285 /* roles */ 286 do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 287 do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); 288 /* permissions */ 289 do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 290 do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); 291} 292 293int deps_add_tests(CU_pSuite suite) 294{ 295 if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { 296 return CU_get_error(); 297 } 298 299 if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { 300 return CU_get_error(); 301 } 302 303 return 0; 304} 305