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