xref: /aosp_15_r20/external/selinux/libsepol/cil/src/cil_deny.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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