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