Home | History | Annotate | Download | only in tests
      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, 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  */
    187 static 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  */
    221 static 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  */
    271 static 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 
    293 int 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