xref: /aosp_15_r20/external/selinux/libsepol/cil/src/cil_build_ast.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include <sepol/policydb/conditional.h>
36 
37 #include "cil_internal.h"
38 #include "cil_flavor.h"
39 #include "cil_log.h"
40 #include "cil_mem.h"
41 #include "cil_tree.h"
42 #include "cil_list.h"
43 #include "cil_parser.h"
44 #include "cil_build_ast.h"
45 #include "cil_copy_ast.h"
46 #include "cil_verify.h"
47 #include "cil_strpool.h"
48 
49 struct cil_args_build {
50 	struct cil_tree_node *ast;
51 	struct cil_db *db;
52 	struct cil_tree_node *tunif;
53 	struct cil_tree_node *in;
54 	struct cil_tree_node *macro;
55 	struct cil_tree_node *optional;
56 	struct cil_tree_node *boolif;
57 };
58 
cil_fill_list(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** list)59 static int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
60 {
61 	int rc = SEPOL_ERR;
62 	struct cil_tree_node *curr;
63 	enum cil_syntax syntax[] = {
64 		CIL_SYN_N_STRINGS,
65 		CIL_SYN_END
66 	};
67 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
68 
69 	rc = __cil_verify_syntax(current, syntax, syntax_len);
70 	if (rc != SEPOL_OK) {
71 		goto exit;
72  	}
73 
74 	cil_list_init(list, flavor);
75 
76 	for (curr = current; curr != NULL; curr = curr->next) {
77 		cil_list_append(*list, CIL_STRING, curr->data);
78 	}
79 
80 	return SEPOL_OK;
81 
82 exit:
83 	return rc;
84 }
85 
cil_gen_declared_string(struct cil_db * db,hashtab_key_t key,struct cil_tree_node * ast_node)86 struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
87 {
88 	struct cil_tree_node *parent = ast_node->parent;
89 	struct cil_macro *macro = NULL;
90 	symtab_t *symtab;
91 	struct cil_symtab_datum *datum;
92 
93 	while (parent) {
94 		if (parent->flavor == CIL_MACRO) {
95 			/* This condition is only reached in the build phase */
96 			macro = parent->data;
97 			break;
98 		} else if (parent->flavor == CIL_CALL) {
99 			/* This condition is only reached in the resolve phase */
100 			struct cil_call *call = parent->data;
101 			macro = call->macro;
102 			break;
103 		}
104 		parent = parent->parent;
105 	}
106 
107 	if (macro && macro->params) {
108 		struct cil_list_item *item;
109 		cil_list_for_each(item, macro->params) {
110 			struct cil_param *param = item->data;
111 			if (param->flavor == CIL_DECLARED_STRING && param->str == key) {
112 				return NULL;
113 			}
114 		}
115 	}
116 
117 	symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_STRINGS];
118 	cil_symtab_get_datum(symtab, key, &datum);
119 	if (datum != NULL) {
120 		return datum;
121 	}
122 
123 	datum = cil_malloc(sizeof(*datum));
124 	cil_symtab_datum_init(datum);
125 	cil_symtab_insert(symtab, key, datum, ast_node);
126 	cil_list_append(db->declared_strings, CIL_DATUM, datum);
127 	return datum;
128 }
129 
130 
cil_allow_multiple_decls(struct cil_db * db,enum cil_flavor f_new,enum cil_flavor f_old)131 static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old)
132 {
133 	if (f_new != f_old) {
134 		return CIL_FALSE;
135 	}
136 
137 	switch (f_new) {
138 	case CIL_TYPE:
139 	case CIL_TYPEATTRIBUTE:
140 		if (db->multiple_decls) {
141 			return CIL_TRUE;
142 		}
143 		break;
144 	case CIL_OPTIONAL:
145 		return CIL_TRUE;
146 		break;
147 	default:
148 		break;
149 	}
150 
151 	return CIL_FALSE;
152 }
153 
cil_add_decl_to_symtab(struct cil_db * db,symtab_t * symtab,hashtab_key_t key,struct cil_symtab_datum * datum,struct cil_tree_node * node)154 int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node)
155 {
156 	int rc;
157 
158 	if (symtab == NULL || datum == NULL || node == NULL) {
159 		return SEPOL_ERR;
160 	}
161 
162 	rc = cil_symtab_insert(symtab, key, datum, node);
163 	if (rc == SEPOL_EEXIST) {
164 		struct cil_symtab_datum *prev;
165 		rc = cil_symtab_get_datum(symtab, key, &prev);
166 		if (rc != SEPOL_OK) {
167 			cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key);
168 			return SEPOL_ERR;
169 		}
170 		if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
171 			/* multiple_decls not ok, ret error */
172 			struct cil_tree_node *n = NODE(prev);
173 			cil_log(CIL_ERR, "Re-declaration of %s %s\n",
174 				cil_node_to_string(node), key);
175 			cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
176 				     cil_node_to_string(n));
177 			return SEPOL_ERR;
178 		}
179 		/* multiple_decls is enabled and works for this datum type, add node */
180 		cil_list_append(prev->nodes, CIL_NODE, node);
181 		node->data = prev;
182 		return SEPOL_EEXIST;
183 	}
184 
185 	return SEPOL_OK;
186 }
187 
cil_gen_node(struct cil_db * db,struct cil_tree_node * ast_node,struct cil_symtab_datum * datum,hashtab_key_t key,enum cil_sym_index sflavor,enum cil_flavor nflavor)188 int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
189 {
190 	int rc = SEPOL_ERR;
191 	symtab_t *symtab = NULL;
192 
193 	rc = cil_verify_name(db, (const char*)key, nflavor);
194 	if (rc != SEPOL_OK) {
195 		goto exit;
196 	}
197 
198 	rc = cil_get_symtab(ast_node->parent, &symtab, sflavor);
199 	if (rc != SEPOL_OK) {
200 		goto exit;
201 	}
202 
203 	ast_node->data = datum;
204 	ast_node->flavor = nflavor;
205 
206 	rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
207 	if (rc != SEPOL_OK) {
208 		goto exit;
209 	}
210 
211 	if (ast_node->parent->flavor == CIL_MACRO) {
212 		rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key);
213 		if (rc != SEPOL_OK) {
214 			goto exit;
215 		}
216 	}
217 
218 	return SEPOL_OK;
219 
220 exit:
221 	return rc;
222 }
223 
cil_clear_node(struct cil_tree_node * ast_node)224 static void cil_clear_node(struct cil_tree_node *ast_node)
225 {
226 	if (ast_node == NULL) {
227 		return;
228 	}
229 
230 	ast_node->data = NULL;
231 	ast_node->flavor = CIL_NONE;
232 }
233 
cil_gen_ordered(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)234 int cil_gen_ordered(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
235 {
236 	enum cil_syntax syntax[] = {
237 		CIL_SYN_STRING,
238 		CIL_SYN_LIST,
239 		CIL_SYN_END
240 	};
241 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
242 	struct cil_ordered *ordered = NULL;
243 	struct cil_list_item *curr = NULL;
244 
245 	int rc = SEPOL_ERR;
246 
247 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
248 		goto exit;
249 	}
250 
251 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
252 	if (rc !=  SEPOL_OK) {
253 		goto exit;
254 	}
255 
256 	cil_ordered_init(&ordered);
257 
258 	rc = cil_fill_list(parse_current->next->cl_head, flavor, &ordered->strs);
259 	if (rc != SEPOL_OK) {
260 		goto exit;
261 	}
262 
263 	cil_list_for_each(curr, ordered->strs) {
264 		if (curr->data == CIL_KEY_UNORDERED) {
265 			if (flavor == CIL_CLASSORDER) {
266 				if (curr == ordered->strs->head && curr->next == NULL) {
267 					cil_log(CIL_ERR, "classorder 'unordered' keyword must be followed by one or more class.\n");
268 					rc = SEPOL_ERR;
269 					goto exit;
270 				} else if (curr != ordered->strs->head) {
271 					cil_log(CIL_ERR, "classorder can only use 'unordered' keyword as the first item in the list.\n");
272 					rc = SEPOL_ERR;
273 					goto exit;
274 				}
275 			} else {
276 				cil_log(CIL_ERR, "The 'unordered' keyword can only be used with classorder rules.\n");
277 				rc = SEPOL_ERR;
278 				goto exit;
279 			}
280 		}
281 	}
282 
283 	ast_node->data = ordered;
284 	ast_node->flavor = flavor;
285 
286 	return SEPOL_OK;
287 
288 exit:
289 	cil_tree_log(parse_current, CIL_ERR, "Bad ordered declaration");
290 	cil_destroy_ordered(ordered);
291 	return rc;
292 }
293 
cil_destroy_ordered(struct cil_ordered * ordered)294 void cil_destroy_ordered(struct cil_ordered *ordered)
295 {
296 	if (ordered == NULL) {
297 		return;
298 	}
299 
300 	if (ordered->strs != NULL) {
301 		cil_list_destroy(&ordered->strs, CIL_FALSE);
302 	}
303 	if (ordered->datums != NULL) {
304 		cil_list_destroy(&ordered->datums, CIL_FALSE);
305 	}
306 
307 	free(ordered);
308 }
309 
310 
cil_gen_block(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint16_t is_abstract)311 int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract)
312 {
313 	enum cil_syntax syntax[] = {
314 		CIL_SYN_STRING,
315 		CIL_SYN_STRING,
316 		CIL_SYN_N_LISTS | CIL_SYN_END,
317 		CIL_SYN_END
318 	};
319 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
320 	char *key = NULL;
321 	struct cil_block *block = NULL;
322 	int rc = SEPOL_ERR;
323 
324 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
325 		goto exit;
326 	}
327 
328 	if (db->qualified_names) {
329 		cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n");
330 		goto exit;
331 	}
332 
333 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
334 	if (rc != SEPOL_OK) {
335 		goto exit;
336 	}
337 
338 	cil_block_init(&block);
339 
340 	block->is_abstract = is_abstract;
341 
342 	key = parse_current->next->data;
343 
344 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK);
345 	if (rc != SEPOL_OK) {
346 		goto exit;
347 	}
348 
349 	return SEPOL_OK;
350 
351 exit:
352 	cil_tree_log(parse_current, CIL_ERR, "Bad block declaration");
353 	cil_destroy_block(block);
354 	cil_clear_node(ast_node);
355 	return rc;
356 }
357 
cil_destroy_block(struct cil_block * block)358 void cil_destroy_block(struct cil_block *block)
359 {
360 	struct cil_list_item *item;
361 	struct cil_tree_node *bi_node;
362 	struct cil_blockinherit *inherit;
363 
364 	if (block == NULL) {
365 		return;
366 	}
367 
368 	cil_symtab_datum_destroy(&block->datum);
369 	cil_symtab_array_destroy(block->symtab);
370 	if (block->bi_nodes != NULL) {
371 		/* unlink blockinherit->block */
372 		cil_list_for_each(item, block->bi_nodes) {
373 			bi_node = item->data;
374 			/* the conditions should always be true, but better be sure */
375 			if (bi_node->flavor == CIL_BLOCKINHERIT) {
376 				inherit = bi_node->data;
377 				if (inherit->block == block) {
378 					inherit->block = NULL;
379 				}
380 			}
381 		}
382 		cil_list_destroy(&block->bi_nodes, CIL_FALSE);
383 	}
384 
385 	free(block);
386 }
387 
cil_gen_blockinherit(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)388 int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
389 {
390 	enum cil_syntax syntax[] = {
391 		CIL_SYN_STRING,
392 		CIL_SYN_STRING,
393 		CIL_SYN_END
394 	};
395 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
396 	struct cil_blockinherit *inherit = NULL;
397 	int rc = SEPOL_ERR;
398 
399 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
400 		goto exit;
401 	}
402 
403 	if (db->qualified_names) {
404 		cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n");
405 		goto exit;
406 	}
407 
408 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
409 	if (rc != SEPOL_OK) {
410 		goto exit;
411 	}
412 
413 	cil_blockinherit_init(&inherit);
414 
415 	inherit->block_str = parse_current->next->data;
416 
417 	ast_node->data = inherit;
418 	ast_node->flavor = CIL_BLOCKINHERIT;
419 
420 	return SEPOL_OK;
421 
422 exit:
423 	cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration");
424 	cil_destroy_blockinherit(inherit);
425 	return rc;
426 }
427 
cil_destroy_blockinherit(struct cil_blockinherit * inherit)428 void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
429 {
430 	if (inherit == NULL) {
431 		return;
432 	}
433 
434 	if (inherit->block != NULL && inherit->block->bi_nodes != NULL) {
435 		struct cil_tree_node *node;
436 		struct cil_list_item *item;
437 
438 		cil_list_for_each(item, inherit->block->bi_nodes) {
439 			node = item->data;
440 			if (node->data == inherit) {
441 				cil_list_remove(inherit->block->bi_nodes, CIL_NODE, node, CIL_FALSE);
442 				break;
443 			}
444 		}
445 	}
446 
447 	free(inherit);
448 }
449 
cil_gen_blockabstract(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)450 int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
451 {
452 	enum cil_syntax syntax[] = {
453 		CIL_SYN_STRING,
454 		CIL_SYN_STRING,
455 		CIL_SYN_END
456 	};
457 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
458 	struct cil_blockabstract *abstract = NULL;
459 	int rc = SEPOL_ERR;
460 
461 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
462 		goto exit;
463 	}
464 
465 	if (db->qualified_names) {
466 		cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n");
467 		goto exit;
468 	}
469 
470 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
471 	if (rc != SEPOL_OK) {
472 		goto exit;
473 	}
474 
475 	cil_blockabstract_init(&abstract);
476 
477 	abstract->block_str = parse_current->next->data;
478 
479 	ast_node->data = abstract;
480 	ast_node->flavor = CIL_BLOCKABSTRACT;
481 
482 	return SEPOL_OK;
483 
484 exit:
485 	cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration");
486 	cil_destroy_blockabstract(abstract);
487 	return rc;
488 }
489 
cil_destroy_blockabstract(struct cil_blockabstract * abstract)490 void cil_destroy_blockabstract(struct cil_blockabstract *abstract)
491 {
492 	if (abstract == NULL) {
493 		return;
494 	}
495 
496 	free(abstract);
497 }
498 
cil_gen_in(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)499 int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
500 {
501 	enum cil_syntax syntax[] = {
502 		CIL_SYN_STRING,
503 		CIL_SYN_STRING,
504 		CIL_SYN_STRING | CIL_SYN_N_LISTS,
505 		CIL_SYN_N_LISTS | CIL_SYN_END,
506 		CIL_SYN_END
507 	};
508 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
509 	int rc = SEPOL_ERR;
510 	struct cil_in *in = NULL;
511 
512 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
513 		goto exit;
514 	}
515 
516 	if (db->qualified_names) {
517 		cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n");
518 		goto exit;
519 	}
520 
521 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
522 	if (rc != SEPOL_OK) {
523 		goto exit;
524 	}
525 
526 	cil_in_init(&in);
527 
528 	if (parse_current->next->next->data) {
529 		char *is_after_str = parse_current->next->data;
530 		if (is_after_str == CIL_KEY_IN_BEFORE) {
531 			in->is_after = CIL_FALSE;
532 		} else if (is_after_str == CIL_KEY_IN_AFTER) {
533 			in->is_after = CIL_TRUE;
534 		} else {
535 			cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n");
536 			rc = SEPOL_ERR;
537 			goto exit;
538 		}
539 		in->block_str = parse_current->next->next->data;
540 	} else {
541 		in->is_after = CIL_FALSE;
542 		in->block_str = parse_current->next->data;
543 	}
544 
545 	ast_node->data = in;
546 	ast_node->flavor = CIL_IN;
547 
548 	return SEPOL_OK;
549 exit:
550 	cil_tree_log(parse_current, CIL_ERR, "Bad in-statement");
551 	cil_destroy_in(in);
552 	return rc;
553 }
554 
cil_destroy_in(struct cil_in * in)555 void cil_destroy_in(struct cil_in *in)
556 {
557 	if (in == NULL) {
558 		return;
559 	}
560 
561 	cil_symtab_array_destroy(in->symtab);
562 
563 	free(in);
564 }
565 
cil_gen_class(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)566 int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
567 {
568 	enum cil_syntax syntax[] = {
569 		CIL_SYN_STRING,
570 		CIL_SYN_STRING,
571 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
572 		CIL_SYN_END
573 	};
574 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
575 	char *key = NULL;
576 	struct cil_class *class = NULL;
577 	struct cil_tree_node *perms = NULL;
578 	int rc = SEPOL_ERR;
579 
580 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
581 	if (rc != SEPOL_OK) {
582 		goto exit;
583 	}
584 
585 	cil_class_init(&class);
586 
587 	key = parse_current->next->data;
588 	if (key == CIL_KEY_UNORDERED) {
589 		cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n");
590 		rc = SEPOL_ERR;
591 		goto exit;
592 	}
593 
594 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS);
595 	if (rc != SEPOL_OK) {
596 		goto exit;
597 	}
598 
599 	if (parse_current->next->next != NULL) {
600 		perms = parse_current->next->next->cl_head;
601 		rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms);
602 		if (rc != SEPOL_OK) {
603 			goto exit;
604 		}
605 		if (class->num_perms > CIL_PERMS_PER_CLASS) {
606 			cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name);
607 			cil_tree_children_destroy(ast_node);
608 			rc = SEPOL_ERR;
609 			goto exit;
610 		}
611 
612 	}
613 
614 	return SEPOL_OK;
615 
616 exit:
617 	cil_tree_log(parse_current, CIL_ERR, "Bad class declaration");
618 	cil_destroy_class(class);
619 	cil_clear_node(ast_node);
620 	return rc;
621 }
622 
cil_destroy_class(struct cil_class * class)623 void cil_destroy_class(struct cil_class *class)
624 {
625 	if (class == NULL) {
626 		return;
627 	}
628 
629 	cil_symtab_datum_destroy(&class->datum);
630 	cil_symtab_destroy(&class->perms);
631 
632 	free(class);
633 }
634 
cil_gen_perm(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor,unsigned int * num_perms)635 int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
636 {
637 	char *key = NULL;
638 	struct cil_perm *perm = NULL;
639 	int rc = SEPOL_ERR;
640 
641 	cil_perm_init(&perm);
642 
643 	key = parse_current->data;
644 	if (key == NULL) {
645 		cil_log(CIL_ERR, "Bad permission\n");
646 		goto exit;
647 	}
648 
649 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor);
650 	if (rc != SEPOL_OK) {
651 		goto exit;
652 	}
653 
654 	perm->value = *num_perms;
655 	(*num_perms)++;
656 
657 	return SEPOL_OK;
658 
659 exit:
660 	cil_destroy_perm(perm);
661 	cil_clear_node(ast_node);
662 	return rc;
663 }
664 
cil_destroy_perm(struct cil_perm * perm)665 void cil_destroy_perm(struct cil_perm *perm)
666 {
667 	if (perm == NULL) {
668 		return;
669 	}
670 
671 	cil_symtab_datum_destroy(&perm->datum);
672 	cil_list_destroy(&perm->classperms, CIL_FALSE);
673 
674 	free(perm);
675 }
676 
cil_gen_perm_nodes(struct cil_db * db,struct cil_tree_node * current_perm,struct cil_tree_node * ast_node,enum cil_flavor flavor,unsigned int * num_perms)677 int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
678 {
679 	int rc = SEPOL_ERR;
680 	struct cil_tree_node *new_ast = NULL;
681 
682 	while(current_perm != NULL) {
683 		if (current_perm->cl_head != NULL) {
684 
685 			rc = SEPOL_ERR;
686 			goto exit;
687 		}
688 		cil_tree_node_init(&new_ast);
689 		new_ast->parent = ast_node;
690 		new_ast->line = current_perm->line;
691 		new_ast->hll_offset = current_perm->hll_offset;
692 
693 		rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
694 		if (rc != SEPOL_OK) {
695 			cil_tree_node_destroy(&new_ast);
696 			goto exit;
697 		}
698 
699 		if (ast_node->cl_head == NULL) {
700 			ast_node->cl_head = new_ast;
701 		} else {
702 			ast_node->cl_tail->next = new_ast;
703 		}
704 		ast_node->cl_tail = new_ast;
705 
706 		current_perm = current_perm->next;
707 	}
708 
709 	return SEPOL_OK;
710 
711 exit:
712 	cil_log(CIL_ERR, "Bad permissions\n");
713 	cil_tree_children_destroy(ast_node);
714 	cil_clear_node(ast_node);
715 	return rc;
716 }
717 
cil_fill_perms(struct cil_tree_node * start_perm,struct cil_list ** perms)718 int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
719 {
720 	int rc = SEPOL_ERR;
721 	enum cil_syntax syntax[] = {
722 		CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
723 		CIL_SYN_END
724 	};
725 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
726 
727 	rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
728 	if (rc != SEPOL_OK) {
729 		goto exit;
730 	}
731 
732 	rc = cil_gen_expr(start_perm, CIL_PERM, perms);
733 	if (rc != SEPOL_OK) {
734 		goto exit;
735 	}
736 
737 	return SEPOL_OK;
738 
739 exit:
740 	cil_log(CIL_ERR, "Bad permission list or expression\n");
741 	return rc;
742 }
743 
cil_fill_classperms(struct cil_tree_node * parse_current,struct cil_classperms ** cp)744 int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp)
745 {
746 	int rc = SEPOL_ERR;
747 	enum cil_syntax syntax[] = {
748 		CIL_SYN_STRING,
749 		CIL_SYN_LIST,
750 		CIL_SYN_END
751 	};
752 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
753 
754 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
755 	if (rc != SEPOL_OK) {
756 		goto exit;
757 	}
758 
759 	cil_classperms_init(cp);
760 
761 	(*cp)->class_str = parse_current->data;
762 
763 	rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs);
764 	if (rc != SEPOL_OK) {
765 		cil_destroy_classperms(*cp);
766 		goto exit;
767 	}
768 
769 	return SEPOL_OK;
770 
771 exit:
772 	cil_log(CIL_ERR, "Bad class-permissions\n");
773 	*cp = NULL;
774 	return rc;
775 }
776 
cil_destroy_classperms(struct cil_classperms * cp)777 void cil_destroy_classperms(struct cil_classperms *cp)
778 {
779 	if (cp == NULL) {
780 		return;
781 	}
782 
783 	cil_list_destroy(&cp->perm_strs, CIL_TRUE);
784 	cil_list_destroy(&cp->perms, CIL_FALSE);
785 
786 	free(cp);
787 }
788 
cil_fill_classperms_set(struct cil_tree_node * parse_current,struct cil_classperms_set ** cp_set)789 void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set)
790 {
791 	cil_classperms_set_init(cp_set);
792 	(*cp_set)->set_str = parse_current->data;
793 }
794 
cil_destroy_classperms_set(struct cil_classperms_set * cp_set)795 void cil_destroy_classperms_set(struct cil_classperms_set *cp_set)
796 {
797 	if (cp_set == NULL) {
798 		return;
799 	}
800 
801 	free(cp_set);
802 }
803 
cil_fill_classperms_list(struct cil_tree_node * parse_current,struct cil_list ** cp_list)804 int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list)
805 {
806 	int rc = SEPOL_ERR;
807 	struct cil_tree_node *curr;
808 
809 	if (parse_current == NULL || cp_list == NULL) {
810 		goto exit;
811 	}
812 
813 	cil_list_init(cp_list, CIL_CLASSPERMS);
814 
815 	curr = parse_current->cl_head;
816 
817 	if (curr == NULL) {
818 		/* Class-perms form: SET1 */
819 		struct cil_classperms_set *new_cp_set;
820 		cil_fill_classperms_set(parse_current, &new_cp_set);
821 		cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set);
822 	} else if (curr->cl_head == NULL) {
823 		/* Class-perms form: (CLASS1 (PERM1 ...)) */
824 		struct cil_classperms *new_cp;
825 		rc = cil_fill_classperms(curr, &new_cp);
826 		if (rc != SEPOL_OK) {
827 			goto exit;
828 		}
829 		cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp);
830 	} else {
831 		cil_log(CIL_ERR, "Bad class-permissions list syntax\n");
832 		rc = SEPOL_ERR;
833 		goto exit;
834 	}
835 
836 	return SEPOL_OK;
837 
838 exit:
839 	cil_log(CIL_ERR, "Problem filling class-permissions list\n");
840 	cil_list_destroy(cp_list, CIL_TRUE);
841 	return rc;
842 }
843 
cil_destroy_classperms_list(struct cil_list ** cp_list)844 void cil_destroy_classperms_list(struct cil_list **cp_list)
845 {
846 	struct cil_list_item *curr;
847 
848 	if (cp_list == NULL || *cp_list == NULL) {
849 		return;
850 	}
851 
852 	cil_list_for_each(curr, *cp_list) {
853 		if (curr->flavor == CIL_CLASSPERMS) {
854 			cil_destroy_classperms(curr->data);
855 		} else {
856 			cil_destroy_classperms_set(curr->data);
857 		}
858 	}
859 
860 	cil_list_destroy(cp_list, CIL_FALSE);
861 }
862 
cil_gen_classpermission(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)863 int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
864 {
865 	int rc = SEPOL_ERR;
866 	char *key = NULL;
867 	struct cil_classpermission *cp = NULL;
868 	enum cil_syntax syntax[] = {
869 		CIL_SYN_STRING,
870 		CIL_SYN_STRING,
871 		CIL_SYN_END
872 	};
873 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
874 
875 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
876 		goto exit;
877 	}
878 
879 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
880 	if (rc != SEPOL_OK) {
881 		goto exit;
882 	}
883 
884 	cil_classpermission_init(&cp);
885 
886 	key = parse_current->next->data;
887 
888 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION);
889 	if (rc != SEPOL_OK) {
890 		goto exit;
891 	}
892 
893 	return SEPOL_OK;
894 
895 exit:
896 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration");
897 	cil_destroy_classpermission(cp);
898 	cil_clear_node(ast_node);
899 	return rc;
900 }
901 
cil_destroy_classpermission(struct cil_classpermission * cp)902 void cil_destroy_classpermission(struct cil_classpermission *cp)
903 {
904 	if (cp == NULL) {
905 		return;
906 	}
907 
908 	if (cp->datum.name != NULL) {
909 		cil_list_destroy(&cp->classperms, CIL_FALSE);
910 	} else {
911 		/* anonymous classpermission from call */
912 		cil_destroy_classperms_list(&cp->classperms);
913 	}
914 
915 	cil_symtab_datum_destroy(&cp->datum);
916 
917 
918 	free(cp);
919 }
920 
cil_gen_classpermissionset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)921 int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
922 {
923 	int rc = SEPOL_ERR;
924 	struct cil_classpermissionset *cps = NULL;
925 	enum cil_syntax syntax[] = {
926 		CIL_SYN_STRING,
927 		CIL_SYN_STRING,
928 		CIL_SYN_STRING | CIL_SYN_LIST,
929 		CIL_SYN_END
930 	};
931 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
932 
933 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
934 		goto exit;
935 	}
936 
937 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
938 	if (rc != SEPOL_OK) {
939 		goto exit;
940 	}
941 
942 	cil_classpermissionset_init(&cps);
943 
944 	cps->set_str = parse_current->next->data;
945 
946 	rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms);
947 	if (rc != SEPOL_OK) {
948 		goto exit;
949 	}
950 
951 	ast_node->data = cps;
952 	ast_node->flavor = CIL_CLASSPERMISSIONSET;
953 
954 	return SEPOL_OK;
955 
956 exit:
957 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset");
958 	cil_destroy_classpermissionset(cps);
959 	return rc;
960 }
961 
cil_destroy_classpermissionset(struct cil_classpermissionset * cps)962 void cil_destroy_classpermissionset(struct cil_classpermissionset *cps)
963 {
964 	if (cps == NULL) {
965 		return;
966 	}
967 
968 	cil_destroy_classperms_list(&cps->classperms);
969 
970 	free(cps);
971 }
972 
cil_gen_map_class(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)973 int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
974 {
975 	enum cil_syntax syntax[] = {
976 		CIL_SYN_STRING,
977 		CIL_SYN_STRING,
978 		CIL_SYN_LIST,
979 		CIL_SYN_END
980 	};
981 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
982 	char *key = NULL;
983 	struct cil_class *map = NULL;
984 	int rc = SEPOL_ERR;
985 
986 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
987 	if (rc != SEPOL_OK) {
988 		goto exit;
989 	}
990 
991 	cil_class_init(&map);
992 
993 	key = parse_current->next->data;
994 
995 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS);
996 	if (rc != SEPOL_OK) {
997 		goto exit;
998 	}
999 
1000 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms);
1001 	if (rc != SEPOL_OK) {
1002 		goto exit;
1003 	}
1004 
1005 	return SEPOL_OK;
1006 
1007 exit:
1008 	cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration");
1009 	cil_destroy_class(map);
1010 	cil_clear_node(ast_node);
1011 	return rc;
1012 }
1013 
cil_gen_classmapping(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1014 int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1015 {
1016 	int rc = SEPOL_ERR;
1017 	struct cil_classmapping *mapping = NULL;
1018 	enum cil_syntax syntax[] = {
1019 		CIL_SYN_STRING,
1020 		CIL_SYN_STRING,
1021 		CIL_SYN_STRING,
1022 		CIL_SYN_STRING | CIL_SYN_LIST,
1023 		CIL_SYN_END
1024 	};
1025 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1026 
1027 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1028 		goto exit;
1029 	}
1030 
1031 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1032 	if (rc != SEPOL_OK) {
1033 		goto exit;
1034 	}
1035 
1036 	cil_classmapping_init(&mapping);
1037 
1038 	mapping->map_class_str = parse_current->next->data;
1039 	mapping->map_perm_str = parse_current->next->next->data;
1040 
1041 	rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms);
1042 	if (rc != SEPOL_OK) {
1043 		goto exit;
1044 	}
1045 
1046 	ast_node->data = mapping;
1047 	ast_node->flavor = CIL_CLASSMAPPING;
1048 
1049 	return SEPOL_OK;
1050 
1051 exit:
1052 	cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration");
1053 	cil_destroy_classmapping(mapping);
1054 	return rc;
1055 }
1056 
cil_destroy_classmapping(struct cil_classmapping * mapping)1057 void cil_destroy_classmapping(struct cil_classmapping *mapping)
1058 {
1059 	if (mapping == NULL) {
1060 		return;
1061 	}
1062 
1063 	cil_destroy_classperms_list(&mapping->classperms);
1064 
1065 	free(mapping);
1066 }
1067 
1068 // TODO try to merge some of this with cil_gen_class (helper function for both)
cil_gen_common(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1069 int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1070 {
1071 	enum cil_syntax syntax[] = {
1072 		CIL_SYN_STRING,
1073 		CIL_SYN_STRING,
1074 		CIL_SYN_LIST,
1075 		CIL_SYN_END
1076 	};
1077 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1078 	char *key = NULL;
1079 	struct cil_class *common = NULL;
1080 	int rc = SEPOL_ERR;
1081 
1082 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1083 		goto exit;
1084 	}
1085 
1086 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1087 	if (rc != SEPOL_OK) {
1088 		goto exit;
1089 	}
1090 
1091 	cil_class_init(&common);
1092 
1093 	key = parse_current->next->data;
1094 
1095 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON);
1096 	if (rc != SEPOL_OK) {
1097 		goto exit;
1098 	}
1099 
1100 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms);
1101 	if (rc != SEPOL_OK) {
1102 		goto exit;
1103 	}
1104 	if (common->num_perms > CIL_PERMS_PER_CLASS) {
1105 		cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name);
1106 		cil_tree_children_destroy(ast_node);
1107 		rc = SEPOL_ERR;
1108 		goto exit;
1109 	}
1110 
1111 	return SEPOL_OK;
1112 
1113 exit:
1114 	cil_tree_log(parse_current, CIL_ERR, "Bad common declaration");
1115 	cil_destroy_class(common);
1116 	cil_clear_node(ast_node);
1117 	return rc;
1118 
1119 }
1120 
cil_gen_classcommon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1121 int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1122 {
1123 	enum cil_syntax syntax[] = {
1124 		CIL_SYN_STRING,
1125 		CIL_SYN_STRING,
1126 		CIL_SYN_STRING,
1127 		CIL_SYN_END
1128 	};
1129 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1130 	struct cil_classcommon *clscom = NULL;
1131 	int rc = SEPOL_ERR;
1132 
1133 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1134 		goto exit;
1135 	}
1136 
1137 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1138 	if (rc != SEPOL_OK) {
1139 		goto exit;
1140 	}
1141 
1142 	cil_classcommon_init(&clscom);
1143 
1144 	clscom->class_str = parse_current->next->data;
1145 	clscom->common_str = parse_current->next->next->data;
1146 
1147 	ast_node->data = clscom;
1148 	ast_node->flavor = CIL_CLASSCOMMON;
1149 
1150 	return SEPOL_OK;
1151 
1152 exit:
1153 	cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration");
1154 	cil_destroy_classcommon(clscom);
1155 	return rc;
1156 
1157 }
1158 
cil_destroy_classcommon(struct cil_classcommon * clscom)1159 void cil_destroy_classcommon(struct cil_classcommon *clscom)
1160 {
1161 	if (clscom == NULL) {
1162 		return;
1163 	}
1164 
1165 	free(clscom);
1166 }
1167 
cil_gen_sid(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1168 int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1169 {
1170 	enum cil_syntax syntax[] = {
1171 		CIL_SYN_STRING,
1172 		CIL_SYN_STRING,
1173 		CIL_SYN_END
1174 	};
1175 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1176 	char *key = NULL;
1177 	struct cil_sid *sid = NULL;
1178 	int rc = SEPOL_ERR;
1179 
1180 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1181 		goto exit;
1182 	}
1183 
1184 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1185 	if (rc != SEPOL_OK) {
1186 		goto exit;
1187 	}
1188 
1189 	cil_sid_init(&sid);
1190 
1191 	key = parse_current->next->data;
1192 
1193 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID);
1194 	if (rc != SEPOL_OK) {
1195 		goto exit;
1196 	}
1197 
1198 	return SEPOL_OK;
1199 
1200 exit:
1201 	cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration");
1202 	cil_destroy_sid(sid);
1203 	cil_clear_node(ast_node);
1204 	return rc;
1205 }
1206 
cil_destroy_sid(struct cil_sid * sid)1207 void cil_destroy_sid(struct cil_sid *sid)
1208 {
1209 	if (sid == NULL) {
1210 		return;
1211 	}
1212 
1213 	cil_symtab_datum_destroy(&sid->datum);
1214 	free(sid);
1215 }
1216 
cil_gen_sidcontext(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1217 int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1218 {
1219 	enum cil_syntax syntax[] = {
1220 		CIL_SYN_STRING,
1221 		CIL_SYN_STRING,
1222 		CIL_SYN_STRING | CIL_SYN_LIST,
1223 		CIL_SYN_END
1224 	};
1225 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1226 	struct cil_sidcontext *sidcon = NULL;
1227 	int rc = SEPOL_ERR;
1228 
1229 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1230 		goto exit;
1231 	}
1232 
1233 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1234 	if (rc != SEPOL_OK) {
1235 		goto exit;
1236 	}
1237 
1238 	cil_sidcontext_init(&sidcon);
1239 
1240 	sidcon->sid_str = parse_current->next->data;
1241 
1242 	if (parse_current->next->next->cl_head == NULL) {
1243 		sidcon->context_str = parse_current->next->next->data;
1244 	} else {
1245 		cil_context_init(&sidcon->context);
1246 
1247 		rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context);
1248 		if (rc != SEPOL_OK) {
1249 			goto exit;
1250 		}
1251 	}
1252 
1253 	ast_node->data = sidcon;
1254 	ast_node->flavor = CIL_SIDCONTEXT;
1255 
1256 	return SEPOL_OK;
1257 
1258 exit:
1259 	cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration");
1260 	cil_destroy_sidcontext(sidcon);
1261 	return rc;
1262 }
1263 
cil_destroy_sidcontext(struct cil_sidcontext * sidcon)1264 void cil_destroy_sidcontext(struct cil_sidcontext *sidcon)
1265 {
1266 	if (sidcon == NULL) {
1267 		return;
1268 	}
1269 
1270 	if (sidcon->context_str == NULL && sidcon->context != NULL) {
1271 		cil_destroy_context(sidcon->context);
1272 	}
1273 
1274 	free(sidcon);
1275 }
1276 
cil_gen_user(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1277 int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1278 {
1279 	enum cil_syntax syntax[] = {
1280 		CIL_SYN_STRING,
1281 		CIL_SYN_STRING,
1282 		CIL_SYN_END
1283 	};
1284 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1285 	char *key = NULL;
1286 	struct cil_user *user = NULL;
1287 	int rc = SEPOL_ERR;
1288 
1289 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1290 		goto exit;
1291 	}
1292 
1293 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1294 	if (rc != SEPOL_OK) {
1295 		goto exit;
1296 	}
1297 
1298 	cil_user_init(&user);
1299 
1300 	key = parse_current->next->data;
1301 
1302 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER);
1303 	if (rc != SEPOL_OK) {
1304 		goto exit;
1305 	}
1306 
1307 	return SEPOL_OK;
1308 
1309 exit:
1310 	cil_tree_log(parse_current, CIL_ERR, "Bad user declaration");
1311 	cil_destroy_user(user);
1312 	cil_clear_node(ast_node);
1313 	return rc;
1314 }
1315 
cil_destroy_user(struct cil_user * user)1316 void cil_destroy_user(struct cil_user *user)
1317 {
1318 	if (user == NULL) {
1319 		return;
1320 	}
1321 
1322 	cil_symtab_datum_destroy(&user->datum);
1323 	ebitmap_destroy(user->roles);
1324 	free(user->roles);
1325 	free(user);
1326 }
1327 
cil_gen_userattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1328 int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1329 {
1330 	enum cil_syntax syntax[] = {
1331 		CIL_SYN_STRING,
1332 		CIL_SYN_STRING,
1333 		CIL_SYN_END
1334 	};
1335 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1336 	char *key = NULL;
1337 	struct cil_userattribute *attr = NULL;
1338 	int rc = SEPOL_ERR;
1339 
1340 	if (parse_current == NULL || ast_node == NULL) {
1341 		goto exit;
1342 	}
1343 
1344 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1345 	if (rc != SEPOL_OK) {
1346 		goto exit;
1347 	}
1348 
1349 	cil_userattribute_init(&attr);
1350 
1351 	key = parse_current->next->data;
1352 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
1353 	if (rc != SEPOL_OK) {
1354 		goto exit;
1355 	}
1356 
1357 	return SEPOL_OK;
1358 exit:
1359 	cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration");
1360 	cil_destroy_userattribute(attr);
1361 	cil_clear_node(ast_node);
1362 	return rc;
1363 }
1364 
cil_destroy_userattribute(struct cil_userattribute * attr)1365 void cil_destroy_userattribute(struct cil_userattribute *attr)
1366 {
1367 	struct cil_list_item *expr = NULL;
1368 	struct cil_list_item *next = NULL;
1369 
1370 	if (attr == NULL) {
1371 		return;
1372 	}
1373 
1374 	if (attr->expr_list != NULL) {
1375 		/* we don't want to destroy the expression stacks (cil_list) inside
1376 		 * this list cil_list_destroy destroys sublists, so we need to do it
1377 		 * manually */
1378 		expr = attr->expr_list->head;
1379 		while (expr != NULL) {
1380 			next = expr->next;
1381 			cil_list_item_destroy(&expr, CIL_FALSE);
1382 			expr = next;
1383 		}
1384 		free(attr->expr_list);
1385 		attr->expr_list = NULL;
1386 	}
1387 
1388 	cil_symtab_datum_destroy(&attr->datum);
1389 	ebitmap_destroy(attr->users);
1390 	free(attr->users);
1391 	free(attr);
1392 }
1393 
cil_gen_userattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1394 int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1395 {
1396 	enum cil_syntax syntax[] = {
1397 		CIL_SYN_STRING,
1398 		CIL_SYN_STRING,
1399 		CIL_SYN_STRING | CIL_SYN_LIST,
1400 		CIL_SYN_END
1401 	};
1402 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1403 	struct cil_userattributeset *attrset = NULL;
1404 	int rc = SEPOL_ERR;
1405 
1406 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1407 		goto exit;
1408 	}
1409 
1410 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1411 	if (rc != SEPOL_OK) {
1412 		goto exit;
1413 	}
1414 
1415 	cil_userattributeset_init(&attrset);
1416 
1417 	attrset->attr_str = parse_current->next->data;
1418 
1419 	rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr);
1420 	if (rc != SEPOL_OK) {
1421 		goto exit;
1422 	}
1423 	ast_node->data = attrset;
1424 	ast_node->flavor = CIL_USERATTRIBUTESET;
1425 
1426 	return SEPOL_OK;
1427 
1428 exit:
1429 	cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration");
1430 	cil_destroy_userattributeset(attrset);
1431 
1432 	return rc;
1433 }
1434 
cil_destroy_userattributeset(struct cil_userattributeset * attrset)1435 void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
1436 {
1437 	if (attrset == NULL) {
1438 		return;
1439 	}
1440 
1441 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
1442 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
1443 
1444 	free(attrset);
1445 }
1446 
cil_gen_userlevel(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1447 int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1448 {
1449 	enum cil_syntax syntax[] = {
1450 		CIL_SYN_STRING,
1451 		CIL_SYN_STRING,
1452 		CIL_SYN_STRING | CIL_SYN_LIST,
1453 		CIL_SYN_END
1454 	};
1455 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1456 	struct cil_userlevel *usrlvl = NULL;
1457 	int rc = SEPOL_ERR;
1458 
1459 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1460 		goto exit;
1461 	}
1462 
1463 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1464 	if (rc != SEPOL_OK) {
1465 		goto exit;
1466 	}
1467 
1468 	cil_userlevel_init(&usrlvl);
1469 
1470 	usrlvl->user_str = parse_current->next->data;
1471 
1472 	if (parse_current->next->next->cl_head == NULL) {
1473 		usrlvl->level_str = parse_current->next->next->data;
1474 	} else {
1475 		cil_level_init(&usrlvl->level);
1476 
1477 		rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level);
1478 		if (rc != SEPOL_OK) {
1479 			goto exit;
1480 		}
1481 	}
1482 
1483 	ast_node->data = usrlvl;
1484 	ast_node->flavor = CIL_USERLEVEL;
1485 
1486 	return SEPOL_OK;
1487 
1488 exit:
1489 	cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration");
1490 	cil_destroy_userlevel(usrlvl);
1491 	return rc;
1492 }
1493 
cil_destroy_userlevel(struct cil_userlevel * usrlvl)1494 void cil_destroy_userlevel(struct cil_userlevel *usrlvl)
1495 {
1496 	if (usrlvl == NULL) {
1497 		return;
1498 	}
1499 
1500 	if (usrlvl->level_str == NULL && usrlvl->level != NULL) {
1501 		cil_destroy_level(usrlvl->level);
1502 	}
1503 
1504 	free(usrlvl);
1505 }
1506 
cil_gen_userrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1507 int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1508 {
1509 	enum cil_syntax syntax[] = {
1510 		CIL_SYN_STRING,
1511 		CIL_SYN_STRING,
1512 		CIL_SYN_STRING | CIL_SYN_LIST,
1513 		CIL_SYN_END
1514 	};
1515 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1516 	struct cil_userrange *userrange = NULL;
1517 	int rc = SEPOL_ERR;
1518 
1519 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1520 		goto exit;
1521 	}
1522 
1523 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1524 	if (rc != SEPOL_OK) {
1525 		goto exit;
1526 	}
1527 
1528 	cil_userrange_init(&userrange);
1529 
1530 	userrange->user_str = parse_current->next->data;
1531 
1532 	if (parse_current->next->next->cl_head == NULL) {
1533 		userrange->range_str = parse_current->next->next->data;
1534 	} else {
1535 		cil_levelrange_init(&userrange->range);
1536 
1537 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range);
1538 		if (rc != SEPOL_OK) {
1539 			goto exit;
1540 		}
1541 	}
1542 
1543 	ast_node->data = userrange;
1544 	ast_node->flavor = CIL_USERRANGE;
1545 
1546 	return SEPOL_OK;
1547 
1548 exit:
1549 	cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration");
1550 	cil_destroy_userrange(userrange);
1551 	return rc;
1552 }
1553 
cil_destroy_userrange(struct cil_userrange * userrange)1554 void cil_destroy_userrange(struct cil_userrange *userrange)
1555 {
1556 	if (userrange == NULL) {
1557 		return;
1558 	}
1559 
1560 	if (userrange->range_str == NULL && userrange->range != NULL) {
1561 		cil_destroy_levelrange(userrange->range);
1562 	}
1563 
1564 	free(userrange);
1565 }
1566 
cil_gen_userprefix(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1567 int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1568 {
1569 	enum cil_syntax syntax[] = {
1570 		CIL_SYN_STRING,
1571 		CIL_SYN_STRING,
1572 		CIL_SYN_STRING,
1573 		CIL_SYN_END
1574 	};
1575 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1576 	struct cil_userprefix *userprefix = NULL;
1577 	int rc = SEPOL_ERR;
1578 
1579 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1580 		goto exit;
1581 	}
1582 
1583 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1584 	if (rc != SEPOL_OK) {
1585 		goto exit;
1586 	}
1587 
1588 	cil_userprefix_init(&userprefix);
1589 
1590 	userprefix->user_str = parse_current->next->data;
1591 	userprefix->prefix_str = parse_current->next->next->data;
1592 
1593 	ast_node->data = userprefix;
1594 	ast_node->flavor = CIL_USERPREFIX;
1595 
1596 	return SEPOL_OK;
1597 exit:
1598 	cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration");
1599 	cil_destroy_userprefix(userprefix);
1600 	return rc;
1601 }
1602 
cil_destroy_userprefix(struct cil_userprefix * userprefix)1603 void cil_destroy_userprefix(struct cil_userprefix *userprefix)
1604 {
1605 	if (userprefix == NULL) {
1606 		return;
1607 	}
1608 
1609 	free(userprefix);
1610 }
1611 
cil_gen_selinuxuser(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1612 int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1613 {
1614 	enum cil_syntax syntax[] = {
1615 		CIL_SYN_STRING,
1616 		CIL_SYN_STRING,
1617 		CIL_SYN_STRING,
1618 		CIL_SYN_STRING | CIL_SYN_LIST,
1619 		CIL_SYN_END
1620 	};
1621 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1622 	struct cil_selinuxuser *selinuxuser = NULL;
1623 	int rc = SEPOL_ERR;
1624 
1625 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1626 		goto exit;
1627 	}
1628 
1629 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1630 	if (rc != SEPOL_OK) {
1631 		goto exit;
1632 	}
1633 
1634 	cil_selinuxuser_init(&selinuxuser);
1635 
1636 	selinuxuser->name_str = parse_current->next->data;
1637 	selinuxuser->user_str = parse_current->next->next->data;
1638 
1639 	if (parse_current->next->next->next->cl_head == NULL) {
1640 		selinuxuser->range_str = parse_current->next->next->next->data;
1641 	} else {
1642 		cil_levelrange_init(&selinuxuser->range);
1643 
1644 		rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range);
1645 		if (rc != SEPOL_OK) {
1646 			goto exit;
1647 		}
1648 	}
1649 
1650 	ast_node->data = selinuxuser;
1651 	ast_node->flavor = CIL_SELINUXUSER;
1652 
1653 	return SEPOL_OK;
1654 exit:
1655 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration");
1656 	cil_destroy_selinuxuser(selinuxuser);
1657 	return rc;
1658 }
1659 
cil_gen_selinuxuserdefault(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1660 int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1661 {
1662 	enum cil_syntax syntax[] = {
1663 		CIL_SYN_STRING,
1664 		CIL_SYN_STRING,
1665 		CIL_SYN_STRING | CIL_SYN_LIST,
1666 		CIL_SYN_END
1667 	};
1668 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1669 	struct cil_selinuxuser *selinuxuser = NULL;
1670 	int rc = SEPOL_ERR;
1671 
1672 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1673 		goto exit;
1674 	}
1675 
1676 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1677 	if (rc != SEPOL_OK) {
1678 		goto exit;
1679 	}
1680 
1681 	cil_selinuxuser_init(&selinuxuser);
1682 
1683 	selinuxuser->name_str = cil_strpool_add("__default__");
1684 	selinuxuser->user_str = parse_current->next->data;
1685 
1686 	if (parse_current->next->next->cl_head == NULL) {
1687 		selinuxuser->range_str = parse_current->next->next->data;
1688 	} else {
1689 		cil_levelrange_init(&selinuxuser->range);
1690 
1691 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range);
1692 		if (rc != SEPOL_OK) {
1693 			goto exit;
1694 		}
1695 	}
1696 
1697 	ast_node->data = selinuxuser;
1698 	ast_node->flavor = CIL_SELINUXUSERDEFAULT;
1699 
1700 	return SEPOL_OK;
1701 exit:
1702 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration");
1703 	cil_destroy_selinuxuser(selinuxuser);
1704 	return rc;
1705 }
1706 
cil_destroy_selinuxuser(struct cil_selinuxuser * selinuxuser)1707 void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser)
1708 {
1709 	if (selinuxuser == NULL) {
1710 		return;
1711 	}
1712 
1713 	if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) {
1714 		cil_destroy_levelrange(selinuxuser->range);
1715 	}
1716 
1717 	free(selinuxuser);
1718 }
1719 
cil_gen_role(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1720 int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1721 {
1722 	enum cil_syntax syntax[] = {
1723 		CIL_SYN_STRING,
1724 		CIL_SYN_STRING,
1725 		CIL_SYN_END
1726 	};
1727 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1728 	char *key = NULL;
1729 	struct cil_role *role = NULL;
1730 	int rc = SEPOL_ERR;
1731 
1732 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1733 		goto exit;
1734 	}
1735 
1736 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1737 	if (rc != SEPOL_OK) {
1738 		goto exit;
1739 	}
1740 
1741 	cil_role_init(&role);
1742 
1743 	key = parse_current->next->data;
1744 
1745 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE);
1746 	if (rc != SEPOL_OK) {
1747 		goto exit;
1748 	}
1749 
1750 	return SEPOL_OK;
1751 
1752 exit:
1753 	cil_tree_log(parse_current, CIL_ERR, "Bad role declaration");
1754 	cil_destroy_role(role);
1755 	cil_clear_node(ast_node);
1756 	return rc;
1757 }
1758 
cil_destroy_role(struct cil_role * role)1759 void cil_destroy_role(struct cil_role *role)
1760 {
1761 	if (role == NULL) {
1762 		return;
1763 	}
1764 
1765 	cil_symtab_datum_destroy(&role->datum);
1766 	ebitmap_destroy(role->types);
1767 	free(role->types);
1768 	free(role);
1769 }
1770 
cil_gen_roletype(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1771 int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1772 {
1773 	enum cil_syntax syntax[] = {
1774 		CIL_SYN_STRING,
1775 		CIL_SYN_STRING,
1776 		CIL_SYN_STRING,
1777 		CIL_SYN_END
1778 	};
1779 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1780 	struct cil_roletype *roletype = NULL;
1781 	int rc = SEPOL_ERR;
1782 
1783 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1784 		goto exit;
1785 	}
1786 
1787 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1788 	if (rc != SEPOL_OK) {
1789 		goto exit;
1790 	}
1791 
1792 	cil_roletype_init(&roletype);
1793 
1794 	roletype->role_str = parse_current->next->data;
1795 	roletype->type_str = parse_current->next->next->data;
1796 
1797 	ast_node->data = roletype;
1798 	ast_node->flavor = CIL_ROLETYPE;
1799 
1800 	return SEPOL_OK;
1801 
1802 exit:
1803 	cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration");
1804 	cil_destroy_roletype(roletype);
1805 	return rc;
1806 }
1807 
cil_destroy_roletype(struct cil_roletype * roletype)1808 void cil_destroy_roletype(struct cil_roletype *roletype)
1809 {
1810 	if (roletype == NULL) {
1811 		return;
1812 	}
1813 
1814 	free(roletype);
1815 }
1816 
cil_gen_userrole(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1817 int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1818 {
1819 	enum cil_syntax syntax[] = {
1820 		CIL_SYN_STRING,
1821 		CIL_SYN_STRING,
1822 		CIL_SYN_STRING,
1823 		CIL_SYN_END
1824 	};
1825 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1826 	struct cil_userrole *userrole = NULL;
1827 	int rc = SEPOL_ERR;
1828 
1829 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1830 		goto exit;
1831 	}
1832 
1833 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1834 	if (rc != SEPOL_OK) {
1835 		goto exit;
1836 	}
1837 
1838 	cil_userrole_init(&userrole);
1839 
1840 	userrole->user_str = parse_current->next->data;
1841 	userrole->role_str = parse_current->next->next->data;
1842 
1843 	ast_node->data = userrole;
1844 	ast_node->flavor = CIL_USERROLE;
1845 
1846 	return SEPOL_OK;
1847 
1848 exit:
1849 	cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration");
1850 	cil_destroy_userrole(userrole);
1851 	return rc;
1852 }
1853 
cil_destroy_userrole(struct cil_userrole * userrole)1854 void cil_destroy_userrole(struct cil_userrole *userrole)
1855 {
1856 	if (userrole == NULL) {
1857 		return;
1858 	}
1859 
1860 	free(userrole);
1861 }
1862 
cil_gen_roletransition(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1863 int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1864 {
1865 	enum cil_syntax syntax[] = {
1866 		CIL_SYN_STRING,
1867 		CIL_SYN_STRING,
1868 		CIL_SYN_STRING,
1869 		CIL_SYN_STRING,
1870 		CIL_SYN_STRING,
1871 		CIL_SYN_END
1872 	};
1873 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1874 	struct cil_roletransition *roletrans = NULL;
1875 	int rc = SEPOL_ERR;
1876 
1877 	if (parse_current == NULL || ast_node == NULL) {
1878 		goto exit;
1879 	}
1880 
1881 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1882 	if (rc != SEPOL_OK) {
1883 		goto exit;
1884 	}
1885 
1886 	cil_roletransition_init(&roletrans);
1887 
1888 	roletrans->src_str = parse_current->next->data;
1889 	roletrans->tgt_str = parse_current->next->next->data;
1890 	roletrans->obj_str = parse_current->next->next->next->data;
1891 	roletrans->result_str = parse_current->next->next->next->next->data;
1892 
1893 	ast_node->data = roletrans;
1894 	ast_node->flavor = CIL_ROLETRANSITION;
1895 
1896 	return SEPOL_OK;
1897 
1898 exit:
1899 	cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule");
1900 	cil_destroy_roletransition(roletrans);
1901 	return rc;
1902 }
1903 
cil_destroy_roletransition(struct cil_roletransition * roletrans)1904 void cil_destroy_roletransition(struct cil_roletransition *roletrans)
1905 {
1906 	if (roletrans == NULL) {
1907 		return;
1908 	}
1909 
1910 	free(roletrans);
1911 }
1912 
cil_gen_roleallow(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1913 int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1914 {
1915 	enum cil_syntax syntax[] = {
1916 		CIL_SYN_STRING,
1917 		CIL_SYN_STRING,
1918 		CIL_SYN_STRING,
1919 		CIL_SYN_END
1920 	};
1921 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1922 	struct cil_roleallow *roleallow = NULL;
1923 	int rc = SEPOL_ERR;
1924 
1925 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1926 		goto exit;
1927 	}
1928 
1929 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1930 	if (rc != SEPOL_OK) {
1931 		goto exit;
1932 	}
1933 
1934 	cil_roleallow_init(&roleallow);
1935 
1936 	roleallow->src_str = parse_current->next->data;
1937 	roleallow->tgt_str = parse_current->next->next->data;
1938 
1939 	ast_node->data = roleallow;
1940 	ast_node->flavor = CIL_ROLEALLOW;
1941 
1942 	return SEPOL_OK;
1943 
1944 exit:
1945 	cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule");
1946 	cil_destroy_roleallow(roleallow);
1947 	return rc;
1948 }
1949 
cil_destroy_roleallow(struct cil_roleallow * roleallow)1950 void cil_destroy_roleallow(struct cil_roleallow *roleallow)
1951 {
1952 	if (roleallow == NULL) {
1953 		return;
1954 	}
1955 
1956 	free(roleallow);
1957 }
1958 
cil_gen_roleattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1959 int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1960 {
1961 	enum cil_syntax syntax[] = {
1962 		CIL_SYN_STRING,
1963 		CIL_SYN_STRING,
1964 		CIL_SYN_END
1965 	};
1966 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1967 	char *key = NULL;
1968 	struct cil_roleattribute *attr = NULL;
1969 	int rc = SEPOL_ERR;
1970 
1971 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1972 		goto exit;
1973 	}
1974 
1975 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1976 	if (rc != SEPOL_OK) {
1977 		goto exit;
1978 	}
1979 
1980 	cil_roleattribute_init(&attr);
1981 
1982 	key = parse_current->next->data;
1983 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE);
1984 	if (rc != SEPOL_OK) {
1985 		goto exit;
1986 	}
1987 
1988 	return SEPOL_OK;
1989 exit:
1990 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration");
1991 	cil_destroy_roleattribute(attr);
1992 	cil_clear_node(ast_node);
1993 	return rc;
1994 }
1995 
cil_destroy_roleattribute(struct cil_roleattribute * attr)1996 void cil_destroy_roleattribute(struct cil_roleattribute *attr)
1997 {
1998 	if (attr == NULL) {
1999 		return;
2000 	}
2001 
2002 	if (attr->expr_list != NULL) {
2003 		/* we don't want to destroy the expression stacks (cil_list) inside
2004 		 * this list cil_list_destroy destroys sublists, so we need to do it
2005 		 * manually */
2006 		struct cil_list_item *expr = attr->expr_list->head;
2007 		while (expr != NULL) {
2008 			struct cil_list_item *next = expr->next;
2009 			cil_list_item_destroy(&expr, CIL_FALSE);
2010 			expr = next;
2011 		}
2012 		free(attr->expr_list);
2013 		attr->expr_list = NULL;
2014 	}
2015 
2016 	cil_symtab_datum_destroy(&attr->datum);
2017 	ebitmap_destroy(attr->roles);
2018 	free(attr->roles);
2019 	free(attr);
2020 }
2021 
cil_gen_roleattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2022 int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2023 {
2024 	enum cil_syntax syntax[] = {
2025 		CIL_SYN_STRING,
2026 		CIL_SYN_STRING,
2027 		CIL_SYN_STRING | CIL_SYN_LIST,
2028 		CIL_SYN_END
2029 	};
2030 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2031 	struct cil_roleattributeset *attrset = NULL;
2032 	int rc = SEPOL_ERR;
2033 
2034 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2035 		goto exit;
2036 	}
2037 
2038 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2039 	if (rc != SEPOL_OK) {
2040 		goto exit;
2041 	}
2042 
2043 	cil_roleattributeset_init(&attrset);
2044 
2045 	attrset->attr_str = parse_current->next->data;
2046 
2047 	rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr);
2048 	if (rc != SEPOL_OK) {
2049 		goto exit;
2050 	}
2051 	ast_node->data = attrset;
2052 	ast_node->flavor = CIL_ROLEATTRIBUTESET;
2053 
2054 	return SEPOL_OK;
2055 
2056 exit:
2057 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration");
2058 	cil_destroy_roleattributeset(attrset);
2059 
2060 	return rc;
2061 }
2062 
cil_destroy_roleattributeset(struct cil_roleattributeset * attrset)2063 void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset)
2064 {
2065 	if (attrset == NULL) {
2066 		return;
2067 	}
2068 
2069 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
2070 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
2071 
2072 	free(attrset);
2073 }
2074 
cil_gen_avrule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2075 int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2076 {
2077 	enum cil_syntax syntax[] = {
2078 		CIL_SYN_STRING,
2079 		CIL_SYN_STRING,
2080 		CIL_SYN_STRING,
2081 		CIL_SYN_STRING | CIL_SYN_LIST,
2082 		CIL_SYN_END
2083 	};
2084 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2085 	struct cil_avrule *rule = NULL;
2086 	int rc = SEPOL_ERR;
2087 
2088 	if (parse_current == NULL || ast_node == NULL) {
2089 		goto exit;
2090 	}
2091 
2092 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2093 	if (rc != SEPOL_OK) {
2094 		goto exit;
2095 	}
2096 
2097 	cil_avrule_init(&rule);
2098 
2099 	rule->is_extended = 0;
2100 	rule->rule_kind = rule_kind;
2101 
2102 	rule->src_str = parse_current->next->data;
2103 	rule->tgt_str = parse_current->next->next->data;
2104 
2105 	rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms);
2106 	if (rc != SEPOL_OK) {
2107 		goto exit;
2108 	}
2109 
2110 	ast_node->data = rule;
2111 	ast_node->flavor = CIL_AVRULE;
2112 
2113 	return SEPOL_OK;
2114 
2115 exit:
2116 	cil_tree_log(parse_current, CIL_ERR, "Bad allow rule");
2117 	cil_destroy_avrule(rule);
2118 	return rc;
2119 }
2120 
cil_destroy_avrule(struct cil_avrule * rule)2121 void cil_destroy_avrule(struct cil_avrule *rule)
2122 {
2123 	if (rule == NULL) {
2124 		return;
2125 	}
2126 
2127 	if (!rule->is_extended) {
2128 		cil_destroy_classperms_list(&rule->perms.classperms);
2129 	} else {
2130 		if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) {
2131 			cil_destroy_permissionx(rule->perms.x.permx);
2132 		}
2133 	}
2134 
2135 	free(rule);
2136 }
2137 
cil_fill_permissionx(struct cil_tree_node * parse_current,struct cil_permissionx * permx)2138 static int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx)
2139 {
2140 	enum cil_syntax syntax[] = {
2141 		CIL_SYN_STRING,
2142 		CIL_SYN_STRING,
2143 		CIL_SYN_LIST,
2144 		CIL_SYN_END
2145 	};
2146 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2147 	int rc = SEPOL_ERR;
2148 
2149 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2150 	if (rc != SEPOL_OK) {
2151 		goto exit;
2152 	}
2153 
2154 	if (parse_current->data == CIL_KEY_IOCTL) {
2155 		permx->kind = CIL_PERMX_KIND_IOCTL;
2156 	} else if (parse_current->data == CIL_KEY_NLMSG) {
2157 		permx->kind = CIL_PERMX_KIND_NLMSG;
2158 	} else {
2159 		cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\" or \"nlmsg\"\n", (char *)parse_current->data);
2160 		rc = SEPOL_ERR;
2161 		goto exit;
2162 	}
2163 
2164 	permx->obj_str = parse_current->next->data;
2165 
2166 	rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str);
2167 	if (rc != SEPOL_OK) {
2168 		goto exit;
2169 	}
2170 
2171 	return SEPOL_OK;
2172 
2173 exit:
2174 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content");
2175 	return rc;
2176 }
2177 
cil_gen_permissionx(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2178 int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2179 {
2180 	enum cil_syntax syntax[] = {
2181 		CIL_SYN_STRING,
2182 		CIL_SYN_STRING,
2183 		CIL_SYN_LIST,
2184 		CIL_SYN_END
2185 	};
2186 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2187 	char *key = NULL;
2188 	struct cil_permissionx *permx = NULL;
2189 	int rc = SEPOL_ERR;
2190 
2191 	if (parse_current == NULL || ast_node == NULL) {
2192 		goto exit;
2193 	}
2194 
2195 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2196 	if (rc != SEPOL_OK) {
2197 		goto exit;
2198 	}
2199 
2200 	cil_permissionx_init(&permx);
2201 
2202 	key = parse_current->next->data;
2203 
2204 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
2205 	if (rc != SEPOL_OK) {
2206 		goto exit;
2207 	}
2208 
2209 	rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
2210 	if (rc != SEPOL_OK) {
2211 		goto exit;
2212 	}
2213 
2214 	return SEPOL_OK;
2215 
2216 exit:
2217 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement");
2218 	cil_destroy_permissionx(permx);
2219 	cil_clear_node(ast_node);
2220 	return rc;
2221 }
2222 
cil_destroy_permissionx(struct cil_permissionx * permx)2223 void cil_destroy_permissionx(struct cil_permissionx *permx)
2224 {
2225 	if (permx == NULL) {
2226 		return;
2227 	}
2228 
2229 	cil_symtab_datum_destroy(&permx->datum);
2230 
2231 	cil_list_destroy(&permx->expr_str, CIL_TRUE);
2232 	ebitmap_destroy(permx->perms);
2233 	free(permx->perms);
2234 	free(permx);
2235 }
2236 
cil_gen_avrulex(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2237 int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2238 {
2239 	enum cil_syntax syntax[] = {
2240 		CIL_SYN_STRING,
2241 		CIL_SYN_STRING,
2242 		CIL_SYN_STRING,
2243 		CIL_SYN_STRING | CIL_SYN_LIST,
2244 		CIL_SYN_END
2245 	};
2246 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2247 	struct cil_avrule *rule = NULL;
2248 	int rc = SEPOL_ERR;
2249 
2250 	if (parse_current == NULL || ast_node == NULL) {
2251 		goto exit;
2252 	}
2253 
2254 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2255 	if (rc != SEPOL_OK) {
2256 		goto exit;
2257 	}
2258 
2259 	cil_avrule_init(&rule);
2260 
2261 	rule->is_extended = 1;
2262 	rule->rule_kind = rule_kind;
2263 	rule->src_str = parse_current->next->data;
2264 	rule->tgt_str = parse_current->next->next->data;
2265 
2266 	if (parse_current->next->next->next->cl_head == NULL) {
2267 		rule->perms.x.permx_str = parse_current->next->next->next->data;
2268 	} else {
2269 		cil_permissionx_init(&rule->perms.x.permx);
2270 
2271 		rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx);
2272 		if (rc != SEPOL_OK) {
2273 			goto exit;
2274 		}
2275 	}
2276 
2277 	ast_node->data = rule;
2278 	ast_node->flavor = CIL_AVRULEX;
2279 
2280 	return SEPOL_OK;
2281 
2282 exit:
2283 	cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule");
2284 	cil_destroy_avrule(rule);
2285 	return rc;
2286 }
2287 
cil_gen_deny_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2288 int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2289 {
2290 	enum cil_syntax syntax[] = {
2291 		CIL_SYN_STRING,
2292 		CIL_SYN_STRING,
2293 		CIL_SYN_STRING,
2294 		CIL_SYN_STRING | CIL_SYN_LIST,
2295 		CIL_SYN_END
2296 	};
2297 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2298 	struct cil_deny_rule *rule = NULL;
2299 	int rc = SEPOL_ERR;
2300 
2301 	if (parse_current == NULL || ast_node == NULL) {
2302 		goto exit;
2303 	}
2304 
2305 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2306 	if (rc != SEPOL_OK) {
2307 		goto exit;
2308 	}
2309 
2310 	cil_deny_rule_init(&rule);
2311 
2312 	rule->src_str = parse_current->next->data;
2313 	rule->tgt_str = parse_current->next->next->data;
2314 
2315 	rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->classperms);
2316 	if (rc != SEPOL_OK) {
2317 		goto exit;
2318 	}
2319 
2320 	ast_node->data = rule;
2321 	ast_node->flavor = CIL_DENY_RULE;
2322 
2323 	return SEPOL_OK;
2324 
2325 exit:
2326 	cil_tree_log(parse_current, CIL_ERR, "Bad deny rule");
2327 	cil_destroy_deny_rule(rule);
2328 	return rc;
2329 }
2330 
cil_destroy_deny_rule(struct cil_deny_rule * rule)2331 void cil_destroy_deny_rule(struct cil_deny_rule *rule)
2332 {
2333 	if (rule == NULL) {
2334 		return;
2335 	}
2336 
2337 	cil_destroy_classperms_list(&rule->classperms);
2338 
2339 	free(rule);
2340 }
2341 
cil_gen_type_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2342 int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2343 {
2344 	enum cil_syntax syntax[] = {
2345 		CIL_SYN_STRING,
2346 		CIL_SYN_STRING,
2347 		CIL_SYN_STRING,
2348 		CIL_SYN_STRING,
2349 		CIL_SYN_STRING,
2350 		CIL_SYN_END
2351 	};
2352 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2353 	struct cil_type_rule *rule = NULL;
2354 	int rc = SEPOL_ERR;
2355 
2356 	if (parse_current == NULL || ast_node == NULL) {
2357 		goto exit;
2358 	}
2359 
2360 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2361 	if (rc != SEPOL_OK) {
2362 		goto exit;
2363 	}
2364 
2365 	cil_type_rule_init(&rule);
2366 
2367 	rule->rule_kind = rule_kind;
2368 	rule->src_str = parse_current->next->data;
2369 	rule->tgt_str = parse_current->next->next->data;
2370 	rule->obj_str = parse_current->next->next->next->data;
2371 	rule->result_str = parse_current->next->next->next->next->data;
2372 
2373 	ast_node->data = rule;
2374 	ast_node->flavor = CIL_TYPE_RULE;
2375 
2376 	return SEPOL_OK;
2377 
2378 exit:
2379 	cil_tree_log(parse_current, CIL_ERR, "Bad type rule");
2380 	cil_destroy_type_rule(rule);
2381 	return rc;
2382 }
2383 
cil_destroy_type_rule(struct cil_type_rule * rule)2384 void cil_destroy_type_rule(struct cil_type_rule *rule)
2385 {
2386 	if (rule == NULL) {
2387 		return;
2388 	}
2389 
2390 	free(rule);
2391 }
2392 
cil_gen_type(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2393 int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2394 {
2395 	enum cil_syntax syntax[] = {
2396 		CIL_SYN_STRING,
2397 		CIL_SYN_STRING,
2398 		CIL_SYN_END
2399 	};
2400 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2401 	char *key = NULL;
2402 	struct cil_type *type = NULL;
2403 	int rc = SEPOL_ERR;
2404 
2405 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2406 		goto exit;
2407 	}
2408 
2409 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2410 	if (rc != SEPOL_OK) {
2411 		goto exit;
2412 	}
2413 
2414 	cil_type_init(&type);
2415 
2416 	key = parse_current->next->data;
2417 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
2418 	if (rc != SEPOL_OK) {
2419 		if (rc == SEPOL_EEXIST) {
2420 			cil_destroy_type(type);
2421 			type = NULL;
2422 		} else {
2423 			goto exit;
2424 		}
2425 	}
2426 
2427 	return SEPOL_OK;
2428 
2429 exit:
2430 	cil_tree_log(parse_current, CIL_ERR, "Bad type declaration");
2431 	cil_destroy_type(type);
2432 	cil_clear_node(ast_node);
2433 	return rc;
2434 }
2435 
cil_destroy_type(struct cil_type * type)2436 void cil_destroy_type(struct cil_type *type)
2437 {
2438 	if (type == NULL) {
2439 		return;
2440 	}
2441 
2442 	cil_symtab_datum_destroy(&type->datum);
2443 	free(type);
2444 }
2445 
cil_gen_typeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2446 int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2447 {
2448 	enum cil_syntax syntax[] = {
2449 		CIL_SYN_STRING,
2450 		CIL_SYN_STRING,
2451 		CIL_SYN_END
2452 	};
2453 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2454 	char *key = NULL;
2455 	struct cil_typeattribute *attr = NULL;
2456 	int rc = SEPOL_ERR;
2457 
2458 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2459 		goto exit;
2460 	}
2461 
2462 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2463 	if (rc != SEPOL_OK) {
2464 		goto exit;
2465 	}
2466 
2467 	cil_typeattribute_init(&attr);
2468 
2469 	key = parse_current->next->data;
2470 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
2471 	if (rc != SEPOL_OK) {
2472 		if (rc == SEPOL_EEXIST) {
2473 			cil_destroy_typeattribute(attr);
2474 			attr = NULL;
2475 		} else {
2476 			goto exit;
2477 		}
2478 	}
2479 
2480 	return SEPOL_OK;
2481 
2482 exit:
2483 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration");
2484 	cil_destroy_typeattribute(attr);
2485 	cil_clear_node(ast_node);
2486 	return rc;
2487 }
2488 
cil_destroy_typeattribute(struct cil_typeattribute * attr)2489 void cil_destroy_typeattribute(struct cil_typeattribute *attr)
2490 {
2491 	if (attr == NULL) {
2492 		return;
2493 	}
2494 
2495 	cil_symtab_datum_destroy(&attr->datum);
2496 
2497 	if (attr->expr_list != NULL) {
2498 		/* we don't want to destroy the expression stacks (cil_list) inside
2499 		 * this list cil_list_destroy destroys sublists, so we need to do it
2500 		 * manually */
2501 		struct cil_list_item *expr = attr->expr_list->head;
2502 		while (expr != NULL) {
2503 			struct cil_list_item *next = expr->next;
2504 			cil_list_item_destroy(&expr, CIL_FALSE);
2505 			expr = next;
2506 		}
2507 		free(attr->expr_list);
2508 		attr->expr_list = NULL;
2509 	}
2510 	ebitmap_destroy(attr->types);
2511 	free(attr->types);
2512 	free(attr);
2513 }
2514 
cil_gen_bool(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2515 int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2516 {
2517 	enum cil_syntax syntax[] = {
2518 		CIL_SYN_STRING,
2519 		CIL_SYN_STRING,
2520 		CIL_SYN_STRING,
2521 		CIL_SYN_END
2522 	};
2523 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2524 	char *key = NULL;
2525 	struct cil_bool *boolean = NULL;
2526 	int rc = SEPOL_ERR;
2527 
2528 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2529 		goto exit;
2530 	}
2531 
2532 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2533 	if (rc != SEPOL_OK) {
2534 		goto exit;
2535 	}
2536 
2537 	cil_bool_init(&boolean);
2538 
2539 	key = parse_current->next->data;
2540 
2541 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2542 		boolean->value = CIL_TRUE;
2543 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2544 		boolean->value = CIL_FALSE;
2545 	} else {
2546 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2547 		rc = SEPOL_ERR;
2548 		goto exit;
2549 	}
2550 
2551 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL);
2552 	if (rc != SEPOL_OK) {
2553 		goto exit;
2554 	}
2555 
2556 	return SEPOL_OK;
2557 
2558 exit:
2559 	if (tunableif) {
2560 		cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration");
2561 	} else {
2562 		cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration");
2563 	}
2564 	cil_destroy_bool(boolean);
2565 	cil_clear_node(ast_node);
2566 	return rc;
2567 }
2568 
cil_destroy_bool(struct cil_bool * boolean)2569 void cil_destroy_bool(struct cil_bool *boolean)
2570 {
2571 	if (boolean == NULL) {
2572 		return;
2573 	}
2574 
2575 	cil_symtab_datum_destroy(&boolean->datum);
2576 	free(boolean);
2577 }
2578 
cil_gen_tunable(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2579 int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2580 {
2581 	enum cil_syntax syntax[] = {
2582 		CIL_SYN_STRING,
2583 		CIL_SYN_STRING,
2584 		CIL_SYN_STRING,
2585 		CIL_SYN_END
2586 	};
2587 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2588 	char *key = NULL;
2589 	struct cil_tunable *tunable = NULL;
2590 	int rc = SEPOL_ERR;
2591 
2592 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2593 		goto exit;
2594 	}
2595 
2596 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2597 	if (rc != SEPOL_OK) {
2598 		goto exit;
2599 	}
2600 
2601 	cil_tunable_init(&tunable);
2602 
2603 	key = parse_current->next->data;
2604 
2605 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2606 		tunable->value = CIL_TRUE;
2607 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2608 		tunable->value = CIL_FALSE;
2609 	} else {
2610 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2611 		rc = SEPOL_ERR;
2612 		goto exit;
2613 	}
2614 
2615 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE);
2616 	if (rc != SEPOL_OK) {
2617 		goto exit;
2618 	}
2619 
2620 	return SEPOL_OK;
2621 
2622 exit:
2623 	cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration");
2624 	cil_destroy_tunable(tunable);
2625 	cil_clear_node(ast_node);
2626 	return rc;
2627 }
2628 
cil_destroy_tunable(struct cil_tunable * tunable)2629 void cil_destroy_tunable(struct cil_tunable *tunable)
2630 {
2631 	if (tunable == NULL) {
2632 		return;
2633 	}
2634 
2635 	cil_symtab_datum_destroy(&tunable->datum);
2636 	free(tunable);
2637 }
2638 
__cil_get_expr_operator_flavor(const char * op)2639 static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
2640 {
2641 	if (op == NULL) return CIL_NONE;
2642 	else if (op == CIL_KEY_AND)   return CIL_AND;
2643 	else if (op == CIL_KEY_OR)    return CIL_OR;
2644 	else if (op == CIL_KEY_NOT)   return CIL_NOT;
2645 	else if (op == CIL_KEY_EQ)    return CIL_EQ;    /* Only conditional */
2646 	else if (op == CIL_KEY_NEQ)   return CIL_NEQ;   /* Only conditional */
2647 	else if (op == CIL_KEY_XOR)   return CIL_XOR;
2648 	else if (op == CIL_KEY_ALL)   return CIL_ALL;   /* Only set and permissionx */
2649 	else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */
2650 	else return CIL_NONE;
2651 }
2652 
2653 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr);
2654 
__cil_fill_expr_helper(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2655 static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2656 {
2657 	int rc = SEPOL_ERR;
2658 	enum cil_flavor op;
2659 
2660 	op = __cil_get_expr_operator_flavor(current->data);
2661 
2662 	rc = cil_verify_expr_syntax(current, op, flavor);
2663 	if (rc != SEPOL_OK) {
2664 		goto exit;
2665 	}
2666 
2667 	if (op != CIL_NONE) {
2668 		cil_list_append(expr, CIL_OP, (void *)op);
2669 		current = current->next;
2670 	}
2671 
2672 	for (;current != NULL; current = current->next) {
2673 		rc = __cil_fill_expr(current, flavor, expr);
2674 		if (rc != SEPOL_OK) {
2675 			goto exit;
2676 		}
2677 	}
2678 
2679 	return SEPOL_OK;
2680 
2681 exit:
2682 	return rc;
2683 }
2684 
__cil_fill_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2685 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2686 {
2687 	int rc = SEPOL_ERR;
2688 
2689 	if (current->cl_head == NULL) {
2690 		enum cil_flavor op = __cil_get_expr_operator_flavor(current->data);
2691 		if (op != CIL_NONE) {
2692 			cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data);
2693 			goto exit;
2694 		}
2695 		cil_list_append(expr, CIL_STRING, current->data);
2696 	} else {
2697 		struct cil_list *sub_expr;
2698 		cil_list_init(&sub_expr, flavor);
2699 		rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
2700 		if (rc != SEPOL_OK) {
2701 			cil_list_destroy(&sub_expr, CIL_TRUE);
2702 			goto exit;
2703 		}
2704 		cil_list_append(expr, CIL_LIST, sub_expr);
2705 	}
2706 
2707 	return SEPOL_OK;
2708 
2709 exit:
2710 	return rc;
2711 }
2712 
2713 
cil_gen_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2714 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2715 {
2716 	int rc = SEPOL_ERR;
2717 
2718 	cil_list_init(expr, flavor);
2719 
2720 	if (current->cl_head == NULL) {
2721 		rc = __cil_fill_expr(current, flavor, *expr);
2722 	} else {
2723 		rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
2724 	}
2725 
2726 	if (rc != SEPOL_OK) {
2727 		cil_list_destroy(expr, CIL_TRUE);
2728 		cil_log(CIL_ERR, "Bad expression\n");
2729 	}
2730 
2731 	return rc;
2732 }
2733 
__cil_get_constraint_operator_flavor(const char * op)2734 static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op)
2735 {
2736 	if (op == CIL_KEY_AND)         return CIL_AND;
2737 	else if (op == CIL_KEY_OR)     return CIL_OR;
2738 	else if (op == CIL_KEY_NOT)    return CIL_NOT;
2739 	else if (op == CIL_KEY_EQ)     return CIL_EQ;
2740 	else if (op == CIL_KEY_NEQ)    return CIL_NEQ;
2741 	else if (op == CIL_KEY_CONS_DOM)    return CIL_CONS_DOM;
2742 	else if (op == CIL_KEY_CONS_DOMBY)  return CIL_CONS_DOMBY;
2743 	else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP;
2744 	else return CIL_NONE;
2745 }
2746 
__cil_get_constraint_operand_flavor(const char * operand)2747 static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand)
2748 {
2749 	if (operand == NULL) return CIL_LIST;
2750 	else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1;
2751 	else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2;
2752 	else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3;
2753 	else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1;
2754 	else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2;
2755 	else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3;
2756 	else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1;
2757 	else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2;
2758 	else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3;
2759 	else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1;
2760 	else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2;
2761 	else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1;
2762 	else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2;
2763 	else return CIL_STRING;
2764 }
2765 
__cil_fill_constraint_leaf_expr(struct cil_tree_node * current,enum cil_flavor expr_flavor,enum cil_flavor op,struct cil_list ** leaf_expr)2766 static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum cil_flavor expr_flavor, enum cil_flavor op, struct cil_list **leaf_expr)
2767 {
2768 	int rc = SEPOL_ERR;
2769 	enum cil_flavor leaf_expr_flavor = CIL_NONE;
2770 	enum cil_flavor l_flavor = CIL_NONE;
2771 	enum cil_flavor r_flavor = CIL_NONE;
2772 
2773 	l_flavor = __cil_get_constraint_operand_flavor(current->next->data);
2774 	r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data);
2775 
2776 	switch (l_flavor) {
2777 	case CIL_CONS_U1:
2778 	case CIL_CONS_U2:
2779 	case CIL_CONS_U3:
2780 		leaf_expr_flavor = CIL_USER;
2781 		break;
2782 	case CIL_CONS_R1:
2783 	case CIL_CONS_R2:
2784 	case CIL_CONS_R3:
2785 		leaf_expr_flavor = CIL_ROLE;
2786 		break;
2787 	case CIL_CONS_T1:
2788 	case CIL_CONS_T2:
2789 	case CIL_CONS_T3:
2790 		leaf_expr_flavor = CIL_TYPE;
2791 		break;
2792 	case CIL_CONS_L1:
2793 	case CIL_CONS_L2:
2794 	case CIL_CONS_H1:
2795 	case CIL_CONS_H2:
2796 		leaf_expr_flavor = CIL_LEVEL;
2797 		break;
2798 	default:
2799 		cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data);
2800 		goto exit;
2801 	}
2802 
2803 	rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor);
2804 	if (rc != SEPOL_OK) {
2805 		goto exit;
2806 	}
2807 
2808 	cil_list_init(leaf_expr, leaf_expr_flavor);
2809 
2810 	cil_list_append(*leaf_expr, CIL_OP, (void *)op);
2811 
2812 	cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor);
2813 
2814 	if (r_flavor == CIL_STRING) {
2815 		cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
2816 	} else if (r_flavor == CIL_LIST) {
2817 		struct cil_list *sub_list;
2818 		rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
2819 		if (rc != SEPOL_OK) {
2820 			cil_list_destroy(leaf_expr, CIL_TRUE);
2821 			goto exit;
2822 		}
2823 		cil_list_append(*leaf_expr, CIL_LIST, sub_list);
2824 	} else {
2825 		cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
2826 	}
2827 
2828 	return SEPOL_OK;
2829 
2830 exit:
2831 
2832 	return SEPOL_ERR;
2833 }
2834 
__cil_fill_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2835 static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2836 {
2837 	int rc = SEPOL_ERR;
2838 	enum cil_flavor op;
2839 	struct cil_list *lexpr;
2840 	struct cil_list *rexpr;
2841 
2842 	if (current->data == NULL || current->cl_head != NULL) {
2843 		cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n");
2844 		goto exit;
2845 	}
2846 
2847 	op = __cil_get_constraint_operator_flavor(current->data);
2848 
2849 	rc = cil_verify_constraint_expr_syntax(current, op);
2850 	if (rc != SEPOL_OK) {
2851 		goto exit;
2852 	}
2853 
2854 	switch (op) {
2855 	case CIL_EQ:
2856 	case CIL_NEQ:
2857 	case CIL_CONS_DOM:
2858 	case CIL_CONS_DOMBY:
2859 	case CIL_CONS_INCOMP:
2860 		rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
2861 		if (rc != SEPOL_OK) {
2862 			goto exit;
2863 		}
2864 		break;
2865 	case CIL_NOT:
2866 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2867 		if (rc != SEPOL_OK) {
2868 			goto exit;
2869 		}
2870 		cil_list_init(expr, flavor);
2871 		cil_list_append(*expr, CIL_OP, (void *)op);
2872 		cil_list_append(*expr, CIL_LIST, lexpr);
2873 		break;
2874 	default:
2875 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2876 		if (rc != SEPOL_OK) {
2877 			goto exit;
2878 		}
2879 		rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr);
2880 		if (rc != SEPOL_OK) {
2881 			cil_list_destroy(&lexpr, CIL_TRUE);
2882 			goto exit;
2883 		}
2884 		cil_list_init(expr, flavor);
2885 		cil_list_append(*expr, CIL_OP, (void *)op);
2886 		cil_list_append(*expr, CIL_LIST, lexpr);
2887 		cil_list_append(*expr, CIL_LIST, rexpr);
2888 		break;
2889 	}
2890 
2891 	return SEPOL_OK;
2892 exit:
2893 
2894 	return rc;
2895 }
2896 
cil_gen_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2897 static int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2898 {
2899 	int rc = SEPOL_ERR;
2900 
2901 	if (current->cl_head == NULL) {
2902 		goto exit;
2903 	}
2904 
2905 	rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr);
2906 	if (rc != SEPOL_OK) {
2907 		goto exit;
2908 	}
2909 
2910 	return SEPOL_OK;
2911 
2912 exit:
2913 
2914 	cil_log(CIL_ERR, "Bad expression tree for constraint\n");
2915 	return rc;
2916 }
2917 
cil_gen_boolif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2918 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2919 {
2920 	enum cil_syntax syntax[] = {
2921 		CIL_SYN_STRING,
2922 		CIL_SYN_STRING | CIL_SYN_LIST,
2923 		CIL_SYN_LIST,
2924 		CIL_SYN_LIST | CIL_SYN_END,
2925 		CIL_SYN_END
2926 	};
2927 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2928 	struct cil_booleanif *bif = NULL;
2929 	struct cil_tree_node *next = NULL;
2930 	int rc = SEPOL_ERR;
2931 
2932 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2933 		goto exit;
2934 	}
2935 
2936 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2937 	if (rc != SEPOL_OK) {
2938 		goto exit;
2939 	}
2940 
2941 	cil_boolif_init(&bif);
2942 	bif->preserved_tunable = tunableif;
2943 
2944 	rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
2945 	if (rc != SEPOL_OK) {
2946 		goto exit;
2947 	}
2948 
2949 	rc = cil_verify_conditional_blocks(parse_current->next->next);
2950 	if (rc != SEPOL_OK) {
2951 		goto exit;
2952 	}
2953 
2954 	/* Destroying expr tree */
2955 	next = parse_current->next->next;
2956 	cil_tree_subtree_destroy(parse_current->next);
2957 	parse_current->next = next;
2958 
2959 	ast_node->flavor = CIL_BOOLEANIF;
2960 	ast_node->data = bif;
2961 
2962 	return SEPOL_OK;
2963 
2964 exit:
2965 	if (tunableif) {
2966 		cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
2967 	} else {
2968 		cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration");
2969 	}
2970 	cil_destroy_boolif(bif);
2971 	return rc;
2972 }
2973 
cil_destroy_boolif(struct cil_booleanif * bif)2974 void cil_destroy_boolif(struct cil_booleanif *bif)
2975 {
2976 	if (bif == NULL) {
2977 		return;
2978 	}
2979 
2980 	cil_list_destroy(&bif->str_expr, CIL_TRUE);
2981 	cil_list_destroy(&bif->datum_expr, CIL_FALSE);
2982 
2983 	free(bif);
2984 }
2985 
cil_gen_tunif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2986 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2987 {
2988 	enum cil_syntax syntax[] = {
2989 		CIL_SYN_STRING,
2990 		CIL_SYN_STRING | CIL_SYN_LIST,
2991 		CIL_SYN_LIST,
2992 		CIL_SYN_LIST | CIL_SYN_END,
2993 		CIL_SYN_END
2994 	};
2995 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2996 	struct cil_tunableif *tif = NULL;
2997 	struct cil_tree_node *next = NULL;
2998 	int rc = SEPOL_ERR;
2999 
3000 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3001 		goto exit;
3002 	}
3003 
3004 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3005 	if (rc != SEPOL_OK) {
3006 		goto exit;
3007 	}
3008 
3009 	cil_tunif_init(&tif);
3010 
3011 	rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
3012 	if (rc != SEPOL_OK) {
3013 		goto exit;
3014 	}
3015 
3016 	rc = cil_verify_conditional_blocks(parse_current->next->next);
3017 	if (rc != SEPOL_OK) {
3018 		goto exit;
3019 	}
3020 
3021 	/* Destroying expr tree */
3022 	next = parse_current->next->next;
3023 	cil_tree_subtree_destroy(parse_current->next);
3024 	parse_current->next = next;
3025 
3026 	ast_node->flavor = CIL_TUNABLEIF;
3027 	ast_node->data = tif;
3028 
3029 	return SEPOL_OK;
3030 
3031 exit:
3032 	cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
3033 	cil_destroy_tunif(tif);
3034 	return rc;
3035 }
3036 
cil_destroy_tunif(struct cil_tunableif * tif)3037 void cil_destroy_tunif(struct cil_tunableif *tif)
3038 {
3039 	if (tif == NULL) {
3040 		return;
3041 	}
3042 
3043 	cil_list_destroy(&tif->str_expr, CIL_TRUE);
3044 	cil_list_destroy(&tif->datum_expr, CIL_FALSE);
3045 
3046 	free(tif);
3047 }
3048 
cil_gen_condblock(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3049 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3050 {
3051 	enum cil_syntax syntax[] = {
3052 		CIL_SYN_STRING,
3053 		CIL_SYN_N_LISTS,
3054 		CIL_SYN_END
3055 	};
3056 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3057 	int rc = SEPOL_ERR;
3058 	struct cil_condblock *cb = NULL;
3059 
3060 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3061 		goto exit;
3062 	}
3063 
3064 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3065 	if (rc != SEPOL_OK) {
3066 		goto exit;
3067 	}
3068 
3069 	if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) {
3070 		rc = SEPOL_ERR;
3071 		cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
3072 		goto exit;
3073 	}
3074 
3075 	ast_node->flavor = CIL_CONDBLOCK;
3076 
3077 	cil_condblock_init(&cb);
3078 	cb->flavor = flavor;
3079 
3080 	ast_node->data = cb;
3081 
3082 	return SEPOL_OK;
3083 
3084 exit:
3085 	cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
3086 		(char*)parse_current->data);
3087 	cil_destroy_condblock(cb);
3088 	return rc;
3089 }
3090 
cil_destroy_condblock(struct cil_condblock * cb)3091 void cil_destroy_condblock(struct cil_condblock *cb)
3092 {
3093 	if (cb == NULL) {
3094 		return;
3095 	}
3096 
3097 	cil_symtab_array_destroy(cb->symtab);
3098 	free(cb);
3099 }
3100 
cil_gen_alias(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3101 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3102 {
3103 	enum cil_syntax syntax[] = {
3104 		CIL_SYN_STRING,
3105 		CIL_SYN_STRING,
3106 		CIL_SYN_END
3107 	};
3108 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3109 	char *key = NULL;
3110 	struct cil_alias *alias = NULL;
3111 	enum cil_sym_index sym_index;
3112 	int rc = SEPOL_ERR;
3113 
3114 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3115 		goto exit;
3116 	}
3117 
3118 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3119 	if (rc != SEPOL_OK) {
3120 		goto exit;
3121 	}
3122 
3123 	cil_alias_init(&alias);
3124 
3125 	key = parse_current->next->data;
3126 
3127 	rc = cil_flavor_to_symtab_index(flavor, &sym_index);
3128 	if (rc != SEPOL_OK) {
3129 		goto exit;
3130 	}
3131 
3132 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor);
3133 	if (rc != SEPOL_OK) {
3134 		goto exit;
3135 	}
3136 
3137 	return SEPOL_OK;
3138 
3139 exit:
3140 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data);
3141 	cil_destroy_alias(alias);
3142 	cil_clear_node(ast_node);
3143 	return rc;
3144 }
3145 
cil_destroy_alias(struct cil_alias * alias)3146 void cil_destroy_alias(struct cil_alias *alias)
3147 {
3148 	if (alias == NULL) {
3149 		return;
3150 	}
3151 
3152 	cil_symtab_datum_destroy(&alias->datum);
3153 	alias->actual = NULL;
3154 
3155 	free(alias);
3156 }
3157 
cil_gen_aliasactual(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3158 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3159 {
3160 	int rc = SEPOL_ERR;
3161 	enum cil_syntax syntax[] = {
3162 		CIL_SYN_STRING,
3163 		CIL_SYN_STRING,
3164 		CIL_SYN_STRING,
3165 		CIL_SYN_END
3166 	};
3167 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3168 	struct cil_aliasactual *aliasactual = NULL;
3169 
3170 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3171 		goto exit;
3172 	}
3173 
3174 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3175 	if (rc != SEPOL_OK) {
3176 		goto exit;
3177 	}
3178 
3179 	cil_aliasactual_init(&aliasactual);
3180 
3181 	aliasactual->alias_str = parse_current->next->data;
3182 
3183 	aliasactual->actual_str = parse_current->next->next->data;
3184 
3185 	ast_node->data = aliasactual;
3186 	ast_node->flavor = flavor;
3187 
3188 	return SEPOL_OK;
3189 
3190 exit:
3191 	cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current));
3192 	cil_clear_node(ast_node);
3193 	return rc;
3194 }
3195 
cil_destroy_aliasactual(struct cil_aliasactual * aliasactual)3196 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
3197 {
3198 	if (aliasactual == NULL) {
3199 		return;
3200 	}
3201 
3202 	free(aliasactual);
3203 }
3204 
cil_gen_typeattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3205 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3206 {
3207 	enum cil_syntax syntax[] = {
3208 		CIL_SYN_STRING,
3209 		CIL_SYN_STRING,
3210 		CIL_SYN_STRING | CIL_SYN_LIST,
3211 		CIL_SYN_END
3212 	};
3213 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3214 	struct cil_typeattributeset *attrset = NULL;
3215 	int rc = SEPOL_ERR;
3216 
3217 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3218 		goto exit;
3219 	}
3220 
3221 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3222 	if (rc != SEPOL_OK) {
3223 		goto exit;
3224 	}
3225 
3226 	cil_typeattributeset_init(&attrset);
3227 
3228 	attrset->attr_str = parse_current->next->data;
3229 
3230 	rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr);
3231 	if (rc != SEPOL_OK) {
3232 		goto exit;
3233 	}
3234 	ast_node->data = attrset;
3235 	ast_node->flavor = CIL_TYPEATTRIBUTESET;
3236 
3237 	return SEPOL_OK;
3238 
3239 exit:
3240 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
3241 	cil_destroy_typeattributeset(attrset);
3242 	return rc;
3243 }
3244 
cil_destroy_typeattributeset(struct cil_typeattributeset * attrset)3245 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
3246 {
3247 	if (attrset == NULL) {
3248 		return;
3249 	}
3250 
3251 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
3252 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
3253 
3254 	free(attrset);
3255 }
3256 
cil_gen_expandtypeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3257 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3258 {
3259 	enum cil_syntax syntax[] = {
3260 		CIL_SYN_STRING,
3261 		CIL_SYN_STRING | CIL_SYN_LIST,
3262 		CIL_SYN_STRING,
3263 		CIL_SYN_END
3264 	};
3265 	char *expand_str;
3266 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3267 	struct cil_expandtypeattribute *expandattr = NULL;
3268 	int rc = SEPOL_ERR;
3269 
3270 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3271 		goto exit;
3272 	}
3273 
3274 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3275 	if (rc != SEPOL_OK) {
3276 		goto exit;
3277 	}
3278 
3279 	cil_expandtypeattribute_init(&expandattr);
3280 
3281 	if (parse_current->next->cl_head == NULL) {
3282 		cil_list_init(&expandattr->attr_strs, CIL_TYPE);
3283 		cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data);
3284 	} else {
3285 		rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs);
3286 		if (rc != SEPOL_OK) {
3287 			goto exit;
3288 		}
3289 	}
3290 
3291 	expand_str = parse_current->next->next->data;
3292 
3293 	if (expand_str == CIL_KEY_CONDTRUE) {
3294 		expandattr->expand = CIL_TRUE;
3295 	} else if (expand_str == CIL_KEY_CONDFALSE) {
3296 		expandattr->expand = CIL_FALSE;
3297 	} else {
3298 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
3299 		rc = SEPOL_ERR;
3300 		goto exit;
3301 	}
3302 
3303 	ast_node->data = expandattr;
3304 	ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
3305 
3306 	return SEPOL_OK;
3307 
3308 exit:
3309 	cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement");
3310 	cil_destroy_expandtypeattribute(expandattr);
3311 	return rc;
3312 }
3313 
cil_destroy_expandtypeattribute(struct cil_expandtypeattribute * expandattr)3314 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
3315 {
3316 	if (expandattr == NULL) {
3317 		return;
3318 	}
3319 
3320 	cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
3321 
3322 	cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
3323 
3324 	free(expandattr);
3325 }
3326 
cil_gen_typepermissive(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3327 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3328 {
3329 	enum cil_syntax syntax[] = {
3330 		CIL_SYN_STRING,
3331 		CIL_SYN_STRING,
3332 		CIL_SYN_END
3333 	};
3334 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3335 	struct cil_typepermissive *typeperm = NULL;
3336 	int rc = SEPOL_ERR;
3337 
3338 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3339 		goto exit;
3340 	}
3341 
3342 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3343 	if (rc != SEPOL_OK) {
3344 		goto exit;
3345 	}
3346 
3347 	cil_typepermissive_init(&typeperm);
3348 
3349 	typeperm->type_str = parse_current->next->data;
3350 
3351 	ast_node->data = typeperm;
3352 	ast_node->flavor = CIL_TYPEPERMISSIVE;
3353 
3354 	return SEPOL_OK;
3355 
3356 exit:
3357 	cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
3358 	cil_destroy_typepermissive(typeperm);
3359 	return rc;
3360 }
3361 
cil_destroy_typepermissive(struct cil_typepermissive * typeperm)3362 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
3363 {
3364 	if (typeperm == NULL) {
3365 		return;
3366 	}
3367 
3368 	free(typeperm);
3369 }
3370 
cil_gen_typetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3371 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3372 {
3373 	int rc = SEPOL_ERR;
3374 	enum cil_syntax syntax[] = {
3375 		CIL_SYN_STRING,
3376 		CIL_SYN_STRING,
3377 		CIL_SYN_STRING,
3378 		CIL_SYN_STRING,
3379 		CIL_SYN_STRING,
3380 		CIL_SYN_STRING | CIL_SYN_END,
3381 		CIL_SYN_END
3382 	};
3383 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3384 	char *s1, *s2, *s3, *s4, *s5;
3385 
3386 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3387 		goto exit;
3388 	}
3389 
3390 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3391 	if (rc != SEPOL_OK) {
3392 		goto exit;
3393 	}
3394 
3395 	s1 = parse_current->next->data;
3396 	s2 = parse_current->next->next->data;
3397 	s3 = parse_current->next->next->next->data;
3398 	s4 = parse_current->next->next->next->next->data;
3399 	s5 = NULL;
3400 
3401 	if (parse_current->next->next->next->next->next) {
3402 		if (s4 == CIL_KEY_STAR) {
3403 			s4 = parse_current->next->next->next->next->next->data;
3404 		} else {
3405 			s5 = parse_current->next->next->next->next->next->data;
3406 		}
3407 	}
3408 
3409 	if (s5) {
3410 		struct cil_nametypetransition *nametypetrans = NULL;
3411 		cil_nametypetransition_init(&nametypetrans);
3412 
3413 		ast_node->data = nametypetrans;
3414 		ast_node->flavor = CIL_NAMETYPETRANSITION;
3415 
3416 		nametypetrans->src_str = s1;
3417 		nametypetrans->tgt_str = s2;
3418 		nametypetrans->obj_str = s3;
3419 		nametypetrans->name_str = s4;
3420 		nametypetrans->name = cil_gen_declared_string(db, s4, ast_node);
3421 		nametypetrans->result_str = s5;
3422 	} else {
3423 		struct cil_type_rule *rule = NULL;
3424 		cil_type_rule_init(&rule);
3425 
3426 		ast_node->data = rule;
3427 		ast_node->flavor = CIL_TYPE_RULE;
3428 
3429 		rule->rule_kind = CIL_TYPE_TRANSITION;
3430 		rule->src_str = s1;
3431 		rule->tgt_str = s2;
3432 		rule->obj_str = s3;
3433 		rule->result_str = s4;
3434 	}
3435 
3436 	return SEPOL_OK;
3437 
3438 exit:
3439 	cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
3440 	return rc;
3441 }
3442 
cil_destroy_typetransition(struct cil_nametypetransition * nametypetrans)3443 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
3444 {
3445 	if (nametypetrans == NULL) {
3446 		return;
3447 	}
3448 
3449 	free(nametypetrans);
3450 }
3451 
cil_gen_rangetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3452 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3453 {
3454 	enum cil_syntax syntax[] = {
3455 		CIL_SYN_STRING,
3456 		CIL_SYN_STRING,
3457 		CIL_SYN_STRING,
3458 		CIL_SYN_STRING,
3459 		CIL_SYN_STRING | CIL_SYN_LIST,
3460 		CIL_SYN_END
3461 	};
3462 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3463 	struct cil_rangetransition *rangetrans = NULL;
3464 	int rc = SEPOL_ERR;
3465 
3466 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3467 		goto exit;
3468 	}
3469 
3470 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3471 	if (rc != SEPOL_OK) {
3472 		goto exit;
3473 	}
3474 
3475 	cil_rangetransition_init(&rangetrans);
3476 
3477 	rangetrans->src_str = parse_current->next->data;
3478 	rangetrans->exec_str = parse_current->next->next->data;
3479 	rangetrans->obj_str = parse_current->next->next->next->data;
3480 
3481 	rangetrans->range_str = NULL;
3482 
3483 	if (parse_current->next->next->next->next->cl_head == NULL) {
3484 		rangetrans->range_str = parse_current->next->next->next->next->data;
3485 	} else {
3486 		cil_levelrange_init(&rangetrans->range);
3487 
3488 		rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range);
3489 		if (rc != SEPOL_OK) {
3490 			goto exit;
3491 		}
3492 	}
3493 
3494 	ast_node->data = rangetrans;
3495 	ast_node->flavor = CIL_RANGETRANSITION;
3496 
3497 	return SEPOL_OK;
3498 
3499 exit:
3500 	cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
3501 	cil_destroy_rangetransition(rangetrans);
3502 	return rc;
3503 }
3504 
cil_destroy_rangetransition(struct cil_rangetransition * rangetrans)3505 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
3506 {
3507 	if (rangetrans == NULL) {
3508 		return;
3509 	}
3510 
3511 	if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
3512 		cil_destroy_levelrange(rangetrans->range);
3513 	}
3514 
3515 	free(rangetrans);
3516 }
3517 
cil_gen_sensitivity(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3518 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3519 {
3520 	enum cil_syntax syntax[] = {
3521 		CIL_SYN_STRING,
3522 		CIL_SYN_STRING,
3523 		CIL_SYN_END
3524 	};
3525 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3526 	char *key = NULL;
3527 	struct cil_sens *sens = NULL;
3528 	int rc = SEPOL_ERR;
3529 
3530 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3531 		goto exit;
3532 	}
3533 
3534 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3535 	if (rc != SEPOL_OK) {
3536 		goto exit;
3537 	}
3538 
3539 	cil_sens_init(&sens);
3540 
3541 	key = parse_current->next->data;
3542 
3543 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
3544 	if (rc != SEPOL_OK) {
3545 		goto exit;
3546 	}
3547 
3548 	return SEPOL_OK;
3549 
3550 exit:
3551 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
3552 	cil_destroy_sensitivity(sens);
3553 	cil_clear_node(ast_node);
3554 	return rc;
3555 }
3556 
cil_destroy_sensitivity(struct cil_sens * sens)3557 void cil_destroy_sensitivity(struct cil_sens *sens)
3558 {
3559 	if (sens == NULL) {
3560 		return;
3561 	}
3562 
3563 	cil_symtab_datum_destroy(&sens->datum);
3564 
3565 	cil_list_destroy(&sens->cats_list, CIL_FALSE);
3566 
3567 	free(sens);
3568 }
3569 
cil_gen_category(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3570 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3571 {
3572 	enum cil_syntax syntax[] = {
3573 		CIL_SYN_STRING,
3574 		CIL_SYN_STRING,
3575 		CIL_SYN_END
3576 	};
3577 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3578 	char *key = NULL;
3579 	struct cil_cat *cat = NULL;
3580 	int rc = SEPOL_ERR;
3581 
3582 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3583 		goto exit;
3584 	}
3585 
3586 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3587 	if (rc != SEPOL_OK) {
3588 		goto exit;
3589 	}
3590 
3591 	cil_cat_init(&cat);
3592 
3593 	key = parse_current->next->data;
3594 
3595 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
3596 	if (rc != SEPOL_OK) {
3597 		goto exit;
3598 	}
3599 
3600 	return SEPOL_OK;
3601 
3602 exit:
3603 	cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
3604 	cil_destroy_category(cat);
3605 	cil_clear_node(ast_node);
3606 	return rc;
3607 }
3608 
cil_destroy_category(struct cil_cat * cat)3609 void cil_destroy_category(struct cil_cat *cat)
3610 {
3611 	if (cat == NULL) {
3612 		return;
3613 	}
3614 
3615 	cil_symtab_datum_destroy(&cat->datum);
3616 	free(cat);
3617 }
3618 
cil_gen_catset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3619 static int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3620 {
3621 	enum cil_syntax syntax[] = {
3622 		CIL_SYN_STRING,
3623 		CIL_SYN_STRING,
3624 		CIL_SYN_LIST,
3625 		CIL_SYN_END
3626 	};
3627 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3628 	char *key = NULL;
3629 	struct cil_catset *catset = NULL;
3630 	int rc = SEPOL_ERR;
3631 
3632 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3633 		goto exit;
3634 	}
3635 
3636 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3637 	if (rc != SEPOL_OK) {
3638 		goto exit;
3639 	}
3640 
3641 	cil_catset_init(&catset);
3642 
3643 	key = parse_current->next->data;
3644 
3645 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
3646 	if (rc != SEPOL_OK) {
3647 		goto exit;
3648 	}
3649 
3650 	rc = cil_fill_cats(parse_current->next->next, &catset->cats);
3651 	if (rc != SEPOL_OK) {
3652 		goto exit;
3653 	}
3654 
3655 	return SEPOL_OK;
3656 
3657 exit:
3658 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
3659 	cil_destroy_catset(catset);
3660 	cil_clear_node(ast_node);
3661 	return rc;
3662 }
3663 
cil_destroy_catset(struct cil_catset * catset)3664 void cil_destroy_catset(struct cil_catset *catset)
3665 {
3666 	if (catset == NULL) {
3667 		return;
3668 	}
3669 
3670 	cil_symtab_datum_destroy(&catset->datum);
3671 
3672 	cil_destroy_cats(catset->cats);
3673 
3674 	free(catset);
3675 }
3676 
cil_gen_senscat(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3677 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3678 {
3679 	enum cil_syntax syntax[] = {
3680 		CIL_SYN_STRING,
3681 		CIL_SYN_STRING,
3682 		CIL_SYN_STRING | CIL_SYN_LIST,
3683 		CIL_SYN_END
3684 	};
3685 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3686 	struct cil_senscat *senscat = NULL;
3687 	int rc = SEPOL_ERR;
3688 
3689 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3690 		goto exit;
3691 	}
3692 
3693 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3694 	if (rc != SEPOL_OK) {
3695 		goto exit;
3696 	}
3697 
3698 	cil_senscat_init(&senscat);
3699 
3700 	senscat->sens_str = parse_current->next->data;
3701 
3702 	rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
3703 	if (rc != SEPOL_OK) {
3704 		goto exit;
3705 	}
3706 
3707 	ast_node->data = senscat;
3708 	ast_node->flavor = CIL_SENSCAT;
3709 
3710 	return SEPOL_OK;
3711 
3712 exit:
3713 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration");
3714 	cil_destroy_senscat(senscat);
3715 	return rc;
3716 }
3717 
cil_destroy_senscat(struct cil_senscat * senscat)3718 void cil_destroy_senscat(struct cil_senscat *senscat)
3719 {
3720 	if (senscat == NULL) {
3721 		return;
3722 	}
3723 
3724 	cil_destroy_cats(senscat->cats);
3725 
3726 	free(senscat);
3727 }
3728 
cil_gen_level(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3729 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3730 {
3731 	enum cil_syntax syntax[] = {
3732 		CIL_SYN_STRING,
3733 		CIL_SYN_STRING,
3734 		CIL_SYN_LIST,
3735 		CIL_SYN_END
3736 	};
3737 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3738 	char *key = NULL;
3739 	struct cil_level *level = NULL;
3740 	int rc = SEPOL_ERR;
3741 
3742 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3743 		goto exit;
3744 	}
3745 
3746 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3747 	if (rc != SEPOL_OK) {
3748 		goto exit;
3749 	}
3750 
3751 	cil_level_init(&level);
3752 
3753 	key = parse_current->next->data;
3754 
3755 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
3756 	if (rc != SEPOL_OK) {
3757 		goto exit;
3758 	}
3759 
3760 	rc = cil_fill_level(parse_current->next->next->cl_head, level);
3761 	if (rc != SEPOL_OK) {
3762 		goto exit;
3763 	}
3764 
3765 	return SEPOL_OK;
3766 
3767 exit:
3768 	cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
3769 	cil_destroy_level(level);
3770 	cil_clear_node(ast_node);
3771 	return rc;
3772 }
3773 
cil_destroy_level(struct cil_level * level)3774 void cil_destroy_level(struct cil_level *level)
3775 {
3776 	if (level == NULL) {
3777 		return;
3778 	}
3779 
3780 	cil_symtab_datum_destroy(&level->datum);
3781 
3782 	cil_destroy_cats(level->cats);
3783 
3784 	free(level);
3785 }
3786 
3787 /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */
cil_fill_levelrange(struct cil_tree_node * low,struct cil_levelrange * lvlrange)3788 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange)
3789 {
3790 	enum cil_syntax syntax[] = {
3791 		CIL_SYN_STRING | CIL_SYN_LIST,
3792 		CIL_SYN_STRING | CIL_SYN_LIST,
3793 		CIL_SYN_END
3794 	};
3795 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3796 	int rc = SEPOL_ERR;
3797 
3798 	if (low == NULL || lvlrange == NULL) {
3799 		goto exit;
3800 	}
3801 
3802 	rc = __cil_verify_syntax(low, syntax, syntax_len);
3803 	if (rc != SEPOL_OK) {
3804 
3805 		goto exit;
3806 	}
3807 
3808 	if (low->cl_head == NULL) {
3809 		lvlrange->low_str = low->data;
3810 	} else {
3811 		cil_level_init(&lvlrange->low);
3812 		rc = cil_fill_level(low->cl_head, lvlrange->low);
3813 		if (rc != SEPOL_OK) {
3814 			goto exit;
3815 		}
3816 	}
3817 
3818 	if (low->next->cl_head == NULL) {
3819 		lvlrange->high_str = low->next->data;
3820 	} else {
3821 		cil_level_init(&lvlrange->high);
3822 		rc = cil_fill_level(low->next->cl_head, lvlrange->high);
3823 		if (rc != SEPOL_OK) {
3824 			goto exit;
3825 		}
3826 	}
3827 
3828 	return SEPOL_OK;
3829 
3830 exit:
3831 	cil_log(CIL_ERR, "Bad levelrange\n");
3832 	return rc;
3833 }
3834 
cil_gen_levelrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3835 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3836 {
3837 	enum cil_syntax syntax[] = {
3838 		CIL_SYN_STRING,
3839 		CIL_SYN_STRING,
3840 		CIL_SYN_LIST,
3841 		CIL_SYN_END
3842 	};
3843 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3844 	char *key = NULL;
3845 	struct cil_levelrange *lvlrange = NULL;
3846 	int rc = SEPOL_ERR;
3847 
3848 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3849 		goto exit;
3850 	}
3851 
3852 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3853 	if (rc != SEPOL_OK) {
3854 		goto exit;
3855 	}
3856 
3857 	cil_levelrange_init(&lvlrange);
3858 
3859 	key = parse_current->next->data;
3860 
3861 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE);
3862 	if (rc != SEPOL_OK) {
3863 		goto exit;
3864 	}
3865 
3866 	rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
3867 	if (rc != SEPOL_OK) {
3868 		goto exit;
3869 	}
3870 
3871 	return SEPOL_OK;
3872 
3873 exit:
3874 	cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
3875 	cil_destroy_levelrange(lvlrange);
3876 	cil_clear_node(ast_node);
3877 	return rc;
3878 }
3879 
cil_destroy_levelrange(struct cil_levelrange * lvlrange)3880 void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
3881 {
3882 	if (lvlrange == NULL) {
3883 		return;
3884 	}
3885 
3886 	cil_symtab_datum_destroy(&lvlrange->datum);
3887 
3888 	if (lvlrange->low_str == NULL) {
3889 		cil_destroy_level(lvlrange->low);
3890 	}
3891 
3892 	if (lvlrange->high_str == NULL) {
3893 		cil_destroy_level(lvlrange->high);
3894 	}
3895 
3896 	free(lvlrange);
3897 }
3898 
cil_gen_constrain(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3899 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3900 {
3901 	enum cil_syntax syntax[] = {
3902 		CIL_SYN_STRING,
3903 		CIL_SYN_STRING | CIL_SYN_LIST,
3904 		CIL_SYN_LIST,
3905 		CIL_SYN_END
3906 	};
3907 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3908 	struct cil_constrain *cons = NULL;
3909 	int rc = SEPOL_ERR;
3910 
3911 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3912 		goto exit;
3913 	}
3914 
3915 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3916 	if (rc != SEPOL_OK) {
3917 		goto exit;
3918 	}
3919 
3920 	cil_constrain_init(&cons);
3921 
3922 	rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
3923 	if (rc != SEPOL_OK) {
3924 		goto exit;
3925 	}
3926 
3927 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr);
3928 	if (rc != SEPOL_OK) {
3929 		goto exit;
3930 	}
3931 
3932 	ast_node->data = cons;
3933 	ast_node->flavor = flavor;
3934 
3935 	return SEPOL_OK;
3936 
3937 exit:
3938 	cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
3939 	cil_destroy_constrain(cons);
3940 	return rc;
3941 }
3942 
cil_destroy_constrain(struct cil_constrain * cons)3943 void cil_destroy_constrain(struct cil_constrain *cons)
3944 {
3945 	if (cons == NULL) {
3946 		return;
3947 	}
3948 
3949 	cil_destroy_classperms_list(&cons->classperms);
3950 	cil_list_destroy(&cons->str_expr, CIL_TRUE);
3951 	cil_list_destroy(&cons->datum_expr, CIL_FALSE);
3952 
3953 	free(cons);
3954 }
3955 
cil_gen_validatetrans(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3956 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3957 {
3958 	enum cil_syntax syntax[] = {
3959 		CIL_SYN_STRING,
3960 		CIL_SYN_STRING,
3961 		CIL_SYN_LIST,
3962 		CIL_SYN_END
3963 	};
3964 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3965 	struct cil_validatetrans *validtrans = NULL;
3966 	int rc = SEPOL_ERR;
3967 
3968 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3969 		goto exit;
3970 	}
3971 
3972 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3973 	if (rc != SEPOL_OK) {
3974 		goto exit;
3975 	}
3976 
3977 	cil_validatetrans_init(&validtrans);
3978 
3979 	validtrans->class_str = parse_current->next->data;
3980 
3981 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr);
3982 	if (rc != SEPOL_OK) {
3983 		goto exit;
3984 	}
3985 
3986 	ast_node->data = validtrans;
3987 	ast_node->flavor = flavor;
3988 
3989 	return SEPOL_OK;
3990 
3991 exit:
3992 	cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
3993 	cil_destroy_validatetrans(validtrans);
3994 	return rc;
3995 
3996 
3997 }
3998 
cil_destroy_validatetrans(struct cil_validatetrans * validtrans)3999 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
4000 {
4001 	if (validtrans == NULL) {
4002 		return;
4003 	}
4004 
4005 	cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
4006 	cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
4007 
4008 	free(validtrans);
4009 }
4010 
4011 /* Fills in context starting from user */
cil_fill_context(struct cil_tree_node * user_node,struct cil_context * context)4012 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context)
4013 {
4014 	enum cil_syntax syntax[] = {
4015 		CIL_SYN_STRING,
4016 		CIL_SYN_STRING,
4017 		CIL_SYN_STRING,
4018 		CIL_SYN_STRING | CIL_SYN_LIST,
4019 		CIL_SYN_END
4020 	};
4021 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4022 	int rc = SEPOL_ERR;
4023 
4024 	if (user_node == NULL || context == NULL) {
4025 		goto exit;
4026 	}
4027 
4028 	rc = __cil_verify_syntax(user_node, syntax, syntax_len);
4029 	if (rc != SEPOL_OK) {
4030 		goto exit;
4031 	}
4032 
4033 	context->user_str = user_node->data;
4034 	context->role_str = user_node->next->data;
4035 	context->type_str = user_node->next->next->data;
4036 
4037 	context->range_str = NULL;
4038 
4039 	if (user_node->next->next->next->cl_head == NULL) {
4040 		context->range_str = user_node->next->next->next->data;
4041 	} else {
4042 		cil_levelrange_init(&context->range);
4043 
4044 		rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range);
4045 		if (rc != SEPOL_OK) {
4046 			goto exit;
4047 		}
4048 	}
4049 
4050 	return SEPOL_OK;
4051 
4052 exit:
4053 	cil_log(CIL_ERR, "Bad context\n");
4054 	return rc;
4055 }
4056 
cil_gen_context(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4057 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4058 {
4059 	enum cil_syntax syntax[] = {
4060 		CIL_SYN_STRING,
4061 		CIL_SYN_STRING,
4062 		CIL_SYN_LIST,
4063 		CIL_SYN_END
4064 	};
4065 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4066 	char *key = NULL;
4067 	struct cil_context *context = NULL;
4068 	int rc = SEPOL_ERR;
4069 
4070 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4071 		goto exit;
4072 	}
4073 
4074 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4075 	if (rc != SEPOL_OK) {
4076 		goto exit;
4077 	}
4078 
4079 	cil_context_init(&context);
4080 
4081 	key = parse_current->next->data;
4082 
4083 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
4084 	if (rc != SEPOL_OK) {
4085 		goto exit;
4086 	}
4087 
4088 	rc = cil_fill_context(parse_current->next->next->cl_head, context);
4089 	if (rc != SEPOL_OK) {
4090 		goto exit;
4091 	}
4092 
4093 	return SEPOL_OK;
4094 
4095 exit:
4096 	cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
4097 	cil_destroy_context(context);
4098 	cil_clear_node(ast_node);
4099 	return SEPOL_ERR;
4100 }
4101 
cil_destroy_context(struct cil_context * context)4102 void cil_destroy_context(struct cil_context *context)
4103 {
4104 	if (context == NULL) {
4105 		return;
4106 	}
4107 
4108 	cil_symtab_datum_destroy(&context->datum);
4109 
4110 	if (context->range_str == NULL && context->range != NULL) {
4111 		cil_destroy_levelrange(context->range);
4112 	}
4113 
4114 	free(context);
4115 }
4116 
cil_gen_filecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4117 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4118 {
4119 	enum cil_syntax syntax[] = {
4120 		CIL_SYN_STRING,
4121 		CIL_SYN_STRING,
4122 		CIL_SYN_STRING,
4123 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
4124 		CIL_SYN_END
4125 	};
4126 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4127 	int rc = SEPOL_ERR;
4128 	struct cil_filecon *filecon = NULL;
4129 	char *type = NULL;
4130 
4131 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4132 		goto exit;
4133 	}
4134 
4135 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4136 	if (rc != SEPOL_OK) {
4137 		goto exit;
4138 	}
4139 
4140 	type = parse_current->next->next->data;
4141 	cil_filecon_init(&filecon);
4142 
4143 	ast_node->data = filecon;
4144 	ast_node->flavor = CIL_FILECON;
4145 
4146 	filecon->path_str = parse_current->next->data;
4147 	/* filecon->path will be NULL if in a macro and the path is an argument */
4148 	filecon->path = cil_gen_declared_string(db, filecon->path_str, ast_node);
4149 
4150 	if (type == CIL_KEY_ANY) {
4151 		filecon->type = CIL_FILECON_ANY;
4152 	} else if (type == CIL_KEY_FILE) {
4153 		filecon->type = CIL_FILECON_FILE;
4154 	} else if (type == CIL_KEY_DIR) {
4155 		filecon->type = CIL_FILECON_DIR;
4156 	} else if (type == CIL_KEY_CHAR) {
4157 		filecon->type = CIL_FILECON_CHAR;
4158 	} else if (type == CIL_KEY_BLOCK) {
4159 		filecon->type = CIL_FILECON_BLOCK;
4160 	} else if (type == CIL_KEY_SOCKET) {
4161 		filecon->type = CIL_FILECON_SOCKET;
4162 	} else if (type == CIL_KEY_PIPE) {
4163 		filecon->type = CIL_FILECON_PIPE;
4164 	} else if (type == CIL_KEY_SYMLINK) {
4165 		filecon->type = CIL_FILECON_SYMLINK;
4166 	} else {
4167 		cil_log(CIL_ERR, "Invalid file type\n");
4168 		rc = SEPOL_ERR;
4169 		goto exit;
4170 	}
4171 
4172 	if (parse_current->next->next->next->cl_head == NULL) {
4173 		filecon->context_str = parse_current->next->next->next->data;
4174 	} else {
4175 		if (parse_current->next->next->next->cl_head->next == NULL) {
4176 			filecon->context = NULL;
4177 		} else {
4178 			cil_context_init(&filecon->context);
4179 
4180 			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
4181 			if (rc != SEPOL_OK) {
4182 				goto exit;
4183 			}
4184 		}
4185 	}
4186 
4187 	return SEPOL_OK;
4188 
4189 exit:
4190 	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
4191 	cil_destroy_filecon(filecon);
4192 	cil_clear_node(ast_node);
4193 	return rc;
4194 }
4195 
4196 //TODO: Should we be checking if the pointer is NULL when passed in?
cil_destroy_filecon(struct cil_filecon * filecon)4197 void cil_destroy_filecon(struct cil_filecon *filecon)
4198 {
4199 	if (filecon == NULL) {
4200 		return;
4201 	}
4202 
4203 	if (filecon->context_str == NULL && filecon->context != NULL) {
4204 		cil_destroy_context(filecon->context);
4205 	}
4206 
4207 	free(filecon);
4208 }
4209 
cil_gen_ibpkeycon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4210 int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4211 {
4212 	enum cil_syntax syntax[] = {
4213 		CIL_SYN_STRING,
4214 		CIL_SYN_STRING,
4215 		CIL_SYN_STRING | CIL_SYN_LIST,
4216 		CIL_SYN_STRING | CIL_SYN_LIST,
4217 		CIL_SYN_END
4218 	};
4219 	size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4220 	int rc = SEPOL_ERR;
4221 	struct cil_ibpkeycon *ibpkeycon = NULL;
4222 
4223 	if (!parse_current || !ast_node)
4224 		goto exit;
4225 
4226 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4227 	if (rc != SEPOL_OK)
4228 		goto exit;
4229 
4230 	cil_ibpkeycon_init(&ibpkeycon);
4231 
4232 	ibpkeycon->subnet_prefix_str = parse_current->next->data;
4233 
4234 	if (parse_current->next->next->cl_head) {
4235 		if (parse_current->next->next->cl_head->next &&
4236 		    !parse_current->next->next->cl_head->next->next) {
4237 			rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0);
4238 			if (rc != SEPOL_OK) {
4239 				cil_log(CIL_ERR, "Improper ibpkey specified\n");
4240 				goto exit;
4241 			}
4242 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0);
4243 			if (rc != SEPOL_OK) {
4244 				cil_log(CIL_ERR, "Improper ibpkey specified\n");
4245 				goto exit;
4246 			}
4247 		} else {
4248 			cil_log(CIL_ERR, "Improper ibpkey range specified\n");
4249 			rc = SEPOL_ERR;
4250 			goto exit;
4251 		}
4252 	} else {
4253 		rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0);
4254 		if (rc != SEPOL_OK) {
4255 			cil_log(CIL_ERR, "Improper ibpkey specified\n");
4256 			goto exit;
4257 		}
4258 		ibpkeycon->pkey_high = ibpkeycon->pkey_low;
4259 	}
4260 
4261 	if (!parse_current->next->next->next->cl_head) {
4262 		ibpkeycon->context_str = parse_current->next->next->next->data;
4263 	} else {
4264 		cil_context_init(&ibpkeycon->context);
4265 
4266 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context);
4267 		if (rc != SEPOL_OK)
4268 			goto exit;
4269 	}
4270 
4271 	ast_node->data = ibpkeycon;
4272 	ast_node->flavor = CIL_IBPKEYCON;
4273 	return SEPOL_OK;
4274 
4275 exit:
4276 	cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration");
4277 	cil_destroy_ibpkeycon(ibpkeycon);
4278 
4279 	return rc;
4280 }
4281 
cil_destroy_ibpkeycon(struct cil_ibpkeycon * ibpkeycon)4282 void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
4283 {
4284 	if (!ibpkeycon)
4285 		return;
4286 
4287 	if (!ibpkeycon->context_str && ibpkeycon->context)
4288 		cil_destroy_context(ibpkeycon->context);
4289 
4290 	free(ibpkeycon);
4291 }
4292 
cil_gen_portcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4293 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4294 {
4295 	enum cil_syntax syntax[] = {
4296 		CIL_SYN_STRING,
4297 		CIL_SYN_STRING,
4298 		CIL_SYN_STRING | CIL_SYN_LIST,
4299 		CIL_SYN_STRING | CIL_SYN_LIST,
4300 		CIL_SYN_END
4301 	};
4302 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4303 	int rc = SEPOL_ERR;
4304 	struct cil_portcon *portcon = NULL;
4305 	char *proto;
4306 
4307 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4308 		goto exit;
4309 	}
4310 
4311 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4312 	if (rc != SEPOL_OK) {
4313 		goto exit;
4314 	}
4315 
4316 	cil_portcon_init(&portcon);
4317 
4318 	proto = parse_current->next->data;
4319 	if (proto == CIL_KEY_UDP) {
4320 		portcon->proto = CIL_PROTOCOL_UDP;
4321 	} else if (proto == CIL_KEY_TCP) {
4322 		portcon->proto = CIL_PROTOCOL_TCP;
4323 	} else if (proto == CIL_KEY_DCCP) {
4324 		portcon->proto = CIL_PROTOCOL_DCCP;
4325 	} else if (proto == CIL_KEY_SCTP) {
4326 		portcon->proto = CIL_PROTOCOL_SCTP;
4327 	} else {
4328 		cil_log(CIL_ERR, "Invalid protocol\n");
4329 		rc = SEPOL_ERR;
4330 		goto exit;
4331 	}
4332 
4333 	if (parse_current->next->next->cl_head != NULL) {
4334 		if (parse_current->next->next->cl_head->next != NULL
4335 		&& parse_current->next->next->cl_head->next->next == NULL) {
4336 			rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
4337 			if (rc != SEPOL_OK) {
4338 				cil_log(CIL_ERR, "Improper port specified\n");
4339 				goto exit;
4340 			}
4341 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
4342 			if (rc != SEPOL_OK) {
4343 				cil_log(CIL_ERR, "Improper port specified\n");
4344 				goto exit;
4345 			}
4346 		} else {
4347 			cil_log(CIL_ERR, "Improper port range specified\n");
4348 			rc = SEPOL_ERR;
4349 			goto exit;
4350 		}
4351 	} else {
4352 		rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
4353 		if (rc != SEPOL_OK) {
4354 			cil_log(CIL_ERR, "Improper port specified\n");
4355 			goto exit;
4356 		}
4357 		portcon->port_high = portcon->port_low;
4358 	}
4359 
4360 	if (parse_current->next->next->next->cl_head == NULL ) {
4361 		portcon->context_str = parse_current->next->next->next->data;
4362 	} else {
4363 		cil_context_init(&portcon->context);
4364 
4365 		rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
4366 		if (rc != SEPOL_OK) {
4367 			goto exit;
4368 		}
4369 	}
4370 
4371 	ast_node->data = portcon;
4372 	ast_node->flavor = CIL_PORTCON;
4373 
4374 	return SEPOL_OK;
4375 
4376 exit:
4377 	cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4378 	cil_destroy_portcon(portcon);
4379 	return rc;
4380 }
4381 
cil_destroy_portcon(struct cil_portcon * portcon)4382 void cil_destroy_portcon(struct cil_portcon *portcon)
4383 {
4384 	if (portcon == NULL) {
4385 		return;
4386 	}
4387 
4388 	if (portcon->context_str == NULL && portcon->context != NULL) {
4389 		cil_destroy_context(portcon->context);
4390 	}
4391 
4392 	free(portcon);
4393 }
4394 
cil_gen_nodecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4395 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4396 {
4397 	enum cil_syntax syntax[] = {
4398 		CIL_SYN_STRING,
4399 		CIL_SYN_STRING | CIL_SYN_LIST,
4400 		CIL_SYN_STRING | CIL_SYN_LIST,
4401 		CIL_SYN_STRING | CIL_SYN_LIST,
4402 		CIL_SYN_END
4403 	};
4404 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4405 	int rc = SEPOL_ERR;
4406 	struct cil_nodecon *nodecon = NULL;
4407 
4408 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4409 		goto exit;
4410 	}
4411 
4412 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4413 	if (rc != SEPOL_OK) {
4414 		goto exit;
4415 	}
4416 
4417 	cil_nodecon_init(&nodecon);
4418 
4419 	if (parse_current->next->cl_head) {
4420 		cil_ipaddr_init(&nodecon->addr);
4421 		rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
4422 		if (rc != SEPOL_OK) {
4423 			goto exit;
4424 		}
4425 	} else {
4426 		char *addr = parse_current->next->data;
4427 		if (strchr(addr, ':') || (strchr(addr, '.') && isdigit(addr[0]))) {
4428 			cil_ipaddr_init(&nodecon->addr);
4429 			rc = cil_fill_ipaddr(parse_current->next, nodecon->addr);
4430 			if (rc != SEPOL_OK) {
4431 				goto exit;
4432 			}
4433 		} else {
4434 			nodecon->addr_str = addr;
4435 		}
4436 	}
4437 
4438 	if (parse_current->next->next->cl_head) {
4439 		cil_ipaddr_init(&nodecon->mask);
4440 		rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
4441 		if (rc != SEPOL_OK) {
4442 			goto exit;
4443 		}
4444 	} else {
4445 		char *mask = parse_current->next->next->data;
4446 		if (strchr(mask, ':') || (strchr(mask, '.') && isdigit(mask[0]))) {
4447 			cil_ipaddr_init(&nodecon->mask);
4448 			rc = cil_fill_ipaddr(parse_current->next->next, nodecon->mask);
4449 			if (rc != SEPOL_OK) {
4450 				goto exit;
4451 			}
4452 		} else {
4453 			nodecon->mask_str = mask;
4454 		}
4455 	}
4456 
4457 	if (parse_current->next->next->next->cl_head == NULL ) {
4458 		nodecon->context_str = parse_current->next->next->next->data;
4459 	} else {
4460 		cil_context_init(&nodecon->context);
4461 
4462 		rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
4463 		if (rc != SEPOL_OK) {
4464 			goto exit;
4465 		}
4466 	}
4467 
4468 	ast_node->data = nodecon;
4469 	ast_node->flavor = CIL_NODECON;
4470 
4471 	return SEPOL_OK;
4472 
4473 exit:
4474 	cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4475 	cil_destroy_nodecon(nodecon);
4476 	return rc;
4477 }
4478 
cil_destroy_nodecon(struct cil_nodecon * nodecon)4479 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4480 {
4481 	if (nodecon == NULL) {
4482 		return;
4483 	}
4484 
4485 	if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4486 		cil_destroy_ipaddr(nodecon->addr);
4487 	}
4488 
4489 	if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4490 		cil_destroy_ipaddr(nodecon->mask);
4491 	}
4492 
4493 	if (nodecon->context_str == NULL && nodecon->context != NULL) {
4494 		cil_destroy_context(nodecon->context);
4495 	}
4496 
4497 	free(nodecon);
4498 }
4499 
cil_gen_genfscon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4500 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4501 {
4502 	enum cil_syntax syntax[] = {
4503 		CIL_SYN_STRING,
4504 		CIL_SYN_STRING,
4505 		CIL_SYN_STRING,
4506 		CIL_SYN_STRING | CIL_SYN_LIST,
4507 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
4508 		CIL_SYN_END
4509 	};
4510 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4511 	struct cil_tree_node *context_node;
4512 	int rc = SEPOL_ERR;
4513 	struct cil_genfscon *genfscon = NULL;
4514 
4515 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4516 		goto exit;
4517 	}
4518 
4519 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4520 	if (rc != SEPOL_OK) {
4521 		goto exit;
4522 	}
4523 
4524 	cil_genfscon_init(&genfscon);
4525 
4526 	genfscon->fs_str = parse_current->next->data;
4527 	genfscon->path_str = parse_current->next->next->data;
4528 
4529 	if (parse_current->next->next->next->next) {
4530 		/* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
4531 		char *file_type = parse_current->next->next->next->data;
4532 		if (file_type == CIL_KEY_ANY) {
4533 			genfscon->file_type = CIL_FILECON_ANY;
4534 		} else if (file_type == CIL_KEY_FILE) {
4535 			genfscon->file_type = CIL_FILECON_FILE;
4536 		} else if (file_type == CIL_KEY_DIR) {
4537 			genfscon->file_type = CIL_FILECON_DIR;
4538 		} else if (file_type == CIL_KEY_CHAR) {
4539 			genfscon->file_type = CIL_FILECON_CHAR;
4540 		} else if (file_type == CIL_KEY_BLOCK) {
4541 			genfscon->file_type = CIL_FILECON_BLOCK;
4542 		} else if (file_type == CIL_KEY_SOCKET) {
4543 			genfscon->file_type = CIL_FILECON_SOCKET;
4544 		} else if (file_type == CIL_KEY_PIPE) {
4545 			genfscon->file_type = CIL_FILECON_PIPE;
4546 		} else if (file_type == CIL_KEY_SYMLINK) {
4547 			genfscon->file_type = CIL_FILECON_SYMLINK;
4548 		} else {
4549 			if (parse_current->next->next->next->cl_head) {
4550 				cil_log(CIL_ERR, "Expecting file type, but found a list\n");
4551 			} else {
4552 				cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type);
4553 			}
4554 			goto exit;
4555 		}
4556 		context_node = parse_current->next->next->next->next;
4557 	} else {
4558 		/* (genfscon <FS_STR> <PATH_STR> ... */
4559 		context_node = parse_current->next->next->next;
4560 	}
4561 
4562 	if (context_node->cl_head) {
4563 		cil_context_init(&genfscon->context);
4564 		rc = cil_fill_context(context_node->cl_head, genfscon->context);
4565 		if (rc != SEPOL_OK) {
4566 			goto exit;
4567 		}
4568 	} else {
4569 		genfscon->context_str = context_node->data;
4570 	}
4571 
4572 	ast_node->data = genfscon;
4573 	ast_node->flavor = CIL_GENFSCON;
4574 
4575 	return SEPOL_OK;
4576 
4577 exit:
4578 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4579 	cil_destroy_genfscon(genfscon);
4580 	return SEPOL_ERR;
4581 }
4582 
cil_destroy_genfscon(struct cil_genfscon * genfscon)4583 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4584 {
4585 	if (genfscon == NULL) {
4586 		return;
4587 	}
4588 
4589 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
4590 		cil_destroy_context(genfscon->context);
4591 	}
4592 
4593 	free(genfscon);
4594 }
4595 
4596 
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4597 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4598 {
4599 	enum cil_syntax syntax[] = {
4600 		CIL_SYN_STRING,
4601 		CIL_SYN_STRING,
4602 		CIL_SYN_STRING | CIL_SYN_LIST,
4603 		CIL_SYN_STRING | CIL_SYN_LIST,
4604 		CIL_SYN_END
4605 	};
4606 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4607 	int rc = SEPOL_ERR;
4608 	struct cil_netifcon *netifcon = NULL;
4609 
4610 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4611 		goto exit;
4612 	}
4613 
4614 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4615 	if (rc != SEPOL_OK) {
4616 		goto exit;
4617 	}
4618 
4619 	cil_netifcon_init(&netifcon);
4620 
4621 	netifcon->interface_str = parse_current->next->data;
4622 
4623 	if (parse_current->next->next->cl_head == NULL) {
4624 		netifcon->if_context_str = parse_current->next->next->data;
4625 	} else {
4626 		cil_context_init(&netifcon->if_context);
4627 
4628 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4629 		if (rc != SEPOL_OK) {
4630 			goto exit;
4631 		}
4632 	}
4633 
4634 	if (parse_current->next->next->next->cl_head == NULL) {
4635 		netifcon->packet_context_str = parse_current->next->next->next->data;
4636 	} else {
4637 		cil_context_init(&netifcon->packet_context);
4638 
4639 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4640 		if (rc != SEPOL_OK) {
4641 			goto exit;
4642 		}
4643 	}
4644 
4645 	ast_node->data = netifcon;
4646 	ast_node->flavor = CIL_NETIFCON;
4647 
4648 	return SEPOL_OK;
4649 
4650 exit:
4651 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4652 	cil_destroy_netifcon(netifcon);
4653 	return SEPOL_ERR;
4654 }
4655 
cil_destroy_netifcon(struct cil_netifcon * netifcon)4656 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4657 {
4658 	if (netifcon == NULL) {
4659 		return;
4660 	}
4661 
4662 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4663 		cil_destroy_context(netifcon->if_context);
4664 	}
4665 
4666 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4667 		cil_destroy_context(netifcon->packet_context);
4668 	}
4669 
4670 	free(netifcon);
4671 }
4672 
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4673 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4674 {
4675 	enum cil_syntax syntax[] = {
4676 		CIL_SYN_STRING,
4677 		CIL_SYN_STRING,
4678 		CIL_SYN_STRING,
4679 		CIL_SYN_STRING | CIL_SYN_LIST,
4680 		CIL_SYN_END
4681 	};
4682 	size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4683 	int rc = SEPOL_ERR;
4684 	struct cil_ibendportcon *ibendportcon = NULL;
4685 
4686 	if (!parse_current || !ast_node)
4687 		goto exit;
4688 
4689 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4690 	if (rc != SEPOL_OK)
4691 		goto exit;
4692 
4693 	cil_ibendportcon_init(&ibendportcon);
4694 
4695 	ibendportcon->dev_name_str = parse_current->next->data;
4696 
4697 	rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4698 	if (rc != SEPOL_OK) {
4699 		cil_log(CIL_ERR, "Improper ibendport port specified\n");
4700 		goto exit;
4701 	}
4702 
4703 	if (!parse_current->next->next->next->cl_head) {
4704 		ibendportcon->context_str = parse_current->next->next->next->data;
4705 	} else {
4706 		cil_context_init(&ibendportcon->context);
4707 
4708 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4709 		if (rc != SEPOL_OK)
4710 			goto exit;
4711 	}
4712 
4713 	ast_node->data = ibendportcon;
4714 	ast_node->flavor = CIL_IBENDPORTCON;
4715 
4716 	return SEPOL_OK;
4717 
4718 exit:
4719 	cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4720 	cil_destroy_ibendportcon(ibendportcon);
4721 	return SEPOL_ERR;
4722 }
4723 
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4724 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4725 {
4726 	if (!ibendportcon)
4727 		return;
4728 
4729 	if (!ibendportcon->context_str && ibendportcon->context)
4730 		cil_destroy_context(ibendportcon->context);
4731 
4732 	free(ibendportcon);
4733 }
4734 
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4735 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4736 {
4737 	enum cil_syntax syntax[] = {
4738 		CIL_SYN_STRING,
4739 		CIL_SYN_STRING,
4740 		CIL_SYN_STRING | CIL_SYN_LIST,
4741 		CIL_SYN_END
4742 	};
4743 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4744 	int rc = SEPOL_ERR;
4745 	struct cil_pirqcon *pirqcon = NULL;
4746 
4747 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4748 		goto exit;
4749 	}
4750 
4751 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4752 	if (rc != SEPOL_OK) {
4753 		goto exit;
4754 	}
4755 
4756 	cil_pirqcon_init(&pirqcon);
4757 
4758 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4759 	if (rc != SEPOL_OK) {
4760 		goto exit;
4761 	}
4762 
4763 	if (parse_current->next->next->cl_head == NULL) {
4764 		pirqcon->context_str = parse_current->next->next->data;
4765 	} else {
4766 		cil_context_init(&pirqcon->context);
4767 
4768 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4769 		if (rc != SEPOL_OK) {
4770 			goto exit;
4771 		}
4772 	}
4773 
4774 	ast_node->data = pirqcon;
4775 	ast_node->flavor = CIL_PIRQCON;
4776 
4777 	return SEPOL_OK;
4778 
4779 exit:
4780 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4781 	cil_destroy_pirqcon(pirqcon);
4782 	return rc;
4783 }
4784 
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4785 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4786 {
4787 	if (pirqcon == NULL) {
4788 		return;
4789 	}
4790 
4791 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4792 		cil_destroy_context(pirqcon->context);
4793 	}
4794 
4795 	free(pirqcon);
4796 }
4797 
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4798 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4799 {
4800 	enum cil_syntax syntax[] = {
4801 		CIL_SYN_STRING,
4802 		CIL_SYN_STRING | CIL_SYN_LIST,
4803 		CIL_SYN_STRING | CIL_SYN_LIST,
4804 		CIL_SYN_END
4805 	};
4806 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4807 	int rc = SEPOL_ERR;
4808 	struct cil_iomemcon *iomemcon = NULL;
4809 
4810 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4811 		goto exit;
4812 	}
4813 
4814 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4815 	if (rc != SEPOL_OK) {
4816 		goto exit;
4817 	}
4818 
4819 	cil_iomemcon_init(&iomemcon);
4820 
4821 	if (parse_current->next->cl_head != NULL) {
4822 		if (parse_current->next->cl_head->next != NULL &&
4823 		    parse_current->next->cl_head->next->next == NULL) {
4824 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4825 			if (rc != SEPOL_OK) {
4826 				cil_log(CIL_ERR, "Improper iomem specified\n");
4827 				goto exit;
4828 			}
4829 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4830 			if (rc != SEPOL_OK) {
4831 				cil_log(CIL_ERR, "Improper iomem specified\n");
4832 				goto exit;
4833 			}
4834 		} else {
4835 			cil_log(CIL_ERR, "Improper iomem range specified\n");
4836 			rc = SEPOL_ERR;
4837 			goto exit;
4838 		}
4839 	} else {
4840 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4841 		if (rc != SEPOL_OK) {
4842 			cil_log(CIL_ERR, "Improper iomem specified\n");
4843 			goto exit;
4844 		}
4845 		iomemcon->iomem_high = iomemcon->iomem_low;
4846 	}
4847 
4848 	if (parse_current->next->next->cl_head == NULL ) {
4849 		iomemcon->context_str = parse_current->next->next->data;
4850 	} else {
4851 		cil_context_init(&iomemcon->context);
4852 
4853 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4854 		if (rc != SEPOL_OK) {
4855 			goto exit;
4856 		}
4857 	}
4858 
4859 	ast_node->data = iomemcon;
4860 	ast_node->flavor = CIL_IOMEMCON;
4861 
4862 	return SEPOL_OK;
4863 
4864 exit:
4865 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4866 	cil_destroy_iomemcon(iomemcon);
4867 	return rc;
4868 }
4869 
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4870 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4871 {
4872 	if (iomemcon == NULL) {
4873 		return;
4874 	}
4875 
4876 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4877 		cil_destroy_context(iomemcon->context);
4878 	}
4879 
4880 	free(iomemcon);
4881 }
4882 
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4883 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4884 {
4885 	enum cil_syntax syntax[] = {
4886 		CIL_SYN_STRING,
4887 		CIL_SYN_STRING | CIL_SYN_LIST,
4888 		CIL_SYN_STRING | CIL_SYN_LIST,
4889 		CIL_SYN_END
4890 	};
4891 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4892 	int rc = SEPOL_ERR;
4893 	struct cil_ioportcon *ioportcon = NULL;
4894 
4895 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4896 		goto exit;
4897 	}
4898 
4899 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4900 	if (rc != SEPOL_OK) {
4901 		goto exit;
4902 	}
4903 
4904 	cil_ioportcon_init(&ioportcon);
4905 
4906 	if (parse_current->next->cl_head != NULL) {
4907 		if (parse_current->next->cl_head->next != NULL &&
4908 		    parse_current->next->cl_head->next->next == NULL) {
4909 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4910 			if (rc != SEPOL_OK) {
4911 				cil_log(CIL_ERR, "Improper ioport specified\n");
4912 				goto exit;
4913 			}
4914 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4915 			if (rc != SEPOL_OK) {
4916 				cil_log(CIL_ERR, "Improper ioport specified\n");
4917 				goto exit;
4918 			}
4919 		} else {
4920 			cil_log(CIL_ERR, "Improper ioport range specified\n");
4921 			rc = SEPOL_ERR;
4922 			goto exit;
4923 		}
4924 	} else {
4925 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4926 		if (rc != SEPOL_OK) {
4927 			cil_log(CIL_ERR, "Improper ioport specified\n");
4928 			goto exit;
4929 		}
4930 		ioportcon->ioport_high = ioportcon->ioport_low;
4931 	}
4932 
4933 	if (parse_current->next->next->cl_head == NULL ) {
4934 		ioportcon->context_str = parse_current->next->next->data;
4935 	} else {
4936 		cil_context_init(&ioportcon->context);
4937 
4938 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
4939 		if (rc != SEPOL_OK) {
4940 			goto exit;
4941 		}
4942 	}
4943 
4944 	ast_node->data = ioportcon;
4945 	ast_node->flavor = CIL_IOPORTCON;
4946 
4947 	return SEPOL_OK;
4948 
4949 exit:
4950 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
4951 	cil_destroy_ioportcon(ioportcon);
4952 	return rc;
4953 }
4954 
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)4955 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
4956 {
4957 	if (ioportcon == NULL) {
4958 		return;
4959 	}
4960 
4961 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
4962 		cil_destroy_context(ioportcon->context);
4963 	}
4964 
4965 	free(ioportcon);
4966 }
4967 
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4968 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4969 {
4970 	enum cil_syntax syntax[] = {
4971 		CIL_SYN_STRING,
4972 		CIL_SYN_STRING,
4973 		CIL_SYN_STRING | CIL_SYN_LIST,
4974 		CIL_SYN_END
4975 	};
4976 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4977 	int rc = SEPOL_ERR;
4978 	struct cil_pcidevicecon *pcidevicecon = NULL;
4979 
4980 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4981 		goto exit;
4982 	}
4983 
4984 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4985 	if (rc != SEPOL_OK) {
4986 		goto exit;
4987 	}
4988 
4989 	cil_pcidevicecon_init(&pcidevicecon);
4990 
4991 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
4992 	if (rc != SEPOL_OK) {
4993 		goto exit;
4994 	}
4995 
4996 	if (parse_current->next->next->cl_head == NULL) {
4997 		pcidevicecon->context_str = parse_current->next->next->data;
4998 	} else {
4999 		cil_context_init(&pcidevicecon->context);
5000 
5001 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5002 		if (rc != SEPOL_OK) {
5003 			goto exit;
5004 		}
5005 	}
5006 
5007 	ast_node->data = pcidevicecon;
5008 	ast_node->flavor = CIL_PCIDEVICECON;
5009 
5010 	return SEPOL_OK;
5011 
5012 exit:
5013 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5014 	cil_destroy_pcidevicecon(pcidevicecon);
5015 	return rc;
5016 }
5017 
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5018 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5019 {
5020 	if (pcidevicecon == NULL) {
5021 		return;
5022 	}
5023 
5024 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5025 		cil_destroy_context(pcidevicecon->context);
5026 	}
5027 
5028 	free(pcidevicecon);
5029 }
5030 
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5031 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5032 {
5033 	enum cil_syntax syntax[] = {
5034 		CIL_SYN_STRING,
5035 		CIL_SYN_STRING,
5036 		CIL_SYN_STRING | CIL_SYN_LIST,
5037 		CIL_SYN_END
5038 	};
5039 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5040 	int rc = SEPOL_ERR;
5041 	struct cil_devicetreecon *devicetreecon = NULL;
5042 
5043 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5044 		goto exit;
5045 	}
5046 
5047 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5048 	if (rc != SEPOL_OK) {
5049 		goto exit;
5050 	}
5051 
5052 	cil_devicetreecon_init(&devicetreecon);
5053 
5054 	devicetreecon->path = parse_current->next->data;
5055 
5056 	if (parse_current->next->next->cl_head == NULL) {
5057 		devicetreecon->context_str = parse_current->next->next->data;
5058 	} else {
5059 		cil_context_init(&devicetreecon->context);
5060 
5061 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5062 		if (rc != SEPOL_OK) {
5063 			goto exit;
5064 		}
5065 	}
5066 
5067 	ast_node->data = devicetreecon;
5068 	ast_node->flavor = CIL_DEVICETREECON;
5069 
5070 	return SEPOL_OK;
5071 
5072 exit:
5073 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5074 	cil_destroy_devicetreecon(devicetreecon);
5075 	return rc;
5076 }
5077 
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5078 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5079 {
5080 	if (devicetreecon == NULL) {
5081 		return;
5082 	}
5083 
5084 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5085 		cil_destroy_context(devicetreecon->context);
5086 	}
5087 
5088 	free(devicetreecon);
5089 }
5090 
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5091 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5092 {
5093 	enum cil_syntax syntax[] = {
5094 		CIL_SYN_STRING,
5095 		CIL_SYN_STRING,
5096 		CIL_SYN_STRING,
5097 		CIL_SYN_STRING | CIL_SYN_LIST,
5098 		CIL_SYN_END
5099 	};
5100 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5101 	char *type = NULL;
5102 	struct cil_fsuse *fsuse = NULL;
5103 	int rc = SEPOL_ERR;
5104 
5105 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5106 		goto exit;
5107 	}
5108 
5109 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5110 	if (rc != SEPOL_OK) {
5111 		goto exit;
5112 	}
5113 
5114 	type = parse_current->next->data;
5115 
5116 	cil_fsuse_init(&fsuse);
5117 
5118 	if (type == CIL_KEY_XATTR) {
5119 		fsuse->type = CIL_FSUSE_XATTR;
5120 	} else if (type == CIL_KEY_TASK) {
5121 		fsuse->type = CIL_FSUSE_TASK;
5122 	} else if (type == CIL_KEY_TRANS) {
5123 		fsuse->type = CIL_FSUSE_TRANS;
5124 	} else {
5125 		cil_log(CIL_ERR, "Invalid fsuse type\n");
5126 		goto exit;
5127 	}
5128 
5129 	fsuse->fs_str = parse_current->next->next->data;
5130 
5131 	if (parse_current->next->next->next->cl_head == NULL) {
5132 		fsuse->context_str = parse_current->next->next->next->data;
5133 	} else {
5134 		cil_context_init(&fsuse->context);
5135 
5136 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5137 		if (rc != SEPOL_OK) {
5138 			goto exit;
5139 		}
5140 	}
5141 
5142 	ast_node->data = fsuse;
5143 	ast_node->flavor = CIL_FSUSE;
5144 
5145 	return SEPOL_OK;
5146 
5147 exit:
5148 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5149 	cil_destroy_fsuse(fsuse);
5150 	return SEPOL_ERR;
5151 }
5152 
cil_destroy_fsuse(struct cil_fsuse * fsuse)5153 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5154 {
5155 	if (fsuse == NULL) {
5156 		return;
5157 	}
5158 
5159 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
5160 		cil_destroy_context(fsuse->context);
5161 	}
5162 
5163 	free(fsuse);
5164 }
5165 
cil_destroy_param(struct cil_param * param)5166 void cil_destroy_param(struct cil_param *param)
5167 {
5168 	if (param == NULL) {
5169 		return;
5170 	}
5171 
5172 	free(param);
5173 }
5174 
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5175 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5176 {
5177 	int rc = SEPOL_ERR;
5178 	char *key = NULL;
5179 	struct cil_macro *macro = NULL;
5180 	struct cil_tree_node *macro_content = NULL;
5181 	struct cil_tree_node *current_item;
5182 	enum cil_syntax syntax[] = {
5183 		CIL_SYN_STRING,
5184 		CIL_SYN_STRING,
5185 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5186 		CIL_SYN_N_LISTS | CIL_SYN_END,
5187 		CIL_SYN_END
5188 	};
5189 	size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
5190 
5191 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5192 		goto exit;
5193 	}
5194 
5195 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5196 	if (rc != SEPOL_OK) {
5197 		goto exit;
5198 	}
5199 
5200 	cil_macro_init(&macro);
5201 
5202 	key = parse_current->next->data;
5203 
5204 	current_item = parse_current->next->next->cl_head;
5205 	while (current_item != NULL) {
5206 		enum cil_syntax param_syntax[] = {
5207 			CIL_SYN_STRING,
5208 			CIL_SYN_STRING,
5209 			CIL_SYN_END
5210 		};
5211 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5212 		char *kind = NULL;
5213 		struct cil_param *param = NULL;
5214 		struct cil_list_item *curr_param;
5215 
5216 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5217 		if (rc != SEPOL_OK) {
5218 			goto exit;
5219 		}
5220 
5221 		if (macro->params == NULL) {
5222 			cil_list_init(&macro->params, CIL_LIST_ITEM);
5223 		}
5224 
5225 		kind = current_item->cl_head->data;
5226 		cil_param_init(&param);
5227 
5228 		if (kind == CIL_KEY_TYPE) {
5229 			param->flavor = CIL_TYPE;
5230 		} else if (kind == CIL_KEY_ROLE) {
5231 			param->flavor = CIL_ROLE;
5232 		} else if (kind == CIL_KEY_USER) {
5233 			param->flavor = CIL_USER;
5234 		} else if (kind == CIL_KEY_SENSITIVITY) {
5235 			param->flavor = CIL_SENS;
5236 		} else if (kind == CIL_KEY_CATEGORY) {
5237 			param->flavor = CIL_CAT;
5238 		} else if (kind == CIL_KEY_CATSET) {
5239 			param->flavor = CIL_CATSET;
5240 		} else if (kind == CIL_KEY_LEVEL) {
5241 			param->flavor = CIL_LEVEL;
5242 		} else if (kind == CIL_KEY_LEVELRANGE) {
5243 			param->flavor = CIL_LEVELRANGE;
5244 		} else if (kind == CIL_KEY_CLASS) {
5245 			param->flavor = CIL_CLASS;
5246 		} else if (kind == CIL_KEY_IPADDR) {
5247 			param->flavor = CIL_IPADDR;
5248 		} else if (kind == CIL_KEY_MAP_CLASS) {
5249 			param->flavor = CIL_MAP_CLASS;
5250 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
5251 			param->flavor = CIL_CLASSPERMISSION;
5252 		} else if (kind == CIL_KEY_BOOL) {
5253 			param->flavor = CIL_BOOL;
5254 		} else if (kind == CIL_KEY_STRING) {
5255 			param->flavor = CIL_DECLARED_STRING;
5256 		} else if (kind == CIL_KEY_NAME) {
5257 			param->flavor = CIL_DECLARED_STRING;
5258 		} else {
5259 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5260 			cil_destroy_param(param);
5261 			goto exit;
5262 		}
5263 
5264 		param->str =  current_item->cl_head->next->data;
5265 
5266 		rc = cil_verify_name(db, param->str, param->flavor);
5267 		if (rc != SEPOL_OK) {
5268 			cil_destroy_param(param);
5269 			goto exit;
5270 		}
5271 
5272 		//walk current list and check for duplicate parameters
5273 		cil_list_for_each(curr_param, macro->params) {
5274 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
5275 				cil_log(CIL_ERR, "Duplicate parameter\n");
5276 				cil_destroy_param(param);
5277 				goto exit;
5278 			}
5279 		}
5280 
5281 		cil_list_append(macro->params, CIL_PARAM, param);
5282 
5283 		current_item = current_item->next;
5284 	}
5285 
5286 	/* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the
5287            node containing the macro name is updated to point to the start of the macro content */
5288 	macro_content = parse_current->next->next->next;
5289 	cil_tree_subtree_destroy(parse_current->next->next);
5290 	parse_current->next->next = macro_content;
5291 	if (macro_content == NULL) {
5292 		/* No statements in macro and macro parameter list was last node */
5293 		parse_current->parent->cl_tail = parse_current->next;
5294 	}
5295 
5296 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5297 	if (rc != SEPOL_OK) {
5298 		goto exit;
5299 	}
5300 
5301 	return SEPOL_OK;
5302 
5303 exit:
5304 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5305 	cil_destroy_macro(macro);
5306 	cil_clear_node(ast_node);
5307 	return SEPOL_ERR;
5308 }
5309 
cil_destroy_macro(struct cil_macro * macro)5310 void cil_destroy_macro(struct cil_macro *macro)
5311 {
5312 	if (macro == NULL) {
5313 		return;
5314 	}
5315 
5316 	cil_symtab_datum_destroy(&macro->datum);
5317 	cil_symtab_array_destroy(macro->symtab);
5318 
5319 	if (macro->params != NULL) {
5320 		cil_list_destroy(&macro->params, 1);
5321 	}
5322 
5323 	free(macro);
5324 }
5325 
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5326 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5327 {
5328 	enum cil_syntax syntax[] = {
5329 		CIL_SYN_STRING,
5330 		CIL_SYN_STRING,
5331 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5332 		CIL_SYN_END
5333 	};
5334 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5335 	struct cil_call *call = NULL;
5336 	int rc = SEPOL_ERR;
5337 
5338 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5339 		goto exit;
5340 	}
5341 
5342 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5343 	if (rc != SEPOL_OK) {
5344 		goto exit;
5345 	}
5346 
5347 	cil_call_init(&call);
5348 
5349 	call->macro_str = parse_current->next->data;
5350 
5351 	if (parse_current->next->next != NULL) {
5352 		cil_tree_init(&call->args_tree);
5353 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5354 	}
5355 
5356 	ast_node->data = call;
5357 	ast_node->flavor = CIL_CALL;
5358 
5359 	return SEPOL_OK;
5360 
5361 exit:
5362 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5363 	cil_destroy_call(call);
5364 	return rc;
5365 }
5366 
cil_destroy_call(struct cil_call * call)5367 void cil_destroy_call(struct cil_call *call)
5368 {
5369 	if (call == NULL) {
5370 		return;
5371 	}
5372 
5373 	call->macro = NULL;
5374 
5375 	if (call->args_tree != NULL) {
5376 		cil_tree_destroy(&call->args_tree);
5377 	}
5378 
5379 	if (call->args != NULL) {
5380 		cil_list_destroy(&call->args, 1);
5381 	}
5382 
5383 	free(call);
5384 }
5385 
cil_destroy_args(struct cil_args * args)5386 void cil_destroy_args(struct cil_args *args)
5387 {
5388 	if (args == NULL) {
5389 		return;
5390 	}
5391 
5392 	if (args->arg_str != NULL) {
5393 		args->arg_str = NULL;
5394 	} else if (args->arg != NULL) {
5395 		struct cil_tree_node *node = args->arg->nodes->head->data;
5396 		switch (args->flavor) {
5397 		case CIL_DECLARED_STRING:
5398 			break;
5399 		case CIL_CATSET:
5400 			cil_destroy_catset((struct cil_catset *)args->arg);
5401 			free(node);
5402 			break;
5403 		case CIL_LEVEL:
5404 			cil_destroy_level((struct cil_level *)args->arg);
5405 			free(node);
5406 			break;
5407 		case CIL_LEVELRANGE:
5408 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5409 			free(node);
5410 			break;
5411 		case CIL_IPADDR:
5412 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5413 			free(node);
5414 			break;
5415 		case CIL_CLASSPERMISSION:
5416 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5417 			free(node);
5418 			break;
5419 		default:
5420 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5421 			break;
5422 		}
5423 	}
5424 
5425 	args->param_str = NULL;
5426 	args->arg = NULL;
5427 
5428 	free(args);
5429 }
5430 
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5431 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5432 {
5433 	enum cil_syntax syntax[] = {
5434 		CIL_SYN_STRING,
5435 		CIL_SYN_STRING,
5436 		CIL_SYN_N_LISTS | CIL_SYN_END,
5437 		CIL_SYN_END
5438 	};
5439 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5440 	char *key = NULL;
5441 	struct cil_optional *optional = NULL;
5442 	int rc = SEPOL_ERR;
5443 
5444 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5445 		goto exit;
5446 	}
5447 
5448 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5449 	if (rc != SEPOL_OK) {
5450 		goto exit;
5451 	}
5452 
5453 	cil_optional_init(&optional);
5454 
5455 	key = parse_current->next->data;
5456 
5457 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5458 	if (rc != SEPOL_OK) {
5459 		if (rc == SEPOL_EEXIST) {
5460 			cil_destroy_optional(optional);
5461 			optional = NULL;
5462 		} else {
5463 			goto exit;
5464 		}
5465 	}
5466 
5467 	return SEPOL_OK;
5468 
5469 exit:
5470 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5471 	cil_destroy_optional(optional);
5472 	cil_clear_node(ast_node);
5473 	return rc;
5474 }
5475 
cil_destroy_optional(struct cil_optional * optional)5476 void cil_destroy_optional(struct cil_optional *optional)
5477 {
5478 	if (optional == NULL) {
5479 		return;
5480 	}
5481 
5482 	cil_symtab_datum_destroy(&optional->datum);
5483 	free(optional);
5484 }
5485 
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5486 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5487 {
5488 	enum cil_syntax syntax[] = {
5489 		CIL_SYN_STRING,
5490 		CIL_SYN_STRING,
5491 		CIL_SYN_END
5492 	};
5493 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5494 	char *key = NULL;
5495 	struct cil_policycap *polcap = NULL;
5496 	int rc = SEPOL_ERR;
5497 
5498 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5499 		goto exit;
5500 	}
5501 
5502 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5503 	if (rc != SEPOL_OK) {
5504 		goto exit;
5505 	}
5506 
5507 	cil_policycap_init(&polcap);
5508 
5509 	key = parse_current->next->data;
5510 
5511 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5512 	if (rc != SEPOL_OK)
5513 		goto exit;
5514 
5515 	return SEPOL_OK;
5516 
5517 exit:
5518 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5519 	cil_destroy_policycap(polcap);
5520 	cil_clear_node(ast_node);
5521 	return rc;
5522 }
5523 
cil_destroy_policycap(struct cil_policycap * polcap)5524 void cil_destroy_policycap(struct cil_policycap *polcap)
5525 {
5526 	if (polcap == NULL) {
5527 		return;
5528 	}
5529 
5530 	cil_symtab_datum_destroy(&polcap->datum);
5531 	free(polcap);
5532 }
5533 
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5534 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5535 {
5536 	enum cil_syntax syntax[] = {
5537 		CIL_SYN_STRING,
5538 		CIL_SYN_STRING,
5539 		CIL_SYN_STRING,
5540 		CIL_SYN_END
5541 	};
5542 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5543 	char *key = NULL;
5544 	struct cil_ipaddr *ipaddr = NULL;
5545 	int rc = SEPOL_ERR;
5546 
5547 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5548 		goto exit;
5549 	}
5550 
5551 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5552 	if (rc != SEPOL_OK) {
5553 		goto exit;
5554 	}
5555 
5556 	cil_ipaddr_init(&ipaddr);
5557 
5558 	key  = parse_current->next->data;
5559 
5560 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5561 	if (rc != SEPOL_OK) {
5562 		goto exit;
5563 	}
5564 
5565 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5566 	if (rc != SEPOL_OK) {
5567 		goto exit;
5568 	}
5569 
5570 	return SEPOL_OK;
5571 
5572 exit:
5573 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5574 	cil_destroy_ipaddr(ipaddr);
5575 	cil_clear_node(ast_node);
5576 	return rc;
5577 }
5578 
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5579 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5580 {
5581 	if (ipaddr == NULL) {
5582 		return;
5583 	}
5584 
5585 	cil_symtab_datum_destroy(&ipaddr->datum);
5586 	free(ipaddr);
5587 }
5588 
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5589 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5590 {
5591 	int rc = SEPOL_ERR;
5592 
5593 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5594 		goto exit;
5595 	}
5596 
5597 	rc = cil_string_to_uint32(int_node->data, integer, base);
5598 	if (rc != SEPOL_OK) {
5599 		goto exit;
5600 	}
5601 
5602 	return SEPOL_OK;
5603 
5604 exit:
5605 	cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5606 	return rc;
5607 }
5608 
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5609 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5610 {
5611 	int rc = SEPOL_ERR;
5612 
5613 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5614 		goto exit;
5615 	}
5616 
5617 	rc = cil_string_to_uint64(int_node->data, integer, base);
5618 	if (rc != SEPOL_OK) {
5619 		goto exit;
5620 	}
5621 
5622 	return SEPOL_OK;
5623 
5624 exit:
5625 	cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5626 	return rc;
5627 }
5628 
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5629 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5630 {
5631 	int rc = SEPOL_ERR;
5632 	char *addr_str;
5633 
5634 	if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5635 		goto exit;
5636 	}
5637 
5638 	addr_str = addr_node->data;
5639 	if (strchr(addr_str, ':')) {
5640 		addr->family = AF_INET6;
5641 	} else if (strchr(addr_str, '.') && isdigit(addr_str[0])) {
5642 		addr->family = AF_INET;
5643 	} else {
5644 		goto exit;
5645 	}
5646 
5647 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5648 	if (rc != 1) {
5649 		rc = SEPOL_ERR;
5650 		goto exit;
5651 	}
5652 
5653 	return SEPOL_OK;
5654 
5655 exit:
5656 	cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "NULL");
5657 	return rc;
5658 }
5659 
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5660 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5661 {
5662 	int rc = SEPOL_ERR;
5663 	enum cil_syntax syntax[] = {
5664 		CIL_SYN_STRING,
5665 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5666 		CIL_SYN_END
5667 	};
5668 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5669 
5670 	if (curr == NULL) {
5671 		goto exit;
5672 	}
5673 
5674 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
5675 	if (rc != SEPOL_OK) {
5676 		goto exit;
5677 	}
5678 
5679 	level->sens_str = curr->data;
5680 	if (curr->next != NULL) {
5681 		rc = cil_fill_cats(curr->next, &level->cats);
5682 		if (rc != SEPOL_OK) {
5683 			goto exit;
5684 		}
5685 	}
5686 
5687 	return SEPOL_OK;
5688 
5689 exit:
5690 	cil_log(CIL_ERR, "Bad level\n");
5691 	return rc;
5692 }
5693 
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5694 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5695 {
5696 	int rc = SEPOL_ERR;
5697 
5698 	cil_cats_init(cats);
5699 
5700 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5701 	if (rc != SEPOL_OK) {
5702 		cil_destroy_cats(*cats);
5703 		*cats = NULL;
5704 	}
5705 
5706 	return rc;
5707 }
5708 
cil_destroy_cats(struct cil_cats * cats)5709 void cil_destroy_cats(struct cil_cats *cats)
5710 {
5711 	if (cats == NULL) {
5712 		return;
5713 	}
5714 
5715 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
5716 
5717 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5718 
5719 	free(cats);
5720 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5721 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5722 {
5723 	enum cil_syntax syntax[] = {
5724 		CIL_SYN_STRING,
5725 		CIL_SYN_STRING,
5726 		CIL_SYN_STRING,
5727 		CIL_SYN_END
5728 	};
5729 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5730 	struct cil_bounds *bounds = NULL;
5731 	int rc = SEPOL_ERR;
5732 
5733 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5734 		goto exit;
5735 	}
5736 
5737 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5738 	if (rc != SEPOL_OK) {
5739 		goto exit;
5740 	}
5741 
5742 	cil_bounds_init(&bounds);
5743 
5744 	bounds->parent_str = parse_current->next->data;
5745 	bounds->child_str = parse_current->next->next->data;
5746 
5747 	ast_node->data = bounds;
5748 
5749 	switch (flavor) {
5750 	case CIL_USER:
5751 		ast_node->flavor = CIL_USERBOUNDS;
5752 		break;
5753 	case CIL_ROLE:
5754 		ast_node->flavor = CIL_ROLEBOUNDS;
5755 		break;
5756 	case CIL_TYPE:
5757 		ast_node->flavor = CIL_TYPEBOUNDS;
5758 		break;
5759 	default:
5760 		break;
5761 	}
5762 
5763 	return SEPOL_OK;
5764 
5765 exit:
5766 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5767 	cil_destroy_bounds(bounds);
5768 	return rc;
5769 }
5770 
cil_destroy_bounds(struct cil_bounds * bounds)5771 void cil_destroy_bounds(struct cil_bounds *bounds)
5772 {
5773 	if (bounds == NULL) {
5774 		return;
5775 	}
5776 
5777 	free(bounds);
5778 }
5779 
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5780 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5781 {
5782 	int rc = SEPOL_ERR;
5783 	struct cil_default *def = NULL;
5784 	char *object;
5785 	enum cil_syntax syntax[] = {
5786 		CIL_SYN_STRING,
5787 		CIL_SYN_STRING | CIL_SYN_LIST,
5788 		CIL_SYN_STRING,
5789 		CIL_SYN_END
5790 	};
5791 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5792 
5793 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5794 	if (rc != SEPOL_OK) {
5795 		goto exit;
5796 	}
5797 
5798 	cil_default_init(&def);
5799 
5800 	def->flavor = flavor;
5801 
5802 	if (parse_current->next->cl_head == NULL) {
5803 		cil_list_init(&def->class_strs, CIL_CLASS);
5804 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5805 	} else {
5806 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5807 		if (rc != SEPOL_OK) {
5808 			goto exit;
5809 		}
5810 	}
5811 
5812 	object = parse_current->next->next->data;
5813 	if (object == CIL_KEY_SOURCE) {
5814 		def->object = CIL_DEFAULT_SOURCE;
5815 	} else if (object == CIL_KEY_TARGET) {
5816 		def->object = CIL_DEFAULT_TARGET;
5817 	} else {
5818 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5819 		rc = SEPOL_ERR;
5820 		goto exit;
5821 	}
5822 
5823 	ast_node->data = def;
5824 	ast_node->flavor = flavor;
5825 
5826 	return SEPOL_OK;
5827 
5828 exit:
5829 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5830 	cil_destroy_default(def);
5831 	return rc;
5832 }
5833 
cil_destroy_default(struct cil_default * def)5834 void cil_destroy_default(struct cil_default *def)
5835 {
5836 	if (def == NULL) {
5837 		return;
5838 	}
5839 
5840 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5841 
5842 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5843 
5844 	free(def);
5845 }
5846 
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5847 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5848 {
5849 	int rc = SEPOL_ERR;
5850 	struct cil_defaultrange *def = NULL;
5851 	char *object;
5852 	char *range;
5853 	enum cil_syntax syntax[] = {
5854 		CIL_SYN_STRING,
5855 		CIL_SYN_STRING | CIL_SYN_LIST,
5856 		CIL_SYN_STRING,
5857 		CIL_SYN_STRING | CIL_SYN_END,
5858 		CIL_SYN_END
5859 	};
5860 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5861 
5862 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5863 	if (rc != SEPOL_OK) {
5864 		goto exit;
5865 	}
5866 
5867 	cil_defaultrange_init(&def);
5868 
5869 	if (parse_current->next->cl_head == NULL) {
5870 		cil_list_init(&def->class_strs, CIL_CLASS);
5871 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5872 	} else {
5873 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5874 		if (rc != SEPOL_OK) {
5875 			goto exit;
5876 		}
5877 	}
5878 
5879 	object = parse_current->next->next->data;
5880 	if (object == CIL_KEY_SOURCE) {
5881 		if (!parse_current->next->next->next) {
5882 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5883 			rc = SEPOL_ERR;
5884 			goto exit;
5885 		}
5886 		range = parse_current->next->next->next->data;
5887 		if (range == CIL_KEY_LOW) {
5888 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
5889 		} else if (range == CIL_KEY_HIGH) {
5890 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5891 		} else if (range == CIL_KEY_LOW_HIGH) {
5892 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5893 		} else {
5894 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5895 			rc = SEPOL_ERR;
5896 			goto exit;
5897 		}
5898 	} else if (object == CIL_KEY_TARGET) {
5899 		if (!parse_current->next->next->next) {
5900 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5901 			rc = SEPOL_ERR;
5902 			goto exit;
5903 		}
5904 		range = parse_current->next->next->next->data;
5905 		if (range == CIL_KEY_LOW) {
5906 			def->object_range = CIL_DEFAULT_TARGET_LOW;
5907 		} else if (range == CIL_KEY_HIGH) {
5908 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
5909 		} else if (range == CIL_KEY_LOW_HIGH) {
5910 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5911 		} else {
5912 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5913 			rc = SEPOL_ERR;
5914 			goto exit;
5915 		}
5916 	} else if (object == CIL_KEY_GLBLUB) {
5917 		def->object_range = CIL_DEFAULT_GLBLUB;
5918 	} else {
5919 		cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n");
5920 		rc = SEPOL_ERR;
5921 		goto exit;
5922 	}
5923 
5924 	ast_node->data = def;
5925 	ast_node->flavor = CIL_DEFAULTRANGE;
5926 
5927 	return SEPOL_OK;
5928 
5929 exit:
5930 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5931 	cil_destroy_defaultrange(def);
5932 	return rc;
5933 }
5934 
cil_destroy_defaultrange(struct cil_defaultrange * def)5935 void cil_destroy_defaultrange(struct cil_defaultrange *def)
5936 {
5937 	if (def == NULL) {
5938 		return;
5939 	}
5940 
5941 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5942 
5943 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5944 
5945 	free(def);
5946 }
5947 
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5948 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5949 {
5950 	int rc = SEPOL_ERR;
5951 	enum cil_syntax syntax[] = {
5952 		CIL_SYN_STRING,
5953 		CIL_SYN_STRING,
5954 		CIL_SYN_END
5955 	};
5956 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5957 	struct cil_handleunknown *unknown = NULL;
5958 	char *unknown_key;
5959 
5960 	if (parse_current == NULL || ast_node == NULL) {
5961 		goto exit;
5962 	}
5963 
5964 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5965 	if (rc != SEPOL_OK) {
5966 		goto exit;
5967 	}
5968 
5969 	cil_handleunknown_init(&unknown);
5970 
5971 	unknown_key = parse_current->next->data;
5972 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
5973 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
5974 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
5975 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
5976 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
5977 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
5978 	} else {
5979 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
5980 		rc = SEPOL_ERR;
5981 		goto exit;
5982 	}
5983 
5984 	ast_node->data = unknown;
5985 	ast_node->flavor = CIL_HANDLEUNKNOWN;
5986 
5987 	return SEPOL_OK;
5988 
5989 exit:
5990 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
5991 	cil_destroy_handleunknown(unknown);
5992 	return rc;
5993 }
5994 
cil_destroy_handleunknown(struct cil_handleunknown * unk)5995 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
5996 {
5997 	free(unk);
5998 }
5999 
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6000 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6001 {
6002 	int rc = SEPOL_ERR;
6003 	enum cil_syntax syntax[] = {
6004 		CIL_SYN_STRING,
6005 		CIL_SYN_STRING,
6006 		CIL_SYN_END
6007 	};
6008 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6009 	struct cil_mls *mls = NULL;
6010 
6011 	if (parse_current == NULL || ast_node == NULL) {
6012 		goto exit;
6013 	}
6014 
6015 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6016 	if (rc != SEPOL_OK) {
6017 		goto exit;
6018 	}
6019 
6020 	cil_mls_init(&mls);
6021 
6022 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6023 		mls->value = CIL_TRUE;
6024 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6025 		mls->value = CIL_FALSE;
6026 	} else {
6027 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6028 		rc = SEPOL_ERR;
6029 		goto exit;
6030 	}
6031 
6032 	ast_node->data = mls;
6033 	ast_node->flavor = CIL_MLS;
6034 
6035 	return SEPOL_OK;
6036 
6037 exit:
6038 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6039 	cil_destroy_mls(mls);
6040 	return rc;
6041 }
6042 
cil_destroy_mls(struct cil_mls * mls)6043 void cil_destroy_mls(struct cil_mls *mls)
6044 {
6045 	free(mls);
6046 }
6047 
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6048 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6049 {
6050 	int rc = SEPOL_ERR;
6051 	enum cil_syntax syntax[] = {
6052 		CIL_SYN_STRING,
6053 		CIL_SYN_STRING,
6054 		CIL_SYN_STRING,
6055 		CIL_SYN_STRING,
6056 		CIL_SYN_N_LISTS | CIL_SYN_END,
6057 		CIL_SYN_END
6058 	};
6059 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6060 	struct cil_src_info *info = NULL;
6061 
6062 	if (parse_current == NULL || ast_node == NULL) {
6063 		goto exit;
6064 	}
6065 
6066 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6067 	if (rc != SEPOL_OK) {
6068 		goto exit;
6069 	}
6070 
6071 	cil_src_info_init(&info);
6072 
6073 	info->kind = parse_current->next->data;
6074 	if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
6075 		cil_log(CIL_ERR, "Invalid src info kind\n");
6076 		rc = SEPOL_ERR;
6077 		goto exit;
6078 	}
6079 
6080 	rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
6081 	if (rc != SEPOL_OK) {
6082 		goto exit;
6083 	}
6084 
6085 	info->path = parse_current->next->next->next->data;
6086 
6087 	ast_node->data = info;
6088 	ast_node->flavor = CIL_SRC_INFO;
6089 
6090 	return SEPOL_OK;
6091 
6092 exit:
6093 	cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6094 	cil_destroy_src_info(info);
6095 	return rc;
6096 }
6097 
cil_destroy_src_info(struct cil_src_info * info)6098 void cil_destroy_src_info(struct cil_src_info *info)
6099 {
6100 	free(info);
6101 }
6102 
check_for_illegal_statement(struct cil_tree_node * parse_current,struct cil_args_build * args)6103 static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
6104 {
6105 	if (args->tunif != NULL) {
6106 		if (parse_current->data == CIL_KEY_TUNABLE) {
6107 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
6108 			return SEPOL_ERR;
6109 		}
6110 	}
6111 
6112 	if (args->in != NULL) {
6113 		struct cil_in *in_block = args->in->data;
6114 		if (parse_current->data == CIL_KEY_TUNABLE ||
6115 			parse_current->data == CIL_KEY_IN) {
6116 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
6117 			return SEPOL_ERR;
6118 		}
6119 		if (in_block->is_after == CIL_TRUE) {
6120 			if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6121 				parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6122 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
6123 				return SEPOL_ERR;
6124 			}
6125 		}
6126 	}
6127 
6128 	if (args->macro != NULL) {
6129 		if (parse_current->data == CIL_KEY_TUNABLE ||
6130 			parse_current->data == CIL_KEY_IN ||
6131 			parse_current->data == CIL_KEY_BLOCK ||
6132 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
6133 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6134 			parse_current->data == CIL_KEY_MACRO) {
6135 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
6136 			return SEPOL_ERR;
6137 		}
6138 	}
6139 
6140 	if (args->optional != NULL) {
6141 		if (parse_current->data == CIL_KEY_TUNABLE ||
6142 			parse_current->data == CIL_KEY_IN ||
6143 			parse_current->data == CIL_KEY_BLOCK ||
6144 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6145 			parse_current->data == CIL_KEY_MACRO) {
6146 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
6147 			return SEPOL_ERR;
6148 		}
6149 	}
6150 
6151 	if (args->boolif != NULL) {
6152 		if (parse_current->data != CIL_KEY_TUNABLEIF &&
6153 			parse_current->data != CIL_KEY_CALL &&
6154 			parse_current->data != CIL_KEY_CONDTRUE &&
6155 			parse_current->data != CIL_KEY_CONDFALSE &&
6156 			parse_current->data != CIL_KEY_ALLOW &&
6157 			parse_current->data != CIL_KEY_DONTAUDIT &&
6158 			parse_current->data != CIL_KEY_AUDITALLOW &&
6159 			parse_current->data != CIL_KEY_TYPETRANSITION &&
6160 			parse_current->data != CIL_KEY_TYPECHANGE &&
6161 			parse_current->data != CIL_KEY_TYPEMEMBER) {
6162 			if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
6163 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
6164 			} else {
6165 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
6166 			}
6167 			return SEPOL_ERR;
6168 		}
6169 	}
6170 
6171 	return SEPOL_OK;
6172 }
6173 
parse_statement(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_parent)6174 static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
6175 {
6176 	struct cil_tree_node *new_ast_node = NULL;
6177 	int rc = SEPOL_ERR;
6178 
6179 	cil_tree_node_init(&new_ast_node);
6180 	new_ast_node->parent = ast_parent;
6181 	new_ast_node->line = parse_current->line;
6182 	new_ast_node->hll_offset = parse_current->hll_offset;
6183 
6184 	if (parse_current->data == CIL_KEY_BLOCK) {
6185 		rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6186 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6187 		rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6188 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6189 		rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6190 	} else if (parse_current->data == CIL_KEY_IN) {
6191 		rc = cil_gen_in(db, parse_current, new_ast_node);
6192 	} else if (parse_current->data == CIL_KEY_CLASS) {
6193 		rc = cil_gen_class(db, parse_current, new_ast_node);
6194 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
6195 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CLASSORDER);
6196 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6197 		rc = cil_gen_map_class(db, parse_current, new_ast_node);
6198 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6199 		rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6200 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6201 		rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6202 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6203 		rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
6204 	} else if (parse_current->data == CIL_KEY_COMMON) {
6205 		rc = cil_gen_common(db, parse_current, new_ast_node);
6206 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6207 		rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6208 	} else if (parse_current->data == CIL_KEY_SID) {
6209 		rc = cil_gen_sid(db, parse_current, new_ast_node);
6210 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6211 		rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6212 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
6213 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SIDORDER);
6214 	} else if (parse_current->data == CIL_KEY_USER) {
6215 		rc = cil_gen_user(db, parse_current, new_ast_node);
6216 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6217 		rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6218 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6219 		rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6220 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
6221 		rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6222 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
6223 		rc = cil_gen_userrange(db, parse_current, new_ast_node);
6224 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6225 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6226 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
6227 		rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6228 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6229 		rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6230 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6231 		rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
6232 	} else if (parse_current->data == CIL_KEY_TYPE) {
6233 		rc = cil_gen_type(db, parse_current, new_ast_node);
6234 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6235 		rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6236 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6237 		rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6238 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6239 		rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
6240 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6241 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
6242 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6243 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
6244 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6245 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6246 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6247 		rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6248 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6249 		rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6250 	} else if (parse_current->data == CIL_KEY_ROLE) {
6251 		rc = cil_gen_role(db, parse_current, new_ast_node);
6252 	} else if (parse_current->data == CIL_KEY_USERROLE) {
6253 		rc = cil_gen_userrole(db, parse_current, new_ast_node);
6254 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
6255 		rc = cil_gen_roletype(db, parse_current, new_ast_node);
6256 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6257 		rc = cil_gen_roletransition(parse_current, new_ast_node);
6258 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6259 		rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6260 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6261 		rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6262 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6263 		rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6264 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6265 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6266 	} else if (parse_current->data == CIL_KEY_BOOL) {
6267 		rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6268 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6269 		rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6270 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
6271 		if (db->preserve_tunables) {
6272 			rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
6273 		} else {
6274 			rc = cil_gen_tunable(db, parse_current, new_ast_node);
6275 		}
6276 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6277 		if (db->preserve_tunables) {
6278 			rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
6279 		} else {
6280 			rc = cil_gen_tunif(db, parse_current, new_ast_node);
6281 		}
6282 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
6283 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
6284 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
6285 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
6286 	} else if (parse_current->data == CIL_KEY_ALLOW) {
6287 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6288 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6289 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6290 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6291 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6292 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6293 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6294 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
6295 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6296 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6297 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6298 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6299 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6300 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6301 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6302 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6303 		rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6304 	} else if (parse_current->data == CIL_KEY_DENY_RULE) {
6305 		rc = cil_gen_deny_rule(parse_current, new_ast_node);
6306 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6307 		rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6308 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6309 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
6310 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6311 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
6312 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6313 		rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6314 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
6315 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
6316 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6317 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
6318 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
6319 		rc = cil_gen_category(db, parse_current, new_ast_node);
6320 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
6321 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
6322 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6323 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
6324 	} else if (parse_current->data == CIL_KEY_CATSET) {
6325 		rc = cil_gen_catset(db, parse_current, new_ast_node);
6326 	} else if (parse_current->data == CIL_KEY_CATORDER) {
6327 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CATORDER);
6328 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6329 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SENSITIVITYORDER);
6330 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
6331 		rc = cil_gen_senscat(db, parse_current, new_ast_node);
6332 	} else if (parse_current->data == CIL_KEY_LEVEL) {
6333 		rc = cil_gen_level(db, parse_current, new_ast_node);
6334 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6335 		rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6336 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6337 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
6338 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6339 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
6340 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6341 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
6342 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6343 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
6344 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
6345 		rc = cil_gen_context(db, parse_current, new_ast_node);
6346 	} else if (parse_current->data == CIL_KEY_FILECON) {
6347 		rc = cil_gen_filecon(db, parse_current, new_ast_node);
6348 	} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6349 		rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6350 	} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6351 		rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6352 	} else if (parse_current->data == CIL_KEY_PORTCON) {
6353 		rc = cil_gen_portcon(db, parse_current, new_ast_node);
6354 	} else if (parse_current->data == CIL_KEY_NODECON) {
6355 		rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6356 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
6357 		rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6358 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
6359 		rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6360 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
6361 		rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6362 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
6363 		rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6364 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
6365 		rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6366 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6367 		rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6368 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6369 		rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6370 	} else if (parse_current->data == CIL_KEY_FSUSE) {
6371 		rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6372 	} else if (parse_current->data == CIL_KEY_MACRO) {
6373 		rc = cil_gen_macro(db, parse_current, new_ast_node);
6374 	} else if (parse_current->data == CIL_KEY_CALL) {
6375 		rc = cil_gen_call(db, parse_current, new_ast_node);
6376 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
6377 		rc = cil_gen_policycap(db, parse_current, new_ast_node);
6378 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
6379 		rc = cil_gen_optional(db, parse_current, new_ast_node);
6380 	} else if (parse_current->data == CIL_KEY_IPADDR) {
6381 		rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6382 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6383 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
6384 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6385 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
6386 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6387 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
6388 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6389 		rc = cil_gen_defaultrange(parse_current, new_ast_node);
6390 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6391 		rc = cil_gen_handleunknown(parse_current, new_ast_node);
6392 	} else if (parse_current->data == CIL_KEY_MLS) {
6393 		rc = cil_gen_mls(parse_current, new_ast_node);
6394 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
6395 		rc = cil_gen_src_info(parse_current, new_ast_node);
6396 	} else {
6397 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6398 		rc = SEPOL_ERR;
6399 	}
6400 
6401 	if (rc == SEPOL_OK) {
6402 		if (ast_parent->cl_head == NULL) {
6403 			ast_parent->cl_head = new_ast_node;
6404 		} else {
6405 			ast_parent->cl_tail->next = new_ast_node;
6406 		}
6407 		ast_parent->cl_tail = new_ast_node;
6408 	} else {
6409 		cil_tree_node_destroy(&new_ast_node);
6410 		new_ast_node = NULL;
6411 	}
6412 
6413 	return new_ast_node;
6414 }
6415 
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6416 static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6417 {
6418 	struct cil_args_build *args = extra_args;
6419 	struct cil_tree_node *new_ast_node = NULL;
6420 	int rc = SEPOL_ERR;
6421 
6422 	if (parse_current->parent->cl_head != parse_current) {
6423 		/* ignore anything that isn't following a parenthesis */
6424 		return SEPOL_OK;
6425 	} else if (parse_current->data == NULL) {
6426 		/* the only time parenthesis can immediately following parenthesis is if
6427 		 * the parent is the root node */
6428 		if (parse_current->parent->parent == NULL) {
6429 			return SEPOL_OK;
6430 		} else {
6431 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6432 			return SEPOL_ERR;
6433 		}
6434 	}
6435 
6436 	rc = check_for_illegal_statement(parse_current, args);
6437 	if (rc != SEPOL_OK) {
6438 		return SEPOL_ERR;
6439 	}
6440 
6441 	new_ast_node = parse_statement(args->db, parse_current, args->ast);
6442 	if (!new_ast_node) {
6443 		return SEPOL_ERR;
6444 	}
6445 
6446 	args->ast = new_ast_node;
6447 
6448 	if (parse_current->data != CIL_KEY_BLOCK &&
6449 		parse_current->data != CIL_KEY_IN &&
6450 		parse_current->data != CIL_KEY_TUNABLEIF &&
6451 		parse_current->data != CIL_KEY_BOOLEANIF &&
6452 		parse_current->data != CIL_KEY_CONDTRUE &&
6453 		parse_current->data != CIL_KEY_CONDFALSE &&
6454 		parse_current->data != CIL_KEY_MACRO &&
6455 		parse_current->data != CIL_KEY_OPTIONAL &&
6456 		parse_current->data != CIL_KEY_SRC_INFO) {
6457 		/* Skip anything that does not contain a list of policy statements */
6458 		*finished = CIL_TREE_SKIP_NEXT;
6459 	}
6460 
6461 	return SEPOL_OK;
6462 }
6463 
__cil_build_ast_first_child_helper(struct cil_tree_node * parse_current,void * extra_args)6464 static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
6465 {
6466 	struct cil_args_build *args = extra_args;
6467 	struct cil_tree_node *ast = args->ast;
6468 
6469 	if (ast->flavor == CIL_TUNABLEIF) {
6470 		args->tunif = ast;
6471 	} else if (ast->flavor == CIL_IN) {
6472 		args->in = ast;
6473 	} else if (ast->flavor == CIL_MACRO) {
6474 		args->macro = ast;
6475 	} else if (ast->flavor == CIL_OPTIONAL) {
6476 		args->optional = ast;
6477 	} else if (ast->flavor == CIL_BOOLEANIF) {
6478 		args->boolif = ast;
6479 	}
6480 
6481 	return SEPOL_OK;
6482 }
6483 
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6484 static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6485 {
6486 	struct cil_args_build *args = extra_args;
6487 	struct cil_tree_node *ast = args->ast;
6488 
6489 	if (ast->flavor == CIL_ROOT) {
6490 		return SEPOL_OK;
6491 	}
6492 
6493 	args->ast = ast->parent;
6494 
6495 	if (ast->flavor == CIL_TUNABLEIF) {
6496 		args->tunif = NULL;
6497 	}
6498 
6499 	if (ast->flavor == CIL_IN) {
6500 		args->in = NULL;
6501 	}
6502 
6503 	if (ast->flavor == CIL_MACRO) {
6504 		args->macro = NULL;
6505 	}
6506 
6507 	if (ast->flavor == CIL_OPTIONAL) {
6508 		struct cil_tree_node *n = ast->parent;
6509 		args->optional = NULL;
6510 		/* Optionals can be nested */
6511 		while (n && n->flavor != CIL_ROOT) {
6512 			if (n->flavor == CIL_OPTIONAL) {
6513 				args->optional = n;
6514 				break;
6515 			}
6516 			n = n->parent;
6517 		}
6518 	}
6519 
6520 	if (ast->flavor == CIL_BOOLEANIF) {
6521 		args->boolif = NULL;
6522 	}
6523 
6524 	// At this point we no longer have any need for parse_current or any of its
6525 	// siblings; they have all been converted to the appropriate AST node. The
6526 	// full parse tree will get deleted elsewhere, but in an attempt to
6527 	// minimize memory usage (of which the parse tree uses a lot), start
6528 	// deleting the parts we don't need now.
6529 	cil_tree_children_destroy(parse_current->parent);
6530 
6531 	return SEPOL_OK;
6532 }
6533 
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6534 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6535 {
6536 	int rc = SEPOL_ERR;
6537 	struct cil_args_build extra_args;
6538 
6539 	if (db == NULL || parse_tree == NULL || ast == NULL) {
6540 		goto exit;
6541 	}
6542 
6543 	extra_args.ast = ast;
6544 	extra_args.db = db;
6545 	extra_args.tunif = NULL;
6546 	extra_args.in = NULL;
6547 	extra_args.macro = NULL;
6548 	extra_args.optional = NULL;
6549 	extra_args.boolif = NULL;
6550 
6551 	rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args);
6552 	if (rc != SEPOL_OK) {
6553 		goto exit;
6554 	}
6555 
6556 	return SEPOL_OK;
6557 
6558 exit:
6559 	return rc;
6560 }
6561