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