xref: /aosp_15_r20/external/selinux/libsepol/cil/src/cil_tree.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
5*2d543d20SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright notice,
8*2d543d20SAndroid Build Coastguard Worker  *       this list of conditions and the following disclaimer.
9*2d543d20SAndroid Build Coastguard Worker  *
10*2d543d20SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright notice,
11*2d543d20SAndroid Build Coastguard Worker  *       this list of conditions and the following disclaimer in the documentation
12*2d543d20SAndroid Build Coastguard Worker  *       and/or other materials provided with the distribution.
13*2d543d20SAndroid Build Coastguard Worker  *
14*2d543d20SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15*2d543d20SAndroid Build Coastguard Worker  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16*2d543d20SAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17*2d543d20SAndroid Build Coastguard Worker  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18*2d543d20SAndroid Build Coastguard Worker  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19*2d543d20SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*2d543d20SAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21*2d543d20SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22*2d543d20SAndroid Build Coastguard Worker  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23*2d543d20SAndroid Build Coastguard Worker  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*2d543d20SAndroid Build Coastguard Worker  *
25*2d543d20SAndroid Build Coastguard Worker  * The views and conclusions contained in the software and documentation are those
26*2d543d20SAndroid Build Coastguard Worker  * of the authors and should not be interpreted as representing official policies,
27*2d543d20SAndroid Build Coastguard Worker  * either expressed or implied, of Tresys Technology, LLC.
28*2d543d20SAndroid Build Coastguard Worker  */
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
31*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
32*2d543d20SAndroid Build Coastguard Worker #include <inttypes.h>
33*2d543d20SAndroid Build Coastguard Worker 
34*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
35*2d543d20SAndroid Build Coastguard Worker 
36*2d543d20SAndroid Build Coastguard Worker #include "cil_internal.h"
37*2d543d20SAndroid Build Coastguard Worker #include "cil_flavor.h"
38*2d543d20SAndroid Build Coastguard Worker #include "cil_log.h"
39*2d543d20SAndroid Build Coastguard Worker #include "cil_tree.h"
40*2d543d20SAndroid Build Coastguard Worker #include "cil_list.h"
41*2d543d20SAndroid Build Coastguard Worker #include "cil_parser.h"
42*2d543d20SAndroid Build Coastguard Worker #include "cil_strpool.h"
43*2d543d20SAndroid Build Coastguard Worker 
cil_tree_get_next_path(struct cil_tree_node * node,char ** info_kind,uint32_t * hll_line,char ** path)44*2d543d20SAndroid Build Coastguard Worker struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path)
45*2d543d20SAndroid Build Coastguard Worker {
46*2d543d20SAndroid Build Coastguard Worker 	int rc;
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker 	if (!node) {
49*2d543d20SAndroid Build Coastguard Worker 		goto exit;
50*2d543d20SAndroid Build Coastguard Worker 	}
51*2d543d20SAndroid Build Coastguard Worker 
52*2d543d20SAndroid Build Coastguard Worker 	node = node->parent;
53*2d543d20SAndroid Build Coastguard Worker 
54*2d543d20SAndroid Build Coastguard Worker 	while (node) {
55*2d543d20SAndroid Build Coastguard Worker 		if (node->flavor == CIL_NODE && node->data == NULL) {
56*2d543d20SAndroid Build Coastguard Worker 			if (node->cl_head && node->cl_head->data == CIL_KEY_SRC_INFO) {
57*2d543d20SAndroid Build Coastguard Worker 				if (!node->cl_head->next || !node->cl_head->next->next || !node->cl_head->next->next->next) {
58*2d543d20SAndroid Build Coastguard Worker 					goto exit;
59*2d543d20SAndroid Build Coastguard Worker 				}
60*2d543d20SAndroid Build Coastguard Worker 				/* Parse Tree */
61*2d543d20SAndroid Build Coastguard Worker 				*info_kind = node->cl_head->next->data;
62*2d543d20SAndroid Build Coastguard Worker 				rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10);
63*2d543d20SAndroid Build Coastguard Worker 				if (rc != SEPOL_OK) {
64*2d543d20SAndroid Build Coastguard Worker 					goto exit;
65*2d543d20SAndroid Build Coastguard Worker 				}
66*2d543d20SAndroid Build Coastguard Worker 				*path = node->cl_head->next->next->next->data;
67*2d543d20SAndroid Build Coastguard Worker 				return node;
68*2d543d20SAndroid Build Coastguard Worker 			}
69*2d543d20SAndroid Build Coastguard Worker 			node = node->parent;
70*2d543d20SAndroid Build Coastguard Worker 		} else if (node->flavor == CIL_SRC_INFO) {
71*2d543d20SAndroid Build Coastguard Worker 				/* AST */
72*2d543d20SAndroid Build Coastguard Worker 				struct cil_src_info *info = node->data;
73*2d543d20SAndroid Build Coastguard Worker 				*info_kind = info->kind;
74*2d543d20SAndroid Build Coastguard Worker 				*hll_line = info->hll_line;
75*2d543d20SAndroid Build Coastguard Worker 				*path = info->path;
76*2d543d20SAndroid Build Coastguard Worker 				return node;
77*2d543d20SAndroid Build Coastguard Worker 		} else {
78*2d543d20SAndroid Build Coastguard Worker 			if (node->flavor == CIL_CALL) {
79*2d543d20SAndroid Build Coastguard Worker 				struct cil_call *call = node->data;
80*2d543d20SAndroid Build Coastguard Worker 				node = NODE(call->macro);
81*2d543d20SAndroid Build Coastguard Worker 			} else if (node->flavor == CIL_BLOCKINHERIT) {
82*2d543d20SAndroid Build Coastguard Worker 				struct cil_blockinherit *inherit = node->data;
83*2d543d20SAndroid Build Coastguard Worker 				node = NODE(inherit->block);
84*2d543d20SAndroid Build Coastguard Worker 			} else {
85*2d543d20SAndroid Build Coastguard Worker 				node = node->parent;
86*2d543d20SAndroid Build Coastguard Worker 			}
87*2d543d20SAndroid Build Coastguard Worker 		}
88*2d543d20SAndroid Build Coastguard Worker 	}
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker exit:
91*2d543d20SAndroid Build Coastguard Worker 	*info_kind = NULL;
92*2d543d20SAndroid Build Coastguard Worker 	*hll_line = 0;
93*2d543d20SAndroid Build Coastguard Worker 	*path = NULL;
94*2d543d20SAndroid Build Coastguard Worker 	return NULL;
95*2d543d20SAndroid Build Coastguard Worker }
96*2d543d20SAndroid Build Coastguard Worker 
cil_tree_get_cil_path(struct cil_tree_node * node)97*2d543d20SAndroid Build Coastguard Worker char *cil_tree_get_cil_path(struct cil_tree_node *node)
98*2d543d20SAndroid Build Coastguard Worker {
99*2d543d20SAndroid Build Coastguard Worker 	char *info_kind;
100*2d543d20SAndroid Build Coastguard Worker 	uint32_t hll_line;
101*2d543d20SAndroid Build Coastguard Worker 	char *path;
102*2d543d20SAndroid Build Coastguard Worker 
103*2d543d20SAndroid Build Coastguard Worker 	while (node) {
104*2d543d20SAndroid Build Coastguard Worker 		node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
105*2d543d20SAndroid Build Coastguard Worker 		if (node && info_kind == CIL_KEY_SRC_CIL) {
106*2d543d20SAndroid Build Coastguard Worker 			return path;
107*2d543d20SAndroid Build Coastguard Worker 		}
108*2d543d20SAndroid Build Coastguard Worker 	}
109*2d543d20SAndroid Build Coastguard Worker 
110*2d543d20SAndroid Build Coastguard Worker 	return NULL;
111*2d543d20SAndroid Build Coastguard Worker }
112*2d543d20SAndroid Build Coastguard Worker 
cil_tree_log(struct cil_tree_node * node,enum cil_log_level lvl,const char * msg,...)113*2d543d20SAndroid Build Coastguard Worker __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...)
114*2d543d20SAndroid Build Coastguard Worker {
115*2d543d20SAndroid Build Coastguard Worker 	va_list ap;
116*2d543d20SAndroid Build Coastguard Worker 
117*2d543d20SAndroid Build Coastguard Worker 	va_start(ap, msg);
118*2d543d20SAndroid Build Coastguard Worker 	cil_vlog(lvl, msg, ap);
119*2d543d20SAndroid Build Coastguard Worker 	va_end(ap);
120*2d543d20SAndroid Build Coastguard Worker 
121*2d543d20SAndroid Build Coastguard Worker 	if (node) {
122*2d543d20SAndroid Build Coastguard Worker 		char *path = NULL;
123*2d543d20SAndroid Build Coastguard Worker 		uint32_t hll_offset = node->hll_offset;
124*2d543d20SAndroid Build Coastguard Worker 
125*2d543d20SAndroid Build Coastguard Worker 		path = cil_tree_get_cil_path(node);
126*2d543d20SAndroid Build Coastguard Worker 
127*2d543d20SAndroid Build Coastguard Worker 		if (path != NULL) {
128*2d543d20SAndroid Build Coastguard Worker 			cil_log(lvl, " at %s:%u", path, node->line);
129*2d543d20SAndroid Build Coastguard Worker 		}
130*2d543d20SAndroid Build Coastguard Worker 
131*2d543d20SAndroid Build Coastguard Worker 		while (node) {
132*2d543d20SAndroid Build Coastguard Worker 			do {
133*2d543d20SAndroid Build Coastguard Worker 				char *info_kind;
134*2d543d20SAndroid Build Coastguard Worker 				uint32_t hll_line;
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker 				node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
137*2d543d20SAndroid Build Coastguard Worker 				if (!node || info_kind == CIL_KEY_SRC_CIL) {
138*2d543d20SAndroid Build Coastguard Worker 					break;
139*2d543d20SAndroid Build Coastguard Worker 				}
140*2d543d20SAndroid Build Coastguard Worker 				if (info_kind == CIL_KEY_SRC_HLL_LMS) {
141*2d543d20SAndroid Build Coastguard Worker 					hll_line += hll_offset - node->hll_offset - 1;
142*2d543d20SAndroid Build Coastguard Worker 				}
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 				cil_log(lvl," from %s:%u", path, hll_line);
145*2d543d20SAndroid Build Coastguard Worker 			} while (1);
146*2d543d20SAndroid Build Coastguard Worker 		}
147*2d543d20SAndroid Build Coastguard Worker 	}
148*2d543d20SAndroid Build Coastguard Worker 
149*2d543d20SAndroid Build Coastguard Worker 	cil_log(lvl,"\n");
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker 
cil_tree_subtree_has_decl(struct cil_tree_node * node)152*2d543d20SAndroid Build Coastguard Worker int cil_tree_subtree_has_decl(struct cil_tree_node *node)
153*2d543d20SAndroid Build Coastguard Worker {
154*2d543d20SAndroid Build Coastguard Worker 	while (node) {
155*2d543d20SAndroid Build Coastguard Worker 		if (node->flavor >= CIL_MIN_DECLARATIVE) {
156*2d543d20SAndroid Build Coastguard Worker 			return CIL_TRUE;
157*2d543d20SAndroid Build Coastguard Worker 		}
158*2d543d20SAndroid Build Coastguard Worker 		if (node->cl_head != NULL) {
159*2d543d20SAndroid Build Coastguard Worker 			if (cil_tree_subtree_has_decl(node->cl_head))
160*2d543d20SAndroid Build Coastguard Worker 				return CIL_TRUE;
161*2d543d20SAndroid Build Coastguard Worker 		}
162*2d543d20SAndroid Build Coastguard Worker 		node = node->next;
163*2d543d20SAndroid Build Coastguard Worker 	}
164*2d543d20SAndroid Build Coastguard Worker 
165*2d543d20SAndroid Build Coastguard Worker 	return CIL_FALSE;
166*2d543d20SAndroid Build Coastguard Worker }
167*2d543d20SAndroid Build Coastguard Worker 
cil_tree_init(struct cil_tree ** tree)168*2d543d20SAndroid Build Coastguard Worker int cil_tree_init(struct cil_tree **tree)
169*2d543d20SAndroid Build Coastguard Worker {
170*2d543d20SAndroid Build Coastguard Worker 	struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
171*2d543d20SAndroid Build Coastguard Worker 
172*2d543d20SAndroid Build Coastguard Worker 	cil_tree_node_init(&new_tree->root);
173*2d543d20SAndroid Build Coastguard Worker 
174*2d543d20SAndroid Build Coastguard Worker 	*tree = new_tree;
175*2d543d20SAndroid Build Coastguard Worker 
176*2d543d20SAndroid Build Coastguard Worker 	return SEPOL_OK;
177*2d543d20SAndroid Build Coastguard Worker }
178*2d543d20SAndroid Build Coastguard Worker 
cil_tree_destroy(struct cil_tree ** tree)179*2d543d20SAndroid Build Coastguard Worker void cil_tree_destroy(struct cil_tree **tree)
180*2d543d20SAndroid Build Coastguard Worker {
181*2d543d20SAndroid Build Coastguard Worker 	if (tree == NULL || *tree == NULL) {
182*2d543d20SAndroid Build Coastguard Worker 		return;
183*2d543d20SAndroid Build Coastguard Worker 	}
184*2d543d20SAndroid Build Coastguard Worker 
185*2d543d20SAndroid Build Coastguard Worker 	cil_tree_subtree_destroy((*tree)->root);
186*2d543d20SAndroid Build Coastguard Worker 	free(*tree);
187*2d543d20SAndroid Build Coastguard Worker 	*tree = NULL;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker 
cil_tree_subtree_destroy(struct cil_tree_node * node)190*2d543d20SAndroid Build Coastguard Worker void cil_tree_subtree_destroy(struct cil_tree_node *node)
191*2d543d20SAndroid Build Coastguard Worker {
192*2d543d20SAndroid Build Coastguard Worker 	cil_tree_children_destroy(node);
193*2d543d20SAndroid Build Coastguard Worker 	cil_tree_node_destroy(&node);
194*2d543d20SAndroid Build Coastguard Worker }
195*2d543d20SAndroid Build Coastguard Worker 
cil_tree_children_destroy(struct cil_tree_node * node)196*2d543d20SAndroid Build Coastguard Worker void cil_tree_children_destroy(struct cil_tree_node *node)
197*2d543d20SAndroid Build Coastguard Worker {
198*2d543d20SAndroid Build Coastguard Worker 	struct cil_tree_node *curr, *next;
199*2d543d20SAndroid Build Coastguard Worker 
200*2d543d20SAndroid Build Coastguard Worker 	if (!node) {
201*2d543d20SAndroid Build Coastguard Worker 		return;
202*2d543d20SAndroid Build Coastguard Worker 	}
203*2d543d20SAndroid Build Coastguard Worker 
204*2d543d20SAndroid Build Coastguard Worker 	curr = node->cl_head;
205*2d543d20SAndroid Build Coastguard Worker 	while (curr) {
206*2d543d20SAndroid Build Coastguard Worker 		next = curr->next;
207*2d543d20SAndroid Build Coastguard Worker 		cil_tree_children_destroy(curr);
208*2d543d20SAndroid Build Coastguard Worker 		cil_tree_node_destroy(&curr);
209*2d543d20SAndroid Build Coastguard Worker 		curr = next;
210*2d543d20SAndroid Build Coastguard Worker 	}
211*2d543d20SAndroid Build Coastguard Worker 	node->cl_head = NULL;
212*2d543d20SAndroid Build Coastguard Worker 	node->cl_tail = NULL;
213*2d543d20SAndroid Build Coastguard Worker }
214*2d543d20SAndroid Build Coastguard Worker 
cil_tree_node_init(struct cil_tree_node ** node)215*2d543d20SAndroid Build Coastguard Worker void cil_tree_node_init(struct cil_tree_node **node)
216*2d543d20SAndroid Build Coastguard Worker {
217*2d543d20SAndroid Build Coastguard Worker 	struct cil_tree_node *new_node = cil_malloc(sizeof(*new_node));
218*2d543d20SAndroid Build Coastguard Worker 	new_node->cl_head = NULL;
219*2d543d20SAndroid Build Coastguard Worker 	new_node->cl_tail = NULL;
220*2d543d20SAndroid Build Coastguard Worker 	new_node->parent = NULL;
221*2d543d20SAndroid Build Coastguard Worker 	new_node->data = NULL;
222*2d543d20SAndroid Build Coastguard Worker 	new_node->next = NULL;
223*2d543d20SAndroid Build Coastguard Worker 	new_node->flavor = CIL_ROOT;
224*2d543d20SAndroid Build Coastguard Worker 	new_node->line = 0;
225*2d543d20SAndroid Build Coastguard Worker 	new_node->hll_offset = 0;
226*2d543d20SAndroid Build Coastguard Worker 
227*2d543d20SAndroid Build Coastguard Worker 	*node = new_node;
228*2d543d20SAndroid Build Coastguard Worker }
229*2d543d20SAndroid Build Coastguard Worker 
cil_tree_node_destroy(struct cil_tree_node ** node)230*2d543d20SAndroid Build Coastguard Worker void cil_tree_node_destroy(struct cil_tree_node **node)
231*2d543d20SAndroid Build Coastguard Worker {
232*2d543d20SAndroid Build Coastguard Worker 	struct cil_symtab_datum *datum;
233*2d543d20SAndroid Build Coastguard Worker 
234*2d543d20SAndroid Build Coastguard Worker 	if (node == NULL || *node == NULL) {
235*2d543d20SAndroid Build Coastguard Worker 		return;
236*2d543d20SAndroid Build Coastguard Worker 	}
237*2d543d20SAndroid Build Coastguard Worker 
238*2d543d20SAndroid Build Coastguard Worker 	if ((*node)->flavor >= CIL_MIN_DECLARATIVE) {
239*2d543d20SAndroid Build Coastguard Worker 		datum = (*node)->data;
240*2d543d20SAndroid Build Coastguard Worker 		cil_symtab_datum_remove_node(datum, *node);
241*2d543d20SAndroid Build Coastguard Worker 		if (datum->nodes == NULL) {
242*2d543d20SAndroid Build Coastguard Worker 			cil_destroy_data(&(*node)->data, (*node)->flavor);
243*2d543d20SAndroid Build Coastguard Worker 		}
244*2d543d20SAndroid Build Coastguard Worker 	} else {
245*2d543d20SAndroid Build Coastguard Worker 		cil_destroy_data(&(*node)->data, (*node)->flavor);
246*2d543d20SAndroid Build Coastguard Worker 	}
247*2d543d20SAndroid Build Coastguard Worker 	free(*node);
248*2d543d20SAndroid Build Coastguard Worker 	*node = NULL;
249*2d543d20SAndroid Build Coastguard Worker }
250*2d543d20SAndroid Build Coastguard Worker 
cil_tree_node_remove(struct cil_tree_node * node)251*2d543d20SAndroid Build Coastguard Worker void cil_tree_node_remove(struct cil_tree_node *node)
252*2d543d20SAndroid Build Coastguard Worker {
253*2d543d20SAndroid Build Coastguard Worker 	struct cil_tree_node *parent, *curr;
254*2d543d20SAndroid Build Coastguard Worker 
255*2d543d20SAndroid Build Coastguard Worker 	if (node == NULL || node->parent == NULL) {
256*2d543d20SAndroid Build Coastguard Worker 		return;
257*2d543d20SAndroid Build Coastguard Worker 	}
258*2d543d20SAndroid Build Coastguard Worker 
259*2d543d20SAndroid Build Coastguard Worker 	parent = node->parent;
260*2d543d20SAndroid Build Coastguard Worker 
261*2d543d20SAndroid Build Coastguard Worker 	if (parent->cl_head == node) {
262*2d543d20SAndroid Build Coastguard Worker 		if (parent->cl_tail == node) {
263*2d543d20SAndroid Build Coastguard Worker 			parent->cl_tail = NULL;
264*2d543d20SAndroid Build Coastguard Worker 		}
265*2d543d20SAndroid Build Coastguard Worker 		parent->cl_head = node->next;
266*2d543d20SAndroid Build Coastguard Worker 		cil_tree_node_destroy(&node);
267*2d543d20SAndroid Build Coastguard Worker 		return;
268*2d543d20SAndroid Build Coastguard Worker 	}
269*2d543d20SAndroid Build Coastguard Worker 
270*2d543d20SAndroid Build Coastguard Worker 	curr = parent->cl_head;
271*2d543d20SAndroid Build Coastguard Worker 	while (curr && curr->next != node) {
272*2d543d20SAndroid Build Coastguard Worker 		curr = curr->next;
273*2d543d20SAndroid Build Coastguard Worker 	}
274*2d543d20SAndroid Build Coastguard Worker 
275*2d543d20SAndroid Build Coastguard Worker 	if (curr == NULL) {
276*2d543d20SAndroid Build Coastguard Worker 		return;
277*2d543d20SAndroid Build Coastguard Worker 	}
278*2d543d20SAndroid Build Coastguard Worker 
279*2d543d20SAndroid Build Coastguard Worker 	if (parent->cl_tail == node) {
280*2d543d20SAndroid Build Coastguard Worker 		parent->cl_tail = curr;
281*2d543d20SAndroid Build Coastguard Worker 	}
282*2d543d20SAndroid Build Coastguard Worker 	curr->next = node->next;
283*2d543d20SAndroid Build Coastguard Worker 	cil_tree_node_destroy(&node);
284*2d543d20SAndroid Build Coastguard Worker }
285*2d543d20SAndroid Build Coastguard Worker 
286*2d543d20SAndroid Build Coastguard Worker /* Perform depth-first walk of the tree
287*2d543d20SAndroid Build Coastguard Worker    Parameters:
288*2d543d20SAndroid Build Coastguard Worker    start_node:          root node to start walking from
289*2d543d20SAndroid Build Coastguard Worker    process_node:        function to call when visiting a node
290*2d543d20SAndroid Build Coastguard Worker                         Takes parameters:
291*2d543d20SAndroid Build Coastguard Worker                             node:     node being visited
292*2d543d20SAndroid Build Coastguard Worker                             finished: boolean indicating to the tree walker that it should move on from this branch
293*2d543d20SAndroid Build Coastguard Worker                             extra_args:    additional data
294*2d543d20SAndroid Build Coastguard Worker    first_child:		Function to call before entering list of children
295*2d543d20SAndroid Build Coastguard Worker                         Takes parameters:
296*2d543d20SAndroid Build Coastguard Worker                             node:     node of first child
297*2d543d20SAndroid Build Coastguard Worker                             extra args:     additional data
298*2d543d20SAndroid Build Coastguard Worker    last_child:		Function to call when finished with the last child of a node's children
299*2d543d20SAndroid Build Coastguard Worker    extra_args:               any additional data to be passed to the helper functions
300*2d543d20SAndroid Build Coastguard Worker */
301*2d543d20SAndroid Build Coastguard Worker 
cil_tree_walk_core(struct cil_tree_node * node,int (* process_node)(struct cil_tree_node * node,uint32_t * finished,void * extra_args),int (* first_child)(struct cil_tree_node * node,void * extra_args),int (* last_child)(struct cil_tree_node * node,void * extra_args),void * extra_args)302*2d543d20SAndroid Build Coastguard Worker static int cil_tree_walk_core(struct cil_tree_node *node,
303*2d543d20SAndroid Build Coastguard Worker 					   int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args),
304*2d543d20SAndroid Build Coastguard Worker 					   int (*first_child)(struct cil_tree_node *node, void *extra_args),
305*2d543d20SAndroid Build Coastguard Worker 					   int (*last_child)(struct cil_tree_node *node, void *extra_args),
306*2d543d20SAndroid Build Coastguard Worker 					   void *extra_args)
307*2d543d20SAndroid Build Coastguard Worker {
308*2d543d20SAndroid Build Coastguard Worker 	int rc = SEPOL_ERR;
309*2d543d20SAndroid Build Coastguard Worker 
310*2d543d20SAndroid Build Coastguard Worker 	while (node) {
311*2d543d20SAndroid Build Coastguard Worker 		uint32_t finished = CIL_TREE_SKIP_NOTHING;
312*2d543d20SAndroid Build Coastguard Worker 
313*2d543d20SAndroid Build Coastguard Worker 		if (process_node != NULL) {
314*2d543d20SAndroid Build Coastguard Worker 			rc = (*process_node)(node, &finished, extra_args);
315*2d543d20SAndroid Build Coastguard Worker 			if (rc != SEPOL_OK) {
316*2d543d20SAndroid Build Coastguard Worker 				cil_tree_log(node, CIL_INFO, "Problem");
317*2d543d20SAndroid Build Coastguard Worker 				return rc;
318*2d543d20SAndroid Build Coastguard Worker 			}
319*2d543d20SAndroid Build Coastguard Worker 		}
320*2d543d20SAndroid Build Coastguard Worker 
321*2d543d20SAndroid Build Coastguard Worker 		if (finished & CIL_TREE_SKIP_NEXT) {
322*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_OK;
323*2d543d20SAndroid Build Coastguard Worker 		}
324*2d543d20SAndroid Build Coastguard Worker 
325*2d543d20SAndroid Build Coastguard Worker 		if (node->cl_head != NULL && !(finished & CIL_TREE_SKIP_HEAD)) {
326*2d543d20SAndroid Build Coastguard Worker 			rc = cil_tree_walk(node, process_node, first_child, last_child, extra_args);
327*2d543d20SAndroid Build Coastguard Worker 			if (rc != SEPOL_OK) {
328*2d543d20SAndroid Build Coastguard Worker 				return rc;
329*2d543d20SAndroid Build Coastguard Worker 			}
330*2d543d20SAndroid Build Coastguard Worker 		}
331*2d543d20SAndroid Build Coastguard Worker 
332*2d543d20SAndroid Build Coastguard Worker 		node = node->next;
333*2d543d20SAndroid Build Coastguard Worker 	}
334*2d543d20SAndroid Build Coastguard Worker 
335*2d543d20SAndroid Build Coastguard Worker 	return SEPOL_OK;
336*2d543d20SAndroid Build Coastguard Worker }
337*2d543d20SAndroid Build Coastguard Worker 
cil_tree_walk(struct cil_tree_node * node,int (* process_node)(struct cil_tree_node * node,uint32_t * finished,void * extra_args),int (* first_child)(struct cil_tree_node * node,void * extra_args),int (* last_child)(struct cil_tree_node * node,void * extra_args),void * extra_args)338*2d543d20SAndroid Build Coastguard Worker int cil_tree_walk(struct cil_tree_node *node,
339*2d543d20SAndroid Build Coastguard Worker 				  int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args),
340*2d543d20SAndroid Build Coastguard Worker 				  int (*first_child)(struct cil_tree_node *node, void *extra_args),
341*2d543d20SAndroid Build Coastguard Worker 				  int (*last_child)(struct cil_tree_node *node, void *extra_args),
342*2d543d20SAndroid Build Coastguard Worker 				  void *extra_args)
343*2d543d20SAndroid Build Coastguard Worker {
344*2d543d20SAndroid Build Coastguard Worker 	int rc = SEPOL_ERR;
345*2d543d20SAndroid Build Coastguard Worker 
346*2d543d20SAndroid Build Coastguard Worker 	if (!node || !node->cl_head) {
347*2d543d20SAndroid Build Coastguard Worker 		return SEPOL_OK;
348*2d543d20SAndroid Build Coastguard Worker 	}
349*2d543d20SAndroid Build Coastguard Worker 
350*2d543d20SAndroid Build Coastguard Worker 	if (first_child != NULL) {
351*2d543d20SAndroid Build Coastguard Worker 		rc = (*first_child)(node->cl_head, extra_args);
352*2d543d20SAndroid Build Coastguard Worker 		if (rc != SEPOL_OK) {
353*2d543d20SAndroid Build Coastguard Worker 			cil_tree_log(node, CIL_INFO, "Problem");
354*2d543d20SAndroid Build Coastguard Worker 			return rc;
355*2d543d20SAndroid Build Coastguard Worker 		}
356*2d543d20SAndroid Build Coastguard Worker 	}
357*2d543d20SAndroid Build Coastguard Worker 
358*2d543d20SAndroid Build Coastguard Worker 	rc = cil_tree_walk_core(node->cl_head, process_node, first_child, last_child, extra_args);
359*2d543d20SAndroid Build Coastguard Worker 	if (rc != SEPOL_OK) {
360*2d543d20SAndroid Build Coastguard Worker 		return rc;
361*2d543d20SAndroid Build Coastguard Worker 	}
362*2d543d20SAndroid Build Coastguard Worker 
363*2d543d20SAndroid Build Coastguard Worker 	if (last_child != NULL) {
364*2d543d20SAndroid Build Coastguard Worker 		rc = (*last_child)(node->cl_tail, extra_args);
365*2d543d20SAndroid Build Coastguard Worker 		if (rc != SEPOL_OK) {
366*2d543d20SAndroid Build Coastguard Worker 			cil_tree_log(node, CIL_INFO, "Problem");
367*2d543d20SAndroid Build Coastguard Worker 			return rc;
368*2d543d20SAndroid Build Coastguard Worker 		}
369*2d543d20SAndroid Build Coastguard Worker 	}
370*2d543d20SAndroid Build Coastguard Worker 
371*2d543d20SAndroid Build Coastguard Worker 	return SEPOL_OK;
372*2d543d20SAndroid Build Coastguard Worker }
373