113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Author : Joshua Brindle <jbrindle@tresys.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	    Karl MacMillan <kmacmillan@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *          Jason Tang     <jtang@tresys.com>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	Added support for binary policy modules
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2004 - 2005 Tresys Technology, LLC
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	This program is free software; you can redistribute it and/or modify
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  	it under the terms of the GNU General Public License as published by
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	the Free Software Foundation, version 2.
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <assert.h>
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdarg.h>
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/policydb.h>
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/avrule_block.h>
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/conditional.h>
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "queue.h"
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "module_compiler.h"
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleunion stack_item_u {
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *avrule;
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_list_t *cond_list;
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct scope_stack {
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	union stack_item_u u;
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int type;		/* for above union: 1 = avrule block, 2 = conditional */
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl;	/* if in an avrule block, which
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 * declaration is current */
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *last_avrule;
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int in_else;		/* if in an avrule block, within ELSE branch */
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int require_given;	/* 1 if this block had at least one require */
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct scope_stack *parent, *child;
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} scope_stack_t;
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern policydb_t *policydbp;
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern queue_t id_queue;
42832e7017f881f0a66e24170b7a2ff1cd9b113239Nicolas Ioossextern int yyerror(const char *msg);
438db96d0cb4feb1323488a5e04a3d4623ba22ffceNicolas Iooss__attribute__ ((format(printf, 1, 2)))
44832e7017f881f0a66e24170b7a2ff1cd9b113239Nicolas Ioossextern void yyerror2(const char *fmt, ...);
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int push_stack(int stack_type, ...);
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void pop_stack(void);
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* keep track of the last item added to the stack */
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic scope_stack_t *stack_top = NULL;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic avrule_block_t *last_block;
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic uint32_t next_decl_id = 1;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint define_policy(int pass, int module_header_given)
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (module_header_given) {
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policydbp->policy_type != POLICY_MOD) {
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    ("Module specification found while not building a policy module.\n");
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (pass == 2) {
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			while ((id = queue_remove(id_queue)) != NULL)
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(id);
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			id = (char *)queue_remove(id_queue);
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!id) {
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("no module name");
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			policydbp->name = id;
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((policydbp->version =
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     queue_remove(id_queue)) == NULL) {
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    ("Expected a module version but none was found.");
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policydbp->policy_type == POLICY_MOD) {
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    ("Building a policy module, but no module specification found.\n");
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* the first declaration within the global avrule
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   block will always have an id of 1 */
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	next_decl_id = 2;
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* reset the scoping stack */
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (stack_top != NULL) {
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		pop_stack();
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (push_stack(1, policydbp->global, policydbp->global->branch_list) ==
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    -1) {
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	last_block = policydbp->global;
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Given the current parse stack, returns 1 if a declaration would be
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * allowed here or 0 if not.  For example, declarations are not
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * allowed in conditionals, so if there are any conditionals in the
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * current scope stack then this would return a 0.
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_declaration_allowed(void)
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack_top->type != 1 || stack_top->in_else) {
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 1;
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Attempt to declare a symbol within the current declaration.  If
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * currently within a non-conditional and in a non-else branch then
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * insert the symbol, return 0 on success if symbol was undeclared.
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * For roles and users, it is legal to have multiple declarations; as
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * such return 1 to indicate that caller must free() the datum because
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * it was not added.  If symbols may not be declared here return -1.
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * For duplicate declarations return -2.  For all else, including out
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * of memory, return -3.  Note that dest_value and datum_value might
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * not be restricted pointers. */
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint declare_symbol(uint32_t symbol_type,
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   hashtab_key_t key, hashtab_datum_t datum,
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   uint32_t * dest_value, uint32_t * datum_value)
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* first check that symbols may be declared here */
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_declaration_allowed()) {
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = symtab_insert(policydbp, symbol_type, key, datum,
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       SCOPE_DECL, decl->decl_id, dest_value);
140f7917ea9cf6af752de98a1e742152d813028c669Caleb Case	if (retval == 1 && dest_value) {
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		symtab_datum_t *s =
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (symtab_datum_t *) hashtab_search(policydbp->
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      symtab[symbol_type].table,
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      key);
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(s != NULL);
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (symbol_type == SYM_LEVELS) {
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dest_value = ((level_datum_t *)s)->level->sens;
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dest_value = s->value;
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (retval == -2) {
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -2;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (retval < 0) {
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -3;
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {		/* fall through possible if retval is 0 */
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (datum_value != NULL) {
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(decl->declared.scope + symbol_type,
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    *datum_value - 1, 1)) {
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -3;
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindlestatic int role_implicit_bounds(hashtab_t roles_tab,
16845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				char *role_id, role_datum_t *role)
16945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle{
17045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	role_datum_t *bounds;
17145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	char *bounds_id, *delim;
17245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
17345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	delim = strrchr(role_id, '.');
17445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!delim)
17545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return 0;	/* no implicit boundary */
17645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
17745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds_id = strdup(role_id);
17845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!bounds_id) {
17945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror("out of memory");
18045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
18145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
18245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds_id[(size_t)(delim - role_id)] = '\0';
18345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
18445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds = hashtab_search(roles_tab, bounds_id);
18545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!bounds) {
18645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror2("role %s doesn't exist, is implicit bounds of %s",
18745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 bounds_id, role_id);
18845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
18945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
19045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
19145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!role->bounds)
19245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		role->bounds = bounds->s.value;
19345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	else if (role->bounds != bounds->s.value) {
19445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror2("role %s has inconsistent bounds %s/%s",
19545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 role_id, bounds_id,
19645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 policydbp->p_role_val_to_name[role->bounds - 1]);
19745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
19845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
19945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	free(bounds_id);
20045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
20145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	return 0;
20245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle}
20345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
20416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciaorole_datum_t *declare_role(unsigned char isattr)
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue), *dest_id = NULL;
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role = NULL, *dest_role = NULL;
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t value;
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no role name");
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) {
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_init(role);
22116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value,
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &value);
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0) {
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role->s.value = value;
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((dest_id = strdup(id)) == NULL) {
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this role was already declared in this module, or error */
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_id = id;
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_datum_destroy(role);
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(role);
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0 || retval == 1) {
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* create a new role_datum_t for this decl, if necessary */
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		hashtab_t roles_tab;
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(stack_top->type == 1);
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (stack_top->parent == NULL) {
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* in parent, so use global symbol table */
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			roles_tab = policydbp->p_roles.table;
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			roles_tab = stack_top->decl->p_roles.table;
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id);
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (dest_role == NULL) {
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((dest_role =
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (role_datum_t *) malloc(sizeof(*dest_role))) ==
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    NULL) {
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_id);
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			role_datum_init(dest_role);
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			dest_role->s.value = value;
25816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
25945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			if (role_implicit_bounds(roles_tab, dest_id, dest_role)) {
26045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				free(dest_id);
26145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				role_datum_destroy(dest_role);
26245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				free(dest_role);
26345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				return NULL;
26445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			}
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (hashtab_insert(roles_tab, dest_id, dest_role)) {
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_id);
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				role_datum_destroy(dest_role);
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_role);
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(dest_id);
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(dest_id);
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of role");
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not declare role here");
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&dest_role->dominates, role->s.value - 1, 1)) {
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("out of memory");
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return dest_role;
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return dest_role;	/* role already declared for this block */
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
303099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletype_datum_t *declare_type(unsigned char primary, unsigned char isattr)
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *typdatum;
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t value = 0;
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)queue_remove(id_queue);
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!id) {
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no type/attribute name?");
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (strcmp(id, "self") == 0) {
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    ("'self' is a reserved type name and may not be declared.");
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!typdatum) {
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_init(typdatum);
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	typdatum->primary = primary;
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = declare_symbol(SYM_TYPES, id, typdatum, &value, &value);
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0 || retval == 1) {
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (typdatum->primary) {
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			typdatum->s.value = value;
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* error occurred (can't have duplicate type declarations) */
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		type_datum_destroy(typdatum);
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(typdatum);
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror2("duplicate declaration of type/attribute");
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not declare type/attribute here");
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return typdatum;
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
366099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindlestatic int user_implicit_bounds(hashtab_t users_tab,
37245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				char *user_id, user_datum_t *user)
37345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle{
37445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	user_datum_t *bounds;
37545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	char *bounds_id, *delim;
37645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
37745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	delim = strrchr(user_id, '.');
37845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!delim)
37945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return 0;	/* no implicit boundary */
38045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
38145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds_id = strdup(user_id);
38245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!bounds_id) {
38345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror("out of memory");
38445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
38545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
38645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds_id[(size_t)(delim - user_id)] = '\0';
38745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
38845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	bounds = hashtab_search(users_tab, bounds_id);
38945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!bounds) {
39045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror2("user %s doesn't exist, is implicit bounds of %s",
39145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 bounds_id, user_id);
39245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
39345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
39445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
39545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	if (!user->bounds)
39645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		user->bounds = bounds->s.value;
39745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	else if (user->bounds != bounds->s.value) {
39845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		yyerror2("user %s has inconsistent bounds %s/%s",
39945728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 user_id, bounds_id,
40045728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			 policydbp->p_role_val_to_name[user->bounds - 1]);
40145728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle		return -1;
40245728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	}
40345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	free(bounds_id);
40445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
40545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle	return 0;
40645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle}
40745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleuser_datum_t *declare_user(void)
40913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
41013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue), *dest_id = NULL;
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user = NULL, *dest_user = NULL;
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t value = 0;
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no user name");
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) {
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_init(user);
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value,
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &value);
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0) {
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user->s.value = value;
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((dest_id = strdup(id)) == NULL) {
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this user was already declared in this module, or error */
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_id = id;
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user_datum_destroy(user);
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(user);
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0 || retval == 1) {
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* create a new user_datum_t for this decl, if necessary */
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		hashtab_t users_tab;
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(stack_top->type == 1);
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (stack_top->parent == NULL) {
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* in parent, so use global symbol table */
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			users_tab = policydbp->p_users.table;
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			users_tab = stack_top->decl->p_users.table;
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id);
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (dest_user == NULL) {
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((dest_user =
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (user_datum_t *) malloc(sizeof(*dest_user))) ==
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    NULL) {
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_id);
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			user_datum_init(dest_user);
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			dest_user->s.value = value;
46345728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			if (user_implicit_bounds(users_tab, dest_id, dest_user)) {
46445728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				free(dest_id);
46545728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				user_datum_destroy(dest_user);
46645728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				free(dest_user);
46745728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle				return NULL;
46845728407d60a5297deac7aa65fd92adf2412d5f7Joshua Brindle			}
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (hashtab_insert(users_tab, dest_id, dest_user)) {
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
47113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_id);
47213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				user_datum_destroy(dest_user);
47313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(dest_user);
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(dest_id);
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(dest_id);
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of user");
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not declare user here");
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return dest_user;
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return dest_user;	/* user already declared for this block */
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
502099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Return a type_datum_t for the local avrule_decl with the given ID.
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * If it does not exist, create one with the same value as 'value'.
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This function assumes that the ID is within scope.  c.f.,
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * is_id_in_scope().
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * NOTE: this function usurps ownership of id afterwards.  The caller
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * shall not reference it nor free() it afterwards.
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletype_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *dest_typdatum;
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t types_tab;
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack_top->parent == NULL) {
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* in global, so use global symbol table */
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		types_tab = policydbp->p_types.table;
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		types_tab = stack_top->decl->p_types.table;
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dest_typdatum = hashtab_search(types_tab, id);
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!dest_typdatum) {
52813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (dest_typdatum == NULL) {
53013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(id);
53113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
53213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
53313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		type_datum_init(dest_typdatum);
53413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_typdatum->s.value = value;
53513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
53613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_typdatum->primary = 1;
53713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_insert(types_tab, id, dest_typdatum)) {
53813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(id);
53913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			type_datum_destroy(dest_typdatum);
54013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(dest_typdatum);
54113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
54213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
54513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
54613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) {
54713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
54813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
54913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
55013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return dest_typdatum;
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao/* Return a role_datum_t for the local avrule_decl with the given ID.
55416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao * If it does not exist, create one with the same value as 'value'.
55516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao * This function assumes that the ID is within scope.  c.f.,
55616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao * is_id_in_scope().
55716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao *
55816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao * NOTE: this function usurps ownership of id afterwards.  The caller
55916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao * shall not reference it nor free() it afterwards.
56016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao */
56116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciaorole_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
56216675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao{
56316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	role_datum_t *dest_roledatum;
56416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	hashtab_t roles_tab;
56516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
56616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	assert(stack_top->type == 1);
56716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
56816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	if (stack_top->parent == NULL) {
56916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		/* in global, so use global symbol table */
57016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		roles_tab = policydbp->p_roles.table;
57116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	} else {
57216675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		roles_tab = stack_top->decl->p_roles.table;
57316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	}
57416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
57516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	dest_roledatum = hashtab_search(roles_tab, id);
57616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	if (!dest_roledatum) {
57716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
57816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		if (dest_roledatum == NULL) {
57916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			free(id);
58016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			return NULL;
58116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		}
58216675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
58316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		role_datum_init(dest_roledatum);
58416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		dest_roledatum->s.value = value;
58516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
58616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
58716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		if (hashtab_insert(roles_tab, id, dest_roledatum)) {
58816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			free(id);
58916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			role_datum_destroy(dest_roledatum);
59016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			free(dest_roledatum);
59116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			return NULL;
59216675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		}
59316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	} else {
59416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		free(id);
59516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao		if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE)
59616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao			return NULL;
59716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	}
59816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
59916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	return dest_roledatum;
60016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao}
60116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
60213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Given the current parse stack, returns 1 if a requirement would be
60313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * allowed here or 0 if not.  For example, the ELSE branch may never
60413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * have its own requirements.
60513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
60613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_require_allowed(void)
60713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
60813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack_top->type == 1 && !stack_top->in_else) {
60913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
61013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
61113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
61213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
61313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Attempt to require a symbol within the current scope.  If currently
61513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * within an optional (and not its else branch), add the symbol to the
61613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * required list.  Return 0 on success, 1 if caller needs to free()
61713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * datum.  If symbols may not be declared here return -1.  For duplicate
61813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * declarations return -2.  For all else, including out of memory,
61913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * return -3..  Note that dest_value and datum_value might not be
62013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * restricted pointers.
62113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
62213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_symbol(uint32_t symbol_type,
62313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   hashtab_key_t key, hashtab_datum_t datum,
62413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   uint32_t * dest_value, uint32_t * datum_value)
62513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
62613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
62713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
62813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
62913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* first check that symbols may be required here */
63013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_require_allowed()) {
63113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
63213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
63313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = symtab_insert(policydbp, symbol_type, key, datum,
63413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       SCOPE_REQ, decl->decl_id, dest_value);
63513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 1) {
63613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		symtab_datum_t *s =
63713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (symtab_datum_t *) hashtab_search(policydbp->
63813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      symtab[symbol_type].table,
63913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      key);
64013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(s != NULL);
64113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (symbol_type == SYM_LEVELS) {
64313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dest_value = ((level_datum_t *)s)->level->sens;
64413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
64513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dest_value = s->value;
64613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
64713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (retval == -2) {
64813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* ignore require statements if that symbol was
64913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * previously declared and is in current scope */
65013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		int prev_declaration_ok = 0;
65113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (is_id_in_scope(symbol_type, key)) {
65213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (symbol_type == SYM_TYPES) {
65313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* check that previous symbol has same
65413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 * type/attribute-ness */
65513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned char new_isattr =
65613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    ((type_datum_t *) datum)->flavor;
65713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				type_datum_t *old_datum =
65813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (type_datum_t *) hashtab_search(policydbp->
65913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    symtab
66013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    [SYM_TYPES].
66113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    table, key);
66213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(old_datum != NULL);
66313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned char old_isattr = old_datum->flavor;
66413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				prev_declaration_ok =
66513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (old_isattr == new_isattr ? 1 : 0);
66613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
66713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				prev_declaration_ok = 1;
66813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
66913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
67013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (prev_declaration_ok) {
67113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* ignore this require statement because it
67213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * was already declared within my scope */
67313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			stack_top->require_given = 1;
67413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 1;
67513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
67613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* previous declaration was not in scope or
67713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * had a mismatched type/attribute, so
67813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * generate an error */
67913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -2;
68013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
68113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (retval < 0) {
68213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -3;
68313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {		/* fall through possible if retval is 0 or 1 */
68413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
68513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (datum_value != NULL) {
68613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(decl->required.scope + symbol_type,
68713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    *datum_value - 1, 1)) {
68813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -3;
68913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
69013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
69113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->require_given = 1;
69213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
69313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
69413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint add_perm_to_class(uint32_t perm_value, uint32_t class_value)
69613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
69713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
69813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_index_t *scope;
69913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(perm_value >= 1);
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(class_value >= 1);
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope = &decl->required;
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (class_value > scope->class_perms_len) {
704581d3eb1281f7c970376649f5027df012269935aNicolas Iooss		uint32_t i;
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_t *new_map = realloc(scope->class_perms_map,
70613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     class_value * sizeof(*new_map));
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (new_map == NULL) {
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
70913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
71013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope->class_perms_map = new_map;
71113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = scope->class_perms_len; i < class_value; i++) {
71213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_init(scope->class_perms_map + i);
71313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
71413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope->class_perms_len = class_value;
71513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
71613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_set_bit(scope->class_perms_map + class_value - 1,
71713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    perm_value - 1, 1)) {
71813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
71913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
72013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
72113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
72213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
72313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
72413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			__attribute__ ((unused)))
72513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
72613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (key)
72713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(key);
72813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(datum);
72913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
73013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
73113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
73213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void class_datum_destroy(class_datum_t * cladatum)
73313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
73413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cladatum != NULL) {
73513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
73613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		hashtab_destroy(cladatum->permissions.table);
73713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(cladatum);
73813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
73913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
74013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_class(int pass)
74213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
74313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *class_id = queue_remove(id_queue);
74413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *perm_id = NULL;
74513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *datum = NULL;
74613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perm = NULL;
74713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
74813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
75013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(class_id);
75113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while ((perm_id = queue_remove(id_queue)) != NULL)
75213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(perm_id);
75313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
75413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
75513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
75613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* first add the class if it is not already there */
75713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (class_id == NULL) {
75813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no class name for class definition?");
75913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
76013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
76113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
76213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((datum = calloc(1, sizeof(*datum))) == NULL ||
76313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
76413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
76513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
76613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
76713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
76813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
76913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &datum->s.value);
77013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (ret) {
77113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
77213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
77313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(class_id);
77413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_datum_destroy(datum);
77513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
77613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
77713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
77813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of class");
77913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(class_id);
78013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_datum_destroy(datum);
78113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
78213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
78313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
78413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require class here");
78513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(class_id);
78613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_datum_destroy(datum);
78713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
78813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
78913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
79013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* a new class was added; reindex everything */
79113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (policydb_index_classes(policydbp)) {
79213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
79313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
79413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
79513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
79613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
79713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
79813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_datum_destroy(datum);
79913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			datum =
80013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    hashtab_search(policydbp->p_classes.table,
80113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   class_id);
80213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(datum);	/* the class datum should have existed */
80313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(class_id);
80413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
80513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
80613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
807099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
80813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
80913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
81013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
81113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* now add each of the permissions to this class's requirements */
81213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while ((perm_id = queue_remove(id_queue)) != NULL) {
81313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		int allocated = 0;
81413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
81513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Is the permission already in the table? */
81613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		perm = hashtab_search(datum->permissions.table, perm_id);
81713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!perm && datum->comdatum)
81813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			perm =
81913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    hashtab_search(datum->comdatum->permissions.table,
82013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   perm_id);
82113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (perm) {
82213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* Yes, drop the name. */
82313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(perm_id);
82413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
82513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* No - allocate and insert an entry for it. */
82613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (policydbp->policy_type == POLICY_BASE) {
82713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror2
82813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    ("Base policy - require of permission %s without prior declaration.",
82913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     perm_id);
83013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(perm_id);
83113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
83213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
83313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			allocated = 1;
83413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((perm = malloc(sizeof(*perm))) == NULL) {
83513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
83613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(perm_id);
83713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
83813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
83913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(perm, 0, sizeof(*perm));
84013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret =
84113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    hashtab_insert(datum->permissions.table, perm_id,
84213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   perm);
84313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ret) {
84413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
84513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(perm_id);
84613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(perm);
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			perm->s.value = datum->permissions.nprim + 1;
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
85113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
85613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Update number of primitives if we allocated one. */
85813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (allocated)
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			datum->permissions.nprim++;
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciaostatic int require_role_or_attribute(int pass, unsigned char isattr)
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role = NULL;
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
87113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
87213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no role name");
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((role = malloc(sizeof(*role))) == NULL) {
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_init(role);
88516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role,
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &role->s.value, &role->s.value);
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_datum_destroy(role);
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(role);
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
89513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
89713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
89813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
90013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of role");
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
90213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
90313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
90413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require role here");
90513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
90613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
90713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
90813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* all roles dominate themselves */
90913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
91013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&role->dominates, role->s.value - 1, 1)) {
91113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory");
91213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
91313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
91413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* role already required */
91813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
920099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
92213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92516675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciaoint require_role(int pass)
92616675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao{
92716675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	return require_role_or_attribute(pass, 0);
92816675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao}
92916675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
93016675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciaoint require_attribute_role(int pass)
93116675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao{
93216675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao	return require_role_or_attribute(pass, 1);
93316675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao}
93416675b7f96b7a61ac64180b1824ec04984b72b3bHarry Ciao
93513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int require_type_or_attribute(int pass, unsigned char isattr)
93613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
93713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
93813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type = NULL;
93913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
94013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
94113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
94213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
94313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
94513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no type name");
94613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
94713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((type = malloc(sizeof(*type))) == NULL) {
94913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
95013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
95113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
95213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
95313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_init(type);
95413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type->primary = 1;
95513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
95613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
95713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    require_symbol(SYM_TYPES, id, (hashtab_datum_t *) type,
95813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &type->s.value, &type->s.value);
95913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
96013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
96113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(type);
96213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
96313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
96413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
96513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
96613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
96713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
96813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
96913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of type/attribute");
97013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
97113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
97213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
97313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require type/attribute here");
97413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
97513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
97613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
97713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
97813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
97913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
98013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* type already required */
98113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
98213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
983099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
98413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
98513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
98613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
98713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
98813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_type(int pass)
98913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
99013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return require_type_or_attribute(pass, 0);
99113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
99213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_attribute(int pass)
99413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
99513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return require_type_or_attribute(pass, 1);
99613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
99713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_user(int pass)
99913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
100013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
100113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user = NULL;
100213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
100313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 1) {
100413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
100513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
100613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
100713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
100813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no user name");
100913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
101013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
101113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((user = malloc(sizeof(*user))) == NULL) {
101213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
101313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
101413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
101513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
101613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_init(user);
101713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
101813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    require_symbol(SYM_USERS, id, (hashtab_datum_t *) user,
101913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &user->s.value, &user->s.value);
102013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
102113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
102213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user_datum_destroy(user);
102313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
102413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
102513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
102613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
102713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
102813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
102913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
103013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of user");
103113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
103213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
103413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require user here");
103513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
103613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
103813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
103913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
104013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
104113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* user already required */
104213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
104313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
1044099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
104513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
104613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
104713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
104813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104980f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciaostatic int require_bool_tunable(int pass, int is_tunable)
105013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
105113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
105213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_bool_datum_t *booldatum = NULL;
105313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
105413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
105513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
105613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
105713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
105813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (id == NULL) {
105913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no boolean name");
106013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
106113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
106213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
106313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cond_destroy_bool(id, booldatum, NULL);
106413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
106513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
106613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
106780f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao	if (is_tunable)
106880f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao		booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
106913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval =
107013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
107113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   &booldatum->s.value, &booldatum->s.value);
107213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
107313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cond_destroy_bool(id, booldatum, NULL);
107413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
107513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
107613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
107713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
107813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
107913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
108013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
108113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of boolean");
108213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
108313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
108413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
108513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require boolean here");
108613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
108713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
108813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
108913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
109013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
109113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
109213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* boolean already required */
109313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
109413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
1095099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
109613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
109713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
109813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
109913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
110080f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciaoint require_bool(int pass)
110180f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao{
110280f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao	return require_bool_tunable(pass, 0);
110380f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao}
110480f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao
110580f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciaoint require_tunable(int pass)
110680f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao{
110780f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao	return require_bool_tunable(pass, 1);
110880f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao}
110980f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao
111013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_sens(int pass)
111113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
111213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
111313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *level = NULL;
111413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
111513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
111613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
111713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
111813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
111913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!id) {
112013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no sensitivity name");
112113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
112213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
112313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level = malloc(sizeof(level_datum_t));
112413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!level) {
112513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
112613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
112713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
112813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
112913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_init(level);
113013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level->level = malloc(sizeof(mls_level_t));
113113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!level->level) {
113213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
113313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		level_datum_destroy(level);
113413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(level);
113513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
113613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
113713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
113813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_level_init(level->level);
113913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level,
114013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				&level->level->sens, &level->level->sens);
114113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
114213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
114313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_destroy(level->level);
114413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(level->level);
114513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		level_datum_destroy(level);
114613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(level);
114713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
114813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
114913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
115013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
115113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
115213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
115313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
115413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of sensitivity");
115513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
115613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
115713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
115813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require sensitivity here");
115913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
116013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
116113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
116213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
116313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
116413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
116513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* sensitivity already required */
116613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
116713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
1168099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
116913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
117013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
117113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
117213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_cat(int pass)
117413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
117513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = queue_remove(id_queue);
117613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_t *cat = NULL;
117713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
117813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
117913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
118013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
118113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!id) {
118313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("no category name");
118413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
118513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat = malloc(sizeof(cat_datum_t));
118713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!cat) {
118813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
118913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		yyerror("Out of memory!");
119013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
119113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
119213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_init(cat);
119313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat,
119513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				&cat->s.value, &cat->s.value);
119613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval != 0) {
119713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(id);
119813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cat_datum_destroy(cat);
119913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(cat);
120013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
120113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (retval) {
120213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -3:{
120313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
120413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
120513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
120613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -2:{
120713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("duplicate declaration of category");
120813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
120913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
121013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case -1:{
121113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("could not require category here");
121213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
121313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
121413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 0:{
121513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
121613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
121713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
121813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;	/* category already required */
121913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
122013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:{
1221099223bd1f08ce0bc897f1a9f47852621bc946c9Dan Albert			abort();	/* should never get here */
122213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
122313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
122413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
122513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
122713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1228581d3eb1281f7c970376649f5027df012269935aNicolas Iooss	uint32_t i;
122913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack == NULL) {
123013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;	/* no matching scope found */
123113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
123213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack->type == 1) {
123313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = stack->decl;
123413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < scope->decl_ids_len; i++) {
123513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (scope->decl_ids[i] == decl->decl_id) {
123613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return 1;
123713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
123813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
123913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
124013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* note that conditionals can't declare or require
124113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * symbols, so skip this level */
124213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
124313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* not within scope of this stack, so try its parent */
124513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return is_scope_in_stack(scope, stack->parent);
124613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
124713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
124913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
125013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope =
125113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
125213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     table, id);
125313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (scope == NULL) {
125413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;	/* id is not known, so return success */
125513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
125613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return is_scope_in_stack(scope, stack_top);
125713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
125813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
125913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
126013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				  scope_index_t * scope)
126113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
126213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (class_value > scope->class_perms_len) {
126313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
126413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
126513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_get_bit(scope->class_perms_map + class_value - 1,
126613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    perm_value - 1)) {
126713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
126813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
126913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
127013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
127113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
127213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
127313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    scope_stack_t * stack)
127413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
127513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack == NULL) {
127613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;	/* no matching scope found */
127713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
127813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack->type == 1) {
127913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = stack->decl;
128013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (is_perm_in_scope_index
128113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (perm_value, class_value, &decl->required)
128213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || is_perm_in_scope_index(perm_value, class_value,
128313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      &decl->declared)) {
128413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 1;
128513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
128613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
128713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* note that conditionals can't declare or require
128813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * symbols, so skip this level */
128913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
129013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
129113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* not within scope of this stack, so try its parent */
129213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return is_perm_in_stack(perm_value, class_value, stack->parent);
129313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
129413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
129513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
129613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
129713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *cladatum =
129813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
129913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     class_id);
130013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perdatum;
130113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cladatum == NULL) {
130213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
130313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
130413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
130513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						   perm_id);
130613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (perdatum == NULL) {
130713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
130813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
130913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return is_perm_in_stack(perdatum->s.value, cladatum->s.value,
131013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				stack_top);
131113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
131213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
131313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlecond_list_t *get_current_cond_list(cond_list_t * cond)
131413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
131513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* FIX ME: do something different here if in a nested
131613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * conditional? */
131713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
131813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return get_decl_cond_list(policydbp, decl, cond);
131913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
132013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
132113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Append the new conditional node to the existing ones.  During
132213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * expansion the list will be reversed -- i.e., the last AV rule will
132313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * be the first one listed in the policy.  This matches the behavior
132413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * of the upstream compiler. */
132513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid append_cond_list(cond_list_t * cond)
132613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
132713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_list_t *old_cond = get_current_cond_list(cond);
132813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *tmp;
132913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(old_cond != NULL);	/* probably out of memory */
133013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (old_cond->avtrue_list == NULL) {
133113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		old_cond->avtrue_list = cond->avtrue_list;
133213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
133313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (tmp = old_cond->avtrue_list; tmp->next != NULL;
133413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     tmp = tmp->next) ;
133513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tmp->next = cond->avtrue_list;
133613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
133713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (old_cond->avfalse_list == NULL) {
133813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		old_cond->avfalse_list = cond->avfalse_list;
133913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
134013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (tmp = old_cond->avfalse_list; tmp->next != NULL;
134113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     tmp = tmp->next) ;
134213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tmp->next = cond->avfalse_list;
134313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
134480f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao
134580f26c5ee865993264ef638480c6a05ab574f7c0Harry Ciao	old_cond->flags |= cond->flags;
134613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
134713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
134813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid append_avrule(avrule_t * avrule)
134913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
135013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
135113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
135213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* currently avrules follow a completely different code path
135313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * for handling avrules and compute types
135413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * (define_cond_avrule_te_avtab, define_cond_compute_type);
135513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * therefore there ought never be a conditional on top of the
135613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * scope stack */
135713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
135813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
135913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack_top->last_avrule == NULL) {
136013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		decl->avrules = avrule;
136113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
136213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		stack_top->last_avrule->next = avrule;
136313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
136413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->last_avrule = avrule;
136513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
136613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
136713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* this doesn't actually append, but really prepends it */
136813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid append_role_trans(role_trans_rule_t * role_tr_rules)
136913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
137013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
137113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* role transitions are not allowed within conditionals */
137313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
137413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_tr_rules->next = decl->role_tr_rules;
137613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	decl->role_tr_rules = role_tr_rules;
137713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
137813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* this doesn't actually append, but really prepends it */
138013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid append_role_allow(role_allow_rule_t * role_allow_rules)
138113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
138213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
138313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
138413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* role allows are not allowed within conditionals */
138513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
138613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
138713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_rules->next = decl->role_allow_rules;
138813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	decl->role_allow_rules = role_allow_rules;
138913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
139013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
139113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* this doesn't actually append, but really prepends it */
1392516cb2a264448421bff692f47f61e8cf2a74237eEric Parisvoid append_filename_trans(filename_trans_rule_t * filename_trans_rules)
1393516cb2a264448421bff692f47f61e8cf2a74237eEric Paris{
1394516cb2a264448421bff692f47f61e8cf2a74237eEric Paris	avrule_decl_t *decl = stack_top->decl;
1395516cb2a264448421bff692f47f61e8cf2a74237eEric Paris
1396516cb2a264448421bff692f47f61e8cf2a74237eEric Paris	/* filename transitions are not allowed within conditionals */
1397516cb2a264448421bff692f47f61e8cf2a74237eEric Paris	assert(stack_top->type == 1);
1398516cb2a264448421bff692f47f61e8cf2a74237eEric Paris
1399516cb2a264448421bff692f47f61e8cf2a74237eEric Paris	filename_trans_rules->next = decl->filename_trans_rules;
1400516cb2a264448421bff692f47f61e8cf2a74237eEric Paris	decl->filename_trans_rules = filename_trans_rules;
1401516cb2a264448421bff692f47f61e8cf2a74237eEric Paris}
1402516cb2a264448421bff692f47f61e8cf2a74237eEric Paris
1403516cb2a264448421bff692f47f61e8cf2a74237eEric Paris/* this doesn't actually append, but really prepends it */
140413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid append_range_trans(range_trans_rule_t * range_tr_rules)
140513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
140613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
140713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
140813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* range transitions are not allowed within conditionals */
140913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
141013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_tr_rules->next = decl->range_tr_rules;
141213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	decl->range_tr_rules = range_tr_rules;
141313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
141413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint begin_optional(int pass)
141613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
141713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *block = NULL;
141813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl;
141913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 1) {
142013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* allocate a new avrule block for this optional block */
142113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((block = avrule_block_create()) == NULL ||
142213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl = avrule_decl_create(next_decl_id)) == NULL) {
142313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
142413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
142513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		block->flags |= AVRULE_OPTIONAL;
142613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		block->branch_list = decl;
142713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		last_block->next = block;
142813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
142913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* select the next block from the chain built during pass 1 */
143013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		block = last_block->next;
143113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(block != NULL &&
143213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       block->branch_list != NULL &&
143313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       block->branch_list->decl_id == next_decl_id);
143413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		decl = block->branch_list;
143513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
143613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (push_stack(1, block, decl) == -1) {
143713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
143813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
143913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->last_avrule = NULL;
144013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	last_block = block;
144113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	next_decl_id++;
144213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
144313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
144413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	yyerror("Out of memory!");
144513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_destroy(block);
144613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
144713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
144813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14495af8c5adb274cc45d3a41ce9b1ab2c7573463d74Nicolas Ioossint end_optional(int pass __attribute__ ((unused)))
145013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
145113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* once nested conditionals are allowed, do the stack unfolding here */
145213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	pop_stack();
145313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
145413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
145513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
145613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint begin_optional_else(int pass)
145713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
145813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl;
145913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1 && stack_top->in_else == 0);
146013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 1) {
146113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* allocate a new declaration and add it to the
146213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * current chain */
146313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
146413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("Out of memory!");
146513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
146613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
146713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		stack_top->decl->next = decl;
146813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
146913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* pick the (hopefully last) declaration of this
147013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   avrule block, built from pass 1 */
147113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		decl = stack_top->decl->next;
147213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(decl != NULL &&
147313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       decl->next == NULL && decl->decl_id == next_decl_id);
147413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
147513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->in_else = 1;
147613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->decl = decl;
147713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->last_avrule = NULL;
147813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top->require_given = 0;
147913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	next_decl_id++;
148013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
148113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
148213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
148313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
148413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1485581d3eb1281f7c970376649f5027df012269935aNicolas Iooss	uint32_t i;
148613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack == NULL) {
148713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
148813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
148913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stack->type == 1) {
149013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope_index_t *src_scope = &stack->decl->required;
149113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope_index_t *dest_scope = &dest->required;
149213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < SYM_NUM; i++) {
149313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_t *src_bitmap = &src_scope->scope[i];
149413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_t *dest_bitmap = &dest_scope->scope[i];
149513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_union(dest_bitmap, src_bitmap)) {
149613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
149713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
149813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
149913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
150013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* now copy class permissions */
150113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (src_scope->class_perms_len > dest_scope->class_perms_len) {
150213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_t *new_map =
150313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    realloc(dest_scope->class_perms_map,
150413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    src_scope->class_perms_len *
150513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    sizeof(*new_map));
150613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_map == NULL) {
150713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
150813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
150913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
151013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			dest_scope->class_perms_map = new_map;
151113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (i = dest_scope->class_perms_len;
151213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     i < src_scope->class_perms_len; i++) {
151313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ebitmap_init(dest_scope->class_perms_map + i);
151413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
151513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			dest_scope->class_perms_len =
151613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    src_scope->class_perms_len;
151713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
151813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < src_scope->class_perms_len; i++) {
151913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
152013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_t *dest_bitmap =
152113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    &dest_scope->class_perms_map[i];
152213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_union(dest_bitmap, src_bitmap)) {
152313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				yyerror("Out of memory!");
152413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
152513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
152613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
152713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
152813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return copy_requirements(dest, stack->parent);
152913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
153013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
153113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* During pass 1, check that at least one thing was required within
153213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * this block, for those places where a REQUIRED is necessary.  During
153313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * pass 2, have this block inherit its parents' requirements.  Return
153413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 0 on success, -1 on failure. */
153513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint end_avrule_block(int pass)
153613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
153713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl = stack_top->decl;
153813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top->type == 1);
153913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pass == 2) {
154013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this avrule_decl inherits all of its parents'
154113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * requirements */
154213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_requirements(decl, stack_top->parent) == -1) {
154313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
154413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
154513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
154613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
154713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!stack_top->in_else && !stack_top->require_given) {
154813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policydbp->policy_type == POLICY_BASE
154913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    && stack_top->parent != NULL) {
155013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* if this is base no require should be in the global block */
155113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
155213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
155313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* non-ELSE branches must have at least one thing required */
155413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			yyerror("This block has no require section.");
155513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
155613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
155713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
155813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
155913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
156013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Push a new scope on to the stack and update the 'last' pointer.
156213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Return 0 on success, -1 if out * of memory. */
156313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int push_stack(int stack_type, ...)
156413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
156513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_stack_t *s = calloc(1, sizeof(*s));
156613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	va_list ap;
156713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (s == NULL) {
156813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
156913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
157013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	va_start(ap, stack_type);
157113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (s->type = stack_type) {
157213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 1:{
157313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			s->u.avrule = va_arg(ap, avrule_block_t *);
157413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			s->decl = va_arg(ap, avrule_decl_t *);
157513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
157613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
157713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case 2:{
157813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			s->u.cond_list = va_arg(ap, cond_list_t *);
157913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
158013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
158113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
158213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* invalid stack type given */
158313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(0);
158413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
158513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	va_end(ap);
158613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s->parent = stack_top;
158713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s->child = NULL;
158813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top = s;
158913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
159013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
159113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
159213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Pop off the most recently added from the stack.  Update the 'last'
159313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * pointer. */
159413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void pop_stack(void)
159513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
159613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_stack_t *parent;
159713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(stack_top != NULL);
159813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	parent = stack_top->parent;
159913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (parent != NULL) {
160013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		parent->child = NULL;
160113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
160213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(stack_top);
160313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	stack_top = parent;
160413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
1605