1 /*
2 * This file is public domain software, i.e. not copyrighted.
3 *
4 * Warranty Exclusion
5 * ------------------
6 * You agree that this software is a non-commercially developed program
7 * that may contain "bugs" (as that term is used in the industry) and
8 * that it may not function as intended. The software is licensed
9 * "as is". NSA makes no, and hereby expressly disclaims all, warranties,
10 * express, implied, statutory, or otherwise with respect to the software,
11 * including noninfringement and the implied warranties of merchantability
12 * and fitness for a particular purpose.
13 *
14 * Limitation of Liability
15 *-----------------------
16 * In no event will NSA be liable for any damages, including loss of data,
17 * lost profits, cost of cover, or other special, incidental, consequential,
18 * direct or indirect damages arising from the software or the use thereof,
19 * however caused and on any theory of liability. This limitation will apply
20 * even if NSA has been advised of the possibility of such damage. You
21 * acknowledge that this is a reasonable allocation of risk.
22 *
23 * Original author: James Carter
24 */
25
26 #include <sepol/policydb/ebitmap.h>
27
28 #include "cil_internal.h"
29 #include "cil_find.h"
30 #include "cil_flavor.h"
31 #include "cil_list.h"
32 #include "cil_strpool.h"
33 #include "cil_log.h"
34 #include "cil_symtab.h"
35 #include "cil_build_ast.h"
36 #include "cil_copy_ast.h"
37 #include "cil_deny.h"
38
39 #define CIL_DENY_ATTR_PREFIX "deny_rule_attr"
40
41 /*
42 * A deny rule is like a neverallow rule, except that permissions are
43 * removed rather than an error reported.
44 *
45 * (allow S1 T1 P1)
46 * (deny S2 T2 P2)
47 *
48 * First, write the allow rule with all of the permissions not in the deny rule
49 * P3 = P1 and not P2
50 * (allow S1 T1 P3)
51 *
52 * Obviously, the rule is only written if P3 is not an empty list. This goes
53 * for the rest of the rules as well--they are only written if the source and
54 * target exist.
55 *
56 * The remaining rules will only involve the common permissions
57 * P4 = P1 and P2
58 *
59 * Next, write the allow rule for any types in S1 that are not in S2
60 * S3 = S1 and not S2
61 * (allow S3 T1 P4)
62 *
63 * Finally, write any allow rules needed to cover the types in T1 that are
64 * not in T2. Since, T1 and T2 might be "self", "notself", or "other", this
65 * requires more complicated handling. Any rule with "self" will not match
66 * a rule with either "notself" or "other".
67 *
68 * if (T1 is self and T2 is self) or (T1 is notself and T2 is notself) then
69 * Nothing more needs to be done.
70 *
71 * The rest of the rules will depend on the intersection of S1 and S2
72 * which cannot be the empty set since the allow and deny rules match.
73 * S4 = S1 and S2
74 *
75 * if T1 is notself or T1 is other or T2 is notself or T2 is other then
76 * if T1 is notself then
77 * if T2 is other then
78 * T = ALL and not S2
79 * (allow S4 T P4)
80 * else [T2 is not self, notself, or other]
81 * S5 = S4 and not T2
82 * S6 = S4 and T2
83 * TA = ALL and not T2
84 * TB = TA and not S4
85 * (allow S6 TA P4)
86 * (allow S5 TB P4)
87 * if cardinality(S5) > 1 then
88 * (allow S5 other P4)
89 * else if T1 is other then
90 * (allow S3 S4 P4)
91 * if T2 is notself then
92 * [Nothing else is needed]
93 * else if T2 is other then
94 * (allow S4 S3 P4)
95 * else [T2 is not self, notself, or other]
96 * S5 = S4 and not T2
97 * S6 = S4 and T2
98 * TC = S1 and not T2
99 * TD = S3 and not T2
100 * (allow S6 TC P4)
101 * (allow S5 TD P4)
102 * if cardinality(S5) > 1 then
103 * (allow S5 other P4)
104 * else [T1 is not self, notself, or other]
105 * S8 = S4 and T1
106 * (allow S8 self P4)
107 * if T2 is notself then
108 * [Nothing else is needed]
109 * else [T2 is other]
110 * T = T1 and not S2
111 * (allow S4 T P4)
112 * else [Neither T1 nor T2 are notself or other]
113 * if T1 is self and T2 is not self then
114 * S5 = S4 and not T2
115 * (allow S5 self P4)
116 * else if T1 is not self and T2 is self then
117 * S7 = S4 and not T1
118 * S8 = S4 and T1
119 * T8 = T1 and not S4
120 * (allow S7 T1 P4)
121 * (allow S8 T8 P4)
122 * if cardinality(S8) > 1 then
123 * (allow S8 other P4)
124 * else [Neither T1 nor T2 is self]
125 * T3 = T1 and not T2
126 * (allow S4 T3 P4)
127 */
128
cil_perm_match(const struct cil_perm * p1,const struct cil_list * pl2)129 static int cil_perm_match(const struct cil_perm *p1, const struct cil_list *pl2)
130 {
131 struct cil_list_item *curr;
132
133 cil_list_for_each(curr, pl2) {
134 struct cil_perm *p = curr->data;
135 if (p == p1) {
136 return CIL_TRUE;
137 }
138 }
139 return CIL_FALSE;
140 }
141
cil_class_perm_match(const struct cil_class * c1,const struct cil_perm * p1,const struct cil_list * cpl2)142 static int cil_class_perm_match(const struct cil_class *c1, const struct cil_perm *p1, const struct cil_list *cpl2)
143 {
144 struct cil_list_item *curr;
145
146 cil_list_for_each(curr, cpl2) {
147 if (curr->flavor == CIL_CLASSPERMS) {
148 struct cil_classperms *cp = curr->data;
149 if (FLAVOR(cp->class) == CIL_CLASS) {
150 if (cp->class == c1) {
151 if (cil_perm_match(p1, cp->perms)) {
152 return CIL_TRUE;
153 }
154 }
155 } else { /* MAP */
156 struct cil_list_item *p;
157 cil_list_for_each(p, cp->perms) {
158 struct cil_perm *cmp = p->data;
159 if (cil_class_perm_match(c1, p1, cmp->classperms)) {
160 return CIL_TRUE;
161 }
162 }
163 }
164 } else { /* SET */
165 struct cil_classperms_set *cp_set = curr->data;
166 struct cil_classpermission *cp = cp_set->set;
167 if (cil_class_perm_match(c1, p1, cp->classperms)) {
168 return CIL_TRUE;
169 }
170 }
171 }
172 return CIL_FALSE;
173 }
174
cil_classperms_match_any(const struct cil_classperms * cp1,const struct cil_list * cpl2)175 static int cil_classperms_match_any(const struct cil_classperms *cp1, const struct cil_list *cpl2)
176 {
177 struct cil_list_item *curr;
178
179 cil_list_for_each(curr, cp1->perms) {
180 struct cil_perm *perm = curr->data;
181 if (cil_class_perm_match(cp1->class, perm, cpl2)) {
182 return CIL_TRUE;
183 }
184 }
185 return CIL_FALSE;
186 }
187
cil_classperms_list_match_any(const struct cil_list * cpl1,const struct cil_list * cpl2)188 int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2)
189 {
190 struct cil_list_item *curr;
191
192 if (!cpl1 || !cpl2) {
193 return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
194 }
195
196 cil_list_for_each(curr, cpl1) {
197 if (curr->flavor == CIL_CLASSPERMS) {
198 struct cil_classperms *cp = curr->data;
199 if (FLAVOR(cp->class) == CIL_CLASS) {
200 if (cil_classperms_match_any(cp, cpl2)) {
201 return CIL_TRUE;
202 }
203 } else { /* MAP */
204 struct cil_list_item *p;
205 cil_list_for_each(p, cp->perms) {
206 struct cil_perm *cmp = p->data;
207 if (cil_classperms_list_match_any(cmp->classperms, cpl2)) {
208 return CIL_TRUE;
209 }
210 }
211 }
212 } else { /* SET */
213 struct cil_classperms_set *cp_set = curr->data;
214 struct cil_classpermission *cp = cp_set->set;
215 if (cil_classperms_list_match_any(cp->classperms, cpl2)) {
216 return CIL_TRUE;
217 }
218 }
219 }
220 return CIL_FALSE;
221 }
222
cil_classperms_match_all(const struct cil_classperms * cp1,const struct cil_list * cpl2)223 static int cil_classperms_match_all(const struct cil_classperms *cp1, const struct cil_list *cpl2)
224 {
225 struct cil_list_item *curr;
226
227 cil_list_for_each(curr, cp1->perms) {
228 struct cil_perm *perm = curr->data;
229 if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
230 return CIL_FALSE;
231 }
232 }
233 return CIL_TRUE;
234 }
235
cil_classperms_list_match_all(const struct cil_list * cpl1,const struct cil_list * cpl2)236 int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2)
237 {
238 struct cil_list_item *curr;
239
240 if (!cpl1 || !cpl2) {
241 return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
242 }
243
244 cil_list_for_each(curr, cpl1) {
245 if (curr->flavor == CIL_CLASSPERMS) {
246 struct cil_classperms *cp = curr->data;
247 if (FLAVOR(cp->class) == CIL_CLASS) {
248 if (!cil_classperms_match_all(cp, cpl2)) {
249 return CIL_FALSE;
250 }
251 } else { /* MAP */
252 struct cil_list_item *p;
253 cil_list_for_each(p, cp->perms) {
254 struct cil_perm *cmp = p->data;
255 if (!cil_classperms_list_match_all(cmp->classperms, cpl2)) {
256 return CIL_FALSE;
257 }
258 }
259 }
260 } else { /* SET */
261 struct cil_classperms_set *cp_set = curr->data;
262 struct cil_classpermission *cp = cp_set->set;
263 if (!cil_classperms_list_match_all(cp->classperms, cpl2)) {
264 return CIL_FALSE;
265 }
266 }
267 }
268 return CIL_TRUE;
269 }
270
cil_classperms_copy(struct cil_classperms ** new,const struct cil_classperms * old)271 static void cil_classperms_copy(struct cil_classperms **new, const struct cil_classperms *old)
272 {
273 cil_classperms_init(new);
274 (*new)->class_str = old->class_str;
275 (*new)->class = old->class;
276 cil_copy_list(old->perm_strs, &(*new)->perm_strs);
277 cil_copy_list(old->perms, &(*new)->perms);
278 }
279
cil_classperms_set_copy(struct cil_classperms_set ** new,const struct cil_classperms_set * old)280 static void cil_classperms_set_copy(struct cil_classperms_set **new, const struct cil_classperms_set *old)
281 {
282 cil_classperms_set_init(new);
283 (*new)->set_str = old->set_str;
284 (*new)->set = old->set;
285 }
286
cil_classperms_list_copy(struct cil_list ** new,const struct cil_list * old)287 void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old)
288 {
289 struct cil_list_item *curr;
290
291 if (!new) {
292 return;
293 }
294
295 if (!old) {
296 *new = NULL;
297 return;
298 }
299
300 cil_list_init(new, CIL_LIST);
301
302 cil_list_for_each(curr, old) {
303 if (curr->flavor == CIL_CLASSPERMS) {
304 struct cil_classperms *new_cp;
305 cil_classperms_copy(&new_cp, curr->data);
306 cil_list_append(*new, CIL_CLASSPERMS, new_cp);
307 } else { /* SET */
308 struct cil_classperms_set *new_cps;
309 cil_classperms_set_copy(&new_cps, curr->data);
310 cil_list_append(*new, CIL_CLASSPERMS_SET, new_cps);
311 }
312 }
313
314 if (cil_list_is_empty(*new)) {
315 cil_list_destroy(new, CIL_FALSE);
316 }
317 }
318
319 /* Append cp1 and cpl2 to result */
cil_classperms_and(struct cil_list ** result,const struct cil_classperms * cp1,const struct cil_list * cpl2)320 static void cil_classperms_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
321 {
322 struct cil_classperms *new_cp = NULL;
323 struct cil_list_item *curr;
324
325 if (cil_classperms_match_all(cp1, cpl2)) {
326 cil_classperms_copy(&new_cp, cp1);
327 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
328 return;
329 }
330
331 cil_list_for_each(curr, cp1->perms) {
332 struct cil_perm *perm = curr->data;
333 if (cil_class_perm_match(cp1->class, perm, cpl2)) {
334 if (new_cp == NULL) {
335 cil_classperms_init(&new_cp);
336 new_cp->class_str = cp1->class_str;
337 new_cp->class = cp1->class;
338 cil_list_init(&new_cp->perm_strs, CIL_PERM);
339 cil_list_init(&new_cp->perms, CIL_PERM);
340 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
341 }
342 cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
343 cil_list_append(new_cp->perms, CIL_DATUM, perm);
344 }
345 }
346 }
347
348 /* Append cp1 and cpl2 to result */
cil_classperms_map_and(struct cil_list ** result,const struct cil_classperms * cp1,const struct cil_list * cpl2)349 static void cil_classperms_map_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
350 {
351 struct cil_classperms *new_cp = NULL;
352 struct cil_list_item *p;
353
354 cil_list_for_each(p, cp1->perms) {
355 struct cil_perm *map_perm = p->data;
356 if (cil_classperms_list_match_all(map_perm->classperms, cpl2)) {
357 if (new_cp == NULL) {
358 cil_classperms_init(&new_cp);
359 new_cp->class_str = cp1->class_str;
360 new_cp->class = cp1->class;
361 cil_list_init(&new_cp->perm_strs, CIL_PERM);
362 cil_list_init(&new_cp->perms, CIL_PERM);
363 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
364 }
365 cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
366 cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
367 } else {
368 struct cil_list *new_cpl = NULL;
369 cil_classperms_list_and(&new_cpl, map_perm->classperms, cpl2);
370 if (new_cpl) {
371 struct cil_list_item *i;
372 cil_list_for_each(i, new_cpl) {
373 cil_list_append(*result, i->flavor, i->data);
374 }
375 cil_list_destroy(&new_cpl, CIL_FALSE);
376 }
377 }
378 }
379 }
380
381 /* Append cps1 and cpl2 to result */
cil_classperms_set_and(struct cil_list ** result,const struct cil_classperms_set * cps1,const struct cil_list * cpl2)382 static void cil_classperms_set_and(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2)
383 {
384 struct cil_classpermission *cp = cps1->set;
385
386 if (cil_classperms_list_match_all(cp->classperms, cpl2)) {
387 struct cil_classperms_set *new_cps;
388 cil_classperms_set_copy(&new_cps, cps1);
389 cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
390 } else {
391 struct cil_list *new_cpl;
392 cil_classperms_list_and(&new_cpl, cp->classperms, cpl2);
393 if (new_cpl) {
394 struct cil_list_item *i;
395 cil_list_for_each(i, new_cpl) {
396 cil_list_append(*result, i->flavor, i->data);
397 }
398 cil_list_destroy(&new_cpl, CIL_FALSE);
399 }
400 }
401 }
402
403 /* result = cpl1 and cpl2 */
cil_classperms_list_and(struct cil_list ** result,const struct cil_list * cpl1,const struct cil_list * cpl2)404 void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2)
405 {
406 struct cil_list_item *curr;
407
408 if (!result) {
409 return;
410 }
411
412 if (!cpl1 || !cpl2) {
413 *result = NULL;
414 return;
415 }
416
417 if (cil_classperms_list_match_all(cpl1, cpl2)) {
418 cil_classperms_list_copy(result, cpl1);
419 return;
420 }
421
422 cil_list_init(result, CIL_LIST);
423
424 cil_list_for_each(curr, cpl1) {
425 if (curr->flavor == CIL_CLASSPERMS) {
426 struct cil_classperms *cp = curr->data;
427 if (FLAVOR(cp->class) == CIL_CLASS) {
428 cil_classperms_and(result, cp, cpl2);
429 } else { /* MAP */
430 cil_classperms_map_and(result, cp, cpl2);
431 }
432 } else { /* SET */
433 struct cil_classperms_set *cps = curr->data;
434 cil_classperms_set_and(result, cps, cpl2);
435 }
436 }
437
438 if (cil_list_is_empty(*result)) {
439 cil_list_destroy(result, CIL_FALSE);
440 }
441 }
442
443 /* Append cp1 and not cpl2 to result */
cil_classperms_andnot(struct cil_list ** result,const struct cil_classperms * cp1,const struct cil_list * cpl2)444 static void cil_classperms_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
445 {
446 struct cil_classperms *new_cp = NULL;
447 struct cil_list_item *curr;
448
449 if (!cil_classperms_match_any(cp1, cpl2)) {
450 cil_classperms_copy(&new_cp, cp1);
451 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
452 return;
453 }
454
455 cil_list_for_each(curr, cp1->perms) {
456 struct cil_perm *perm = curr->data;
457 if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
458 if (new_cp == NULL) {
459 cil_classperms_init(&new_cp);
460 new_cp->class_str = cp1->class_str;
461 new_cp->class = cp1->class;
462 cil_list_init(&new_cp->perm_strs, CIL_PERM);
463 cil_list_init(&new_cp->perms, CIL_PERM);
464 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
465 }
466 cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
467 cil_list_append(new_cp->perms, CIL_DATUM, perm);
468 }
469 }
470 }
471
472 /* Append cp1 and not cpl2 to result */
cil_classperms_map_andnot(struct cil_list ** result,const struct cil_classperms * cp1,const struct cil_list * cpl2)473 static void cil_classperms_map_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
474 {
475 struct cil_classperms *new_cp = NULL;
476 struct cil_list_item *p;
477
478 cil_list_for_each(p, cp1->perms) {
479 struct cil_perm *map_perm = p->data;
480 if (!cil_classperms_list_match_any(map_perm->classperms, cpl2)) {
481 if (new_cp == NULL) {
482 cil_classperms_init(&new_cp);
483 new_cp->class_str = cp1->class_str;
484 new_cp->class = cp1->class;
485 cil_list_init(&new_cp->perm_strs, CIL_PERM);
486 cil_list_init(&new_cp->perms, CIL_PERM);
487 cil_list_append(*result, CIL_CLASSPERMS, new_cp);
488 }
489 cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
490 cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
491 } else {
492 struct cil_list *new_cpl = NULL;
493 cil_classperms_list_andnot(&new_cpl, map_perm->classperms, cpl2);
494 if (new_cpl) {
495 struct cil_list_item *i;
496 cil_list_for_each(i, new_cpl) {
497 cil_list_append(*result, i->flavor, i->data);
498 }
499 cil_list_destroy(&new_cpl, CIL_FALSE);
500 }
501 }
502 }
503 }
504
505 /* Append cps1 and not cpl2 to result */
cil_classperms_set_andnot(struct cil_list ** result,const struct cil_classperms_set * cps1,const struct cil_list * cpl2)506 static void cil_classperms_set_andnot(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2)
507 {
508 struct cil_classpermission *cp = cps1->set;
509
510 if (!cil_classperms_list_match_any(cp->classperms, cpl2)) {
511 struct cil_classperms_set *new_cps;
512 cil_classperms_set_copy(&new_cps, cps1);
513 cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
514 } else {
515 struct cil_list *new_cpl;
516 cil_classperms_list_andnot(&new_cpl, cp->classperms, cpl2);
517 if (new_cpl) {
518 struct cil_list_item *i;
519 cil_list_for_each(i, new_cpl) {
520 cil_list_append(*result, i->flavor, i->data);
521 }
522 cil_list_destroy(&new_cpl, CIL_FALSE);
523 }
524 }
525 }
526
527 /* result = cpl1 and not cpl2 */
cil_classperms_list_andnot(struct cil_list ** result,const struct cil_list * cpl1,const struct cil_list * cpl2)528 void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2)
529 {
530 struct cil_list_item *curr;
531
532 if (!result) {
533 return;
534 }
535
536 if (!cpl1) {
537 *result = NULL;
538 return;
539 }
540
541 if (!cpl2 || !cil_classperms_list_match_any(cpl1, cpl2)) {
542 cil_classperms_list_copy(result, cpl1);
543 return;
544 }
545
546 cil_list_init(result, CIL_LIST);
547
548 cil_list_for_each(curr, cpl1) {
549 if (curr->flavor == CIL_CLASSPERMS) {
550 struct cil_classperms *cp = curr->data;
551 if (FLAVOR(cp->class) == CIL_CLASS) {
552 cil_classperms_andnot(result, cp, cpl2);
553 } else { /* MAP */
554 cil_classperms_map_andnot(result, cp, cpl2);
555 }
556 } else { /* SET */
557 struct cil_classperms_set *cps = curr->data;
558 cil_classperms_set_andnot(result, cps, cpl2);
559 }
560 }
561
562 if (cil_list_is_empty(*result)) {
563 cil_list_destroy(result, CIL_FALSE);
564 }
565 }
566
cil_datum_cardinality(const struct cil_symtab_datum * d)567 static int cil_datum_cardinality(const struct cil_symtab_datum *d)
568 {
569 if (!d) {
570 return 0;
571 }
572 if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
573 return 1;
574 } else {
575 struct cil_typeattribute *a = (struct cil_typeattribute *)d;
576 return ebitmap_cardinality(a->types);
577 }
578 }
579
580 /* result = ALL and not d2 */
cil_datum_not(ebitmap_t * result,const struct cil_symtab_datum * d,int max)581 static int cil_datum_not(ebitmap_t *result, const struct cil_symtab_datum *d, int max)
582 {
583 int rc = SEPOL_OK;
584
585 if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
586 struct cil_type *t = (struct cil_type *)d;
587 ebitmap_t e;
588
589 ebitmap_init(&e);
590 rc = ebitmap_set_bit(&e, t->value, 1);
591 if (rc != SEPOL_OK) {
592 ebitmap_destroy(&e);
593 goto exit;
594 }
595
596 ebitmap_init(result);
597 rc = ebitmap_not(result, &e, max);
598 if (rc != SEPOL_OK) {
599 ebitmap_destroy(&e);
600 ebitmap_destroy(result);
601 goto exit;
602 }
603 ebitmap_destroy(&e);
604 } else {
605 struct cil_typeattribute *a = (struct cil_typeattribute *)d;
606
607 ebitmap_init(result);
608 rc = ebitmap_not(result, a->types, max);
609 if (rc != SEPOL_OK) {
610 ebitmap_destroy(result);
611 goto exit;
612 }
613 }
614 exit:
615 return rc;
616 }
617
618 /* result = d1 and d2 */
cil_datums_and(ebitmap_t * result,const struct cil_symtab_datum * d1,const struct cil_symtab_datum * d2)619 static int cil_datums_and(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2)
620 {
621 int rc = SEPOL_OK;
622 enum cil_flavor f1 = FLAVOR(d1);
623 enum cil_flavor f2 = FLAVOR(d2);
624
625 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
626 struct cil_type *t1 = (struct cil_type *)d1;
627 struct cil_type *t2 = (struct cil_type *)d2;
628 ebitmap_init(result);
629 if (t1->value == t2->value) {
630 rc = ebitmap_set_bit(result, t1->value, 1);
631 if (rc != SEPOL_OK) {
632 ebitmap_destroy(result);
633 goto exit;
634 }
635 }
636 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
637 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
638 struct cil_type *t2 = (struct cil_type *)d2;
639 ebitmap_init(result);
640 if (ebitmap_get_bit(a1->types, t2->value)) {
641 rc = ebitmap_set_bit(result, t2->value, 1);
642 if (rc != SEPOL_OK) {
643 ebitmap_destroy(result);
644 goto exit;
645 }
646 }
647 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
648 struct cil_type *t1 = (struct cil_type *)d1;
649 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
650 ebitmap_init(result);
651 if (ebitmap_get_bit(a2->types, t1->value)) {
652 rc = ebitmap_set_bit(result, t1->value, 1);
653 if (rc != SEPOL_OK) {
654 ebitmap_destroy(result);
655 goto exit;
656 }
657 }
658 } else {
659 /* Both are attributes */
660 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
661 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
662 rc = ebitmap_and(result, a1->types, a2->types);
663 if (rc != SEPOL_OK) {
664 ebitmap_destroy(result);
665 goto exit;
666 }
667 }
668 exit:
669 return rc;
670 }
671
672 /* result = d1 and not d2 */
cil_datums_andnot(ebitmap_t * result,const struct cil_symtab_datum * d1,const struct cil_symtab_datum * d2)673 static int cil_datums_andnot(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2)
674 {
675 int rc = SEPOL_OK;
676 enum cil_flavor f1 = FLAVOR(d1);
677 enum cil_flavor f2 = FLAVOR(d2);
678
679 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
680 struct cil_type *t1 = (struct cil_type *)d1;
681 struct cil_type *t2 = (struct cil_type *)d2;
682 ebitmap_init(result);
683 if (t1->value != t2->value) {
684 rc = ebitmap_set_bit(result, t1->value, 1);
685 if (rc != SEPOL_OK) {
686 ebitmap_destroy(result);
687 goto exit;
688 }
689 }
690 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
691 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
692 struct cil_type *t2 = (struct cil_type *)d2;
693 rc = ebitmap_cpy(result, a1->types);
694 if (rc != SEPOL_OK) {
695 goto exit;
696 }
697 rc = ebitmap_set_bit(result, t2->value, 0);
698 if (rc != SEPOL_OK) {
699 ebitmap_destroy(result);
700 goto exit;
701 }
702 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
703 struct cil_type *t1 = (struct cil_type *)d1;
704 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
705 ebitmap_init(result);
706 if (!ebitmap_get_bit(a2->types, t1->value)) {
707 rc = ebitmap_set_bit(result, t1->value, 1);
708 if (rc != SEPOL_OK) {
709 ebitmap_destroy(result);
710 goto exit;
711 }
712 }
713 } else {
714 /* Both are attributes */
715 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
716 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
717 rc = ebitmap_andnot(result, a1->types, a2->types, a1->types->highbit);
718 if (rc != SEPOL_OK) {
719 ebitmap_destroy(result);
720 goto exit;
721 }
722 }
723 exit:
724 return rc;
725 }
726
num_digits(unsigned n)727 static size_t num_digits(unsigned n)
728 {
729 size_t num = 1;
730 while (n >= 10) {
731 n /= 10;
732 num++;
733 }
734 return num;
735 }
736
cil_create_new_attribute_name(unsigned num)737 static char *cil_create_new_attribute_name(unsigned num)
738 {
739 char *s1 = NULL;
740 char *s2 = NULL;
741 size_t len_num = num_digits(num);
742 size_t len = strlen(CIL_DENY_ATTR_PREFIX) + 1 + len_num + 1;
743 int rc;
744
745 if (len >= CIL_MAX_NAME_LENGTH) {
746 cil_log(CIL_ERR, "Name length greater than max name length of %d",
747 CIL_MAX_NAME_LENGTH);
748 goto exit;
749 }
750
751 s1 = cil_malloc(len);
752 rc = snprintf(s1, len, "%s_%u", CIL_DENY_ATTR_PREFIX, num);
753 if (rc < 0 || (size_t)rc >= len) {
754 cil_log(CIL_ERR, "Error creating new attribute name");
755 free(s1);
756 goto exit;
757 }
758
759 s2 = cil_strpool_add(s1);
760 free(s1);
761
762 exit:
763 return s2;
764 }
765
cil_create_and_expr_list(enum cil_flavor f1,void * v1,enum cil_flavor f2,void * v2)766 static struct cil_list *cil_create_and_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
767 {
768 struct cil_list *expr;
769
770 cil_list_init(&expr, CIL_TYPE);
771 cil_list_append(expr, CIL_OP, (void *)CIL_AND);
772 cil_list_append(expr, f1, v1);
773 cil_list_append(expr, f2, v2);
774
775 return expr;
776 }
777
cil_create_andnot_expr_list(enum cil_flavor f1,void * v1,enum cil_flavor f2,void * v2)778 static struct cil_list *cil_create_andnot_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
779 {
780 struct cil_list *expr, *sub_expr;
781
782 cil_list_init(&expr, CIL_TYPE);
783 cil_list_append(expr, CIL_OP, (void *)CIL_AND);
784 cil_list_append(expr, f1, v1);
785 cil_list_init(&sub_expr, CIL_TYPE);
786 cil_list_append(sub_expr, CIL_OP, (void *)CIL_NOT);
787 cil_list_append(sub_expr, f2, v2);
788 cil_list_append(expr, CIL_LIST, sub_expr);
789
790 return expr;
791 }
792
cil_create_and_insert_node(struct cil_tree_node * prev,enum cil_flavor flavor,void * data)793 static struct cil_tree_node *cil_create_and_insert_node(struct cil_tree_node *prev, enum cil_flavor flavor, void *data)
794 {
795 struct cil_tree_node *new;
796
797 cil_tree_node_init(&new);
798 new->parent = prev->parent;
799 new->line = prev->line;
800 new->hll_offset = prev->hll_offset;
801 new->flavor = flavor;
802 new->data = data;
803 new->next = prev->next;
804 prev->next = new;
805
806 return new;
807 }
808
cil_create_and_insert_attribute_and_set(struct cil_db * db,struct cil_tree_node * prev,struct cil_list * str_expr,struct cil_list * datum_expr,ebitmap_t * types,struct cil_symtab_datum ** d)809 static int cil_create_and_insert_attribute_and_set(struct cil_db *db, struct cil_tree_node *prev, struct cil_list *str_expr, struct cil_list *datum_expr, ebitmap_t *types, struct cil_symtab_datum **d)
810 {
811 struct cil_tree_node *attr_node = NULL;
812 char *name;
813 struct cil_typeattribute *attr = NULL;
814 struct cil_tree_node *attrset_node = NULL;
815 struct cil_typeattributeset *attrset = NULL;
816 symtab_t *symtab = NULL;
817 int rc = SEPOL_ERR;
818
819 name = cil_create_new_attribute_name(db->num_types_and_attrs);
820 if (!name) {
821 goto exit;
822 }
823
824 cil_typeattributeset_init(&attrset);
825 attrset->attr_str = name;
826 attrset->str_expr = str_expr;
827 attrset->datum_expr = datum_expr;
828
829 cil_typeattribute_init(&attr);
830 cil_list_init(&attr->expr_list, CIL_TYPE);
831 cil_list_append(attr->expr_list, CIL_LIST, datum_expr);
832 attr->types = types;
833 attr->used = CIL_ATTR_AVRULE;
834 attr->keep = (ebitmap_cardinality(types) < db->attrs_expand_size) ? CIL_FALSE : CIL_TRUE;
835
836 attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr);
837 attrset_node = cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset);
838
839 rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES);
840 if (rc != SEPOL_OK) {
841 goto exit;
842 }
843
844 rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node);
845 if (rc != SEPOL_OK) {
846 goto exit;
847 }
848
849 db->num_types_and_attrs++;
850
851 *d = &attr->datum;
852
853 return SEPOL_OK;
854
855 exit:
856 if (attr_node) {
857 cil_destroy_typeattribute(attr_node->data); // This will not destroy datum_expr
858 free(attr_node);
859 }
860 if (attrset_node) {
861 prev->next = attrset_node->next;
862 free(attrset_node);
863 }
864 return rc;
865 }
866
867 struct attr_symtab_map_data {
868 struct cil_symtab_datum *d;
869 ebitmap_t *types;
870 };
871
cil_check_attribute_in_symtab(hashtab_key_t k,hashtab_datum_t d,void * args)872 static int cil_check_attribute_in_symtab(__attribute__((unused))hashtab_key_t k, hashtab_datum_t d, void *args)
873 {
874 struct attr_symtab_map_data *data = args;
875
876 if (FLAVOR(d) == CIL_TYPEATTRIBUTE) {
877 struct cil_typeattribute *attr = (struct cil_typeattribute *)d;
878 if (ebitmap_cmp(data->types, attr->types)) {
879 data->d = d;
880 }
881 }
882 return SEPOL_OK;
883 }
884
cil_check_for_previously_defined_attribute(struct cil_db * db,ebitmap_t * types,struct cil_symtab_datum * d)885 static struct cil_symtab_datum *cil_check_for_previously_defined_attribute(struct cil_db *db, ebitmap_t *types, struct cil_symtab_datum *d)
886 {
887 symtab_t *local_symtab, *root_symtab;
888 struct attr_symtab_map_data data;
889 int rc;
890
891 data.d = NULL;
892 data.types = types;
893
894 local_symtab = d->symtab;
895 root_symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_TYPES];
896
897 if (local_symtab != root_symtab) {
898 rc = cil_symtab_map(local_symtab, cil_check_attribute_in_symtab, &data);
899 if (rc != SEPOL_OK) {
900 return NULL;
901 }
902 }
903
904 if (!data.d) {
905 rc = cil_symtab_map(root_symtab, cil_check_attribute_in_symtab, &data);
906 if (rc != SEPOL_OK) {
907 return NULL;
908 }
909 }
910
911 return data.d;
912 }
913
cil_create_attribute_all_and_not_d(struct cil_db * db,struct cil_symtab_datum * d,struct cil_symtab_datum ** d3)914 static int cil_create_attribute_all_and_not_d(struct cil_db *db, struct cil_symtab_datum *d, struct cil_symtab_datum **d3)
915 {
916 struct cil_list *str_expr;
917 struct cil_list *datum_expr;
918 ebitmap_t *types;
919 int rc;
920
921 *d3 = NULL;
922
923 if (!d) {
924 return SEPOL_ERR;
925 }
926
927 str_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_STRING, d->fqn);
928 datum_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_DATUM, d);
929
930 types = cil_malloc(sizeof(*types));
931 rc = cil_datum_not(types, d, db->num_types);
932 if (rc != SEPOL_OK) {
933 goto exit;
934 }
935
936 if (ebitmap_is_empty(types)) {
937 rc = SEPOL_OK;
938 goto exit;
939 }
940
941 if (ebitmap_cardinality(types) == 1) {
942 unsigned i = ebitmap_highest_set_bit(types);
943 *d3 = DATUM(db->val_to_type[i]);
944 ebitmap_destroy(types);
945 rc = SEPOL_OK;
946 goto exit;
947 }
948
949 *d3 = cil_check_for_previously_defined_attribute(db, types, d);
950 if (*d3) {
951 ebitmap_destroy(types);
952 rc = SEPOL_OK;
953 goto exit;
954 }
955
956 rc = cil_create_and_insert_attribute_and_set(db, NODE(d), str_expr, datum_expr, types, d3);
957 if (rc != SEPOL_OK) {
958 goto exit;
959 }
960
961 return SEPOL_OK;
962
963 exit:
964 cil_list_destroy(&str_expr, CIL_FALSE);
965 cil_list_destroy(&datum_expr, CIL_FALSE);
966 free(types);
967 return rc;
968 }
969
cil_create_attribute_d1_and_not_d2(struct cil_db * db,struct cil_symtab_datum * d1,struct cil_symtab_datum * d2,struct cil_symtab_datum ** d3)970 static int cil_create_attribute_d1_and_not_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3)
971 {
972 struct cil_list *str_expr;
973 struct cil_list *datum_expr;
974 ebitmap_t *types;
975 int rc;
976
977 if (!d2) {
978 *d3 = d1;
979 return SEPOL_OK;
980 }
981
982 *d3 = NULL;
983
984 if (!d1 || d1 == d2) {
985 return SEPOL_OK;
986 }
987
988 str_expr = cil_create_andnot_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
989 datum_expr = cil_create_andnot_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
990
991 types = cil_malloc(sizeof(*types));
992 rc = cil_datums_andnot(types, d1, d2);
993 if (rc != SEPOL_OK) {
994 goto exit;
995 }
996 if (ebitmap_is_empty(types)) {
997 rc = SEPOL_OK;
998 goto exit;
999 }
1000
1001 if (ebitmap_cardinality(types) == 1) {
1002 unsigned i = ebitmap_highest_set_bit(types);
1003 *d3 = DATUM(db->val_to_type[i]);
1004 ebitmap_destroy(types);
1005 rc = SEPOL_OK;
1006 goto exit;
1007 }
1008
1009 *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1010 if (*d3) {
1011 ebitmap_destroy(types);
1012 rc = SEPOL_OK;
1013 goto exit;
1014 }
1015
1016 rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1017 if (rc != SEPOL_OK) {
1018 goto exit;
1019 }
1020
1021 return SEPOL_OK;
1022
1023 exit:
1024 cil_list_destroy(&str_expr, CIL_FALSE);
1025 cil_list_destroy(&datum_expr, CIL_FALSE);
1026 free(types);
1027 return rc;
1028 }
1029
cil_create_attribute_d1_and_d2(struct cil_db * db,struct cil_symtab_datum * d1,struct cil_symtab_datum * d2,struct cil_symtab_datum ** d3)1030 static int cil_create_attribute_d1_and_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3)
1031 {
1032 struct cil_list *str_expr;
1033 struct cil_list *datum_expr;
1034 ebitmap_t *types;
1035 int rc;
1036
1037 if (d1 == d2) {
1038 *d3 = d1;
1039 return SEPOL_OK;
1040 }
1041
1042 *d3 = NULL;
1043
1044 if (!d1 || !d2) {
1045 return SEPOL_OK;
1046 }
1047
1048 str_expr = cil_create_and_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
1049 datum_expr = cil_create_and_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
1050
1051 types = cil_malloc(sizeof(*types));
1052 rc = cil_datums_and(types, d1, d2);
1053 if (rc != SEPOL_OK) {
1054 goto exit;
1055 }
1056 if (ebitmap_is_empty(types)) {
1057 rc = SEPOL_OK;
1058 goto exit;
1059 }
1060
1061 if (ebitmap_cardinality(types) == 1) {
1062 unsigned i = ebitmap_highest_set_bit(types);
1063 *d3 = DATUM(db->val_to_type[i]);
1064 ebitmap_destroy(types);
1065 rc = SEPOL_OK;
1066 goto exit;
1067 }
1068
1069 *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1070 if (*d3) {
1071 ebitmap_destroy(types);
1072 rc = SEPOL_OK;
1073 goto exit;
1074 }
1075
1076 rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1077 if (rc != SEPOL_OK) {
1078 goto exit;
1079 }
1080
1081 return SEPOL_OK;
1082
1083 exit:
1084 cil_list_destroy(&str_expr, CIL_FALSE);
1085 cil_list_destroy(&datum_expr, CIL_FALSE);
1086 free(types);
1087 return rc;
1088 }
1089
cil_create_avrule(struct cil_symtab_datum * src,struct cil_symtab_datum * tgt,struct cil_list * classperms)1090 static struct cil_avrule *cil_create_avrule(struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms)
1091 {
1092 struct cil_avrule *new;
1093
1094 cil_avrule_init(&new);
1095 new->is_extended = CIL_FALSE;
1096 new->rule_kind = CIL_AVRULE_ALLOWED;
1097 new->src_str = src->name;
1098 new->src = src;
1099 new->tgt_str = tgt->name;
1100 new->tgt = tgt;
1101 new->perms.classperms = classperms;
1102
1103 return new;
1104 }
1105
cil_create_and_add_avrule(struct cil_tree_node * curr,struct cil_symtab_datum * src,struct cil_symtab_datum * tgt,struct cil_list * classperms)1106 static struct cil_tree_node *cil_create_and_add_avrule(struct cil_tree_node *curr, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms)
1107 {
1108 struct cil_avrule *new_avrule;
1109 struct cil_list *new_cp_list;
1110
1111 if (!src || !tgt) {
1112 return curr;
1113 }
1114
1115 cil_classperms_list_copy(&new_cp_list, classperms);
1116 new_avrule = cil_create_avrule(src, tgt, new_cp_list);
1117 return cil_create_and_insert_node(curr, CIL_AVRULE, new_avrule);
1118 }
1119
cil_remove_permissions_from_special_rule(struct cil_db * db,struct cil_tree_node * curr,struct cil_symtab_datum * s1,struct cil_symtab_datum * t1,struct cil_symtab_datum * s2,struct cil_symtab_datum * t2,struct cil_list * p4,struct cil_symtab_datum * s3,struct cil_symtab_datum * s4)1120 static int cil_remove_permissions_from_special_rule(struct cil_db *db, struct cil_tree_node *curr, struct cil_symtab_datum *s1, struct cil_symtab_datum *t1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2, struct cil_list *p4, struct cil_symtab_datum *s3, struct cil_symtab_datum *s4)
1121 {
1122 int rc;
1123
1124 if (t1 == DATUM(db->notselftype)) {
1125 if (t2 == DATUM(db->othertype)) {
1126 struct cil_symtab_datum *t;
1127 rc = cil_create_attribute_all_and_not_d(db, s2, &t);
1128 if (rc != SEPOL_OK) {
1129 goto exit;
1130 }
1131 curr = cil_create_and_add_avrule(curr, s4, t, p4);
1132 } else {
1133 struct cil_symtab_datum *s5, *s6, *ta, *tb;
1134 rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1135 if (rc != SEPOL_OK) {
1136 goto exit;
1137 }
1138 rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1139 if (rc != SEPOL_OK) {
1140 goto exit;
1141 }
1142 rc = cil_create_attribute_all_and_not_d(db, t2, &ta);
1143 if (rc != SEPOL_OK) {
1144 goto exit;
1145 }
1146 rc = cil_create_attribute_d1_and_not_d2(db, ta, s4, &tb);
1147 if (rc != SEPOL_OK) {
1148 goto exit;
1149 }
1150 curr = cil_create_and_add_avrule(curr, s6, ta, p4);
1151 curr = cil_create_and_add_avrule(curr, s5, tb, p4);
1152 if (cil_datum_cardinality(s5) > 1) {
1153 curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1154 }
1155 }
1156 } else if (t1 == DATUM(db->othertype)) {
1157 curr = cil_create_and_add_avrule(curr, s3, s4, p4);
1158 if (t2 == DATUM(db->notselftype)) {
1159 /* Nothing else is needed */
1160 } else if (t2 == DATUM(db->othertype)) {
1161 curr = cil_create_and_add_avrule(curr, s4, s3, p4);
1162 } else {
1163 struct cil_symtab_datum *s5, *s6, *tc, *td;
1164 rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1165 if (rc != SEPOL_OK) {
1166 goto exit;
1167 }
1168 rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1169 if (rc != SEPOL_OK) {
1170 goto exit;
1171 }
1172 rc = cil_create_attribute_d1_and_not_d2(db, s1, t2, &tc);
1173 if (rc != SEPOL_OK) {
1174 goto exit;
1175 }
1176 rc = cil_create_attribute_d1_and_not_d2(db, s3, t2, &td);
1177 if (rc != SEPOL_OK) {
1178 goto exit;
1179 }
1180 curr = cil_create_and_add_avrule(curr, s6, tc, p4);
1181 curr = cil_create_and_add_avrule(curr, s5, td, p4);
1182 if (cil_datum_cardinality(s5) > 1) {
1183 curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1184 }
1185 }
1186 } else {
1187 struct cil_symtab_datum *s8;
1188 rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1189 if (rc != SEPOL_OK) {
1190 goto exit;
1191 }
1192 curr = cil_create_and_add_avrule(curr, s8, DATUM(db->selftype), p4);
1193 if (t2 == DATUM(db->notselftype)) {
1194 /* Nothing else is needed */
1195 } else { /* t2 == DATUM(db->othertype) */
1196 struct cil_symtab_datum *t;
1197 rc = cil_create_attribute_d1_and_not_d2(db, t1, s2, &t);
1198 if (rc != SEPOL_OK) {
1199 goto exit;
1200 }
1201 curr = cil_create_and_add_avrule(curr, s4, t, p4);
1202 }
1203 }
1204 return SEPOL_OK;
1205
1206 exit:
1207 return rc;
1208 }
1209
cil_remove_permissions_from_rule(struct cil_db * db,struct cil_tree_node * allow_node,const struct cil_tree_node * deny_node)1210 static int cil_remove_permissions_from_rule(struct cil_db *db, struct cil_tree_node *allow_node, const struct cil_tree_node *deny_node)
1211 {
1212 struct cil_avrule *allow_rule = allow_node->data;
1213 struct cil_deny_rule *deny_rule = deny_node->data;
1214 struct cil_symtab_datum *s1 = allow_rule->src;
1215 struct cil_symtab_datum *t1 = allow_rule->tgt;
1216 struct cil_list *p1 = allow_rule->perms.classperms;
1217 struct cil_symtab_datum *s2 = deny_rule->src;
1218 struct cil_symtab_datum *t2 = deny_rule->tgt;
1219 struct cil_list *p2 = deny_rule->classperms;
1220 struct cil_list *p3 = NULL;
1221 struct cil_list *p4 = NULL;
1222 struct cil_symtab_datum *s3, *s4;
1223 struct cil_tree_node *curr = allow_node;
1224 int rc;
1225
1226 cil_classperms_list_andnot(&p3, p1, p2);
1227 if (!cil_list_is_empty(p3)) {;
1228 curr = cil_create_and_add_avrule(curr, s1, t1, p3);
1229 }
1230 cil_destroy_classperms_list(&p3);
1231 p3 = NULL;
1232
1233 cil_classperms_list_and(&p4, p1, p2);
1234 if (cil_list_is_empty(p4)) {
1235 cil_tree_log(allow_node, CIL_ERR, "Allow rule did not match deny rule: No matching class and permissions");
1236 cil_tree_log((struct cil_tree_node *)deny_node, CIL_ERR, "Deny rule");
1237 rc = SEPOL_ERR;
1238 goto exit;
1239 }
1240
1241 rc = cil_create_attribute_d1_and_not_d2(db, s1, s2, &s3);
1242 if (rc != SEPOL_OK) {
1243 goto exit;
1244 }
1245 curr = cil_create_and_add_avrule(curr, s3, t1, p4);
1246
1247 if ((t1 == DATUM(db->selftype) && t2 == DATUM(db->selftype)) ||
1248 (t1 == DATUM(db->notselftype) && t2 == DATUM(db->notselftype))) {
1249 /* Nothing more needs to be done */
1250 rc = SEPOL_OK;
1251 goto exit;
1252 }
1253
1254 rc = cil_create_attribute_d1_and_d2(db, s1, s2, &s4);
1255 if (rc != SEPOL_OK) {
1256 goto exit;
1257 }
1258
1259 if (t1 == DATUM(db->notselftype) || t1 == DATUM(db->othertype) ||
1260 t2 == DATUM(db->notselftype) || t2 == DATUM(db->othertype)) {
1261 rc = cil_remove_permissions_from_special_rule(db, curr, s1, t1, s2, t2, p4, s3, s4);
1262 goto exit;
1263 }
1264
1265 if (t1 == DATUM(db->selftype) && t2 != DATUM(db->selftype)) {
1266 struct cil_symtab_datum *s5;
1267 rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1268 if (rc != SEPOL_OK) {
1269 goto exit;
1270 }
1271 curr = cil_create_and_add_avrule(curr, s5, DATUM(db->selftype), p4);
1272 } else if (t1 != DATUM(db->selftype) && t2 == DATUM(db->selftype)) {
1273 struct cil_symtab_datum *s7, *s8, *t8;
1274 rc = cil_create_attribute_d1_and_not_d2(db, s4, t1, &s7);
1275 if (rc != SEPOL_OK) {
1276 goto exit;
1277 }
1278 rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1279 if (rc != SEPOL_OK) {
1280 goto exit;
1281 }
1282 rc = cil_create_attribute_d1_and_not_d2(db, t1, s4, &t8);
1283 if (rc != SEPOL_OK) {
1284 goto exit;
1285 }
1286 curr = cil_create_and_add_avrule(curr, s7, t1, p4);
1287 curr = cil_create_and_add_avrule(curr, s8, t8, p4);
1288 if (cil_datum_cardinality(s8) > 1) {
1289 curr = cil_create_and_add_avrule(curr, s8, DATUM(db->othertype), p4);
1290 }
1291 } else {
1292 struct cil_symtab_datum *t3;
1293 rc = cil_create_attribute_d1_and_not_d2(db, t1, t2, &t3);
1294 if (rc != SEPOL_OK) {
1295 goto exit;
1296 }
1297 curr = cil_create_and_add_avrule(curr, s4, t3, p4);
1298 }
1299
1300 exit:
1301 if (p4) {
1302 cil_destroy_classperms_list(&p4);
1303 }
1304 return rc;
1305 }
1306
cil_find_matching_allow_rules(struct cil_list * matching,struct cil_tree_node * start,struct cil_tree_node * deny_node)1307 static int cil_find_matching_allow_rules(struct cil_list *matching, struct cil_tree_node *start, struct cil_tree_node *deny_node)
1308 {
1309 struct cil_deny_rule *deny_rule = deny_node->data;
1310 struct cil_avrule target;
1311
1312 target.rule_kind = CIL_AVRULE_ALLOWED;
1313 target.is_extended = CIL_FALSE;
1314 target.src = deny_rule->src;
1315 target.tgt = deny_rule->tgt;
1316 target.perms.classperms = deny_rule->classperms;
1317
1318 return cil_find_matching_avrule_in_ast(start, CIL_AVRULE, &target, matching, CIL_FALSE);
1319 }
1320
cil_process_deny_rule(struct cil_db * db,struct cil_tree_node * start,struct cil_tree_node * deny_node)1321 static int cil_process_deny_rule(struct cil_db *db, struct cil_tree_node *start, struct cil_tree_node *deny_node)
1322 {
1323 struct cil_list *matching;
1324 struct cil_list_item *item;
1325 int rc;
1326
1327 cil_list_init(&matching, CIL_NODE);
1328
1329 rc = cil_find_matching_allow_rules(matching, start, deny_node);
1330 if (rc != SEPOL_OK) {
1331 goto exit;
1332 }
1333
1334 cil_list_for_each(item, matching) {
1335 struct cil_tree_node *allow_node = item->data;
1336 rc = cil_remove_permissions_from_rule(db, allow_node, deny_node);
1337 cil_tree_node_remove(allow_node);
1338 if (rc != SEPOL_OK) {
1339 goto exit;
1340 }
1341
1342 }
1343
1344 exit:
1345 cil_list_destroy(&matching, CIL_FALSE);
1346 return rc;
1347 }
1348
cil_process_deny_rules(struct cil_db * db,struct cil_tree_node * start,struct cil_list * deny_rules)1349 static int cil_process_deny_rules(struct cil_db *db, struct cil_tree_node *start, struct cil_list *deny_rules)
1350 {
1351 struct cil_list_item *item;
1352 int rc = SEPOL_OK;
1353
1354 cil_list_for_each(item, deny_rules) {
1355 struct cil_tree_node *deny_node = item->data;
1356 rc = cil_process_deny_rule(db, start, deny_node);
1357 if (rc != SEPOL_OK) {
1358 goto exit;
1359 }
1360 cil_tree_node_remove(deny_node);
1361 }
1362
1363 exit:
1364 return rc;
1365 }
1366
__cil_find_deny_rules(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1367 static int __cil_find_deny_rules(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1368 {
1369 struct cil_list *deny_rules = extra_args;
1370
1371 if (node->flavor == CIL_BLOCK) {
1372 struct cil_block *block = node->data;
1373 if (block->is_abstract == CIL_TRUE) {
1374 *finished = CIL_TREE_SKIP_HEAD;
1375 }
1376 } else if (node->flavor == CIL_MACRO) {
1377 *finished = CIL_TREE_SKIP_HEAD;
1378 } else if (node->flavor == CIL_DENY_RULE) {
1379 cil_list_append(deny_rules, CIL_DENY_RULE, node);
1380 }
1381 return SEPOL_OK;
1382 }
1383
cil_process_deny_rules_in_ast(struct cil_db * db)1384 int cil_process_deny_rules_in_ast(struct cil_db *db)
1385 {
1386 struct cil_tree_node *start;
1387 struct cil_list *deny_rules;
1388 int rc = SEPOL_ERR;
1389
1390 cil_list_init(&deny_rules, CIL_DENY_RULE);
1391
1392 if (!db) {
1393 cil_log(CIL_ERR, "No CIL db provided to process deny rules\n");
1394 goto exit;
1395 }
1396
1397 start = db->ast->root;
1398 rc = cil_tree_walk(start, __cil_find_deny_rules, NULL, NULL, deny_rules);
1399 if (rc != SEPOL_OK) {
1400 cil_log(CIL_ERR, "An error occurred while getting deny rules\n");
1401 goto exit;
1402 }
1403
1404 rc = cil_process_deny_rules(db, start, deny_rules);
1405 if (rc != SEPOL_OK) {
1406 cil_log(CIL_ERR, "An error occurred while processing deny rules\n");
1407 goto exit;
1408 }
1409
1410 exit:
1411 cil_list_destroy(&deny_rules, CIL_FALSE);
1412 return rc;
1413 }
1414