18c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Author : Joshua Brindle <jbrindle@tresys.com>
28c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *	    Karl MacMillan <kmacmillan@tresys.com>
38c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *          Jason Tang     <jtang@tresys.com>
48c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *	Added support for binary policy modules
58c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *
68c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * Copyright (C) 2004 - 2005 Tresys Technology, LLC
78c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *	This program is free software; you can redistribute it and/or modify
88c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *  	it under the terms of the GNU General Public License as published by
98c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *	the Free Software Foundation, version 2.
108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <assert.h>
138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <stdarg.h>
148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <stdlib.h>
158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <string.h>
168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <sepol/policydb/policydb.h>
188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <sepol/policydb/avrule_block.h>
198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include <sepol/policydb/conditional.h>
208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include "queue.h"
228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android#include "module_compiler.h"
238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidunion stack_item_u {
258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_block_t *avrule;
268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cond_list_t *cond_list;
278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android};
288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidtypedef struct scope_stack {
308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	union stack_item_u u;
318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int type;		/* for above union: 1 = avrule block, 2 = conditional */
328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl;	/* if in an avrule block, which
338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				 * declaration is current */
348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_t *last_avrule;
358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int in_else;		/* if in an avrule block, within ELSE branch */
368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int require_given;	/* 1 if this block had at least one require */
378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	struct scope_stack *parent, *child;
388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android} scope_stack_t;
398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidextern policydb_t *policydbp;
418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidextern queue_t id_queue;
428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidextern int yyerror(char *msg);
438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidextern void yyerror2(char *fmt, ...);
448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int push_stack(int stack_type, ...);
468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic void pop_stack(void);
478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* keep track of the last item added to the stack */
498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic scope_stack_t *stack_top = NULL;
508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic avrule_block_t *last_block;
518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic uint32_t next_decl_id = 1;
528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint define_policy(int pass, int module_header_given)
548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id;
568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (module_header_given) {
588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (policydbp->policy_type != POLICY_MOD) {
598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror
608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    ("Module specification found while not building a policy module.\n");
618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (pass == 2) {
658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			while ((id = queue_remove(id_queue)) != NULL)
668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(id);
678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			id = (char *)queue_remove(id_queue);
698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (!id) {
708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("no module name");
718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			policydbp->name = id;
748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if ((policydbp->version =
758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			     queue_remove(id_queue)) == NULL) {
768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror
778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    ("Expected a module version but none was found.");
788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (policydbp->policy_type == POLICY_MOD) {
838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror
848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    ("Building a policy module, but no module specification found.\n");
858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* the first declaration within the global avrule
898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	   block will always have an id of 1 */
908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	next_decl_id = 2;
918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* reset the scoping stack */
938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	while (stack_top != NULL) {
948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		pop_stack();
958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (push_stack(1, policydbp->global, policydbp->global->branch_list) ==
978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    -1) {
988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	last_block = policydbp->global;
1018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
1028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
1038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Given the current parse stack, returns 1 if a declaration would be
1058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * allowed here or 0 if not.  For example, declarations are not
1068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * allowed in conditionals, so if there are any conditionals in the
1078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * current scope stack then this would return a 0.
1088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
1098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int is_declaration_allowed(void)
1108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
1118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack_top->type != 1 || stack_top->in_else) {
1128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
1138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 1;
1158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
1168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Attempt to declare a symbol within the current declaration.  If
1188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * currently within a non-conditional and in a non-else branch then
1198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * insert the symbol, return 0 on success if symbol was undeclared.
1208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * For roles and users, it is legal to have multiple declarations; as
1218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * such return 1 to indicate that caller must free() the datum because
1228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * it was not added.  If symbols may not be declared here return -1.
1238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * For duplicate declarations return -2.  For all else, including out
1248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * of memory, return -3.  Note that dest_value and datum_value might
1258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * not be restricted pointers. */
1268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint declare_symbol(uint32_t symbol_type,
1278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		   hashtab_key_t key, hashtab_datum_t datum,
1288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		   uint32_t * dest_value, uint32_t * datum_value)
1298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
1308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
1318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
1328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* first check that symbols may be declared here */
1348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!is_declaration_allowed()) {
1358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
1368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval = symtab_insert(policydbp, symbol_type, key, datum,
1388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			       SCOPE_DECL, decl->decl_id, dest_value);
1398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 1 && dest_value) {
1408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		symtab_datum_t *s =
1418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    (symtab_datum_t *) hashtab_search(policydbp->
1428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android						      symtab[symbol_type].table,
1438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android						      key);
1448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(s != NULL);
1458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (symbol_type == SYM_LEVELS) {
1478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			*dest_value = ((level_datum_t *)s)->level->sens;
1488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
1498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			*dest_value = s->value;
1508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
1518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else if (retval == -2) {
1528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -2;
1538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else if (retval < 0) {
1548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -3;
1558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {		/* fall through possible if retval is 0 */
1568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (datum_value != NULL) {
1588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (ebitmap_set_bit(decl->declared.scope + symbol_type,
1598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    *datum_value - 1, 1)) {
1608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -3;
1618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
1628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return retval;
1648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
1658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int role_implicit_bounds(hashtab_t roles_tab,
1678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				char *role_id, role_datum_t *role)
1688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
1698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_t *bounds;
1708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *bounds_id, *delim;
1718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	delim = strrchr(role_id, '.');
1738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!delim)
1748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;	/* no implicit boundary */
1758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds_id = strdup(role_id);
1778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!bounds_id) {
1788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("out of memory");
1798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
1808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds_id[(size_t)(delim - role_id)] = '\0';
1828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds = hashtab_search(roles_tab, bounds_id);
1848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!bounds) {
1858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror2("role %s doesn't exist, is implicit bounds of %s",
1868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 bounds_id, role_id);
1878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
1888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!role->bounds)
1918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		role->bounds = bounds->s.value;
1928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	else if (role->bounds != bounds->s.value) {
1938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror2("role %s has inconsistent bounds %s/%s",
1948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 role_id, bounds_id,
1958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 policydbp->p_role_val_to_name[role->bounds - 1]);
1968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
1978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	free(bounds_id);
1998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
2008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
2018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
2028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
2038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidrole_datum_t *declare_role(unsigned char isattr)
2048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
2058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue), *dest_id = NULL;
2068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_t *role = NULL, *dest_role = NULL;
2078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
2088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	uint32_t value;
2098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
2108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
2118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no role name");
2128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
2138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
2148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) {
2158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
2168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
2178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
2188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
2198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_init(role);
2208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
2218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
2228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value,
2238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &value);
2248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 0) {
2258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		role->s.value = value;
2268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if ((dest_id = strdup(id)) == NULL) {
2278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
2288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
2298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
2318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* this role was already declared in this module, or error */
2328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_id = id;
2338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		role_datum_destroy(role);
2348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(role);
2358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
2368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 0 || retval == 1) {
2378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* create a new role_datum_t for this decl, if necessary */
2388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		hashtab_t roles_tab;
2398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(stack_top->type == 1);
2408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (stack_top->parent == NULL) {
2418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* in parent, so use global symbol table */
2428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			roles_tab = policydbp->p_roles.table;
2438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
2448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			roles_tab = stack_top->decl->p_roles.table;
2458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id);
2478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_role == NULL) {
2488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if ((dest_role =
2498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			     (role_datum_t *) malloc(sizeof(*dest_role))) ==
2508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    NULL) {
2518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
2528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
2538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
2548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
2558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			role_datum_init(dest_role);
2568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			dest_role->s.value = value;
2578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
2588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (role_implicit_bounds(roles_tab, dest_id, dest_role)) {
2598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
2608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				role_datum_destroy(dest_role);
2618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_role);
2628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
2638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
2648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (hashtab_insert(roles_tab, dest_id, dest_role)) {
2658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
2668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
2678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				role_datum_destroy(dest_role);
2688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_role);
2698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
2708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
2718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
2728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(dest_id);
2738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
2758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(dest_id);
2768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
2778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
2788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
2798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
2808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
2818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
2838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of role");
2848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
2858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
2878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not declare role here");
2888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
2898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
2918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (ebitmap_set_bit
2928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    (&dest_role->dominates, role->s.value - 1, 1)) {
2938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("out of memory");
2948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
2958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
2968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return dest_role;
2978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
2988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
2998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return dest_role;	/* role already declared for this block */
3008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
3028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
3038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
3068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidtype_datum_t *declare_type(unsigned char primary, unsigned char isattr)
3088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
3098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id;
3108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type_datum_t *typdatum;
3118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
3128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	uint32_t value = 0;
3138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	id = (char *)queue_remove(id_queue);
3158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!id) {
3168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no type/attribute name?");
3178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
3188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (strcmp(id, "self") == 0) {
3208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror
3218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    ("'self' is a reserved type name and may not be declared.");
3228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
3238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
3248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
3278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!typdatum) {
3288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
3298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
3308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
3318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type_datum_init(typdatum);
3338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	typdatum->primary = primary;
3348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
3358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval = declare_symbol(SYM_TYPES, id, typdatum, &value, &value);
3378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 0 || retval == 1) {
3388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (typdatum->primary) {
3398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			typdatum->s.value = value;
3408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
3428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* error occurred (can't have duplicate type declarations) */
3438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
3448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		type_datum_destroy(typdatum);
3458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(typdatum);
3468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
3488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
3498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
3508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
3518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
3538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror2("duplicate declaration of type/attribute");
3548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
3558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
3578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not declare type/attribute here");
3588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
3598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:
3618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
3628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return typdatum;
3638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
3658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
3668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
3678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
3698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int user_implicit_bounds(hashtab_t users_tab,
3718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				char *user_id, user_datum_t *user)
3728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
3738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	user_datum_t *bounds;
3748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *bounds_id, *delim;
3758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	delim = strrchr(user_id, '.');
3778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!delim)
3788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;	/* no implicit boundary */
3798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds_id = strdup(user_id);
3818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!bounds_id) {
3828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("out of memory");
3838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
3848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds_id[(size_t)(delim - user_id)] = '\0';
3868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	bounds = hashtab_search(users_tab, bounds_id);
3888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!bounds) {
3898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror2("user %s doesn't exist, is implicit bounds of %s",
3908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 bounds_id, user_id);
3918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
3928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
3938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
3948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!user->bounds)
3958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		user->bounds = bounds->s.value;
3968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	else if (user->bounds != bounds->s.value) {
3978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror2("user %s has inconsistent bounds %s/%s",
3988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 user_id, bounds_id,
3998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 policydbp->p_role_val_to_name[user->bounds - 1]);
4008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
4018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
4028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	free(bounds_id);
4038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
4048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
4058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
4068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
4078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androiduser_datum_t *declare_user(void)
4088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
4098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue), *dest_id = NULL;
4108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	user_datum_t *user = NULL, *dest_user = NULL;
4118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
4128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	uint32_t value = 0;
4138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
4148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
4158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no user name");
4168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
4178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
4188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) {
4198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
4208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
4218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return NULL;
4228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
4238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	user_datum_init(user);
4248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
4258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
4268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value,
4278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &value);
4288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
4298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 0) {
4308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		user->s.value = value;
4318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if ((dest_id = strdup(id)) == NULL) {
4328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
4338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
4348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
4368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* this user was already declared in this module, or error */
4378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_id = id;
4388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		user_datum_destroy(user);
4398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(user);
4408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
4418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 0 || retval == 1) {
4428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* create a new user_datum_t for this decl, if necessary */
4438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		hashtab_t users_tab;
4448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(stack_top->type == 1);
4458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (stack_top->parent == NULL) {
4468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* in parent, so use global symbol table */
4478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			users_tab = policydbp->p_users.table;
4488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
4498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			users_tab = stack_top->decl->p_users.table;
4508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id);
4528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_user == NULL) {
4538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if ((dest_user =
4548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			     (user_datum_t *) malloc(sizeof(*dest_user))) ==
4558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    NULL) {
4568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
4578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
4588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
4598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
4608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			user_datum_init(dest_user);
4618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			dest_user->s.value = value;
4628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (user_implicit_bounds(users_tab, dest_id, dest_user)) {
4638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
4648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				user_datum_destroy(dest_user);
4658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_user);
4668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
4678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
4688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (hashtab_insert(users_tab, dest_id, dest_user)) {
4698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
4708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_id);
4718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				user_datum_destroy(dest_user);
4728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(dest_user);
4738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return NULL;
4748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
4758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
4768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(dest_id);
4778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
4798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(dest_id);
4808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
4818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
4828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
4838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
4848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
4858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
4878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of user");
4888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
4898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
4918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not declare user here");
4928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
4938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
4958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return dest_user;
4968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
4978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
4988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return dest_user;	/* user already declared for this block */
4998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
5018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
5028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
5048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
5058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Return a type_datum_t for the local avrule_decl with the given ID.
5078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * If it does not exist, create one with the same value as 'value'.
5088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * This function assumes that the ID is within scope.  c.f.,
5098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * is_id_in_scope().
5108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *
5118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * NOTE: this function usurps ownership of id afterwards.  The caller
5128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * shall not reference it nor free() it afterwards.
5138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
5148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidtype_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
5158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
5168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type_datum_t *dest_typdatum;
5178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	hashtab_t types_tab;
5188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
5198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack_top->parent == NULL) {
5208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* in global, so use global symbol table */
5218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		types_tab = policydbp->p_types.table;
5228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
5238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		types_tab = stack_top->decl->p_types.table;
5248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
5258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	dest_typdatum = hashtab_search(types_tab, id);
5268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!dest_typdatum) {
5278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
5288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_typdatum == NULL) {
5298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(id);
5308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		type_datum_init(dest_typdatum);
5338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_typdatum->s.value = value;
5348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
5358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_typdatum->primary = 1;
5368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (hashtab_insert(types_tab, id, dest_typdatum)) {
5378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(id);
5388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			type_datum_destroy(dest_typdatum);
5398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(dest_typdatum);
5408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
5448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
5458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) {
5468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
5498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return dest_typdatum;
5508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
5518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Return a role_datum_t for the local avrule_decl with the given ID.
5538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * If it does not exist, create one with the same value as 'value'.
5548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * This function assumes that the ID is within scope.  c.f.,
5558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * is_id_in_scope().
5568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android *
5578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * NOTE: this function usurps ownership of id afterwards.  The caller
5588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * shall not reference it nor free() it afterwards.
5598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
5608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidrole_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
5618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
5628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_t *dest_roledatum;
5638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	hashtab_t roles_tab;
5648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
5668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack_top->parent == NULL) {
5688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* in global, so use global symbol table */
5698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		roles_tab = policydbp->p_roles.table;
5708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
5718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		roles_tab = stack_top->decl->p_roles.table;
5728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
5738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	dest_roledatum = hashtab_search(roles_tab, id);
5758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!dest_roledatum) {
5768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
5778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_roledatum == NULL) {
5788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(id);
5798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		role_datum_init(dest_roledatum);
5838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_roledatum->s.value = value;
5848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
5858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (hashtab_insert(roles_tab, id, dest_roledatum)) {
5878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(id);
5888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			role_datum_destroy(dest_roledatum);
5898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(dest_roledatum);
5908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
5928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
5938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
5948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE)
5958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return NULL;
5968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
5978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
5988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return dest_roledatum;
5998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
6008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Given the current parse stack, returns 1 if a requirement would be
6028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * allowed here or 0 if not.  For example, the ELSE branch may never
6038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * have its own requirements.
6048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
6058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int is_require_allowed(void)
6068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
6078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack_top->type == 1 && !stack_top->in_else) {
6088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;
6098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
6108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
6118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
6128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Attempt to require a symbol within the current scope.  If currently
6148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * within an optional (and not its else branch), add the symbol to the
6158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * required list.  Return 0 on success, 1 if caller needs to free()
6168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * datum.  If symbols may not be declared here return -1.  For duplicate
6178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * declarations return -2.  For all else, including out of memory,
6188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * return -3..  Note that dest_value and datum_value might not be
6198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * restricted pointers.
6208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android */
6218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_symbol(uint32_t symbol_type,
6228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		   hashtab_key_t key, hashtab_datum_t datum,
6238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		   uint32_t * dest_value, uint32_t * datum_value)
6248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
6258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
6268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
6278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* first check that symbols may be required here */
6298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!is_require_allowed()) {
6308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
6318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
6328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval = symtab_insert(policydbp, symbol_type, key, datum,
6338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			       SCOPE_REQ, decl->decl_id, dest_value);
6348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval == 1) {
6358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		symtab_datum_t *s =
6368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    (symtab_datum_t *) hashtab_search(policydbp->
6378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android						      symtab[symbol_type].table,
6388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android						      key);
6398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(s != NULL);
6408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (symbol_type == SYM_LEVELS) {
6428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			*dest_value = ((level_datum_t *)s)->level->sens;
6438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
6448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			*dest_value = s->value;
6458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
6468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else if (retval == -2) {
6478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* ignore require statements if that symbol was
6488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		 * previously declared and is in current scope */
6498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		int prev_declaration_ok = 0;
6508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (is_id_in_scope(symbol_type, key)) {
6518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (symbol_type == SYM_TYPES) {
6528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				/* check that previous symbol has same
6538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				 * type/attribute-ness */
6548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				unsigned char new_isattr =
6558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    ((type_datum_t *) datum)->flavor;
6568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				type_datum_t *old_datum =
6578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    (type_datum_t *) hashtab_search(policydbp->
6588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android								    symtab
6598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android								    [SYM_TYPES].
6608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android								    table, key);
6618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				assert(old_datum != NULL);
6628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				unsigned char old_isattr = old_datum->flavor;
6638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				prev_declaration_ok =
6648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    (old_isattr == new_isattr ? 1 : 0);
6658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			} else {
6668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				prev_declaration_ok = 1;
6678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
6688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
6698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (prev_declaration_ok) {
6708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* ignore this require statement because it
6718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 * was already declared within my scope */
6728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			stack_top->require_given = 1;
6738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 1;
6748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
6758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* previous declaration was not in scope or
6768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 * had a mismatched type/attribute, so
6778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			 * generate an error */
6788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -2;
6798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
6808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else if (retval < 0) {
6818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -3;
6828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {		/* fall through possible if retval is 0 or 1 */
6838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
6848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (datum_value != NULL) {
6858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (ebitmap_set_bit(decl->required.scope + symbol_type,
6868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    *datum_value - 1, 1)) {
6878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -3;
6888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
6898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
6908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->require_given = 1;
6918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return retval;
6928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
6938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint add_perm_to_class(uint32_t perm_value, uint32_t class_value)
6958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
6968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
6978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	scope_index_t *scope;
6988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
6998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(perm_value >= 1);
7008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(class_value >= 1);
7018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	scope = &decl->required;
7028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (class_value > scope->class_perms_len) {
7038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		int i;
7048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		ebitmap_t *new_map = realloc(scope->class_perms_map,
7058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					     class_value * sizeof(*new_map));
7068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (new_map == NULL) {
7078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
7088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		scope->class_perms_map = new_map;
7108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (i = scope->class_perms_len; i < class_value; i++) {
7118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_init(scope->class_perms_map + i);
7128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		scope->class_perms_len = class_value;
7148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (ebitmap_set_bit(scope->class_perms_map + class_value - 1,
7168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    perm_value - 1, 1)) {
7178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
7188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
7208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
7218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
7238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			__attribute__ ((unused)))
7248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
7258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (key)
7268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(key);
7278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	free(datum);
7288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
7298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
7308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic void class_datum_destroy(class_datum_t * cladatum)
7328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
7338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (cladatum != NULL) {
7348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
7358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		hashtab_destroy(cladatum->permissions.table);
7368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(cladatum);
7378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
7398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_class(int pass)
7418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
7428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *class_id = queue_remove(id_queue);
7438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *perm_id = NULL;
7448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	class_datum_t *datum = NULL;
7458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	perm_datum_t *perm = NULL;
7468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int ret;
7478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
7498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(class_id);
7508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		while ((perm_id = queue_remove(id_queue)) != NULL)
7518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(perm_id);
7528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
7538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* first add the class if it is not already there */
7568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (class_id == NULL) {
7578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no class name for class definition?");
7588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
7598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
7618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((datum = calloc(1, sizeof(*datum))) == NULL ||
7628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
7638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
7648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		goto cleanup;
7658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
7668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	ret =
7678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
7688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &datum->s.value);
7698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (ret) {
7708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
7718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
7728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(class_id);
7738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			class_datum_destroy(datum);
7748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			goto cleanup;
7758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
7778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of class");
7788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(class_id);
7798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			class_datum_destroy(datum);
7808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			goto cleanup;
7818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
7838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require class here");
7848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(class_id);
7858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			class_datum_destroy(datum);
7868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			goto cleanup;
7878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
7898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* a new class was added; reindex everything */
7908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (policydb_index_classes(policydbp)) {
7918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
7928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				goto cleanup;
7938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
7948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			break;
7958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
7968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
7978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			class_datum_destroy(datum);
7988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			datum =
7998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    hashtab_search(policydbp->p_classes.table,
8008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					   class_id);
8018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(datum);	/* the class datum should have existed */
8028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(class_id);
8038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			break;
8048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
8058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
8068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
8078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
8088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
8108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* now add each of the permissions to this class's requirements */
8118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	while ((perm_id = queue_remove(id_queue)) != NULL) {
8128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		int allocated = 0;
8138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
8148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* Is the permission already in the table? */
8158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		perm = hashtab_search(datum->permissions.table, perm_id);
8168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (!perm && datum->comdatum)
8178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			perm =
8188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    hashtab_search(datum->comdatum->permissions.table,
8198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					   perm_id);
8208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (perm) {
8218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* Yes, drop the name. */
8228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			free(perm_id);
8238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
8248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* No - allocate and insert an entry for it. */
8258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (policydbp->policy_type == POLICY_BASE) {
8268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror2
8278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    ("Base policy - require of permission %s without prior declaration.",
8288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				     perm_id);
8298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(perm_id);
8308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				goto cleanup;
8318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
8328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			allocated = 1;
8338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if ((perm = malloc(sizeof(*perm))) == NULL) {
8348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
8358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(perm_id);
8368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				goto cleanup;
8378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
8388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			memset(perm, 0, sizeof(*perm));
8398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ret =
8408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    hashtab_insert(datum->permissions.table, perm_id,
8418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					   perm);
8428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (ret) {
8438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
8448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(perm_id);
8458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				free(perm);
8468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				goto cleanup;
8478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
8488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			perm->s.value = datum->permissions.nprim + 1;
8498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
8508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
8518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
8528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
8538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			goto cleanup;
8548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
8558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
8568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* Update number of primitives if we allocated one. */
8578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (allocated)
8588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			datum->permissions.nprim++;
8598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
8618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android      cleanup:
8628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return -1;
8638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
8648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
8658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int require_role_or_attribute(int pass, unsigned char isattr)
8668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
8678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
8688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_t *role = NULL;
8698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
8708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
8718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
8728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
8738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
8758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no role name");
8768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
8778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((role = malloc(sizeof(*role))) == NULL) {
8798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
8808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
8818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
8828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_datum_init(role);
8848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
8858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
8868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role,
8878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &role->s.value, &role->s.value);
8888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
8898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
8908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		role_datum_destroy(role);
8918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(role);
8928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
8938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
8948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
8958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
8968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
8978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
8988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
8998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of role");
9008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
9018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
9038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require role here");
9048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
9058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
9078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* all roles dominate themselves */
9088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (ebitmap_set_bit
9098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    (&role->dominates, role->s.value - 1, 1)) {
9108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory");
9118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
9128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
9138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
9148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
9168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* role already required */
9178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
9198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
9208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_role(int pass)
9258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return require_role_or_attribute(pass, 0);
9278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_attribute_role(int pass)
9308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return require_role_or_attribute(pass, 1);
9328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int require_type_or_attribute(int pass, unsigned char isattr)
9358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
9378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type_datum_t *type = NULL;
9388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
9398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
9408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
9418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
9428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
9448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no type name");
9458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
9468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((type = malloc(sizeof(*type))) == NULL) {
9488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
9498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
9508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
9518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type_datum_init(type);
9538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type->primary = 1;
9548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	type->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
9558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
9568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    require_symbol(SYM_TYPES, id, (hashtab_datum_t *) type,
9578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &type->s.value, &type->s.value);
9588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
9598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
9608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(type);
9618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
9638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
9648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
9658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
9668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
9688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of type/attribute");
9698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
9708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
9728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require type/attribute here");
9738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
9748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
9768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
9778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
9798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* type already required */
9808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
9828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
9838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
9848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
9858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_type(int pass)
9888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return require_type_or_attribute(pass, 0);
9908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_attribute(int pass)
9938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return require_type_or_attribute(pass, 1);
9958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
9968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
9978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_user(int pass)
9988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
9998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
10008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	user_datum_t *user = NULL;
10018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
10028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 1) {
10038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
10048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
10058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
10078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no user name");
10088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
10098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((user = malloc(sizeof(*user))) == NULL) {
10118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
10128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
10138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
10148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	user_datum_init(user);
10168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
10178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    require_symbol(SYM_USERS, id, (hashtab_datum_t *) user,
10188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &user->s.value, &user->s.value);
10198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
10208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
10218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		user_datum_destroy(user);
10228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
10248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
10258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
10268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
10298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of user");
10308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
10338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require user here");
10348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
10378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
10388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
10408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* user already required */
10418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
10438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
10448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
10478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1048cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalleystatic int require_bool_tunable(int pass, int is_tunable)
10498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
10508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
10518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cond_bool_datum_t *booldatum = NULL;
10528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
10538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
10548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
10558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
10568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (id == NULL) {
10588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no boolean name");
10598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
10608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
10628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		cond_destroy_bool(id, booldatum, NULL);
10638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
10648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
10658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1066cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley	if (is_tunable)
1067cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley		booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
10688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval =
10698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
10708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			   &booldatum->s.value, &booldatum->s.value);
10718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
10728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		cond_destroy_bool(id, booldatum, NULL);
10738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
10758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
10768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
10778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
10808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of boolean");
10818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
10848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require boolean here");
10858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
10868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
10888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
10898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
10918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* boolean already required */
10928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
10948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
10958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
10968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
10978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
10988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
1099cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalleyint require_bool(int pass)
1100cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley{
1101cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley	return require_bool_tunable(pass, 0);
1102cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley}
1103cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley
1104cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalleyint require_tunable(int pass)
1105cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley{
1106cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley	return require_bool_tunable(pass, 1);
1107cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley}
1108cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley
11098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_sens(int pass)
11108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
11118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
11128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	level_datum_t *level = NULL;
11138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
11148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
11158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
11178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!id) {
11198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no sensitivity name");
11208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
11218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	level = malloc(sizeof(level_datum_t));
11238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!level) {
11248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
11268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
11278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	level_datum_init(level);
11298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	level->level = malloc(sizeof(mls_level_t));
11308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!level->level) {
11318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		level_datum_destroy(level);
11338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(level);
11348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
11358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
11368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	mls_level_init(level->level);
11388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level,
11398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				&level->level->sens, &level->level->sens);
11408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
11418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		mls_level_destroy(level->level);
11438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(level->level);
11448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		level_datum_destroy(level);
11458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(level);
11468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
11488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
11498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
11508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
11518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
11538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of sensitivity");
11548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
11558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
11578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require sensitivity here");
11588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
11598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
11618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
11628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
11648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* sensitivity already required */
11658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
11678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
11688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
11698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
11718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
11728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint require_cat(int pass)
11738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
11748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	char *id = queue_remove(id_queue);
11758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cat_datum_t *cat = NULL;
11768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int retval;
11778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
11788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
11808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!id) {
11828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("no category name");
11838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
11848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cat = malloc(sizeof(cat_datum_t));
11868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!cat) {
11878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		yyerror("Out of memory!");
11898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
11908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
11918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cat_datum_init(cat);
11928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
11938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat,
11948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				&cat->s.value, &cat->s.value);
11958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (retval != 0) {
11968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(id);
11978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		cat_datum_destroy(cat);
11988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		free(cat);
11998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (retval) {
12018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -3:{
12028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
12038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
12048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -2:{
12068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("duplicate declaration of category");
12078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
12088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case -1:{
12108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("could not require category here");
12118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
12128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 0:{
12148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
12158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
12178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;	/* category already required */
12188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:{
12208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			assert(0);	/* should never get here */
12218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
12248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
12268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
12278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int i;
12288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack == NULL) {
12298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;	/* no matching scope found */
12308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack->type == 1) {
12328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		avrule_decl_t *decl = stack->decl;
12338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (i = 0; i < scope->decl_ids_len; i++) {
12348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (scope->decl_ids[i] == decl->decl_id) {
12358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return 1;
12368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
12378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
12398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* note that conditionals can't declare or require
12408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		 * symbols, so skip this level */
12418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* not within scope of this stack, so try its parent */
12448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return is_scope_in_stack(scope, stack->parent);
12458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
12468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
12488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
12498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	scope_datum_t *scope =
12508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
12518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					     table, id);
12528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (scope == NULL) {
12538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;	/* id is not known, so return success */
12548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return is_scope_in_stack(scope, stack_top);
12568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
12578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
12598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				  scope_index_t * scope)
12608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
12618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (class_value > scope->class_perms_len) {
12628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;
12638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (ebitmap_get_bit(scope->class_perms_map + class_value - 1,
12658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    perm_value - 1)) {
12668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;
12678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
12698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
12708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
12728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    scope_stack_t * stack)
12738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
12748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack == NULL) {
12758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;	/* no matching scope found */
12768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack->type == 1) {
12788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		avrule_decl_t *decl = stack->decl;
12798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (is_perm_in_scope_index
12808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    (perm_value, class_value, &decl->required)
12818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    || is_perm_in_scope_index(perm_value, class_value,
12828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					      &decl->declared)) {
12838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 1;
12848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
12858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
12868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* note that conditionals can't declare or require
12878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		 * symbols, so skip this level */
12888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
12898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* not within scope of this stack, so try its parent */
12918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return is_perm_in_stack(perm_value, class_value, stack->parent);
12928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
12938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
12948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
12958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
12968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	class_datum_t *cladatum =
12978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
12988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android					     class_id);
12998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	perm_datum_t *perdatum;
13008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (cladatum == NULL) {
13018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;
13028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
13038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
13048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android						   perm_id);
13058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (perdatum == NULL) {
13068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 1;
13078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
13088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return is_perm_in_stack(perdatum->s.value, cladatum->s.value,
13098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				stack_top);
13108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidcond_list_t *get_current_cond_list(cond_list_t * cond)
13138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* FIX ME: do something different here if in a nested
13158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	 * conditional? */
13168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
13178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return get_decl_cond_list(policydbp, decl, cond);
13188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Append the new conditional node to the existing ones.  During
13218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * expansion the list will be reversed -- i.e., the last AV rule will
13228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * be the first one listed in the policy.  This matches the behavior
13238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * of the upstream compiler. */
13248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_cond_list(cond_list_t * cond)
13258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	cond_list_t *old_cond = get_current_cond_list(cond);
13278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_t *tmp;
13288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(old_cond != NULL);	/* probably out of memory */
13298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (old_cond->avtrue_list == NULL) {
13308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		old_cond->avtrue_list = cond->avtrue_list;
13318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
13328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (tmp = old_cond->avtrue_list; tmp->next != NULL;
13338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		     tmp = tmp->next) ;
13348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		tmp->next = cond->avtrue_list;
13358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
13368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (old_cond->avfalse_list == NULL) {
13378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		old_cond->avfalse_list = cond->avfalse_list;
13388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
13398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (tmp = old_cond->avfalse_list; tmp->next != NULL;
13408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		     tmp = tmp->next) ;
13418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		tmp->next = cond->avfalse_list;
13428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
1343cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley
1344cd88c5c44f93ca14828bdae024fae6e0287ba71dStephen Smalley	old_cond->flags |= cond->flags;
13458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_avrule(avrule_t * avrule)
13488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
13508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* currently avrules follow a completely different code path
13528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	 * for handling avrules and compute types
13538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	 * (define_cond_avrule_te_avtab, define_cond_compute_type);
13548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	 * therefore there ought never be a conditional on top of the
13558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	 * scope stack */
13568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
13578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack_top->last_avrule == NULL) {
13598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		decl->avrules = avrule;
13608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
13618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		stack_top->last_avrule->next = avrule;
13628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
13638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->last_avrule = avrule;
13648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* this doesn't actually append, but really prepends it */
13678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_role_trans(role_trans_rule_t * role_tr_rules)
13688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
13708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* role transitions are not allowed within conditionals */
13728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
13738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_tr_rules->next = decl->role_tr_rules;
13758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	decl->role_tr_rules = role_tr_rules;
13768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* this doesn't actually append, but really prepends it */
13798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_role_allow(role_allow_rule_t * role_allow_rules)
13808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
13828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* role allows are not allowed within conditionals */
13848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
13858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	role_allow_rules->next = decl->role_allow_rules;
13878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	decl->role_allow_rules = role_allow_rules;
13888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
13898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* this doesn't actually append, but really prepends it */
13918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_filename_trans(filename_trans_rule_t * filename_trans_rules)
13928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
13938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
13948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* filename transitions are not allowed within conditionals */
13968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
13978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
13988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	filename_trans_rules->next = decl->filename_trans_rules;
13998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	decl->filename_trans_rules = filename_trans_rules;
14008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
14018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* this doesn't actually append, but really prepends it */
14038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidvoid append_range_trans(range_trans_rule_t * range_tr_rules)
14048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
14058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
14068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* range transitions are not allowed within conditionals */
14088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
14098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	range_tr_rules->next = decl->range_tr_rules;
14118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	decl->range_tr_rules = range_tr_rules;
14128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
14138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint begin_optional(int pass)
14158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
14168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_block_t *block = NULL;
14178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl;
14188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 1) {
14198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* allocate a new avrule block for this optional block */
14208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if ((block = avrule_block_create()) == NULL ||
14218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    (decl = avrule_decl_create(next_decl_id)) == NULL) {
14228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			goto cleanup;
14238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
14248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		block->flags |= AVRULE_OPTIONAL;
14258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		block->branch_list = decl;
14268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		last_block->next = block;
14278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
14288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* select the next block from the chain built during pass 1 */
14298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		block = last_block->next;
14308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(block != NULL &&
14318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		       block->branch_list != NULL &&
14328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		       block->branch_list->decl_id == next_decl_id);
14338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		decl = block->branch_list;
14348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
14358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (push_stack(1, block, decl) == -1) {
14368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		goto cleanup;
14378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
14388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->last_avrule = NULL;
14398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	last_block = block;
14408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	next_decl_id++;
14418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
14428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android      cleanup:
14438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	yyerror("Out of memory!");
14448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_block_destroy(block);
14458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return -1;
14468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
14478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint end_optional(int pass)
14498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
14508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	/* once nested conditionals are allowed, do the stack unfolding here */
14518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	pop_stack();
14528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
14538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
14548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint begin_optional_else(int pass)
14568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
14578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl;
14588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1 && stack_top->in_else == 0);
14598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 1) {
14608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* allocate a new declaration and add it to the
14618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		 * current chain */
14628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
14638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("Out of memory!");
14648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
14658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
14668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		stack_top->decl->next = decl;
14678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	} else {
14688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* pick the (hopefully last) declaration of this
14698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		   avrule block, built from pass 1 */
14708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		decl = stack_top->decl->next;
14718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(decl != NULL &&
14728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		       decl->next == NULL && decl->decl_id == next_decl_id);
14738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
14748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->in_else = 1;
14758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->decl = decl;
14768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->last_avrule = NULL;
14778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top->require_given = 0;
14788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	next_decl_id++;
14798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
14808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
14818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
14828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
14838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
14848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	int i;
14858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack == NULL) {
14868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
14878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
14888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (stack->type == 1) {
14898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		scope_index_t *src_scope = &stack->decl->required;
14908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		scope_index_t *dest_scope = &dest->required;
14918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (i = 0; i < SYM_NUM; i++) {
14928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_t *src_bitmap = &src_scope->scope[i];
14938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_t *dest_bitmap = &dest_scope->scope[i];
14948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (ebitmap_union(dest_bitmap, src_bitmap)) {
14958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
14968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
14978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
14988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
14998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* now copy class permissions */
15008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (src_scope->class_perms_len > dest_scope->class_perms_len) {
15018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_t *new_map =
15028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    realloc(dest_scope->class_perms_map,
15038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    src_scope->class_perms_len *
15048c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				    sizeof(*new_map));
15058c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (new_map == NULL) {
15068c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
15078c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
15088c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
15098c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			dest_scope->class_perms_map = new_map;
15108c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			for (i = dest_scope->class_perms_len;
15118c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			     i < src_scope->class_perms_len; i++) {
15128c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				ebitmap_init(dest_scope->class_perms_map + i);
15138c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
15148c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			dest_scope->class_perms_len =
15158c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    src_scope->class_perms_len;
15168c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15178c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		for (i = 0; i < src_scope->class_perms_len; i++) {
15188c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
15198c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			ebitmap_t *dest_bitmap =
15208c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			    &dest_scope->class_perms_map[i];
15218c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			if (ebitmap_union(dest_bitmap, src_bitmap)) {
15228c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				yyerror("Out of memory!");
15238c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android				return -1;
15248c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			}
15258c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15268c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
15278c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return copy_requirements(dest, stack->parent);
15288c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
15298c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
15308c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* During pass 1, check that at least one thing was required within
15318c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * this block, for those places where a REQUIRED is necessary.  During
15328c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * pass 2, have this block inherit its parents' requirements.  Return
15338c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * 0 on success, -1 on failure. */
15348c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidint end_avrule_block(int pass)
15358c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
15368c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	avrule_decl_t *decl = stack_top->decl;
15378c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top->type == 1);
15388c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (pass == 2) {
15398c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* this avrule_decl inherits all of its parents'
15408c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		 * requirements */
15418c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (copy_requirements(decl, stack_top->parent) == -1) {
15428c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
15438c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15448c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return 0;
15458c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
15468c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (!stack_top->in_else && !stack_top->require_given) {
15478c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		if (policydbp->policy_type == POLICY_BASE
15488c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		    && stack_top->parent != NULL) {
15498c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* if this is base no require should be in the global block */
15508c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return 0;
15518c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		} else {
15528c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			/* non-ELSE branches must have at least one thing required */
15538c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			yyerror("This block has no require section.");
15548c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			return -1;
15558c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15568c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
15578c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
15588c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
15598c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
15608c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Push a new scope on to the stack and update the 'last' pointer.
15618c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * Return 0 on success, -1 if out * of memory. */
15628c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic int push_stack(int stack_type, ...)
15638c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
15648c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	scope_stack_t *s = calloc(1, sizeof(*s));
15658c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	va_list ap;
15668c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (s == NULL) {
15678c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		return -1;
15688c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
15698c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	va_start(ap, stack_type);
15708c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	switch (s->type = stack_type) {
15718c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 1:{
15728c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			s->u.avrule = va_arg(ap, avrule_block_t *);
15738c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			s->decl = va_arg(ap, avrule_decl_t *);
15748c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			break;
15758c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15768c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	case 2:{
15778c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			s->u.cond_list = va_arg(ap, cond_list_t *);
15788c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android			break;
15798c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		}
15808c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	default:
15818c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		/* invalid stack type given */
15828c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		assert(0);
15838c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
15848c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	va_end(ap);
15858c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	s->parent = stack_top;
15868c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	s->child = NULL;
15878c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top = s;
15888c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	return 0;
15898c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
15908c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android
15918c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android/* Pop off the most recently added from the stack.  Update the 'last'
15928c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android * pointer. */
15938c48de15b1afeb1cd01a753195a29b1a7811dbfSE Androidstatic void pop_stack(void)
15948c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android{
15958c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	scope_stack_t *parent;
15968c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	assert(stack_top != NULL);
15978c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	parent = stack_top->parent;
15988c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	if (parent != NULL) {
15998c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android		parent->child = NULL;
16008c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	}
16018c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	free(stack_top);
16028c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android	stack_top = parent;
16038c48de15b1afeb1cd01a753195a29b1a7811dbfSE Android}
1604