xref: /aosp_15_r20/external/selinux/checkpolicy/module_compiler.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /* Author : Joshua Brindle <[email protected]>
2  *	    Karl MacMillan <[email protected]>
3  *          Jason Tang     <[email protected]>
4  *	Added support for binary policy modules
5  *
6  * Copyright (C) 2004 - 2005 Tresys Technology, LLC
7  *	This program is free software; you can redistribute it and/or modify
8  *  	it under the terms of the GNU General Public License as published by
9  *	the Free Software Foundation, version 2.
10  */
11 
12 #include <assert.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <sepol/policydb/policydb.h>
18 #include <sepol/policydb/avrule_block.h>
19 #include <sepol/policydb/conditional.h>
20 
21 #include "queue.h"
22 #include "module_compiler.h"
23 
24 typedef struct scope_stack {
25 	int type;		/* 1 = avrule block, 2 = conditional */
26 	avrule_decl_t *decl;	/* if in an avrule block, which
27 				 * declaration is current */
28 	avrule_t *last_avrule;
29 	int in_else;		/* if in an avrule block, within ELSE branch */
30 	int require_given;	/* 1 if this block had at least one require */
31 	struct scope_stack *parent;
32 } scope_stack_t;
33 
34 extern policydb_t *policydbp;
35 extern queue_t id_queue;
36 extern int yyerror(const char *msg);
37 __attribute__ ((format(printf, 1, 2)))
38 extern void yyerror2(const char *fmt, ...);
39 
40 static int push_stack(int stack_type, ...);
41 static void pop_stack(void);
42 
43 /* keep track of the last item added to the stack */
44 static scope_stack_t *stack_top = NULL;
45 static avrule_block_t *last_block;
46 static uint32_t next_decl_id = 1;
47 
48 static const char * const flavor_str[SYM_NUM] = {
49 	[SYM_COMMONS] = "common",
50 	[SYM_CLASSES] = "class",
51 	[SYM_ROLES] = "role",
52 	[SYM_TYPES] = "type",
53 	[SYM_USERS] = "user",
54 	[SYM_BOOLS] = "bool",
55 	[SYM_LEVELS] = "level",
56 	[SYM_CATS] = "cat"
57 };
58 
print_error_msg(int ret,uint32_t symbol_type)59 static void print_error_msg(int ret, uint32_t symbol_type)
60 {
61 	switch (ret) {
62 	case -3:
63 		yyerror("Out of memory!");
64 		break;
65 	case -2:
66 		yyerror2("Duplicate declaration of %s", flavor_str[symbol_type]);
67 		break;
68 	case -1:
69 		yyerror2("Could not declare %s here", flavor_str[symbol_type]);
70 		break;
71 	default:
72 		yyerror2("Unknown error %d", ret);
73 	}
74 }
75 
define_policy(int pass,int module_header_given)76 int define_policy(int pass, int module_header_given)
77 {
78 	char *id;
79 
80 	if (module_header_given) {
81 		if (policydbp->policy_type != POLICY_MOD) {
82 			yyerror
83 			    ("Module specification found while not building a policy module.");
84 			return -1;
85 		}
86 
87 		if (pass == 2) {
88 			while ((id = queue_remove(id_queue)) != NULL)
89 				free(id);
90 		} else {
91 			id = (char *)queue_remove(id_queue);
92 			if (!id) {
93 				yyerror("no module name");
94 				return -1;
95 			}
96 			free(policydbp->name);
97 			policydbp->name = id;
98 			if ((policydbp->version =
99 			     queue_remove(id_queue)) == NULL) {
100 				yyerror
101 				    ("Expected a module version but none was found.");
102 				return -1;
103 			}
104 		}
105 	} else {
106 		if (policydbp->policy_type == POLICY_MOD) {
107 			yyerror
108 			    ("Building a policy module, but no module specification found.");
109 			return -1;
110 		}
111 	}
112 	/* the first declaration within the global avrule
113 	   block will always have an id of 1 */
114 	next_decl_id = 2;
115 
116 	/* reset the scoping stack */
117 	while (stack_top != NULL) {
118 		pop_stack();
119 	}
120 	if (push_stack(1, policydbp->global, policydbp->global->branch_list) ==
121 	    -1) {
122 		return -1;
123 	}
124 	last_block = policydbp->global;
125 	return 0;
126 }
127 
128 /* Given the current parse stack, returns 1 if a declaration or require would
129  * be allowed here or 0 if not.  For example, declarations and requirements are
130  * not allowed in conditionals, so if there are any conditionals in the
131  * current scope stack then this would return a 0.
132  */
is_creation_allowed(void)133 static int is_creation_allowed(void)
134 {
135 	if (stack_top->type != 1 || stack_top->in_else) {
136 		return 0;
137 	}
138 	return 1;
139 }
140 
141 /* Attempt to declare or require a symbol within the current scope.
142  * Returns:
143  *  0: Success - Symbol had not been previously created.
144  *  1: Success - Symbol had already been created and caller must free datum.
145  * -1: Failure - Symbol cannot be created here
146  * -2: Failure - Duplicate declaration or type/attribute mismatch
147  * -3: Failure - Out of memory or some other error
148  */
create_symbol(uint32_t symbol_type,hashtab_key_t key,hashtab_datum_t datum,uint32_t * dest_value,uint32_t scope)149 static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum,
150 			 uint32_t * dest_value, uint32_t scope)
151 {
152 	avrule_decl_t *decl = stack_top->decl;
153 	int ret;
154 
155 	if (!is_creation_allowed()) {
156 		return -1;
157 	}
158 
159 	ret = symtab_insert(policydbp, symbol_type, key, datum, scope,
160 			    decl->decl_id, dest_value);
161 
162 	if (ret == 1 && dest_value) {
163 		hashtab_datum_t s =
164 			hashtab_search(policydbp->symtab[symbol_type].table,
165 				       key);
166 		assert(s != NULL);
167 
168 		if (symbol_type == SYM_LEVELS) {
169 			*dest_value = ((level_datum_t *)s)->level->sens;
170 		} else {
171 			*dest_value = ((symtab_datum_t *)s)->value;
172 		}
173 	} else if (ret == -2) {
174 		return -2;
175 	} else if (ret < 0) {
176 		return -3;
177 	}
178 
179 	return ret;
180 }
181 
182 /* Attempt to declare a symbol within the current declaration.  If
183  * currently within a non-conditional and in a non-else branch then
184  * insert the symbol, return 0 on success if symbol was undeclared.
185  * For roles and users, it is legal to have multiple declarations; as
186  * such return 1 to indicate that caller must free() the datum because
187  * it was not added.  If symbols may not be declared here return -1.
188  * For duplicate declarations return -2.  For all else, including out
189  * of memory, return -3.  Note that dest_value and datum_value might
190  * not be restricted pointers. */
declare_symbol(uint32_t symbol_type,hashtab_key_t key,hashtab_datum_t datum,uint32_t * dest_value,uint32_t * datum_value)191 int declare_symbol(uint32_t symbol_type,
192 		   hashtab_key_t key, hashtab_datum_t datum,
193 		   uint32_t * dest_value, uint32_t * datum_value)
194 {
195 	avrule_decl_t *decl = stack_top->decl;
196 	int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL);
197 
198 	if (ret < 0) {
199 		return ret;
200 	}
201 
202 	if (ebitmap_set_bit(decl->declared.scope + symbol_type,
203 			    *datum_value - 1, 1)) {
204 		return -3;
205 	}
206 
207 	return ret;
208 }
209 
role_implicit_bounds(hashtab_t roles_tab,char * role_id,role_datum_t * role)210 static int role_implicit_bounds(hashtab_t roles_tab,
211 				char *role_id, role_datum_t *role)
212 {
213 	role_datum_t *bounds;
214 	char *bounds_id, *delim;
215 
216 	delim = strrchr(role_id, '.');
217 	if (!delim)
218 		return 0;	/* no implicit boundary */
219 
220 	bounds_id = strdup(role_id);
221 	if (!bounds_id) {
222 		yyerror("out of memory");
223 		return -1;
224 	}
225 	bounds_id[(size_t)(delim - role_id)] = '\0';
226 
227 	bounds = hashtab_search(roles_tab, bounds_id);
228 	if (!bounds) {
229 		yyerror2("role %s doesn't exist, is implicit bounds of %s",
230 			 bounds_id, role_id);
231 		free(bounds_id);
232 		return -1;
233 	}
234 
235 	if (!role->bounds)
236 		role->bounds = bounds->s.value;
237 	else if (role->bounds != bounds->s.value) {
238 		yyerror2("role %s has inconsistent bounds %s/%s",
239 			 role_id, bounds_id,
240 			 policydbp->p_role_val_to_name[role->bounds - 1]);
241 		free(bounds_id);
242 		return -1;
243 	}
244 	free(bounds_id);
245 
246 	return 0;
247 }
248 
create_role(uint32_t scope,unsigned char isattr,role_datum_t ** role,char ** key)249 static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role, char **key)
250 {
251 	char *id = queue_remove(id_queue);
252 	role_datum_t *datum = NULL;
253 	int ret;
254 	uint32_t value;
255 
256 	*role = NULL;
257 	*key = NULL;
258 	isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE;
259 
260 	if (id == NULL) {
261 		yyerror("no role name");
262 		return -1;
263 	}
264 
265 	datum = malloc(sizeof(*datum));
266 	if (datum == NULL) {
267 		yyerror("Out of memory!");
268 		free(id);
269 		return -1;
270 	}
271 
272 	role_datum_init(datum);
273 	datum->flavor = isattr;
274 
275 	if (scope == SCOPE_DECL) {
276 		ret = declare_symbol(SYM_ROLES, id, datum, &value, &value);
277 	} else {
278 		ret = require_symbol(SYM_ROLES, id, datum, &value, &value);
279 	}
280 
281 	if (ret == 0) {
282 		datum->s.value = value;
283 		*role = datum;
284 		*key = strdup(id);
285 		if (*key == NULL) {
286 			yyerror("Out of memory!");
287 			return -1;
288 		}
289 	} else if (ret == 1) {
290 		*role = hashtab_search(policydbp->symtab[SYM_ROLES].table, id);
291 		if (*role && (isattr != (*role)->flavor)) {
292 			yyerror2("Identifier %s used as both an attribute and a role",
293 				 id);
294 			free(id);
295 			role_datum_destroy(datum);
296 			free(datum);
297 			return -1;
298 		}
299 		datum->s.value = value;
300 		*role = datum;
301 		*key = id;
302 	} else {
303 		print_error_msg(ret, SYM_ROLES);
304 		free(id);
305 		role_datum_destroy(datum);
306 		free(datum);
307 	}
308 
309 	return ret;
310 }
311 
declare_role(unsigned char isattr)312 role_datum_t *declare_role(unsigned char isattr)
313 {
314 	char *key = NULL;
315 	role_datum_t *role = NULL;
316 	role_datum_t *dest_role = NULL;
317 	hashtab_t roles_tab;
318 	int ret, ret2;
319 
320 	ret = create_role(SCOPE_DECL, isattr, &role, &key);
321 	if (ret < 0) {
322 		return NULL;
323 	}
324 
325 	/* create a new role_datum_t for this decl, if necessary */
326 	assert(stack_top->type == 1);
327 
328 	if (stack_top->parent == NULL) {
329 		/* in parent, so use global symbol table */
330 		roles_tab = policydbp->p_roles.table;
331 	} else {
332 		roles_tab = stack_top->decl->p_roles.table;
333 	}
334 
335 	dest_role = hashtab_search(roles_tab, key);
336 	if (dest_role == NULL) {
337 		if (ret == 0) {
338 			dest_role = malloc(sizeof(*dest_role));
339 			if (dest_role == NULL) {
340 				yyerror("Out of memory!");
341 				free(key);
342 				return NULL;
343 			}
344 			role_datum_init(dest_role);
345 			dest_role->s.value = role->s.value;
346 			dest_role->flavor = role->flavor;
347 		} else {
348 			dest_role = role;
349 		}
350 		ret2 = role_implicit_bounds(roles_tab, key, dest_role);
351 		if (ret2 != 0) {
352 			free(key);
353 			role_datum_destroy(dest_role);
354 			free(dest_role);
355 			return NULL;
356 		}
357 		ret2 = hashtab_insert(roles_tab, key, dest_role);
358 		if (ret2 != 0) {
359 			yyerror("Out of memory!");
360 			free(key);
361 			role_datum_destroy(dest_role);
362 			free(dest_role);
363 			return NULL;
364 		}
365 	} else {
366 		free(key);
367 		if (ret == 1) {
368 			role_datum_destroy(role);
369 			free(role);
370 		}
371 	}
372 
373 	if (ret == 0) {
374 		ret2 = ebitmap_set_bit(&dest_role->dominates, dest_role->s.value - 1, 1);
375 		if (ret2 != 0) {
376 			yyerror("out of memory");
377 			return NULL;
378 		}
379 	}
380 
381 	return dest_role;
382 }
383 
create_type(uint32_t scope,unsigned char isattr,type_datum_t ** type)384 static int create_type(uint32_t scope, unsigned char isattr, type_datum_t **type)
385 {
386 	char *id;
387 	type_datum_t *datum;
388 	int ret;
389 	uint32_t value = 0;
390 
391 	*type = NULL;
392 	isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE;
393 
394 	id = (char *)queue_remove(id_queue);
395 	if (!id) {
396 		yyerror("no type/attribute name?");
397 		return -1;
398 	}
399 	if (strcmp(id, "self") == 0) {
400 		yyerror("\"self\" is a reserved type name.");
401 		free(id);
402 		return -1;
403 	}
404 
405 	datum = malloc(sizeof(*datum));
406 	if (!datum) {
407 		yyerror("Out of memory!");
408 		free(id);
409 		return -1;
410 	}
411 	type_datum_init(datum);
412 	datum->primary = 1;
413 	datum->flavor = isattr;
414 
415 	if (scope == SCOPE_DECL) {
416 		ret = declare_symbol(SYM_TYPES, id, datum, &value, &value);
417 	} else {
418 		ret = require_symbol(SYM_TYPES, id, datum, &value, &value);
419 	}
420 
421 	if (ret == 0) {
422 		datum->s.value = value;
423 		*type = datum;
424 	} else if (ret == 1) {
425 		type_datum_destroy(datum);
426 		free(datum);
427 		*type = hashtab_search(policydbp->symtab[SYM_TYPES].table, id);
428 		if (*type && (isattr != (*type)->flavor)) {
429 			yyerror2("Identifier %s used as both an attribute and a type",
430 				 id);
431 			free(id);
432 			return -1;
433 		}
434 		free(id);
435 	} else {
436 		print_error_msg(ret, SYM_TYPES);
437 		free(id);
438 		type_datum_destroy(datum);
439 		free(datum);
440 	}
441 
442 	return ret;
443 }
444 
declare_type(unsigned char primary,unsigned char isattr)445 type_datum_t *declare_type(unsigned char primary, unsigned char isattr)
446 {
447 	type_datum_t *type = NULL;
448 	int ret = create_type(SCOPE_DECL, isattr, &type);
449 
450 	if (ret == 0) {
451 		type->primary = primary;
452 	}
453 
454 	return type;
455 }
456 
user_implicit_bounds(hashtab_t users_tab,char * user_id,user_datum_t * user)457 static int user_implicit_bounds(hashtab_t users_tab,
458 				char *user_id, user_datum_t *user)
459 {
460 	user_datum_t *bounds;
461 	char *bounds_id, *delim;
462 
463 	delim = strrchr(user_id, '.');
464 	if (!delim)
465 		return 0;	/* no implicit boundary */
466 
467 	bounds_id = strdup(user_id);
468 	if (!bounds_id) {
469 		yyerror("out of memory");
470 		return -1;
471 	}
472 	bounds_id[(size_t)(delim - user_id)] = '\0';
473 
474 	bounds = hashtab_search(users_tab, bounds_id);
475 	if (!bounds) {
476 		yyerror2("user %s doesn't exist, is implicit bounds of %s",
477 			 bounds_id, user_id);
478 		free(bounds_id);
479 		return -1;
480 	}
481 
482 	if (!user->bounds)
483 		user->bounds = bounds->s.value;
484 	else if (user->bounds != bounds->s.value) {
485 		yyerror2("user %s has inconsistent bounds %s/%s",
486 			 user_id, bounds_id,
487 			 policydbp->p_role_val_to_name[user->bounds - 1]);
488 		free(bounds_id);
489 		return -1;
490 	}
491 	free(bounds_id);
492 
493 	return 0;
494 }
495 
create_user(uint32_t scope,user_datum_t ** user,char ** key)496 static int create_user(uint32_t scope, user_datum_t **user, char **key)
497 {
498 	char *id = queue_remove(id_queue);
499 	user_datum_t *datum = NULL;
500 	int ret;
501 	uint32_t value;
502 
503 	*user = NULL;
504 	*key = NULL;
505 
506 	if (id == NULL) {
507 		yyerror("no user name");
508 		return -1;
509 	}
510 
511 	datum = malloc(sizeof(*datum));
512 	if (datum == NULL) {
513 		yyerror("Out of memory!");
514 		free(id);
515 		return -1;
516 	}
517 
518 	user_datum_init(datum);
519 
520 	if (scope == SCOPE_DECL) {
521 		ret = declare_symbol(SYM_USERS, id, datum, &value, &value);
522 	} else {
523 		ret = require_symbol(SYM_USERS, id, datum, &value, &value);
524 	}
525 
526 	if (ret == 0) {
527 		datum->s.value = value;
528 		*user = datum;
529 		*key = strdup(id);
530 		if (*key == NULL) {
531 			yyerror("Out of memory!");
532 			return -1;
533 		}
534 	} else if (ret == 1) {
535 		datum->s.value = value;
536 		*user = datum;
537 		*key = id;
538 	} else {
539 		print_error_msg(ret, SYM_USERS);
540 		free(id);
541 		user_datum_destroy(datum);
542 		free(datum);
543 	}
544 
545 	return ret;
546 }
547 
declare_user(void)548 user_datum_t *declare_user(void)
549 {
550 	char *key = NULL;
551 	user_datum_t *user = NULL;
552 	user_datum_t *dest_user = NULL;
553 	hashtab_t users_tab;
554 	int ret, ret2;
555 
556 	ret = create_user(SCOPE_DECL, &user, &key);
557 	if (ret < 0) {
558 		return NULL;
559 	}
560 
561 	/* create a new user_datum_t for this decl, if necessary */
562 	assert(stack_top->type == 1);
563 
564 	if (stack_top->parent == NULL) {
565 		/* in parent, so use global symbol table */
566 		users_tab = policydbp->p_users.table;
567 	} else {
568 		users_tab = stack_top->decl->p_users.table;
569 	}
570 
571 	dest_user = hashtab_search(users_tab, key);
572 	if (dest_user == NULL) {
573 		if (ret == 0) {
574 			dest_user = malloc(sizeof(*dest_user));
575 			if (dest_user == NULL) {
576 				yyerror("Out of memory!");
577 				free(key);
578 				return NULL;
579 			}
580 			user_datum_init(dest_user);
581 			dest_user->s.value = user->s.value;
582 		} else {
583 			dest_user = user;
584 		}
585 		ret2 = user_implicit_bounds(users_tab, key, dest_user);
586 		if (ret2 != 0) {
587 			free(key);
588 			user_datum_destroy(dest_user);
589 			free(dest_user);
590 			return NULL;
591 		}
592 		ret2 = hashtab_insert(users_tab, key, dest_user);
593 		if (ret2 != 0) {
594 			yyerror("Out of memory!");
595 			free(key);
596 			user_datum_destroy(dest_user);
597 			free(dest_user);
598 			return NULL;
599 		}
600 	} else {
601 		free(key);
602 		if (ret == 1) {
603 			user_datum_destroy(user);
604 			free(user);
605 		}
606 	}
607 
608 	return dest_user;
609 }
610 
611 /* Return a type_datum_t for the local avrule_decl with the given ID.
612  * If it does not exist, create one with the same value as 'value'.
613  * This function assumes that the ID is within scope.  c.f.,
614  * is_id_in_scope().
615  *
616  * NOTE: this function usurps ownership of id afterwards.  The caller
617  * shall not reference it nor free() it afterwards.
618  */
get_local_type(char * id,uint32_t value,unsigned char isattr)619 type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
620 {
621 	type_datum_t *dest_typdatum;
622 	hashtab_t types_tab;
623 	assert(stack_top->type == 1);
624 	if (stack_top->parent == NULL) {
625 		/* in global, so use global symbol table */
626 		types_tab = policydbp->p_types.table;
627 	} else {
628 		types_tab = stack_top->decl->p_types.table;
629 	}
630 	dest_typdatum = hashtab_search(types_tab, id);
631 	if (!dest_typdatum) {
632 		dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
633 		if (dest_typdatum == NULL) {
634 			free(id);
635 			return NULL;
636 		}
637 		type_datum_init(dest_typdatum);
638 		dest_typdatum->s.value = value;
639 		dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
640 		dest_typdatum->primary = 1;
641 		if (hashtab_insert(types_tab, id, dest_typdatum)) {
642 			free(id);
643 			type_datum_destroy(dest_typdatum);
644 			free(dest_typdatum);
645 			return NULL;
646 		}
647 
648 	} else {
649 		free(id);
650 		if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) {
651 			return NULL;
652 		}
653 	}
654 	return dest_typdatum;
655 }
656 
657 /* Return a role_datum_t for the local avrule_decl with the given ID.
658  * If it does not exist, create one with the same value as 'value'.
659  * This function assumes that the ID is within scope.  c.f.,
660  * is_id_in_scope().
661  *
662  * NOTE: this function usurps ownership of id afterwards.  The caller
663  * shall not reference it nor free() it afterwards.
664  */
get_local_role(char * id,uint32_t value,unsigned char isattr)665 role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
666 {
667 	role_datum_t *dest_roledatum;
668 	hashtab_t roles_tab;
669 
670 	assert(stack_top->type == 1);
671 
672 	if (stack_top->parent == NULL) {
673 		/* in global, so use global symbol table */
674 		roles_tab = policydbp->p_roles.table;
675 	} else {
676 		roles_tab = stack_top->decl->p_roles.table;
677 	}
678 
679 	dest_roledatum = hashtab_search(roles_tab, id);
680 	if (!dest_roledatum) {
681 		dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
682 		if (dest_roledatum == NULL) {
683 			free(id);
684 			return NULL;
685 		}
686 
687 		role_datum_init(dest_roledatum);
688 		dest_roledatum->s.value = value;
689 		dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
690 
691 		if (hashtab_insert(roles_tab, id, dest_roledatum)) {
692 			free(id);
693 			role_datum_destroy(dest_roledatum);
694 			free(dest_roledatum);
695 			return NULL;
696 		}
697 	} else {
698 		free(id);
699 		if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE)
700 			return NULL;
701 	}
702 
703 	return dest_roledatum;
704 }
705 
706 /* Attempt to require a symbol within the current scope.  If currently
707  * within an optional (and not its else branch), add the symbol to the
708  * required list.  Return 0 on success, 1 if caller needs to free()
709  * datum.  If symbols may not be declared here return -1.  For duplicate
710  * declarations return -2.  For all else, including out of memory,
711  * return -3..  Note that dest_value and datum_value might not be
712  * restricted pointers.
713  */
require_symbol(uint32_t symbol_type,hashtab_key_t key,hashtab_datum_t datum,uint32_t * dest_value,uint32_t * datum_value)714 int require_symbol(uint32_t symbol_type,
715 		   hashtab_key_t key, hashtab_datum_t datum,
716 		   uint32_t * dest_value, uint32_t * datum_value)
717 {
718 	avrule_decl_t *decl = stack_top->decl;
719 	int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_REQ);
720 
721 	if (ret < 0) {
722 		return ret;
723 	}
724 
725 	if (ebitmap_set_bit(decl->required.scope + symbol_type,
726 			    *datum_value - 1, 1)) {
727 		return -3;
728 	}
729 
730 	stack_top->require_given = 1;
731 	return ret;
732 }
733 
add_perm_to_class(uint32_t perm_value,uint32_t class_value)734 int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
735 {
736 	avrule_decl_t *decl = stack_top->decl;
737 	scope_index_t *scope;
738 
739 	assert(perm_value >= 1);
740 	assert(class_value >= 1);
741 	scope = &decl->required;
742 	if (class_value > scope->class_perms_len) {
743 		uint32_t i;
744 		ebitmap_t *new_map = realloc(scope->class_perms_map,
745 					     class_value * sizeof(*new_map));
746 		if (new_map == NULL) {
747 			return -1;
748 		}
749 		scope->class_perms_map = new_map;
750 		for (i = scope->class_perms_len; i < class_value; i++) {
751 			ebitmap_init(scope->class_perms_map + i);
752 		}
753 		scope->class_perms_len = class_value;
754 	}
755 	if (ebitmap_set_bit(scope->class_perms_map + class_value - 1,
756 			    perm_value - 1, 1)) {
757 		return -1;
758 	}
759 	return 0;
760 }
761 
perm_destroy(hashtab_key_t key,hashtab_datum_t datum,void * p)762 static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
763 			__attribute__ ((unused)))
764 {
765 	if (key)
766 		free(key);
767 	free(datum);
768 	return 0;
769 }
770 
class_datum_destroy(class_datum_t * cladatum)771 static void class_datum_destroy(class_datum_t * cladatum)
772 {
773 	if (cladatum != NULL) {
774 		hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
775 		hashtab_destroy(cladatum->permissions.table);
776 		free(cladatum);
777 	}
778 }
779 
require_class(int pass)780 int require_class(int pass)
781 {
782 	char *class_id = queue_remove(id_queue);
783 	char *perm_id = NULL;
784 	class_datum_t *datum = NULL;
785 	perm_datum_t *perm = NULL;
786 	int ret;
787 
788 	if (pass == 2) {
789 		free(class_id);
790 		while ((perm_id = queue_remove(id_queue)) != NULL)
791 			free(perm_id);
792 		return 0;
793 	}
794 
795 	/* first add the class if it is not already there */
796 	if (class_id == NULL) {
797 		yyerror("no class name for class definition?");
798 		return -1;
799 	}
800 
801 	if ((datum = calloc(1, sizeof(*datum))) == NULL ||
802 	    symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
803 		yyerror("Out of memory!");
804 		class_datum_destroy(datum);
805 		return -1;
806 	}
807 	ret =
808 	    require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
809 			   &datum->s.value);
810 	if (ret < 0) {
811 		print_error_msg(ret, SYM_CLASSES);
812 		free(class_id);
813 		class_datum_destroy(datum);
814 		return -1;
815 	}
816 
817 	if (ret == 0) {
818 		/* a new class was added; reindex everything */
819 		if (policydb_index_classes(policydbp)) {
820 			yyerror("Out of memory!");
821 			return -1;
822 		}
823 	} else {
824 		class_datum_destroy(datum);
825 		datum = hashtab_search(policydbp->p_classes.table, class_id);
826 		assert(datum);	/* the class datum should have existed */
827 		free(class_id);
828 	}
829 
830 	/* now add each of the permissions to this class's requirements */
831 	while ((perm_id = queue_remove(id_queue)) != NULL) {
832 		int allocated = 0;
833 
834 		/* Is the permission already in the table? */
835 		perm = hashtab_search(datum->permissions.table, perm_id);
836 		if (!perm && datum->comdatum)
837 			perm =
838 			    hashtab_search(datum->comdatum->permissions.table,
839 					   perm_id);
840 		if (perm) {
841 			/* Yes, drop the name. */
842 			free(perm_id);
843 		} else {
844 			/* No - allocate and insert an entry for it. */
845 			if (policydbp->policy_type == POLICY_BASE) {
846 				yyerror2
847 				    ("Base policy - require of permission %s without prior declaration.",
848 				     perm_id);
849 				free(perm_id);
850 				return -1;
851 			}
852 			if (datum->permissions.nprim >= PERM_SYMTAB_SIZE) {
853 				yyerror2("Class %s would have too many permissions "
854 					 "to fit in an access vector with permission %s",
855 					 policydbp->p_class_val_to_name[datum->s.value - 1],
856 					 perm_id);
857 				free(perm_id);
858 				return -1;
859 			}
860 			allocated = 1;
861 			if ((perm = malloc(sizeof(*perm))) == NULL) {
862 				yyerror("Out of memory!");
863 				free(perm_id);
864 				return -1;
865 			}
866 			memset(perm, 0, sizeof(*perm));
867 			ret =
868 			    hashtab_insert(datum->permissions.table, perm_id,
869 					   perm);
870 			if (ret) {
871 				yyerror("Out of memory!");
872 				free(perm_id);
873 				free(perm);
874 				return -1;
875 			}
876 			perm->s.value = datum->permissions.nprim + 1;
877 		}
878 
879 		if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
880 			yyerror("Out of memory!");
881 			return -1;
882 		}
883 
884 		/* Update number of primitives if we allocated one. */
885 		if (allocated)
886 			datum->permissions.nprim++;
887 	}
888 	return 0;
889 }
890 
require_role_or_attribute(int pass,unsigned char isattr)891 static int require_role_or_attribute(int pass, unsigned char isattr)
892 {
893 	char *key = NULL;
894 	role_datum_t *role = NULL;
895 	int ret;
896 
897 	if (pass == 2) {
898 		free(queue_remove(id_queue));
899 		return 0;
900 	}
901 
902 	ret = create_role(SCOPE_REQ, isattr, &role, &key);
903 	if (ret < 0) {
904 		return -1;
905 	}
906 
907 	free(key);
908 
909 	if (ret == 0) {
910 		ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1);
911 		if (ret != 0) {
912 			yyerror("Out of memory");
913 			return -1;
914 		}
915 	} else {
916 		role_datum_destroy(role);
917 		free(role);
918 	}
919 
920 	return 0;
921 }
922 
require_role(int pass)923 int require_role(int pass)
924 {
925 	return require_role_or_attribute(pass, 0);
926 }
927 
require_attribute_role(int pass)928 int require_attribute_role(int pass)
929 {
930 	return require_role_or_attribute(pass, 1);
931 }
932 
require_type_or_attribute(int pass,unsigned char isattr)933 static int require_type_or_attribute(int pass, unsigned char isattr)
934 {
935 	type_datum_t *type = NULL;
936 	int ret;
937 
938 	if (pass == 2) {
939 		free(queue_remove(id_queue));
940 		return 0;
941 	}
942 
943 	ret = create_type(SCOPE_REQ, isattr, &type);
944 
945 	if (ret < 0) {
946 		return -1;
947 	}
948 
949 	return 0;
950 }
951 
require_type(int pass)952 int require_type(int pass)
953 {
954 	return require_type_or_attribute(pass, 0);
955 }
956 
require_attribute(int pass)957 int require_attribute(int pass)
958 {
959 	return require_type_or_attribute(pass, 1);
960 }
961 
require_user(int pass)962 int require_user(int pass)
963 {
964 	char *key = NULL;
965 	user_datum_t *user = NULL;
966 	int ret;
967 
968 	if (pass == 1) {
969 		free(queue_remove(id_queue));
970 		return 0;
971 	}
972 
973 	ret = create_user(SCOPE_REQ, &user, &key);
974 	if (ret < 0) {
975 		return -1;
976 	}
977 
978 	free(key);
979 
980 	if (ret == 1) {
981 		user_datum_destroy(user);
982 		free(user);
983 	}
984 
985 	return 0;
986 }
987 
require_bool_tunable(int pass,int is_tunable)988 static int require_bool_tunable(int pass, int is_tunable)
989 {
990 	char *id = queue_remove(id_queue);
991 	cond_bool_datum_t *booldatum = NULL;
992 	int retval;
993 	if (pass == 2) {
994 		free(id);
995 		return 0;
996 	}
997 	if (id == NULL) {
998 		yyerror("no boolean name");
999 		return -1;
1000 	}
1001 	if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
1002 		cond_destroy_bool(id, booldatum, NULL);
1003 		yyerror("Out of memory!");
1004 		return -1;
1005 	}
1006 	if (is_tunable)
1007 		booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
1008 	retval =
1009 	    require_symbol(SYM_BOOLS, id, booldatum,
1010 			   &booldatum->s.value, &booldatum->s.value);
1011 	if (retval != 0) {
1012 		cond_destroy_bool(id, booldatum, NULL);
1013 		if (retval < 0) {
1014 			print_error_msg(retval, SYM_BOOLS);
1015 			return -1;
1016 		}
1017 	}
1018 
1019 	return 0;
1020 }
1021 
require_bool(int pass)1022 int require_bool(int pass)
1023 {
1024 	return require_bool_tunable(pass, 0);
1025 }
1026 
require_tunable(int pass)1027 int require_tunable(int pass)
1028 {
1029 	return require_bool_tunable(pass, 1);
1030 }
1031 
require_sens(int pass)1032 int require_sens(int pass)
1033 {
1034 	char *id = queue_remove(id_queue);
1035 	level_datum_t *level = NULL;
1036 	int retval;
1037 	if (pass == 2) {
1038 		free(id);
1039 		return 0;
1040 	}
1041 	if (!id) {
1042 		yyerror("no sensitivity name");
1043 		return -1;
1044 	}
1045 	level = malloc(sizeof(level_datum_t));
1046 	if (!level) {
1047 		free(id);
1048 		yyerror("Out of memory!");
1049 		return -1;
1050 	}
1051 	level_datum_init(level);
1052 	level->level = malloc(sizeof(mls_level_t));
1053 	if (!level->level) {
1054 		free(id);
1055 		level_datum_destroy(level);
1056 		free(level);
1057 		yyerror("Out of memory!");
1058 		return -1;
1059 	}
1060 	mls_level_init(level->level);
1061 	retval = require_symbol(SYM_LEVELS, id, level,
1062 				&level->level->sens, &level->level->sens);
1063 	if (retval != 0) {
1064 		free(id);
1065 		mls_level_destroy(level->level);
1066 		free(level->level);
1067 		level_datum_destroy(level);
1068 		free(level);
1069 		if (retval < 0) {
1070 			print_error_msg(retval, SYM_LEVELS);
1071 			return -1;
1072 		}
1073 	}
1074 
1075 	return 0;
1076 }
1077 
require_cat(int pass)1078 int require_cat(int pass)
1079 {
1080 	char *id = queue_remove(id_queue);
1081 	cat_datum_t *cat = NULL;
1082 	int retval;
1083 	if (pass == 2) {
1084 		free(id);
1085 		return 0;
1086 	}
1087 	if (!id) {
1088 		yyerror("no category name");
1089 		return -1;
1090 	}
1091 	cat = malloc(sizeof(cat_datum_t));
1092 	if (!cat) {
1093 		free(id);
1094 		yyerror("Out of memory!");
1095 		return -1;
1096 	}
1097 	cat_datum_init(cat);
1098 
1099 	retval = require_symbol(SYM_CATS, id, cat,
1100 				&cat->s.value, &cat->s.value);
1101 	if (retval != 0) {
1102 		free(id);
1103 		cat_datum_destroy(cat);
1104 		free(cat);
1105 		if (retval < 0) {
1106 			print_error_msg(retval, SYM_CATS);
1107 			return -1;
1108 		}
1109 	}
1110 
1111 	return 0;
1112 }
1113 
is_scope_in_stack(const scope_datum_t * scope,const scope_stack_t * stack)1114 static int is_scope_in_stack(const scope_datum_t * scope, const scope_stack_t * stack)
1115 {
1116 	uint32_t i;
1117 	if (stack == NULL) {
1118 		return 0;	/* no matching scope found */
1119 	}
1120 	if (stack->type == 1) {
1121 		const avrule_decl_t *decl = stack->decl;
1122 		for (i = 0; i < scope->decl_ids_len; i++) {
1123 			if (scope->decl_ids[i] == decl->decl_id) {
1124 				return 1;
1125 			}
1126 		}
1127 	} else {
1128 		/* note that conditionals can't declare or require
1129 		 * symbols, so skip this level */
1130 	}
1131 
1132 	/* not within scope of this stack, so try its parent */
1133 	return is_scope_in_stack(scope, stack->parent);
1134 }
1135 
is_id_in_scope(uint32_t symbol_type,const_hashtab_key_t id)1136 int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id)
1137 {
1138 	const scope_datum_t *scope =
1139 	    (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
1140 					     table, id);
1141 	if (scope == NULL) {
1142 		return 1;	/* id is not known, so return success */
1143 	}
1144 	return is_scope_in_stack(scope, stack_top);
1145 }
1146 
is_perm_in_scope_index(uint32_t perm_value,uint32_t class_value,const scope_index_t * scope)1147 static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
1148 				  const scope_index_t * scope)
1149 {
1150 	if (class_value > scope->class_perms_len) {
1151 		return 1;
1152 	}
1153 	if (ebitmap_get_bit(scope->class_perms_map + class_value - 1,
1154 			    perm_value - 1)) {
1155 		return 1;
1156 	}
1157 	return 0;
1158 }
1159 
is_perm_in_stack(uint32_t perm_value,uint32_t class_value,const scope_stack_t * stack)1160 static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
1161 			    const scope_stack_t * stack)
1162 {
1163 	if (stack == NULL) {
1164 		return 0;	/* no matching scope found */
1165 	}
1166 	if (stack->type == 1) {
1167 		avrule_decl_t *decl = stack->decl;
1168 		if (is_perm_in_scope_index
1169 		    (perm_value, class_value, &decl->required)
1170 		    || is_perm_in_scope_index(perm_value, class_value,
1171 					      &decl->declared)) {
1172 			return 1;
1173 		}
1174 	} else {
1175 		/* note that conditionals can't declare or require
1176 		 * symbols, so skip this level */
1177 	}
1178 
1179 	/* not within scope of this stack, so try its parent */
1180 	return is_perm_in_stack(perm_value, class_value, stack->parent);
1181 }
1182 
is_perm_in_scope(const_hashtab_key_t perm_id,const_hashtab_key_t class_id)1183 int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id)
1184 {
1185 	const class_datum_t *cladatum =
1186 	    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
1187 					     class_id);
1188 	const perm_datum_t *perdatum;
1189 	if (cladatum == NULL) {
1190 		return 1;
1191 	}
1192 	perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
1193 						   perm_id);
1194 	if (perdatum == NULL) {
1195 		return 1;
1196 	}
1197 	return is_perm_in_stack(perdatum->s.value, cladatum->s.value,
1198 				stack_top);
1199 }
1200 
get_current_cond_list(cond_list_t * cond)1201 cond_list_t *get_current_cond_list(cond_list_t * cond)
1202 {
1203 	/* FIX ME: do something different here if in a nested
1204 	 * conditional? */
1205 	avrule_decl_t *decl = stack_top->decl;
1206 	return get_decl_cond_list(policydbp, decl, cond);
1207 }
1208 
1209 /* Append the new conditional node to the existing ones.  During
1210  * expansion the list will be reversed -- i.e., the last AV rule will
1211  * be the first one listed in the policy.  This matches the behavior
1212  * of the upstream compiler. */
append_cond_list(cond_list_t * cond)1213 void append_cond_list(cond_list_t * cond)
1214 {
1215 	cond_list_t *old_cond = get_current_cond_list(cond);
1216 	avrule_t *tmp;
1217 	assert(old_cond != NULL);	/* probably out of memory */
1218 	if (old_cond->avtrue_list == NULL) {
1219 		old_cond->avtrue_list = cond->avtrue_list;
1220 	} else {
1221 		for (tmp = old_cond->avtrue_list; tmp->next != NULL;
1222 		     tmp = tmp->next) ;
1223 		tmp->next = cond->avtrue_list;
1224 	}
1225 	if (old_cond->avfalse_list == NULL) {
1226 		old_cond->avfalse_list = cond->avfalse_list;
1227 	} else {
1228 		for (tmp = old_cond->avfalse_list; tmp->next != NULL;
1229 		     tmp = tmp->next) ;
1230 		tmp->next = cond->avfalse_list;
1231 	}
1232 
1233 	old_cond->flags |= cond->flags;
1234 }
1235 
append_avrule(avrule_t * avrule)1236 void append_avrule(avrule_t * avrule)
1237 {
1238 	avrule_decl_t *decl = stack_top->decl;
1239 
1240 	/* currently avrules follow a completely different code path
1241 	 * for handling avrules and compute types
1242 	 * (define_cond_avrule_te_avtab, define_cond_compute_type);
1243 	 * therefore there ought never be a conditional on top of the
1244 	 * scope stack */
1245 	assert(stack_top->type == 1);
1246 
1247 	if (stack_top->last_avrule == NULL) {
1248 		decl->avrules = avrule;
1249 	} else {
1250 		stack_top->last_avrule->next = avrule;
1251 	}
1252 	stack_top->last_avrule = avrule;
1253 }
1254 
1255 /* this doesn't actually append, but really prepends it */
append_role_trans(role_trans_rule_t * role_tr_rules)1256 void append_role_trans(role_trans_rule_t * role_tr_rules)
1257 {
1258 	avrule_decl_t *decl = stack_top->decl;
1259 
1260 	/* role transitions are not allowed within conditionals */
1261 	assert(stack_top->type == 1);
1262 
1263 	role_tr_rules->next = decl->role_tr_rules;
1264 	decl->role_tr_rules = role_tr_rules;
1265 }
1266 
1267 /* this doesn't actually append, but really prepends it */
append_role_allow(role_allow_rule_t * role_allow_rules)1268 void append_role_allow(role_allow_rule_t * role_allow_rules)
1269 {
1270 	avrule_decl_t *decl = stack_top->decl;
1271 
1272 	/* role allows are not allowed within conditionals */
1273 	assert(stack_top->type == 1);
1274 
1275 	role_allow_rules->next = decl->role_allow_rules;
1276 	decl->role_allow_rules = role_allow_rules;
1277 }
1278 
1279 /* this doesn't actually append, but really prepends it */
append_filename_trans(filename_trans_rule_t * filename_trans_rules)1280 void append_filename_trans(filename_trans_rule_t * filename_trans_rules)
1281 {
1282 	avrule_decl_t *decl = stack_top->decl;
1283 
1284 	/* filename transitions are not allowed within conditionals */
1285 	assert(stack_top->type == 1);
1286 
1287 	filename_trans_rules->next = decl->filename_trans_rules;
1288 	decl->filename_trans_rules = filename_trans_rules;
1289 }
1290 
1291 /* this doesn't actually append, but really prepends it */
append_range_trans(range_trans_rule_t * range_tr_rules)1292 void append_range_trans(range_trans_rule_t * range_tr_rules)
1293 {
1294 	avrule_decl_t *decl = stack_top->decl;
1295 
1296 	/* range transitions are not allowed within conditionals */
1297 	assert(stack_top->type == 1);
1298 
1299 	range_tr_rules->next = decl->range_tr_rules;
1300 	decl->range_tr_rules = range_tr_rules;
1301 }
1302 
begin_optional(int pass)1303 int begin_optional(int pass)
1304 {
1305 	avrule_block_t *block = NULL;
1306 	avrule_decl_t *decl;
1307 	if (pass == 1) {
1308 		/* allocate a new avrule block for this optional block */
1309 		if ((block = avrule_block_create()) == NULL ||
1310 		    (decl = avrule_decl_create(next_decl_id)) == NULL) {
1311 			goto cleanup;
1312 		}
1313 		block->flags |= AVRULE_OPTIONAL;
1314 		block->branch_list = decl;
1315 		last_block->next = block;
1316 	} else {
1317 		/* select the next block from the chain built during pass 1 */
1318 		block = last_block->next;
1319 		assert(block != NULL &&
1320 		       block->branch_list != NULL &&
1321 		       block->branch_list->decl_id == next_decl_id);
1322 		decl = block->branch_list;
1323 	}
1324 	if (push_stack(1, block, decl) == -1) {
1325 		goto cleanup;
1326 	}
1327 	stack_top->last_avrule = NULL;
1328 	last_block = block;
1329 	next_decl_id++;
1330 	return 0;
1331       cleanup:
1332 	yyerror("Out of memory!");
1333 	avrule_block_destroy(block);
1334 	return -1;
1335 }
1336 
end_optional(int pass)1337 int end_optional(int pass __attribute__ ((unused)))
1338 {
1339 	/* once nested conditionals are allowed, do the stack unfolding here */
1340 	pop_stack();
1341 	return 0;
1342 }
1343 
begin_optional_else(int pass)1344 int begin_optional_else(int pass)
1345 {
1346 	avrule_decl_t *decl;
1347 	assert(stack_top->type == 1 && stack_top->in_else == 0);
1348 	if (pass == 1) {
1349 		/* allocate a new declaration and add it to the
1350 		 * current chain */
1351 		if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
1352 			yyerror("Out of memory!");
1353 			return -1;
1354 		}
1355 		stack_top->decl->next = decl;
1356 	} else {
1357 		/* pick the (hopefully last) declaration of this
1358 		   avrule block, built from pass 1 */
1359 		decl = stack_top->decl->next;
1360 		assert(decl != NULL &&
1361 		       decl->next == NULL && decl->decl_id == next_decl_id);
1362 	}
1363 	stack_top->in_else = 1;
1364 	stack_top->decl = decl;
1365 	stack_top->last_avrule = NULL;
1366 	stack_top->require_given = 0;
1367 	next_decl_id++;
1368 	return 0;
1369 }
1370 
copy_requirements(avrule_decl_t * dest,const scope_stack_t * stack)1371 static int copy_requirements(avrule_decl_t * dest, const scope_stack_t * stack)
1372 {
1373 	uint32_t i;
1374 	if (stack == NULL) {
1375 		return 0;
1376 	}
1377 	if (stack->type == 1) {
1378 		const scope_index_t *src_scope = &stack->decl->required;
1379 		scope_index_t *dest_scope = &dest->required;
1380 		for (i = 0; i < SYM_NUM; i++) {
1381 			const ebitmap_t *src_bitmap = &src_scope->scope[i];
1382 			ebitmap_t *dest_bitmap = &dest_scope->scope[i];
1383 			if (ebitmap_union(dest_bitmap, src_bitmap)) {
1384 				yyerror("Out of memory!");
1385 				return -1;
1386 			}
1387 		}
1388 		/* now copy class permissions */
1389 		if (src_scope->class_perms_len > dest_scope->class_perms_len) {
1390 			ebitmap_t *new_map =
1391 			    realloc(dest_scope->class_perms_map,
1392 				    src_scope->class_perms_len *
1393 				    sizeof(*new_map));
1394 			if (new_map == NULL) {
1395 				yyerror("Out of memory!");
1396 				return -1;
1397 			}
1398 			dest_scope->class_perms_map = new_map;
1399 			for (i = dest_scope->class_perms_len;
1400 			     i < src_scope->class_perms_len; i++) {
1401 				ebitmap_init(dest_scope->class_perms_map + i);
1402 			}
1403 			dest_scope->class_perms_len =
1404 			    src_scope->class_perms_len;
1405 		}
1406 		for (i = 0; i < src_scope->class_perms_len; i++) {
1407 			const ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
1408 			ebitmap_t *dest_bitmap =
1409 			    &dest_scope->class_perms_map[i];
1410 			if (ebitmap_union(dest_bitmap, src_bitmap)) {
1411 				yyerror("Out of memory!");
1412 				return -1;
1413 			}
1414 		}
1415 	}
1416 	return copy_requirements(dest, stack->parent);
1417 }
1418 
1419 /* During pass 1, check that at least one thing was required within
1420  * this block, for those places where a REQUIRED is necessary.  During
1421  * pass 2, have this block inherit its parents' requirements.  Return
1422  * 0 on success, -1 on failure. */
end_avrule_block(int pass)1423 int end_avrule_block(int pass)
1424 {
1425 	avrule_decl_t *decl = stack_top->decl;
1426 	assert(stack_top->type == 1);
1427 	if (pass == 2) {
1428 		/* this avrule_decl inherits all of its parents'
1429 		 * requirements */
1430 		if (copy_requirements(decl, stack_top->parent) == -1) {
1431 			return -1;
1432 		}
1433 		return 0;
1434 	}
1435 	if (!stack_top->in_else && !stack_top->require_given) {
1436 		if (policydbp->policy_type == POLICY_BASE
1437 		    && stack_top->parent != NULL) {
1438 			/* if this is base no require should be in the global block */
1439 			return 0;
1440 		} else {
1441 			/* non-ELSE branches must have at least one thing required */
1442 			yyerror("This block has no require section.");
1443 			return -1;
1444 		}
1445 	}
1446 	return 0;
1447 }
1448 
1449 /* Push a new scope on to the stack and update the 'last' pointer.
1450  * Return 0 on success, -1 if out * of memory. */
push_stack(int stack_type,...)1451 static int push_stack(int stack_type, ...)
1452 {
1453 	scope_stack_t *s = calloc(1, sizeof(*s));
1454 	va_list ap;
1455 	if (s == NULL) {
1456 		return -1;
1457 	}
1458 	va_start(ap, stack_type);
1459 	switch (s->type = stack_type) {
1460 	case 1:{
1461 			va_arg(ap, avrule_block_t *);
1462 			s->decl = va_arg(ap, avrule_decl_t *);
1463 			break;
1464 		}
1465 	case 2:{
1466 			va_arg(ap, cond_list_t *);
1467 			break;
1468 		}
1469 	default:
1470 		/* invalid stack type given */
1471 		assert(0);
1472 	}
1473 	va_end(ap);
1474 	s->parent = stack_top;
1475 	stack_top = s;
1476 	return 0;
1477 }
1478 
1479 /* Pop off the most recently added from the stack.  Update the 'last'
1480  * pointer. */
pop_stack(void)1481 static void pop_stack(void)
1482 {
1483 	scope_stack_t *parent;
1484 	assert(stack_top != NULL);
1485 	parent = stack_top->parent;
1486 	free(stack_top);
1487 	stack_top = parent;
1488 }
1489 
1490 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
module_compiler_reset(void)1491 void module_compiler_reset(void)
1492 {
1493 	while (stack_top)
1494 		pop_stack();
1495 
1496 	last_block = NULL;
1497 	next_decl_id = 1;
1498 }
1499 #endif
1500