1
2#include "cil_internal.h"
3#include "cil_log.h"
4#include "cil_list.h"
5#include "cil_symtab.h"
6
7static inline void cil_reset_classperms_list(struct cil_list *cp_list);
8static inline void cil_reset_level(struct cil_level *level);
9static inline void cil_reset_levelrange(struct cil_levelrange *levelrange);
10static inline void cil_reset_context(struct cil_context *context);
11
12
13static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
14{
15	struct cil_perm *perm = (struct cil_perm *)d;
16
17	perm->value -= *((int *)args);
18
19	return SEPOL_OK;
20}
21
22static void cil_reset_class(struct cil_class *class)
23{
24	if (class->common != NULL) {
25		struct cil_class *common = class->common;
26		cil_symtab_map(&common->perms, __class_reset_perm_values, &common->num_perms);
27		/* during a re-resolve, we need to reset the common, so a classcommon
28		 * statement isn't seen as a duplicate */
29		class->num_perms -= common->num_perms;
30		class->common = NULL; /* Must make this NULL or there will be an error when re-resolving */
31	}
32	class->ordered = CIL_FALSE;
33}
34
35static void cil_reset_perm(struct cil_perm *perm)
36{
37	cil_reset_classperms_list(perm->classperms);
38}
39
40static inline void cil_reset_classperms(struct cil_classperms *cp)
41{
42	if (cp == NULL) {
43		return;
44	}
45
46	cil_list_destroy(&cp->perms, CIL_FALSE);
47}
48
49static void cil_reset_classpermission(struct cil_classpermission *cp)
50{
51	if (cp == NULL) {
52		return;
53	}
54
55	cil_reset_classperms_list(cp->classperms);
56}
57
58static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
59{
60	cil_reset_classpermission(cp_set->set);
61}
62
63static inline void cil_reset_classperms_list(struct cil_list *cp_list)
64{
65	struct cil_list_item *curr;
66
67	if (cp_list == NULL) {
68		return;
69	}
70
71	cil_list_for_each(curr, cp_list) {
72		if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP */
73			cil_reset_classperms(curr->data);
74		} else if (curr->flavor == CIL_CLASSPERMS_SET) { /* SET */
75			cil_reset_classperms_set(curr->data);
76		}
77	}
78}
79
80static void cil_reset_classpermissionset(struct cil_classpermissionset *cps)
81{
82	cil_reset_classperms_list(cps->classperms);
83}
84
85static void cil_reset_classmapping(struct cil_classmapping *cm)
86{
87	cil_reset_classperms_list(cm->classperms);
88}
89
90static void cil_reset_alias(struct cil_alias *alias)
91{
92	/* reset actual to NULL during a re-resolve */
93	alias->actual = NULL;
94}
95
96static void cil_reset_user(struct cil_user *user)
97{
98	/* reset the bounds to NULL during a re-resolve */
99	user->bounds = NULL;
100	user->dftlevel = NULL;
101	user->range = NULL;
102}
103
104static void cil_reset_userattr(struct cil_userattribute *attr)
105{
106	struct cil_list_item *expr = NULL;
107	struct cil_list_item *next = NULL;
108
109	/* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a userattribute statement */
110	if (attr->expr_list != NULL) {
111		/* we don't want to destroy the expression stacks (cil_list) inside
112		 * this list cil_list_destroy destroys sublists, so we need to do it
113		 * manually */
114		expr = attr->expr_list->head;
115		while (expr != NULL) {
116			next = expr->next;
117			cil_list_item_destroy(&expr, CIL_FALSE);
118			expr = next;
119		}
120		free(attr->expr_list);
121		attr->expr_list = NULL;
122	}
123}
124
125static void cil_reset_userattributeset(struct cil_userattributeset *uas)
126{
127	cil_list_destroy(&uas->datum_expr, CIL_FALSE);
128}
129
130static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
131{
132	if (selinuxuser->range_str == NULL) {
133		cil_reset_levelrange(selinuxuser->range);
134	}
135}
136
137static void cil_reset_role(struct cil_role *role)
138{
139	/* reset the bounds to NULL during a re-resolve */
140	role->bounds = NULL;
141}
142
143static void cil_reset_roleattr(struct cil_roleattribute *attr)
144{
145	/* during a re-resolve, we need to reset the lists of expression stacks  associated with this attribute from a attributeroles statement */
146	if (attr->expr_list != NULL) {
147		/* we don't want to destroy the expression stacks (cil_list) inside
148		 * this list cil_list_destroy destroys sublists, so we need to do it
149		 * manually */
150		struct cil_list_item *expr = attr->expr_list->head;
151		while (expr != NULL) {
152			struct cil_list_item *next = expr->next;
153			cil_list_item_destroy(&expr, CIL_FALSE);
154			expr = next;
155		}
156		free(attr->expr_list);
157		attr->expr_list = NULL;
158	}
159}
160
161static void cil_reset_roleattributeset(struct cil_roleattributeset *ras)
162{
163	cil_list_destroy(&ras->datum_expr, CIL_FALSE);
164}
165
166static void cil_reset_type(struct cil_type *type)
167{
168	/* reset the bounds to NULL during a re-resolve */
169	type->bounds = NULL;
170}
171
172static void cil_reset_typeattr(struct cil_typeattribute *attr)
173{
174	/* during a re-resolve, we need to reset the lists of expression stacks  associated with this attribute from a attributetypes statement */
175	if (attr->expr_list != NULL) {
176		/* we don't want to destroy the expression stacks (cil_list) inside
177		 * this list cil_list_destroy destroys sublists, so we need to do it
178		 * manually */
179		struct cil_list_item *expr = attr->expr_list->head;
180		while (expr != NULL) {
181			struct cil_list_item *next = expr->next;
182			cil_list_item_destroy(&expr, CIL_FALSE);
183			expr = next;
184		}
185		free(attr->expr_list);
186		attr->expr_list = NULL;
187	}
188	attr->used = CIL_FALSE;
189}
190
191static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)
192{
193	cil_list_destroy(&tas->datum_expr, CIL_FALSE);
194}
195
196static void cil_reset_avrule(struct cil_avrule *rule)
197{
198	cil_reset_classperms_list(rule->perms.classperms);
199}
200
201static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans)
202{
203	if (rangetrans->range_str == NULL) {
204		cil_reset_levelrange(rangetrans->range);
205	}
206}
207
208static void cil_reset_sens(struct cil_sens *sens)
209{
210	/* during a re-resolve, we need to reset the categories associated with
211	 * this sensitivity from a (sensitivitycategory) statement */
212	cil_list_destroy(&sens->cats_list, CIL_FALSE);
213	sens->ordered = CIL_FALSE;
214}
215
216static void cil_reset_cat(struct cil_cat *cat)
217{
218	cat->ordered = CIL_FALSE;
219}
220
221static inline void cil_reset_cats(struct cil_cats *cats)
222{
223	if (cats != NULL) {
224		cats->evaluated = CIL_FALSE;
225		cil_list_destroy(&cats->datum_expr, CIL_FALSE);
226	}
227}
228
229
230static void cil_reset_senscat(struct cil_senscat *senscat)
231{
232	cil_reset_cats(senscat->cats);
233}
234
235static void cil_reset_catset(struct cil_catset *catset)
236{
237	cil_reset_cats(catset->cats);
238}
239
240static inline void cil_reset_level(struct cil_level *level)
241{
242	cil_reset_cats(level->cats);
243}
244
245static inline void cil_reset_levelrange(struct cil_levelrange *levelrange)
246{
247	if (levelrange->low_str == NULL) {
248		cil_reset_level(levelrange->low);
249	}
250
251	if (levelrange->high_str == NULL) {
252		cil_reset_level(levelrange->high);
253	}
254}
255
256static inline void cil_reset_userlevel(struct cil_userlevel *userlevel)
257{
258	if (userlevel->level_str == NULL) {
259		cil_reset_level(userlevel->level);
260	}
261}
262
263static inline void cil_reset_userrange(struct cil_userrange *userrange)
264{
265	if (userrange->range_str == NULL) {
266		cil_reset_levelrange(userrange->range);
267	}
268}
269
270static inline void cil_reset_context(struct cil_context *context)
271{
272	if (context->range_str == NULL) {
273		cil_reset_levelrange(context->range);
274	}
275}
276
277static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext)
278{
279	if (sidcontext->context_str == NULL) {
280		cil_reset_context(sidcontext->context);
281	}
282}
283
284static void cil_reset_filecon(struct cil_filecon *filecon)
285{
286	if (filecon->context_str == NULL && filecon->context != NULL) {
287		cil_reset_context(filecon->context);
288	}
289}
290
291static void cil_reset_portcon(struct cil_portcon *portcon)
292{
293	if (portcon->context_str == NULL) {
294		cil_reset_context(portcon->context);
295	}
296}
297
298static void cil_reset_nodecon(struct cil_nodecon *nodecon)
299{
300	if (nodecon->context_str == NULL) {
301		cil_reset_context(nodecon->context);
302	}
303}
304
305static void cil_reset_genfscon(struct cil_genfscon *genfscon)
306{
307	if (genfscon->context_str == NULL) {
308		cil_reset_context(genfscon->context);
309	}
310}
311
312static void cil_reset_netifcon(struct cil_netifcon *netifcon)
313{
314	if (netifcon->if_context_str == NULL) {
315		cil_reset_context(netifcon->if_context);
316	}
317
318	if (netifcon->packet_context_str == NULL) {
319		cil_reset_context(netifcon->packet_context);
320	}
321}
322
323static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon)
324{
325	if (pirqcon->context_str == NULL) {
326		cil_reset_context(pirqcon->context);
327	}
328}
329
330static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon)
331{
332	if (iomemcon->context_str == NULL) {
333		cil_reset_context(iomemcon->context);
334	}
335}
336
337static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon)
338{
339	if (ioportcon->context_str == NULL) {
340		cil_reset_context(ioportcon->context);
341	}
342}
343
344static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
345{
346	if (pcidevicecon->context_str == NULL) {
347		cil_reset_context(pcidevicecon->context);
348	}
349}
350
351static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon)
352{
353	if (devicetreecon->context_str == NULL) {
354		cil_reset_context(devicetreecon->context);
355	}
356}
357
358static void cil_reset_fsuse(struct cil_fsuse *fsuse)
359{
360	if (fsuse->context_str == NULL) {
361		cil_reset_context(fsuse->context);
362	}
363}
364
365static void cil_reset_sid(struct cil_sid *sid)
366{
367	/* reset the context to NULL during a re-resolve */
368	sid->context = NULL;
369	sid->ordered = CIL_FALSE;
370}
371
372static void cil_reset_constrain(struct cil_constrain *con)
373{
374	cil_reset_classperms_list(con->classperms);
375	cil_list_destroy(&con->datum_expr, CIL_FALSE);
376}
377
378static void cil_reset_validatetrans(struct cil_validatetrans *vt)
379{
380	cil_list_destroy(&vt->datum_expr, CIL_FALSE);
381}
382
383static void cil_reset_default(struct cil_default *def)
384{
385	cil_list_destroy(&def->class_datums, CIL_FALSE);
386}
387
388static void cil_reset_defaultrange(struct cil_defaultrange *def)
389{
390	cil_list_destroy(&def->class_datums, CIL_FALSE);
391}
392
393static void cil_reset_booleanif(struct cil_booleanif *bif)
394{
395	cil_list_destroy(&bif->datum_expr, CIL_FALSE);
396}
397
398int __cil_reset_node(struct cil_tree_node *node,  __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
399{
400	switch (node->flavor) {
401	case CIL_CLASS:
402		cil_reset_class(node->data);
403		break;
404	case CIL_PERM:
405	case CIL_MAP_PERM:
406		cil_reset_perm(node->data);
407		break;
408	case CIL_CLASSPERMISSION:
409		cil_reset_classpermission(node->data);
410		break;
411	case CIL_CLASSPERMISSIONSET:
412		cil_reset_classpermissionset(node->data);
413		break;
414	case CIL_CLASSMAPPING:
415		cil_reset_classmapping(node->data);
416		break;
417	case CIL_TYPEALIAS:
418	case CIL_SENSALIAS:
419	case CIL_CATALIAS:
420		cil_reset_alias(node->data);
421		break;
422	case CIL_USERRANGE:
423		cil_reset_userrange(node->data);
424		break;
425	case CIL_USERLEVEL:
426		cil_reset_userlevel(node->data);
427		break;
428	case CIL_USER:
429		cil_reset_user(node->data);
430		break;
431	case CIL_USERATTRIBUTE:
432		cil_reset_userattr(node->data);
433		break;
434	case CIL_USERATTRIBUTESET:
435		cil_reset_userattributeset(node->data);
436		break;
437	case CIL_SELINUXUSERDEFAULT:
438	case CIL_SELINUXUSER:
439		cil_reset_selinuxuser(node->data);
440		break;
441	case CIL_ROLE:
442		cil_reset_role(node->data);
443		break;
444	case CIL_ROLEATTRIBUTE:
445		cil_reset_roleattr(node->data);
446		break;
447	case CIL_ROLEATTRIBUTESET:
448		cil_reset_roleattributeset(node->data);
449		break;
450	case CIL_TYPE:
451		cil_reset_type(node->data);
452		break;
453	case CIL_TYPEATTRIBUTE:
454		cil_reset_typeattr(node->data);
455		break;
456	case CIL_TYPEATTRIBUTESET:
457		cil_reset_typeattributeset(node->data);
458		break;
459	case CIL_RANGETRANSITION:
460		cil_reset_rangetransition(node->data);
461		break;
462	case CIL_AVRULE:
463		cil_reset_avrule(node->data);
464		break;
465	case CIL_SENS:
466		cil_reset_sens(node->data);
467		break;
468	case CIL_CAT:
469		cil_reset_cat(node->data);
470		break;
471	case CIL_SENSCAT:
472		cil_reset_senscat(node->data);
473		break;
474	case CIL_CATSET:
475		cil_reset_catset(node->data);
476		break;
477	case CIL_LEVEL:
478		cil_reset_level(node->data);
479		break;
480	case CIL_LEVELRANGE:
481		cil_reset_levelrange(node->data);
482		break;
483	case CIL_CONTEXT:
484		cil_reset_context(node->data);
485		break;
486	case CIL_SIDCONTEXT:
487		cil_reset_sidcontext(node->data);
488		break;
489	case CIL_FILECON:
490		cil_reset_filecon(node->data);
491		break;
492	case CIL_PORTCON:
493		cil_reset_portcon(node->data);
494		break;
495	case CIL_NODECON:
496		cil_reset_nodecon(node->data);
497		break;
498	case CIL_GENFSCON:
499		cil_reset_genfscon(node->data);
500		break;
501	case CIL_NETIFCON:
502		cil_reset_netifcon(node->data);
503		break;
504	case CIL_PIRQCON:
505		cil_reset_pirqcon(node->data);
506		break;
507	case CIL_IOMEMCON:
508		cil_reset_iomemcon(node->data);
509		break;
510	case CIL_IOPORTCON:
511		cil_reset_ioportcon(node->data);
512		break;
513	case CIL_PCIDEVICECON:
514		cil_reset_pcidevicecon(node->data);
515		break;
516	case CIL_DEVICETREECON:
517		cil_reset_devicetreecon(node->data);
518		break;
519	case CIL_FSUSE:
520		cil_reset_fsuse(node->data);
521		break;
522	case CIL_SID:
523		cil_reset_sid(node->data);
524		break;
525	case CIL_CONSTRAIN:
526	case CIL_MLSCONSTRAIN:
527		cil_reset_constrain(node->data);
528		break;
529	case CIL_VALIDATETRANS:
530	case CIL_MLSVALIDATETRANS:
531		cil_reset_validatetrans(node->data);
532		break;
533	case CIL_DEFAULTUSER:
534	case CIL_DEFAULTROLE:
535	case CIL_DEFAULTTYPE:
536		cil_reset_default(node->data);
537		break;
538	case CIL_DEFAULTRANGE:
539		cil_reset_defaultrange(node->data);
540		break;
541	case CIL_BOOLEANIF:
542		cil_reset_booleanif(node->data);
543		break;
544	case CIL_TUNABLEIF:
545	case CIL_CALL:
546		break; /* Not effected by optional block disabling */
547	case CIL_MACRO:
548	case CIL_SIDORDER:
549	case CIL_CLASSORDER:
550	case CIL_CATORDER:
551	case CIL_SENSITIVITYORDER:
552		break; /* Nothing to reset */
553	default:
554		break;
555	}
556
557	return SEPOL_OK;
558}
559
560int cil_reset_ast(struct cil_tree_node *current)
561{
562	int rc = SEPOL_ERR;
563
564	rc = cil_tree_walk(current, __cil_reset_node, NULL, NULL, NULL);
565	if (rc != SEPOL_OK) {
566		cil_log(CIL_ERR, "Failed to reset AST\n");
567		return SEPOL_ERR;
568	}
569
570	return SEPOL_OK;
571}
572