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,char * policy,char * decl_type)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 */
deps_modreq_global(void)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 */
do_deps_modreq_opt(int req_met,int ret_val,int b,char * policy,char * decl_type)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 */
deps_modreq_opt(void)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
deps_add_tests(CU_pSuite suite)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