expand.c revision 13cd4c8960688af11ad23b4c946149015c80d54
113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *          Jason Tang <jtang@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	    Joshua Brindle <jbrindle@tresys.com>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2004-2005 Tresys Technology, LLC
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2007 Red Hat, Inc.
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is free software; you can redistribute it and/or
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  modify it under the terms of the GNU Lesser General Public
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License as published by the Free Software Foundation; either
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  version 2.1 of the License, or (at your option) any later version.
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is distributed in the hope that it will be useful,
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Lesser General Public License for more details.
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  You should have received a copy of the GNU Lesser General Public
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License along with this library; if not, write to the Free Software
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "context.h"
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/policydb.h>
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/conditional.h>
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/hashtab.h>
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/expand.h>
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/hierarchy.h>
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/avrule_block.h>
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdarg.h>
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <assert.h>
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "private.h"
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct expand_state {
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int verbose;
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *typemap;
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *boolmap;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *rolemap;
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *usermap;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *base;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *out;
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_handle_t *handle;
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int expand_neverallow;
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} expand_state_t;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void expand_state_init(expand_state_t * state)
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(state, 0, sizeof(expand_state_t));
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(dst);
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(src, tnode, i) {
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(tnode, i))
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!map[i])
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(dst, map[i] - 1, 1))
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *new_type;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((type->flavor == TYPE_TYPE && !type->primary)
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || type->flavor == TYPE_ALIAS) {
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* aliases are handled later */
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_TYPES)) {
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying type or attribute %s", id);
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_id == NULL) {
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type = (type_datum_t *) malloc(sizeof(type_datum_t));
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_type) {
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return SEPOL_ENOMEM;
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_type, 0, sizeof(type_datum_t));
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->flavor = type->flavor;
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->flags = type->flags;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->s.value = ++state->out->p_types.nprim;
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_type->s.value > UINT16_MAX) {
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_type);
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "type space overflow");
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->primary = 1;
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->typemap[type->s.value - 1] = new_type->s.value;
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_types.table,
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_type);
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_type);
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_type->flags & TYPE_FLAGS_PERMISSIVE)
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) {
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!\n");
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum,
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 void *data)
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *new_type;
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union;
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor != TYPE_ATTRIB)
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_TYPES)) {
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "converting attribute %s", id);
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type = hashtab_search(state->out->p_types.table, id);
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_type) {
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "attribute %s vanished!", id);
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&type->types, &tmp_union, state->typemap)) {
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "out of memory");
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then union tmp_union onto &new_type->types */
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_type->types, &tmp_union)) {
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union);
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	symtab_t *s;
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perm, *new_perm;
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm = (perm_datum_t *) datum;
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s = (symtab_t *) data;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t));
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_perm) {
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_perm, 0, sizeof(perm_datum_t));
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_perm);
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_perm->s.value = perm->s.value;
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s->nprim++;
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm);
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_perm);
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				void *data)
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	common_datum_t *common, *new_common;
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	common = (common_datum_t *) datum;
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying common %s", id);
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_common = (common_datum_t *) malloc(sizeof(common_datum_t));
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_common) {
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_common, 0, sizeof(common_datum_t));
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) {
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_common->s.value = common->s.value;
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_commons.nprim++;
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    hashtab_insert(state->out->p_commons.table, new_id,
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t *) new_common);
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (common->permissions.table, perm_copy_callback,
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_common->permissions)) {
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int constraint_node_clone(constraint_node_t ** dst,
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 constraint_node_t * src,
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 expand_state_t * state)
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_node_t *new_con = NULL, *last_new_con = NULL;
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_expr_t *new_expr = NULL;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*dst = NULL;
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (src != NULL) {
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		constraint_expr_t *expr, *expr_l = NULL;
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_con =
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (constraint_node_t *) malloc(sizeof(constraint_node_t));
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_con) {
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto out_of_mem;
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_con, 0, sizeof(constraint_node_t));
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_con->permissions = src->permissions;
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (expr = src->expr; expr; expr = expr->next) {
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) {
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out_of_mem;
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (constraint_expr_init(new_expr) == -1) {
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out_of_mem;
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->expr_type = expr->expr_type;
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->attr = expr->attr;
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->op = expr->op;
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_expr->expr_type == CEXPR_NAMES) {
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (new_expr->attr & CEXPR_TYPE) {
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					/* Type sets require expansion and conversion. */
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (expand_convert_type_set(state->out,
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    state->
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    typemap,
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    expr->
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    type_names,
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    &new_expr->
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    names, 1)) {
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else if (new_expr->attr & CEXPR_ROLE) {
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else if (new_expr->attr & CEXPR_USER) {
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					/* Other kinds of sets do not. */
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_cpy(&new_expr->names,
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							&expr->names)) {
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (expr_l) {
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				expr_l->next = new_expr;
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				new_con->expr = new_expr;
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			expr_l = new_expr;
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr = NULL;
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (last_new_con == NULL) {
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_con;
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			last_new_con->next = new_con;
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		last_new_con = new_con;
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		src = src->next;
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_con)
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_con);
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_expr_destroy(new_expr);
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *class, *new_class;
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class = (class_datum_t *) datum;
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_CLASSES)) {
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
37513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying class %s", id);
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class = (class_datum_t *) malloc(sizeof(class_datum_t));
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_class) {
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_class, 0, sizeof(class_datum_t));
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) {
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class->s.value = class->s.value;
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_classes.nprim++;
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
40113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    hashtab_insert(state->out->p_classes.table, new_id,
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t *) new_class);
40613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
40713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
40913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
41013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (class->permissions.table, perm_copy_callback,
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_class->permissions)) {
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (class->comkey) {
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->comkey = strdup(class->comkey);
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_class->comkey) {
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->comdatum =
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_search(state->out->p_commons.table,
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   new_class->comkey);
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_class->comdatum) {
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "could not find common datum %s",
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    new_class->comkey);
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->permissions.nprim +=
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    new_class->comdatum->permissions.nprim;
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    void *data)
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *class, *new_class;
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class = (class_datum_t *) datum;
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class = hashtab_search(state->out->p_classes.table, id);
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_class) {
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "class %s vanished", id);
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* constraints */
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (constraint_node_clone
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (&new_class->constraints, class->constraints, state) == -1
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || constraint_node_clone(&new_class->validatetrans,
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     class->validatetrans, state) == -1) {
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
46813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* The aliases have to be copied after the types and attributes to be certain that
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the out symbol table will have the type that the alias refers. Otherwise, we
47113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * won't be able to find the type value for the alias. We can't depend on the
47213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * declaration ordering because of the hash table.
47313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *alias, *new_alias;
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	alias = (type_datum_t *) datum;
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* ignore regular types */
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_TYPE && alias->primary)
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* ignore attributes */
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_ATTRIB)
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying alias %s", id);
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_alias = (type_datum_t *) malloc(sizeof(type_datum_t));
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_alias) {
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return SEPOL_ENOMEM;
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_alias, 0, sizeof(type_datum_t));
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_TYPE)
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_alias->s.value = state->typemap[alias->s.value - 1];
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else if (alias->flavor == TYPE_ALIAS)
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_alias->s.value = state->typemap[alias->primary - 1];
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(0);	/* unreachable */
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_alias->flags = alias->flags;
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_types.table,
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_alias);
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_alias);
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
52813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->typemap[alias->s.value - 1] = new_alias->s.value;
53113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_alias->flags & TYPE_FLAGS_PERMISSIVE)
53313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) {
53413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
53513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
53613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
53713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
53913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
54013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data)
54213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t mapped_roles;
54413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role = (role_datum_t *) datum;
54513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
54613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap))
54813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
54913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&role->dominates);
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&role->dominates, &mapped_roles))
55313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
55413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&mapped_roles);
55613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
55813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
55913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
56013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
56113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
56213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
56313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
56413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
56513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role;
56613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *new_role;
56713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
56813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union_types;
56913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
57013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
57113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role = (role_datum_t *) datum;
57213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
57313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
57413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (strcmp(id, OBJECT_R) == 0) {
57513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* object_r is always value 1 */
57613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->rolemap[role->s.value - 1] = 1;
57713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
57813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
57913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
58013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_ROLES)) {
58113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
58213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
58313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
58413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
58513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
58613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying role %s", id);
58713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
58813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_role =
58913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (role_datum_t *) hashtab_search(state->out->p_roles.table, id);
59013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_role) {
59113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role = (role_datum_t *) malloc(sizeof(role_datum_t));
59213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_role) {
59313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
59413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
59513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
59613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_role, 0, sizeof(role_datum_t));
59713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
59813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = strdup(id);
59913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_id) {
60013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
60113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
60213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
60313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
60413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->out->p_roles.nprim++;
60513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role->s.value = state->out->p_roles.nprim;
60613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->rolemap[role->s.value - 1] = new_role->s.value;
60713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->out->p_roles.table,
60813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
60913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_role);
61013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
61213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "hashtab overflow");
61313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_role);
61413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
61513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
61613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
61713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
61813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* The dominates bitmap is going to be wrong for the moment,
62013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	 * we'll come back later and remap them, after we are sure all
62113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	 * the roles have been added */
62213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_role->dominates, &role->dominates)) {
62313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
62413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
62513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
62613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
62713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&tmp_union_types);
62813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
62913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* convert types in the role datum in the global symtab */
63013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
63113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, state->typemap, &role->types, &tmp_union_types, 1)) {
63213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union_types);
63313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
63413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
63513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
63613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
63713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_role->types.types, &tmp_union_types)) {
63813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
63913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union_types);
64013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
64113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
64213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union_types);
64313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
64513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
64613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
64813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, sepol_handle_t * h)
64913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
65013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_semantic_cat_t *cat;
65113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *levdatum;
65213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
65313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
65413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_level_init(l);
65513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
65613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!p->mls)
65713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
65813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
65913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Required not declared. */
66013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!sl->sens)
66113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
66213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	l->sens = sl->sens;
66413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
66513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    p->p_sens_val_to_name[l->
66613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									  sens -
66713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									  1]);
66813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cat = sl->cat; cat; cat = cat->next) {
66913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cat->low > cat->high) {
67013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(h, "Category range is not valid %s.%s",
67113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_cat_val_to_name[cat->low - 1],
67213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_cat_val_to_name[cat->high - 1]);
67313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
67413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
67513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = cat->low - 1; i < cat->high; i++) {
67613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
67713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(h, "Category %s can not be associate with "
67813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "level %s",
67913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_cat_val_to_name[i],
68013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_sens_val_to_name[l->sens - 1]);
68113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
68213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(&l->cat, i, 1)) {
68313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(h, "Out of memory!");
68413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
68513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
68613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
68713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
68813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
68913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
69013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
69113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r,
69313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, sepol_handle_t * h)
69413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
69513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0)
69613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
69713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) {
69913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_semantic_level_destroy(&sr->level[0]);
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!mls_level_dom(&r->level[1], &r->level[0])) {
70413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_destroy(r);
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(h, "MLS range high level does not dominate low level");
70613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
71013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
71113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
71313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
71413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
71513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
71613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
71713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user;
71813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *new_user;
71913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
72013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union;
72113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
72213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
72313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user = (user_datum_t *) datum;
72413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
72513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
72613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_USERS)) {
72713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
72813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
72913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
73013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
73113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
73213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying user %s", id);
73313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
73413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_user =
73513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (user_datum_t *) hashtab_search(state->out->p_users.table, id);
73613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_user) {
73713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user = (user_datum_t *) malloc(sizeof(user_datum_t));
73813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_user) {
73913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
74013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
74113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
74213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_user, 0, sizeof(user_datum_t));
74313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->out->p_users.nprim++;
74513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user->s.value = state->out->p_users.nprim;
74613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->usermap[user->s.value - 1] = new_user->s.value;
74713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = strdup(id);
74913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_id) {
75013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
75113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
75213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
75313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->out->p_users.table,
75413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
75513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_user);
75613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
75713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "hashtab overflow");
75813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			user_datum_destroy(new_user);
75913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_user);
76013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
76113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
76213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
76313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
76413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the semantic MLS info */
76513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_range_expand(&user->range,
76613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      &new_user->exp_range,
76713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
76813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
76913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
77013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_level_expand(&user->dfltlevel,
77113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      &new_user->exp_dfltlevel,
77213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
77313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
77413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
77513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!mls_level_between(&new_user->exp_dfltlevel,
77613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &new_user->exp_range.level[0],
77713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &new_user->exp_range.level[1])) {
77813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "default level not within user "
77913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "range");
78013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
78113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
78213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
78313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* require that the MLS info match */
78413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_t tmp_range;
78513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_t tmp_level;
78613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
78713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_range_expand(&user->range, &tmp_range,
78813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
78913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
79013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
79113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
79213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
79313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_range_destroy(&tmp_range);
79413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
79513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
79613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
79713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
79813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_range_destroy(&tmp_range);
79913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_level_destroy(&tmp_level);
80013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
80113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
80213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_destroy(&tmp_range);
80313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_destroy(&tmp_level);
80413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
80513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
80613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&tmp_union);
80713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
80813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* get global roles for this user */
80913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (role_set_expand(&user->roles, &tmp_union, state->base, state->rolemap)) {
81013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
81113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union);
81213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
81313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
81413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
81513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_user->roles.roles, &tmp_union)) {
81613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
81713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union);
81813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
81913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
82013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union);
82113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
82313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
82413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
82613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
82713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
82813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
82913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
83013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_bool_datum_t *bool, *new_bool;
83113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
83213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
83313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
83413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	bool = (cond_bool_datum_t *) datum;
83513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
83613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
83713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_BOOLS)) {
83813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
83913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
84013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
84113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
84313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying boolean %s", id);
84413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
84613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_bool) {
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
85213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_bool);
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
85613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
85713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_bools.nprim++;
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool->s.value = state->out->p_bools.nprim;
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_bools.table,
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_bool);
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
86613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_bool);
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->boolmap[bool->s.value - 1] = new_bool->s.value;
87213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool->state = bool->state;
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *level = (level_datum_t *) datum, *new_level = NULL;
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = (char *)key, *new_id = NULL;
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_LEVELS)) {
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying sensitivity level %s", id);
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level = (level_datum_t *) malloc(sizeof(level_datum_t));
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_level)
89513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_init(new_level);
89713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t));
89813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_level->level)
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
90013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_level_init(new_level->level);
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
90213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id)
90313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
90413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_level_cpy(new_level->level, level->level)) {
90613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
90713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
90813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level->isalias = level->isalias;
90913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_levels.nprim++;
91013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
91113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_insert(state->out->p_levels.table,
91213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_key_t) new_id,
91313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t) new_level)) {
91413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
91813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
92013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_level != NULL && new_level->level != NULL) {
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_destroy(new_level->level);
92213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_level->level);
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_destroy(new_level);
92513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_level);
92613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
92713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
92813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
92913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
93113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
93213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
93313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
93413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL;
93513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = (char *)key, *new_id = NULL;
93613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_CATS)) {
93813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
93913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
94013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
94313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying category attribute %s", id);
94413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t));
94613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_cat)
94713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
94813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_init(new_cat);
94913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
95013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id)
95113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
95213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat->s.value = cat->s.value;
95413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat->isalias = cat->isalias;
95513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_cats.nprim++;
95613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_insert(state->out->p_cats.table,
95713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) {
95813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
95913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
96013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
96113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
96213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
96313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
96413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
96513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_destroy(new_cat);
96613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_cat);
96713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
96813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
96913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
97013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
97113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules)
97213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
97313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
97413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_t *cur_allow, *n, *l;
97513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_rule_t *cur;
97613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t roles, new_roles;
97713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
97813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
97913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* start at the end of the list */
98013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (l = state->out->role_allow; l && l->next; l = l->next) ;
98113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
98213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = rules;
98313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
98413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&roles);
98513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&new_roles);
98613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
98713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (role_set_expand(&cur->roles, &roles, state->out, state->rolemap)) {
98813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
98913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
99013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
99113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->rolemap)) {
99313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
99413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
99513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
99613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&roles, snode, i) {
99813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
99913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
100013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&new_roles, tnode, j) {
100113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
100213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
100313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* check for duplicates */
100413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cur_allow = state->out->role_allow;
100513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				while (cur_allow) {
100613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if ((cur_allow->role == i + 1) &&
100713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (cur_allow->new_role == j + 1))
100813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						break;
100913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					cur_allow = cur_allow->next;
101013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
101113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur_allow)
101213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
101313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n = (role_allow_t *)
101413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    malloc(sizeof(role_allow_t));
101513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n) {
101613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
101713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
101813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
101913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				memset(n, 0, sizeof(role_allow_t));
102013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->role = i + 1;
102113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->new_role = j + 1;
102213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (l) {
102313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					l->next = n;
102413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
102513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state->out->role_allow = n;
102613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
102713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l = n;
102813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
102913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
103113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&roles);
103213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&new_roles);
103313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
103413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
103513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
103613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
103713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
103813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
103913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
104113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
104213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
104313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_t *n, *l, *cur_trans;
104413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_rule_t *cur;
104513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t roles, types;
104613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *rnode, *tnode;
104713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* start at the end of the list */
104913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (l = state->out->role_tr; l && l->next; l = l->next) ;
105013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = rules;
105213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
105313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&roles);
105413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&types);
105513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (role_set_expand(&cur->roles, &roles, state->out, state->rolemap)) {
105713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
105813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
105913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
106013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set
106113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->out, state->typemap, &cur->types, &types, 1)) {
106213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
106313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
106413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
106513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&roles, rnode, i) {
106613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(rnode, i))
106713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
106813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&types, tnode, j) {
106913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
107013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
107113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
107213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cur_trans = state->out->role_tr;
107313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				while (cur_trans) {
107413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if ((cur_trans->role == i + 1) &&
107513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (cur_trans->type == j + 1)) {
107613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						if (cur_trans->new_role ==
107713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    cur->new_role) {
107813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							break;
107913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						} else {
108013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							ERR(state->handle,
108113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    "Conflicting role trans rule %s %s : %s",
108213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    state->out->
108313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    p_role_val_to_name
108413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    [i],
108513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    state->out->
108613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    p_type_val_to_name
108713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    [j],
108813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    state->out->
108913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    p_role_val_to_name
109013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							    [cur->new_role -
109113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							     1]);
109213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							return -1;
109313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						}
109413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
109513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					cur_trans = cur_trans->next;
109613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
109713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur_trans)
109813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
109913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
110013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n = (role_trans_t *)
110113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    malloc(sizeof(role_trans_t));
110213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n) {
110313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
110413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
110513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
110613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				memset(n, 0, sizeof(role_trans_t));
110713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->role = i + 1;
110813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->type = j + 1;
110913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->new_role = state->rolemap[cur->new_role - 1];
111013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (l) {
111113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					l->next = n;
111213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
111313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state->out->role_tr = n;
111413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
111513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l = n;
111613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
111713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
111813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
111913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&roles);
112013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&types);
112113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
112213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
112313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
112413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
112513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
112613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
112713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
112813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      mls_semantic_range_t * trange,
112913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      expand_state_t * state)
113013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
113113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_trans_t *rt, *check_rt = state->out->range_tr;
113213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_range_t exp_range;
113313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc = -1;
113413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
113513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_semantic_range_expand(trange, &exp_range, state->out,
113613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				      state->handle))
113713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
113813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
113913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check for duplicates/conflicts */
114013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (check_rt) {
114113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((check_rt->source_type == stype) &&
114213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (check_rt->target_type == ttype) &&
114313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (check_rt->target_class == tclass)) {
114413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (mls_range_eq(&check_rt->target_range, &exp_range)) {
114513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* duplicate */
114613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
114713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
114813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* conflict */
114913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle,
115013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "Conflicting range trans rule %s %s : %s",
115113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    state->out->p_type_val_to_name[stype - 1],
115213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    state->out->p_type_val_to_name[ttype - 1],
115313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    state->out->p_class_val_to_name[tclass -
115413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    1]);
115513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out;
115613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
115713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
115813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		check_rt = check_rt->next;
115913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
116013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (check_rt) {
116113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this is a dup - skip */
116213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = 0;
116313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
116413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
116513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
116613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt = (range_trans_t *) calloc(1, sizeof(range_trans_t));
116713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!rt) {
116813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
116913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
117013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
117113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->next = state->out->range_tr;
117313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->range_tr = rt;
117413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->source_type = stype;
117613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->target_type = ttype;
117713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->target_class = tclass;
117813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_range_cpy(&rt->target_range, &exp_range)) {
117913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
118013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
118113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rc = 0;
118413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
118613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_range_destroy(&exp_range);
118713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return rc;
118813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
118913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_range_trans(expand_state_t * state,
119113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      range_trans_rule_t * rules)
119213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
119313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j, k;
119413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_trans_rule_t *rule;
119513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
119713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode, *cnode;
119813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
120013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "expanding range transitions");
120113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
120213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (rule = rules; rule; rule = rule->next) {
120313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&stypes);
120413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&ttypes);
120513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
120613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the type sets */
120713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set(state->out, state->typemap,
120813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    &rule->stypes, &stypes, 1)) {
120913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
121013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
121113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
121213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set(state->out, state->typemap,
121313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    &rule->ttypes, &ttypes, 1)) {
121413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_destroy(&stypes);
121513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
121613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
121713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
121813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* loop on source type */
122013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&stypes, snode, i) {
122113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
122213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
122313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* loop on target type */
122413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&ttypes, tnode, j) {
122513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
122613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
122713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* loop on target class */
122813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ebitmap_for_each_bit(&rule->tclasses, cnode, k) {
122913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!ebitmap_node_get_bit(cnode, k))
123013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
123113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
123213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (exp_rangetr_helper(i + 1,
123313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       j + 1,
123413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       k + 1,
123513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       &rule->trange,
123613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       state)) {
123713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						ebitmap_destroy(&stypes);
123813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						ebitmap_destroy(&ttypes);
123913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						return -1;
124013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
124113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
124213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
124313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
124413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&stypes);
124613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&ttypes);
124713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
124813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
125013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
125113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
125213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Search for an AV tab node within a hash table with the given key.
125313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * If the node does not exist, create it and return it; otherwise
125413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * return the pre-existing one.
125513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle*/
125613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
125713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   avtab_t * avtab, avtab_key_t * key,
125813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   cond_av_list_t ** cond)
125913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
126013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
126113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t avdatum;
126213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *nl;
126313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	node = avtab_search_node(avtab, key);
126513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* If this is for conditional policies, keep searching in case
126713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   the node is part of my conditional avtab. */
126813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond) {
126913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (node) {
127013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (node->parse_context == cond)
127113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
127213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node = avtab_search_node_next(node, key->specified);
127313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
127413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
127513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
127613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!node) {
127713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(&avdatum, 0, sizeof avdatum);
127813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this is used to get the node - insertion is actually unique */
127913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(avtab, key, &avdatum);
128013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
128113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle, "hash table overflow");
128213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
128313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
128413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cond) {
128513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->parse_context = cond;
128613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t));
128713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!nl) {
128813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(handle, "Memory error");
128913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
129013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
129113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(nl, 0, sizeof(cond_av_list_t));
129213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl->node = node;
129313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl->next = *cond;
129413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*cond = nl;
129513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
129613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
129713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
129813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return node;
129913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
130013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
130113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_SUCCESS   1
130213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_CONFLICT  0
130313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_ERROR    -1
130413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
130513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_terule_helper(sepol_handle_t * handle,
130613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policydb_t * p, uint32_t * typemap,
130713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t specified, cond_av_list_t ** cond,
130813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cond_av_list_t ** other, uint32_t stype,
130913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t ttype, class_perm_node_t * perms,
131013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				avtab_t * avtab, int enabled)
131113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
131213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t avkey;
131313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avdatump;
131413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
131513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur;
131613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int conflict;
131713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t oldtype = 0, spec = 0;
131813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
131913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (specified & AVRULE_TRANSITION) {
132013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_TRANSITION;
132113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_MEMBER) {
132213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_MEMBER;
132313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_CHANGE) {
132413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_CHANGE;
132513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
132613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(0);	/* unreachable */
132713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
132813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
132913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = perms;
133013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
133113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		uint32_t remapped_data =
133213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    typemap ? typemap[cur->data - 1] : cur->data;
133313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.source_type = stype + 1;
133413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.target_type = ttype + 1;
133513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.target_class = cur->class;
133613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.specified = spec;
133713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
133813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		conflict = 0;
133913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* check to see if the expanded TE already exists --
134013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * either in the global scope or in another
134113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * conditional AV tab */
134213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_search_node(&p->te_avtab, &avkey);
134313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (node) {
134413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			conflict = 1;
134513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
134613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node = avtab_search_node(&p->te_cond_avtab, &avkey);
134713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (node && node->parse_context != other) {
134813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				conflict = 2;
134913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
135013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
135113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
135213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (conflict) {
135313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump = &node->datum;
135413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (specified & AVRULE_TRANSITION) {
135513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
135613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (specified & AVRULE_MEMBER) {
135713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
135813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (specified & AVRULE_CHANGE) {
135913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
136013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
136113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
136213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (oldtype == remapped_data) {
136313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* if the duplicate is inside the same scope (eg., unconditional
136413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 * or in same conditional then ignore it */
136513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((conflict == 1 && cond == NULL)
136613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    || node->parse_context == cond)
136713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return EXPAND_RULE_SUCCESS;
136813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(handle, "duplicate TE rule for %s %s:%s %s",
136913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[avkey.source_type -
137013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  1],
137113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[avkey.target_type -
137213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  1],
137313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_class_val_to_name[avkey.target_class -
137413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   1],
137513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[oldtype - 1]);
137613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return EXPAND_RULE_CONFLICT;
137713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
137813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle,
137913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "conflicting TE rule for (%s, %s:%s):  old was %s, new is %s",
138013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[avkey.source_type - 1],
138113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[avkey.target_type - 1],
138213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_class_val_to_name[avkey.target_class - 1],
138313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[oldtype - 1],
138413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[remapped_data - 1]);
138513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return EXPAND_RULE_CONFLICT;
138613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
138713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
138813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = find_avtab_node(handle, avtab, &avkey, cond);
138913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node)
139013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
139113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (enabled) {
139213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified |= AVTAB_ENABLED;
139313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
139413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified &= ~AVTAB_ENABLED;
139513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
139613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
139713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avdatump = &node->datum;
139813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (specified & AVRULE_TRANSITION) {
139913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data = remapped_data;
140013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_MEMBER) {
140113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data = remapped_data;
140213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_CHANGE) {
140313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data = remapped_data;
140413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
140513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(0);	/* should never occur */
140613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
140713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
140813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
140913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
141013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
141213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
141313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avrule_helper(sepol_handle_t * handle,
141513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t specified,
141613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cond_av_list_t ** cond,
141713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t stype, uint32_t ttype,
141813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				class_perm_node_t * perms, avtab_t * avtab,
141913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				int enabled)
142013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
142113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t avkey;
142213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avdatump;
142313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
142413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur;
142513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t spec = 0;
142613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
142713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (specified & AVRULE_ALLOWED) {
142813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_ALLOWED;
142913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_AUDITALLOW) {
143013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_AUDITALLOW;
143113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_AUDITDENY) {
143213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_AUDITDENY;
143313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_DONTAUDIT) {
143413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (handle && handle->disable_dontaudit)
143513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return EXPAND_RULE_SUCCESS;
143613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_AUDITDENY;
143713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (specified & AVRULE_NEVERALLOW) {
143813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		spec = AVTAB_NEVERALLOW;
143913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
144013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(0);	/* unreachable */
144113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
144213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
144313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = perms;
144413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
144513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.source_type = stype + 1;
144613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.target_type = ttype + 1;
144713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.target_class = cur->class;
144813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avkey.specified = spec;
144913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
145013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = find_avtab_node(handle, avtab, &avkey, cond);
145113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node)
145213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return EXPAND_RULE_ERROR;
145313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (enabled) {
145413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified |= AVTAB_ENABLED;
145513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
145613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified &= ~AVTAB_ENABLED;
145713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
145813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
145913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avdatump = &node->datum;
146013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (specified & AVRULE_ALLOWED) {
146113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data |= cur->data;
146213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_AUDITALLOW) {
146313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data |= cur->data;
146413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_NEVERALLOW) {
146513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data |= cur->data;
146613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_AUDITDENY) {
146713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* Since a '0' in an auditdeny mask represents
146813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * a permission we do NOT want to audit
146913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * (dontaudit), we use the '&' operand to
147013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * ensure that all '0's in the mask are
147113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * retained (much unlike the allow and
147213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * auditallow cases).
147313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 */
147413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data &= cur->data;
147513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (specified & AVRULE_DONTAUDIT) {
147613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (avdatump->data)
147713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				avdatump->data &= ~cur->data;
147813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			else
147913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				avdatump->data = ~cur->data;
148013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
148113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(0);	/* should never occur */
148213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
148313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
148413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
148513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
148613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
148713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
148813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
148913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_rule_helper(sepol_handle_t * handle,
149013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, uint32_t * typemap,
149113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avrule_t * source_rule, avtab_t * dest_avtab,
149213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      cond_av_list_t ** cond, cond_av_list_t ** other,
149313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      int enabled,
149413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      ebitmap_t * stypes, ebitmap_t * ttypes)
149513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
149613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
149713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
149813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
149913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
150013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(stypes, snode, i) {
150113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
150213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
150313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (source_rule->flags & RULE_SELF) {
150413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (source_rule->specified & AVRULE_AV) {
150513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((retval =
150613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     expand_avrule_helper(handle,
150713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->
150813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  specified, cond, i, i,
150913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->perms,
151013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  dest_avtab,
151113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  enabled)) !=
151213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
151313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
151413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
151513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
151613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((retval =
151713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     expand_terule_helper(handle, p,
151813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  typemap,
151913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->
152013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  specified, cond,
152113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  other, i, i,
152213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->perms,
152313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  dest_avtab,
152413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  enabled)) !=
152513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
152613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
152713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
152813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
152913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
153013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(ttypes, tnode, j) {
153113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
153213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
153313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (source_rule->specified & AVRULE_AV) {
153413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((retval =
153513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     expand_avrule_helper(handle,
153613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->
153713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  specified, cond, i, j,
153813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->perms,
153913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  dest_avtab,
154013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  enabled)) !=
154113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
154213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
154313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
154413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
154513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((retval =
154613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     expand_terule_helper(handle, p,
154713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  typemap,
154813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->
154913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  specified, cond,
155013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  other, i, j,
155113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  source_rule->perms,
155213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  dest_avtab,
155313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  enabled)) !=
155413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
155513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
155613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
155713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
155813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
155913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
156013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
156213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
156313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
156513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Expand a rule into a given avtab - checking for conflicting type
156613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * rules in the destination policy.  Return EXPAND_RULE_SUCCESS on
156713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * success, EXPAND_RULE_CONFLICT if the rule conflicts with something
156813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * (and hence was not added), or EXPAND_RULE_ERROR on error.
156913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
157013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int convert_and_expand_rule(sepol_handle_t * handle,
157113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   policydb_t * dest_pol, uint32_t * typemap,
157213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   avrule_t * source_rule, avtab_t * dest_avtab,
157313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   cond_av_list_t ** cond,
157413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   cond_av_list_t ** other, int enabled,
157513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   int do_neverallow)
157613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
157713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
157813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
157913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned char alwaysexpand;
158013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
158113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW)
158213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_SUCCESS;
158313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
158413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&stypes);
158513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&ttypes);
158613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
158713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Force expansion for type rules and for self rules. */
158813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	alwaysexpand = ((source_rule->specified & AVRULE_TYPE) ||
158913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			(source_rule->flags & RULE_SELF));
159013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
159113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
159213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand))
159313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_ERROR;
159413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
159513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand))
159613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_ERROR;
159713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
159813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = expand_rule_helper(handle, dest_pol, typemap,
159913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    source_rule, dest_avtab,
160013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    cond, other, enabled, &stypes, &ttypes);
160113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
160213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
160313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
160413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
160513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
160613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules,
160713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 avtab_t * dest_avtab, cond_av_list_t ** list,
160813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 cond_av_list_t ** other, uint32_t * typemap,
160913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 int enabled, expand_state_t * state)
161013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
161113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *cur;
161213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = source_rules;
161413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
161513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (convert_and_expand_rule(state->handle, dest_pol,
161613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    typemap, cur, dest_avtab,
161713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    list, other, enabled,
161813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    0) != EXPAND_RULE_SUCCESS) {
161913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
162013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
162113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
162213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
162313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
162413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
162513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
162613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
162713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
162813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_node_map_bools(expand_state_t * state, cond_node_t * cn)
162913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
163013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_expr_t *cur;
163113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
163213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
163313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = cn->expr;
163413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
163513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cur->bool)
163613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur->bool = state->boolmap[cur->bool - 1];
163713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
163813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
163913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
164013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++)
164113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1];
164213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
164313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize_expr(state->out, cn)) {
164413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error while normalizing conditional");
164513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
164613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
164713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
164813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
164913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
165013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
165113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* copy the nodes in *reverse* order -- the result is that the last
165213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * given conditional appears first in the policy, so as to match the
165313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * behavior of the upstream compiler */
165413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_node_copy(expand_state_t * state, cond_node_t * cn)
165513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
165613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_t *new_cond, *tmp;
165713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
165813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cn == NULL) {
165913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
166013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
166113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_node_copy(state, cn->next)) {
166213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
166313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
166413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize_expr(state->base, cn)) {
166513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error while normalizing conditional");
166613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
166713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
166813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
166913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* create a new temporary conditional node with the booleans
167013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * mapped */
167113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmp = cond_node_create(state->base, cn);
167213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!tmp) {
167313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory");
167413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
167513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
167613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
167713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_node_map_bools(state, tmp)) {
167813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error mapping booleans");
167913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
168013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
168113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
168213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cond = cond_node_search(state->out, state->out->cond_list, tmp);
168313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_cond) {
168413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cond_node_destroy(tmp);
168513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(tmp);
168613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
168713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
168813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
168913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_destroy(tmp);
169013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(tmp);
169113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
169213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_avrule_list_copy
169313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, cn->avtrue_list, &state->out->te_cond_avtab,
169413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_cond->true_list, &new_cond->false_list, state->typemap,
169513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     new_cond->cur_state, state))
169613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
169713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_avrule_list_copy
169813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, cn->avfalse_list, &state->out->te_cond_avtab,
169913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_cond->false_list, &new_cond->true_list, state->typemap,
170013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     !new_cond->cur_state, state))
170113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
170213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
170313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
170413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
170513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
170613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int context_copy(context_struct_t * dst, context_struct_t * src,
170713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			expand_state_t * state)
170813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
170913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->user = state->usermap[src->user - 1];
171013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->role = state->rolemap[src->role - 1];
171113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->type = state->typemap[src->type - 1];
171213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return mls_context_cpy(dst, src);
171313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
171413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
171513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int ocontext_copy(expand_state_t * state)
171613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
171713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
171813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *n, *l;
171913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
172013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < OCON_NUM; i++) {
172113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		l = NULL;
172213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (c = state->base->ocontexts[i]; c; c = c->next) {
172313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			n = malloc(sizeof(ocontext_t));
172413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!n) {
172513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
172613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
172713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
172813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(n, 0, sizeof(ocontext_t));
172913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (l) {
173013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l->next = n;
173113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
173213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				state->out->ocontexts[i] = n;
173313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
173413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			l = n;
173513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (context_copy(&n->context[0], &c->context[0], state)) {
173613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
173713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
173813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
173913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			switch (i) {
174013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_ISID:
174113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->sid[0] = c->sid[0];
174213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
174313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_FS:	/* FALLTHROUGH */
174413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NETIF:
174513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.name = strdup(c->u.name);
174613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n->u.name) {
174713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
174813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
174913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
175013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (context_copy
175113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (&n->context[1], &c->context[1], state)) {
175213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
175313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
175413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
175513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
175613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_PORT:
175713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.protocol = c->u.port.protocol;
175813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.low_port = c->u.port.low_port;
175913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.high_port = c->u.port.high_port;
176013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
176113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NODE:
176213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.node.addr = c->u.node.addr;
176313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.node.mask = c->u.node.mask;
176413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
176513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_FSUSE:
176613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->v.behavior = c->v.behavior;
176713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.name = strdup(c->u.name);
176813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n->u.name) {
176913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
177013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
177113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
177213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
177313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NODE6:
177413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				for (j = 0; j < 4; j++)
177513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					n->u.node6.addr[j] = c->u.node6.addr[j];
177613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				for (j = 0; j < 4; j++)
177713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					n->u.node6.mask[j] = c->u.node6.mask[j];
177813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
177913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			default:
178013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* shouldn't get here */
178113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(0);
178213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
178313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
178413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
178513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
178613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
178713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int genfs_copy(expand_state_t * state)
178913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
179013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *newc, *l;
179113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genfs_t *genfs, *newgenfs, *end;
179213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
179313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	end = NULL;
179413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (genfs = state->base->genfs; genfs; genfs = genfs->next) {
179513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newgenfs = malloc(sizeof(genfs_t));
179613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!newgenfs) {
179713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
179813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
179913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
180013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(newgenfs, 0, sizeof(genfs_t));
180113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newgenfs->fstype = strdup(genfs->fstype);
180213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!newgenfs->fstype) {
180313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
180413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
180513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
180613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
180713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		l = NULL;
180813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (c = genfs->head; c; c = c->next) {
180913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc = malloc(sizeof(ocontext_t));
181013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!newc) {
181113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
181213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
181313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
181413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(newc, 0, sizeof(ocontext_t));
181513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc->u.name = strdup(c->u.name);
181613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!newc->u.name) {
181713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
181813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
181913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
182013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc->v.sclass = c->v.sclass;
182113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_copy(&newc->context[0], &c->context[0], state);
182213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (l)
182313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l->next = newc;
182413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			else
182513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				newgenfs->head = newc;
182613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			l = newc;
182713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
182813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!end) {
182913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->out->genfs = newgenfs;
183013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
183113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			end->next = newgenfs;
183213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
183313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		end = newgenfs;
183413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
183513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
183613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
183713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
183813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_attr_map(hashtab_key_t key
183913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 __attribute__ ((unused)), hashtab_datum_t datum,
184013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 void *ptr)
184113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
184213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type;
184313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = ptr;
184413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p = state->out;
184513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
184613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
184713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
184813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
184913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor == TYPE_ATTRIB) {
185013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_cpy(&p->attr_type_map[type->s.value - 1],
185113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				&type->types)) {
185213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
185313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
185413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
185513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&type->types, tnode, i) {
185613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, i))
185713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
185813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(&p->type_attr_map[i],
185913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    type->s.value - 1, 1)) {
186013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
186113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
186213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
186313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
186413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
186513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
186613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
186713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
186813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
186913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 __attribute__ ((unused)))
187013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
187113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(key);
187213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_destroy((type_datum_t *) datum);
187313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(datum);
187413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
187513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
187613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_attr_remove(hashtab_key_t key
187713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    __attribute__ ((unused)), hashtab_datum_t datum,
187813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    void *args)
187913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
188013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *typdatum;
188113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p;
188213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
188313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	typdatum = (type_datum_t *) datum;
188413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p = (policydb_t *) args;
188513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (typdatum->flavor == TYPE_ATTRIB) {
188613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		p->type_val_to_struct[typdatum->s.value - 1] = NULL;
188713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		p->p_type_val_to_name[typdatum->s.value - 1] = NULL;
188813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
188913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
189013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
189113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
189213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
189313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy.
189413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * this should not be called until after all the blocks have been processed and the attributes in target policy
189513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * are complete. */
189613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_convert_type_set(policydb_t * p, uint32_t * typemap,
189713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    type_set_t * set, ebitmap_t * types,
189813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    unsigned char alwaysexpand)
189913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
190013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_t tmpset;
190113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
190213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_init(&tmpset);
190313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
190413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&set->types, &tmpset.types, typemap))
190513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
190613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
190713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&set->negset, &tmpset.negset, typemap))
190813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
190913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmpset.flags = set->flags;
191113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_expand(&tmpset, types, p, alwaysexpand))
191313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
191413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_destroy(&tmpset);
191613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
191813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
191913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
192013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Expand a rule into a given avtab - checking for conflicting type
192113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * rules.  Return 1 on success, 0 if the rule conflicts with something
192213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * (and hence was not added), or -1 on error. */
192313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_rule(sepol_handle_t * handle,
192413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		policydb_t * source_pol,
192513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_t * source_rule, avtab_t * dest_avtab,
192613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cond_av_list_t ** cond, cond_av_list_t ** other, int enabled)
192713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
192813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
192913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
193013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
193113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (source_rule->specified & AVRULE_NEVERALLOW)
193213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
193313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
193413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&stypes);
193513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&ttypes);
193613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
193713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1))
193813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
193913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1))
194013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
194113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = expand_rule_helper(handle, source_pol, NULL,
194213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    source_rule, dest_avtab,
194313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    cond, other, enabled, &stypes, &ttypes);
194413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
194513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
194613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
194713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
194813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
194913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * p, uint32_t * rolemap)
195013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
195113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
195213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *rnode;
195313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t mapped_roles;
195413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(r);
195613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&mapped_roles);
195713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (x->flags & ROLE_STAR) {
195913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < p->p_roles.nprim++; i++)
196013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(r, i, 1))
196113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
196213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
196313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
196413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
196513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rolemap) {
196613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (map_ebitmap(&x->roles, &mapped_roles, rolemap))
196713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
196813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
196913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_cpy(&mapped_roles, &x->roles))
197013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
197113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
197213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&mapped_roles, rnode, i) {
197413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(rnode, i)) {
197513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(r, i, 1))
197613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
197713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
197813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
197913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
198013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&mapped_roles);
198113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
198213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* if role is to be complimented, invert the entire bitmap here */
198313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (x->flags & ROLE_COMP) {
198413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < ebitmap_length(r); i++) {
198513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(r, i)) {
198613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(r, i, 0))
198713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
198813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
198913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(r, i, 1))
199013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
199113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
199213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
199313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
199413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
199513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
199613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
199713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Expand a type set into an ebitmap containing the types. This
199813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * handles the negset, attributes, and flags.
199913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Attribute expansion depends on several factors:
200013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - if alwaysexpand is 1, then they will be expanded,
200113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - if the type set has a negset or flags, then they will be expanded,
200213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - otherwise, they will not be expanded.
200313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
200413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p,
200513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    unsigned char alwaysexpand)
200613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
200713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
200813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t types, neg_types;
200913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
201013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&types);
201213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(t);
201313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alwaysexpand || ebitmap_length(&set->negset) || set->flags) {
201513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* First go through the types and OR all the attributes to types */
201613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&set->types, tnode, i) {
201713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_node_get_bit(tnode, i)) {
201813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (p->type_val_to_struct[i]->flavor ==
201913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    TYPE_ATTRIB) {
202013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_union
202113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (&types,
202213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     &p->type_val_to_struct[i]->
202313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     types)) {
202413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						return -1;
202513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
202613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
202713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_set_bit(&types, i, 1)) {
202813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						return -1;
202913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
203013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
203113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
203213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
203313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
203413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* No expansion of attributes, just copy the set as is. */
203513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_cpy(&types, &set->types))
203613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
203713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
203813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
203913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Now do the same thing for negset */
204013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&neg_types);
204113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&set->negset, tnode, i) {
204213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)) {
204313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
204413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
204513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_union
204613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (&neg_types,
204713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     &p->type_val_to_struct[i]->types)) {
204813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
204913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
205013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
205113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(&neg_types, i, 1)) {
205213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
205313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
205413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
205513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
205613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
205713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
205813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set->flags & TYPE_STAR) {
205913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* set all types not in neg_types */
206013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < p->p_types.nprim; i++) {
206113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(&neg_types, i))
206213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
206313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
206413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
206513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
206613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(t, i, 1))
206713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
206813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
206913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
207013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
207113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&types, tnode, i) {
207313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)
207413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    && (!ebitmap_get_bit(&neg_types, i)))
207513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(t, i, 1))
207613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
207713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
207813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set->flags & TYPE_COMP) {
208013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < p->p_types.nprim; i++) {
208113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
208213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
208313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(!ebitmap_get_bit(t, i));
208413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
208513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
208613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(t, i)) {
208713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(t, i, 0))
208813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
208913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
209013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(t, i, 1))
209113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
209213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
209313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
209413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
209513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
209613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
209713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
209813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&types);
209913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&neg_types);
210013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
210213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
210313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
210513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   avrule_t * source_rule)
210613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
210713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
210813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *avrule;
210913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur_perm, *new_perm, *tail_perm;
211013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
211113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&stypes);
211213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&ttypes);
211313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
211413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
211513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->stypes, &stypes, 1))
211613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
211713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
211813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1))
211913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
212013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
212113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule = (avrule_t *) malloc(sizeof(avrule_t));
212213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!avrule)
212313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
212413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
212513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_init(avrule);
212613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule->specified = AVRULE_NEVERALLOW;
212713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule->line = source_rule->line;
212813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule->flags = source_rule->flags;
212913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
213013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&avrule->stypes.types, &stypes))
213113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
213213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
213313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&avrule->ttypes.types, &ttypes))
213413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
213513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
213613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur_perm = source_rule->perms;
213713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail_perm = NULL;
213813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur_perm) {
213913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_perm =
214013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
214113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_perm)
214213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
214313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		class_perm_node_init(new_perm);
214413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_perm->class = cur_perm->class;
214513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(new_perm->class);
214613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
214713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* once we have modules with permissions we'll need to map the permissions (and classes) */
214813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_perm->data = cur_perm->data;
214913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!avrule->perms)
215113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avrule->perms = new_perm;
215213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (tail_perm)
215413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail_perm->next = new_perm;
215513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail_perm = new_perm;
215613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_perm = cur_perm->next;
215713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
215813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* just prepend the avrule to the first branch; it'll never be
216013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   written to disk */
216113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!dest_pol->global->branch_list->avrules)
216213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_pol->global->branch_list->avrules = avrule;
216313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else {
216413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule->next = dest_pol->global->branch_list->avrules;
216513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_pol->global->branch_list->avrules = avrule;
216613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
216713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
216813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
216913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
217013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
217113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
217213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
217313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
217413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
217513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
217613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&avrule->stypes.types);
217713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&avrule->ttypes.types);
217813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur_perm = avrule->perms;
217913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur_perm) {
218013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail_perm = cur_perm->next;
218113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(cur_perm);
218213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_perm = tail_perm;
218313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
218413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(avrule);
218513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
218613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
218713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
218813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
218913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow
219013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * rules are copied or expanded as per the settings in the state object; all
219113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * other AV rules are expanded.  If neverallow rules are expanded, they are not
219213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * copied, otherwise they are copied for later use by the assertion checker.
219313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
219413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_and_expand_avrule_block(expand_state_t * state)
219513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
219613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *curblock = state->base->global;
219713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *prevblock;
219813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = -1;
219913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
220013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) {
220113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		ERR(state->handle, "Out of Memory!");
220213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		return -1;
220313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	}
220413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
220513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) {
220613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		ERR(state->handle, "Out of Memory!");
220713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		return -1;
220813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	}
220913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
221013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (curblock) {
221113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = curblock->enabled;
221213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_t *cur_avrule;
221313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
221413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (decl == NULL) {
221513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* nothing was enabled within this block */
221613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cont;
221713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
221813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
221913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy role allows and role trans */
222013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_role_allows(state, decl->role_allow_rules) != 0 ||
222113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    copy_role_trans(state, decl->role_tr_rules) != 0) {
222213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
222313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
222413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
222513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the range transition rules */
222613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_range_trans(state, decl->range_tr_rules))
222713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
222813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
222913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy rules */
223013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_avrule = decl->avrules;
223113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur_avrule != NULL) {
223213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!(state->expand_neverallow)
223313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    && cur_avrule->specified & AVRULE_NEVERALLOW) {
223413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* copy this over directly so that assertions are checked later */
223513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (copy_neverallow
223613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (state->out, state->typemap, cur_avrule))
223713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
223813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "Error while copying neverallow.");
223913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
224013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur_avrule->specified & AVRULE_NEVERALLOW) {
224113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state->out->unsupported_format = 1;
224213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
224313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (convert_and_expand_rule
224413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (state->handle, state->out, state->typemap,
224513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     cur_avrule, &state->out->te_avtab, NULL,
224613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     NULL, 0,
224713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     state->expand_neverallow) !=
224813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
224913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto cleanup;
225013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
225113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
225213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur_avrule = cur_avrule->next;
225313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
225413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
225513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy conditional rules */
225613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cond_node_copy(state, decl->cond_list))
225713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
225813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
225913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cont:
226013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		prevblock = curblock;
226113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		curblock = curblock->next;
226213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
226313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->handle && state->handle->expand_consume_base) {
226413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* set base top avrule block in case there
226513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 			 * is an error condition and the policy needs
226613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 			 * to be destroyed */
226713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->base->global = curblock;
226813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avrule_block_destroy(prevblock);
226913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
227013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
227113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
227313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
227513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
227613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
227713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
227913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This function allows external users of the library (such as setools) to
228013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * expand only the avrules and optionally perform expansion of neverallow rules
228113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * or expand into the same policy for analysis purposes.
228213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
228313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_module_avrules(sepol_handle_t * handle, policydb_t * base,
228413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  policydb_t * out, uint32_t * typemap,
228513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  uint32_t * boolmap, uint32_t * rolemap,
228613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  uint32_t * usermap, int verbose,
228713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  int expand_neverallow)
228813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
228913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t state;
229013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
229113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_init(&state);
229213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
229313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.base = base;
229413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out = out;
229513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.typemap = typemap;
229613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.boolmap = boolmap;
229713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.rolemap = rolemap;
229813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.usermap = usermap;
229913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.handle = handle;
230013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.verbose = verbose;
230113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.expand_neverallow = expand_neverallow;
230213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
230313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return copy_and_expand_avrule_block(&state);
230413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
230513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
230613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Linking should always be done before calling expand, even if
230713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * there is only a base since all optionals are dealt with at link time
230813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the base passed in should be indexed and avrule blocks should be
230913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * enabled.
231013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
231113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_module(sepol_handle_t * handle,
231213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		  policydb_t * base, policydb_t * out, int verbose, int check)
231313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
231413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = -1;
231513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
231613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t state;
231713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *curblock;
231813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
231913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_init(&state);
232013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
232113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.verbose = verbose;
232213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.typemap = NULL;
232313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.base = base;
232413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out = out;
232513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.handle = handle;
232613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
232713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base->policy_type != POLICY_BASE) {
232813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Target of expand was not a base policy.");
232913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
233013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
233113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
233213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->policy_type = POLICY_KERN;
233313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->policyvers = POLICYDB_VERSION_MAX;
233413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
233513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Copy mls state from base to out */
233613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	out->mls = base->mls;
233713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	out->handle_unknown = base->handle_unknown;
233813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
233913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Copy policy capabilities */
234013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&out->policycaps, &base->policycaps)) {
234113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
234213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
234313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
234413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
234513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((state.typemap =
234613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     (uint32_t *) calloc(state.base->p_types.nprim,
234713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 sizeof(uint32_t))) == NULL) {
234813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
234913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
235013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
235113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
235213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t));
235313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.boolmap) {
235413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
235513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
235613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
235713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
235813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t));
235913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.rolemap) {
236013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
236113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
236213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
236313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
236413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t));
236513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.usermap) {
236613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
236713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
236813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
236913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* order is important - types must be first */
237113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy types */
237313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) {
237413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
237513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
237613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* convert attribute type sets */
237813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
237913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_types.table, attr_convert_callback, &state)) {
238013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
238113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
238213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy commons */
238413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
238513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_commons.table, common_copy_callback, &state)) {
238613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
238713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
238813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy classes, note, this does not copy constraints, constraints can't be
239013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * copied until after all the blocks have been processed and attributes are complete */
239113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
239213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_classes.table, class_copy_callback, &state)) {
239313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
239413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
239513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
239613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy aliases */
239713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state))
239813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
239913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
240013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* index here so that type indexes are available for role_copy_callback */
240113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
240213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
240313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
240413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
240513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
240613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy roles */
240713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
240813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
240913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
241013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy MLS's sensitivity level and categories - this needs to be done
241113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * before expanding users (they need to be indexed too) */
241213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
241313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
241413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
241513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
241613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
241713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
241813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
241913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
242013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
242113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy users */
242213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
242313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
242413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
242513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy bools */
242613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
242713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
242813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
242913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_classes(out)) {
243013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out classes");
243113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
243213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
243313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
243413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
243513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
243613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
243713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
243813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* loop through all decls and union attributes, roles, users */
243913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (curblock = state.base->global; curblock != NULL;
244013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     curblock = curblock->next) {
244113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = curblock->enabled;
244213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
244313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (decl == NULL) {
244413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* nothing was enabled within this block */
244513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
244613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
244713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
244813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* convert attribute type sets */
244913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
245013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_types.table, attr_convert_callback, &state)) {
245113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
245213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
245313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
245413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy roles */
245513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
245613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_roles.table, role_copy_callback, &state))
245713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
245813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
245913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy users */
246013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
246113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_users.table, user_copy_callback, &state))
246213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
246313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
246413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
246513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
246613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* remap role dominates bitmaps */
246713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) {
246813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
246913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
247013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
247113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (copy_and_expand_avrule_block(&state) < 0) {
247213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error during expand");
247313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
247413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
247513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
247613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy constraints */
247713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
247813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_classes.table, constraint_copy_callback, &state)) {
247913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
248013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
248113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
248213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_optimize_lists(state.out->cond_list);
248313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	evaluate_conds(state.out);
248413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
248513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy ocontexts */
248613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ocontext_copy(&state))
248713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
248813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
248913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy genfs */
249013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (genfs_copy(&state))
249113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
249213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
249313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Build the type<->attribute maps and remove attributes. */
249413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->attr_type_map = malloc(state.out->p_types.nprim *
249513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					  sizeof(ebitmap_t));
249613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->type_attr_map = malloc(state.out->p_types.nprim *
249713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					  sizeof(ebitmap_t));
249813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.out->attr_type_map || !state.out->type_attr_map) {
249913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
250013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
250113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
250213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < state.out->p_types.nprim; i++) {
250313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&state.out->type_attr_map[i]);
250413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&state.out->attr_type_map[i]);
250513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* add the type itself as the degenerate case */
250613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) {
250713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle, "Out of memory!");
250813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
250913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
251013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
251113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.out->p_types.table, type_attr_map, &state))
251213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
251313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_map_remove_on_error(state.out->p_types.table,
251413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    type_attr_remove, type_destroy, state.out);
251513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (check) {
251613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hierarchy_check_constraints(handle, state.out))
251713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
251813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
251913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (check_assertions
252013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (handle, state.out,
252113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     state.out->global->branch_list->avrules))
252213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 goto cleanup;
252313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
252413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
252513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
252613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
252713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
252813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.typemap);
252913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.boolmap);
253013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.rolemap);
253113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.usermap);
253213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
253313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
253413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
253513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
253613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
253713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
253813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avd;
253913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
254013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
254113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	node = avtab_search_node(a, k);
254213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!node) {
254313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = avtab_insert(a, k, d);
254413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc)
254513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
254613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return rc;
254713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
254813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
254913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((k->specified & AVTAB_ENABLED) !=
255013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (node->key.specified & AVTAB_ENABLED)) {
255113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(a, k, d);
255213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
255313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
255413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
255513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
255613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
255713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
255813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
255913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avd = &node->datum;
256013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (k->specified & ~AVTAB_ENABLED) {
256113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_ALLOWED:
256213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITALLOW:
256313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data |= d->data;
256413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
256513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITDENY:
256613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data &= d->data;
256713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
256813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
256913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Type conflict!");
257013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
257113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
257213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
257313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
257413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
257513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
257613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestruct expand_avtab_data {
257713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_t *expa;
257813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p;
257913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
258013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
258113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
258213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args)
258313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
258413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct expand_avtab_data *ptr = args;
258513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_t *expa = ptr->expa;
258613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p = ptr->p;
258713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
258813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
258913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
259013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
259113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
259213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
259313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t newkey;
259413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
259513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
259613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.target_class = k->target_class;
259713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.specified = k->specified;
259813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
259913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stype && ttype) {
260013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Both are individual types, no expansion required. */
260113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return expand_avtab_insert(expa, k, d);
260213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
260313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
260413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stype) {
260513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Source is an individual type, target is an attribute. */
260613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.source_type = k->source_type;
260713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
260813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
260913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
261013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
261113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
261213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
261313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
261413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
261513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
261613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
261713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
261813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ttype) {
261913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Target is an individual type, source is an attribute. */
262013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.target_type = k->target_type;
262113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(sattr, snode, i) {
262213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
262313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
262413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
262513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
262613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
262713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
262813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
262913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
263013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
263113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
263213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Both source and target type are attributes. */
263313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(sattr, snode, i) {
263413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
263513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
263613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
263713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
263813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
263913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
264013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
264113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
264213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
264313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
264413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
264513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
264613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
264713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
264813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
264913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
265013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa)
265113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
265213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct expand_avtab_data data;
265313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
265413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
265513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Out of memory!");
265613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
265713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
265813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
265913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data.expa = expa;
266013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data.p = p;
266113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return avtab_map(a, expand_avtab_node, &data);
266213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
266313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
266413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_cond_insert(cond_av_list_t ** l,
266513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avtab_t * expa,
266613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avtab_key_t * k, avtab_datum_t * d)
266713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
266813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
266913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avd;
267013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *nl;
267113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
267213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	node = avtab_search_node(expa, k);
267313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!node ||
267413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (k->specified & AVTAB_ENABLED) !=
267513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (node->key.specified & AVTAB_ENABLED)) {
267613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(expa, k, d);
267713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
267813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
267913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
268013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
268113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node->parse_context = (void *)1;
268213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl = (cond_av_list_t *) malloc(sizeof(*nl));
268313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!nl) {
268413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
268513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
268613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
268713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(nl, 0, sizeof(*nl));
268813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl->node = node;
268913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl->next = *l;
269013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*l = nl;
269113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
269213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
269313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
269413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avd = &node->datum;
269513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (k->specified & ~AVTAB_ENABLED) {
269613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_ALLOWED:
269713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITALLOW:
269813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data |= d->data;
269913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
270013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITDENY:
270113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data &= d->data;
270213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
270313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
270413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Type conflict!");
270513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
270613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
270713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
270813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
270913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
271013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
271113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_cond_av_node(policydb_t * p,
271213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avtab_ptr_t node,
271313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cond_av_list_t ** newl, avtab_t * expa)
271413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
271513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t *k = &node->key;
271613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *d = &node->datum;
271713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
271813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
271913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
272013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
272113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
272213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
272313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t newkey;
272413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
272513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
272613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.target_class = k->target_class;
272713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.specified = k->specified;
272813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
272913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stype && ttype) {
273013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Both are individual types, no expansion required. */
273113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return expand_cond_insert(newl, expa, k, d);
273213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
273313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
273413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (stype) {
273513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Source is an individual type, target is an attribute. */
273613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.source_type = k->source_type;
273713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
273813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
273913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
274013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
274113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
274213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
274313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
274413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
274513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
274613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
274713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
274813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ttype) {
274913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Target is an individual type, source is an attribute. */
275013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.target_type = k->target_type;
275113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(sattr, snode, i) {
275213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
275313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
275413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
275513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
275613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
275713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
275813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
275913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
276013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
276113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
276213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Both source and target type are attributes. */
276313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(sattr, snode, i) {
276413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
276513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
276613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
276713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
276813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
276913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
277013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
277113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
277213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
277313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
277413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
277513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
277613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
277713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
277813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
277913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
278013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_cond_av_list(policydb_t * p, cond_av_list_t * l,
278113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cond_av_list_t ** newl, avtab_t * expa)
278213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
278313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *cur;
278413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
278513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
278613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
278713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
278813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Out of memory!");
278913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
279013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
279113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
279213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*newl = NULL;
279313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cur = l; cur; cur = cur->next) {
279413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = cur->node;
279513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = expand_cond_av_node(p, node, newl, expa);
279613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc)
279713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return rc;
279813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
279913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
280013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
280113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
2802