• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
83 static policydb_t bases_met[NUM_BASES];
84 static policydb_t bases_notmet[NUM_BASES];
85 
86 extern int mls;
87 
deps_test_init(void)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 
deps_test_cleanup(void)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  */
do_deps_modreq_global(int req_met,int b,const char * policy,const char * decl_type)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  */
deps_modreq_global(void)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  */
do_deps_modreq_opt(int req_met,int ret_val,int b,const char * policy,const char * decl_type)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  */
deps_modreq_opt(void)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 
deps_add_tests(CU_pSuite suite)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