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>
36dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts#include <inttypes.h>
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "private.h"
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct expand_state {
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int verbose;
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *typemap;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *boolmap;
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *rolemap;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *usermap;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *base;
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *out;
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_handle_t *handle;
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int expand_neverallow;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} expand_state_t;
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void expand_state_init(expand_state_t * state)
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(state, 0, sizeof(expand_state_t));
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(dst);
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(src, tnode, i) {
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(tnode, i))
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!map[i])
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(dst, map[i] - 1, 1))
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *new_type;
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((type->flavor == TYPE_TYPE && !type->primary)
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || type->flavor == TYPE_ALIAS) {
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* aliases are handled later */
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_TYPES)) {
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying type or attribute %s", id);
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_id == NULL) {
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type = (type_datum_t *) malloc(sizeof(type_datum_t));
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_type) {
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return SEPOL_ENOMEM;
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_type, 0, sizeof(type_datum_t));
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->flavor = type->flavor;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->flags = type->flags;
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->s.value = ++state->out->p_types.nprim;
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_type->s.value > UINT16_MAX) {
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_type);
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "type space overflow");
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type->primary = 1;
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->typemap[type->s.value - 1] = new_type->s.value;
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_types.table,
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_type);
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_type);
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_type->flags & TYPE_FLAGS_PERMISSIVE)
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) {
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!\n");
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum,
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 void *data)
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *new_type;
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union;
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor != TYPE_ATTRIB)
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_TYPES)) {
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "converting attribute %s", id);
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type = hashtab_search(state->out->p_types.table, id);
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_type) {
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "attribute %s vanished!", id);
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&type->types, &tmp_union, state->typemap)) {
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "out of memory");
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then union tmp_union onto &new_type->types */
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_type->types, &tmp_union)) {
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union);
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	symtab_t *s;
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perm, *new_perm;
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm = (perm_datum_t *) datum;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s = (symtab_t *) data;
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t));
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_perm) {
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_perm, 0, sizeof(perm_datum_t));
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_perm);
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_perm->s.value = perm->s.value;
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s->nprim++;
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm);
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_perm);
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				void *data)
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	common_datum_t *common, *new_common;
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	common = (common_datum_t *) datum;
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying common %s", id);
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_common = (common_datum_t *) malloc(sizeof(common_datum_t));
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_common) {
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_common, 0, sizeof(common_datum_t));
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) {
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
25592788715dc793f805b0ae56844216b844a34ea22Alice Chu		/* free memory created by symtab_init first, then free new_common */
25692788715dc793f805b0ae56844216b844a34ea22Alice Chu		symtab_destroy(&new_common->permissions);
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_common->s.value = common->s.value;
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_commons.nprim++;
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    hashtab_insert(state->out->p_commons.table, new_id,
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t *) new_common);
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_common);
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (common->permissions.table, perm_copy_callback,
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_common->permissions)) {
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int constraint_node_clone(constraint_node_t ** dst,
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 constraint_node_t * src,
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 expand_state_t * state)
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_node_t *new_con = NULL, *last_new_con = NULL;
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_expr_t *new_expr = NULL;
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*dst = NULL;
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (src != NULL) {
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		constraint_expr_t *expr, *expr_l = NULL;
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_con =
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (constraint_node_t *) malloc(sizeof(constraint_node_t));
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_con) {
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto out_of_mem;
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_con, 0, sizeof(constraint_node_t));
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_con->permissions = src->permissions;
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (expr = src->expr; expr; expr = expr->next) {
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) {
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out_of_mem;
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (constraint_expr_init(new_expr) == -1) {
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out_of_mem;
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->expr_type = expr->expr_type;
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->attr = expr->attr;
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr->op = expr->op;
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_expr->expr_type == CEXPR_NAMES) {
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (new_expr->attr & CEXPR_TYPE) {
3129eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					/*
3139eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					 * Copy over constraint policy source types and/or
3149eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					 * attributes for sepol_compute_av_reason_buffer(3)
3159eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					 * so that utilities can analyse constraint errors.
3169eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					 */
3179eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					if (map_ebitmap(&expr->type_names->types,
3189eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines							&new_expr->type_names->types,
3199eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines							state->typemap)) {
3209eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines						ERR(NULL, "Failed to map type_names->types");
3219eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines						goto out_of_mem;
3229eefe11b3a94307a3f5432316a59d1f8e3268429Richard Haines					}
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					/* Type sets require expansion and conversion. */
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (expand_convert_type_set(state->out,
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    state->
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    typemap,
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    expr->
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    type_names,
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    &new_expr->
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								    names, 1)) {
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else if (new_expr->attr & CEXPR_ROLE) {
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else if (new_expr->attr & CEXPR_USER) {
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					/* Other kinds of sets do not. */
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_cpy(&new_expr->names,
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							&expr->names)) {
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto out_of_mem;
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (expr_l) {
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				expr_l->next = new_expr;
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				new_con->expr = new_expr;
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			expr_l = new_expr;
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_expr = NULL;
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (last_new_con == NULL) {
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_con;
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			last_new_con->next = new_con;
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		last_new_con = new_con;
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		src = src->next;
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_con)
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_con);
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	constraint_expr_destroy(new_expr);
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Parisstatic int class_copy_default_new_object(expand_state_t *state,
37609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris					 class_datum_t *olddatum,
37709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris					 class_datum_t *newdatum)
37809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris{
37909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_user) {
38009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
38109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default user definitions");
38209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
38309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
38409c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_user = olddatum->default_user;
38509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris
38609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
38709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_role) {
38809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
38909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default role definitions");
39009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
39109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
39209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_role = olddatum->default_role;
39309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
394693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris	if (olddatum->default_type) {
395693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
396693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris			ERR(state->handle, "Found conflicting default type definitions");
397693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris			return SEPOL_ENOTSUP;
398693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		}
399693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		newdatum->default_type = olddatum->default_type;
400693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris	}
40109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_range) {
40209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
40309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default range definitions");
40409c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
40509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
40609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_range = olddatum->default_range;
40709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
40809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	return 0;
40909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris}
41009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *class, *new_class;
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class = (class_datum_t *) datum;
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_CLASSES)) {
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying class %s", id);
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class = (class_datum_t *) malloc(sizeof(class_datum_t));
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_class) {
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_class, 0, sizeof(class_datum_t));
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) {
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class->s.value = class->s.value;
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_classes.nprim++;
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	ret = class_copy_default_new_object(state, class, new_class);
44709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (ret) {
44809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		free(new_class);
44909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		return ret;
45009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
45109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    hashtab_insert(state->out->p_classes.table, new_id,
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t *) new_class);
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_class);
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
46813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (class->permissions.table, perm_copy_callback,
47113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_class->permissions)) {
47213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
47313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (class->comkey) {
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->comkey = strdup(class->comkey);
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_class->comkey) {
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->comdatum =
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_search(state->out->p_commons.table,
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   new_class->comkey);
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_class->comdatum) {
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "could not find common datum %s",
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    new_class->comkey);
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_class->permissions.nprim +=
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    new_class->comdatum->permissions.nprim;
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    void *data)
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *class, *new_class;
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class = (class_datum_t *) datum;
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class = hashtab_search(state->out->p_classes.table, id);
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_class) {
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "class %s vanished", id);
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* constraints */
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (constraint_node_clone
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (&new_class->constraints, class->constraints, state) == -1
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || constraint_node_clone(&new_class->validatetrans,
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     class->validatetrans, state) == -1) {
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
525f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle/*
526f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle * The boundaries have to be copied after the types/roles/users are copied,
527f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle * because it refers hashtab to lookup destinated objects.
528f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle */
529f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int type_bounds_copy_callback(hashtab_key_t key,
530f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
531f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
532f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	expand_state_t *state = (expand_state_t *) data;
533f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	type_datum_t *type = (type_datum_t *) datum;
534f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	type_datum_t *dest;
535f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
536f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
537f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!type->bounds)
538f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
539f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
540f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!is_id_enabled((char *)key, state->base, SYM_TYPES))
541f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
542f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
543f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->typemap[type->bounds - 1];
544f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
545f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->out->p_types.table, (char *)key);
546f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
547f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "Type lookup failed for %s", (char *)key);
548f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
549f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
550f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
551f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
552f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
553f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
554f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
555f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
556f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
557f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
558f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
559f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int role_bounds_copy_callback(hashtab_key_t key,
560f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
561f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
562f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	expand_state_t *state = (expand_state_t *) data;
563f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	role_datum_t *role = (role_datum_t *) datum;
564f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	role_datum_t *dest;
565f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
566f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
567f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!role->bounds)
568f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
569f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
570f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!is_id_enabled((char *)key, state->base, SYM_ROLES))
571f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
572f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
573f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->rolemap[role->bounds - 1];
574f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
575f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->out->p_roles.table, (char *)key);
576f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
577f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "Role lookup failed for %s", (char *)key);
578f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
579f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
580f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
581f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
582f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
583f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
584f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
585f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
586f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
587f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
588f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
589f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int user_bounds_copy_callback(hashtab_key_t key,
590f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
591f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
592f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	expand_state_t *state = (expand_state_t *) data;
593f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	user_datum_t *user = (user_datum_t *) datum;
594f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	user_datum_t *dest;
595f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
596f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
597f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!user->bounds)
598f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
599f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
600f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!is_id_enabled((char *)key, state->base, SYM_USERS))
601f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
602f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
603f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->usermap[user->bounds - 1];
604f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
605f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->out->p_users.table, (char *)key);
606f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
607f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "User lookup failed for %s", (char *)key);
608f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
609f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
610f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
611f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
612f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
613f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
614f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
615f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
616f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
617f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
618f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
61913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* The aliases have to be copied after the types and attributes to be certain that
62013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the out symbol table will have the type that the alias refers. Otherwise, we
62113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * won't be able to find the type value for the alias. We can't depend on the
62213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * declaration ordering because of the hash table.
62313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
62413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
62513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
62613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
62713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
62813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
62913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *alias, *new_alias;
63013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
631e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle	uint32_t prival;
63213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
63313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = (char *)key;
63413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	alias = (type_datum_t *) datum;
63513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
63613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
63713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* ignore regular types */
63813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_TYPE && alias->primary)
63913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
64013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* ignore attributes */
64213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_ATTRIB)
64313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
64413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
645e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle	if (alias->flavor == TYPE_ALIAS)
646e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle		prival = alias->primary;
647e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle	else
648e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle		prival = alias->s.value;
649e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle
650e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle	if (!is_id_enabled(state->base->p_type_val_to_name[prival - 1],
651e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle			state->base, SYM_TYPES)) {
652e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle		/* The primary type for this alias is not enabled, the alias
653e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle 		 * shouldn't be either */
654e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle		return 0;
655e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle	}
656e61b36a5c78852c5d30d9512e0c69546d23ea25cJoshua Brindle
65713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
65813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying alias %s", id);
65913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
66113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
66213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
66313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
66413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
66513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_alias = (type_datum_t *) malloc(sizeof(type_datum_t));
66713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_alias) {
66813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
66913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
67013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return SEPOL_ENOMEM;
67113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
67213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(new_alias, 0, sizeof(type_datum_t));
67313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alias->flavor == TYPE_TYPE)
67413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_alias->s.value = state->typemap[alias->s.value - 1];
67513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else if (alias->flavor == TYPE_ALIAS)
67613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_alias->s.value = state->typemap[alias->primary - 1];
67713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
67813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(0);	/* unreachable */
67913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
68013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_alias->flags = alias->flags;
68113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
68213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_types.table,
68313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
68413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_alias);
68513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
68613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
68713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
68813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_alias);
68913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
69013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
69113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
69213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->typemap[alias->s.value - 1] = new_alias->s.value;
69413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_alias->flags & TYPE_FLAGS_PERMISSIVE)
69613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) {
69713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
69813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
69913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data)
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
70613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t mapped_roles;
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role = (role_datum_t *) datum;
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
70913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap))
71113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
71213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&role->dominates);
71413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&role->dominates, &mapped_roles))
71613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
71713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&mapped_roles);
71913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
72013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
72113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
72213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
723d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao/* For the role attribute in the base module, escalate its counterpart's
724d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao * types.types ebitmap in the out module to the counterparts of all the
725d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao * regular role that belongs to the current role attribute. Note, must be
726d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao * invoked after role_copy_callback so that state->rolemap is available.
727d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao */
728d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciaostatic int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
729d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			     void *data)
730d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao{
731d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	char *id, *base_reg_role_id;
732d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	role_datum_t *role, *new_role, *regular_role;
733d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	expand_state_t *state;
734d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	ebitmap_node_t *rnode;
735d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	unsigned int i;
736d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	ebitmap_t mapped_roles;
737d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
738d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	id = key;
739d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	role = (role_datum_t *)datum;
740d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	state = (expand_state_t *)data;
741d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
742d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (strcmp(id, OBJECT_R) == 0) {
743d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		/* object_r is never a role attribute by far */
744d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		return 0;
745d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	}
746d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
7472ef297d4c80b7e55d9a33e20b44c540ffc6ad351Harry Ciao	if (!is_id_enabled(id, state->base, SYM_ROLES)) {
7482ef297d4c80b7e55d9a33e20b44c540ffc6ad351Harry Ciao		/* identifier's scope is not enabled */
7492ef297d4c80b7e55d9a33e20b44c540ffc6ad351Harry Ciao		return 0;
7502ef297d4c80b7e55d9a33e20b44c540ffc6ad351Harry Ciao	}
7512ef297d4c80b7e55d9a33e20b44c540ffc6ad351Harry Ciao
752d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (role->flavor != ROLE_ATTRIB)
753d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		return 0;
754d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
755d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (state->verbose)
756d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		INFO(state->handle, "fixing role attribute %s", id);
757d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
758d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	new_role =
759d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		(role_datum_t *)hashtab_search(state->out->p_roles.table, id);
760d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
761d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB);
762d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
763d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	ebitmap_init(&mapped_roles);
764d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap))
765d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		return -1;
766d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (ebitmap_union(&new_role->roles, &mapped_roles)) {
767d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		ERR(state->handle, "Out of memory!");
768d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		ebitmap_destroy(&mapped_roles);
769d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		return -1;
770d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	}
771d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	ebitmap_destroy(&mapped_roles);
772d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
773d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	ebitmap_for_each_bit(&role->roles, rnode, i) {
774d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		if (ebitmap_node_get_bit(rnode, i)) {
775d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			/* take advantage of sym_val_to_name[]
776d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			 * of the base module */
777d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			base_reg_role_id = state->base->p_role_val_to_name[i];
778d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			regular_role = (role_datum_t *)hashtab_search(
779d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao						state->out->p_roles.table,
780d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao						base_reg_role_id);
781d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			assert(regular_role != NULL &&
782d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			       regular_role->flavor == ROLE_ROLE);
783d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
784d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			if (ebitmap_union(&regular_role->types.types,
785d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao					  &new_role->types.types)) {
786d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao				ERR(state->handle, "Out of memory!");
787d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao				return -1;
788d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao			}
789d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		}
790d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	}
791d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
792d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	return 0;
793d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao}
794d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao
79513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
79613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
79713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
79813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
79913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
80013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role;
80113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *new_role;
80213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
80313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union_types;
80413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
80513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
80613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role = (role_datum_t *) datum;
80713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
80813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
80913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (strcmp(id, OBJECT_R) == 0) {
81013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* object_r is always value 1 */
81113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->rolemap[role->s.value - 1] = 1;
81213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
81313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
81413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
81513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_ROLES)) {
81613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
81713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
81813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
81913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
82113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying role %s", id);
82213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_role =
82413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (role_datum_t *) hashtab_search(state->out->p_roles.table, id);
82513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_role) {
82613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role = (role_datum_t *) malloc(sizeof(role_datum_t));
82713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_role) {
82813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
82913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
83013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
83113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_role, 0, sizeof(role_datum_t));
83213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
83313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = strdup(id);
83413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_id) {
83513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
836afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			free(new_role);
83713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
83813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
83913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->out->p_roles.nprim++;
841d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		new_role->flavor = role->flavor;
84213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role->s.value = state->out->p_roles.nprim;
84313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->rolemap[role->s.value - 1] = new_role->s.value;
84413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->out->p_roles.table,
84513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
84613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_role);
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "hashtab overflow");
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_role);
85113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
85213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* The dominates bitmap is going to be wrong for the moment,
85713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	 * we'll come back later and remap them, after we are sure all
85813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	 * the roles have been added */
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_role->dominates, &role->dominates)) {
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&tmp_union_types);
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* convert types in the role datum in the global symtab */
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, state->typemap, &role->types, &tmp_union_types, 1)) {
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union_types);
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
87113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
87213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_role->types.types, &tmp_union_types)) {
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union_types);
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union_types);
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
88513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, sepol_handle_t * h)
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_semantic_cat_t *cat;
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *levdatum;
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_level_init(l);
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!p->mls)
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
89513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Required not declared. */
89713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!sl->sens)
89813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	l->sens = sl->sens;
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
902afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris						    p->p_sens_val_to_name[l->sens - 1]);
903afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	if (!levdatum) {
904afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		ERR(h, "%s: Impossible situation found, nothing in p_levels.table.\n",
905afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		    __func__);
906afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		errno = ENOENT;
907afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		return -1;
908afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	}
90913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cat = sl->cat; cat; cat = cat->next) {
91013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cat->low > cat->high) {
91113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(h, "Category range is not valid %s.%s",
91213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_cat_val_to_name[cat->low - 1],
91313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_cat_val_to_name[cat->high - 1]);
91413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = cat->low - 1; i < cat->high; i++) {
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
918e7694874c20efaf6670f6639b0383077015b8d0cChris PeBenito				ERR(h, "Category %s can not be associated with "
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "level %s",
92013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_cat_val_to_name[i],
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_sens_val_to_name[l->sens - 1]);
922e7694874c20efaf6670f6639b0383077015b8d0cChris PeBenito				return -1;
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(&l->cat, i, 1)) {
92513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(h, "Out of memory!");
92613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
92713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
92813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
92913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
93013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
93213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
93313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r,
93513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, sepol_handle_t * h)
93613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
93713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0)
93813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
93913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) {
94113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_semantic_level_destroy(&sr->level[0]);
94213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
94313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!mls_level_dom(&r->level[1], &r->level[0])) {
94613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_destroy(r);
94713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(h, "MLS range high level does not dominate low level");
94813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
94913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
95013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
95213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
95313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
95513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
95613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
95713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
95813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
95913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user;
96013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *new_user;
96113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
96213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp_union;
96313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
96413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
96513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user = (user_datum_t *) datum;
96613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
96713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
96813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_USERS)) {
96913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
97013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
97113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
97213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
97313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
97413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying user %s", id);
97513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
97613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_user =
97713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (user_datum_t *) hashtab_search(state->out->p_users.table, id);
97813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_user) {
97913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user = (user_datum_t *) malloc(sizeof(user_datum_t));
98013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_user) {
98113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
98213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
98313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
98413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_user, 0, sizeof(user_datum_t));
98513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
98613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->out->p_users.nprim++;
98713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user->s.value = state->out->p_users.nprim;
98813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->usermap[user->s.value - 1] = new_user->s.value;
98913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = strdup(id);
99113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_id) {
99213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
993afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			free(new_user);
99413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
99513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
99613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->out->p_users.table,
99713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
99813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_user);
99913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
100013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "hashtab overflow");
100113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			user_datum_destroy(new_user);
100213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_user);
100313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
100413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
100513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
100613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
100713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the semantic MLS info */
100813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_range_expand(&user->range,
100913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      &new_user->exp_range,
101013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
101113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
101213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
101313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_level_expand(&user->dfltlevel,
101413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      &new_user->exp_dfltlevel,
101513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
101613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
101713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
101813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!mls_level_between(&new_user->exp_dfltlevel,
101913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &new_user->exp_range.level[0],
102013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &new_user->exp_range.level[1])) {
102113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "default level not within user "
102213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "range");
102313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
102413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
102513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
102613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* require that the MLS info match */
102713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_t tmp_range;
102813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_t tmp_level;
102913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
103013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_range_expand(&user->range, &tmp_range,
103113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
103213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
103313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
103513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      state->out, state->handle)) {
103613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_range_destroy(&tmp_range);
103713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
103813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
104013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
104113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_range_destroy(&tmp_range);
104213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mls_level_destroy(&tmp_level);
104313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
104413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
104513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_range_destroy(&tmp_range);
104613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_destroy(&tmp_level);
104713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
104813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&tmp_union);
105013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* get global roles for this user */
10523592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) {
105313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
105413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union);
105513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
105613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
105713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_user->roles.roles, &tmp_union)) {
105913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
106013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&tmp_union);
106113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
106213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
106313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp_union);
106413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
106513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
106613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
106713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
106813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
106913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
107013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
107113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
107213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state;
107313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_bool_datum_t *bool, *new_bool;
107413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *new_id;
107513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
107613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	id = key;
107713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	bool = (cond_bool_datum_t *) datum;
107813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state = (expand_state_t *) data;
107913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
108013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_BOOLS)) {
108113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
108213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
108313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
108413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10855722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	if (bool->flags & COND_BOOL_FLAGS_TUNABLE) {
10865722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao		/* Skip tunables */
10875722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao		return 0;
10885722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	}
10895722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao
109013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
109113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying boolean %s", id);
109213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
109313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
109413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_bool) {
109513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
109613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
109713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
109813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
109913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
110013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id) {
110113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
110213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_bool);
110313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
110413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
110513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
110613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_bools.nprim++;
110713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool->s.value = state->out->p_bools.nprim;
110813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
110913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = hashtab_insert(state->out->p_bools.table,
111013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_key_t) new_id,
111113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     (hashtab_datum_t) new_bool);
111213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
111313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "hashtab overflow");
111413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_bool);
111513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_id);
111613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
111713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
111813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
111913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->boolmap[bool->s.value - 1] = new_bool->s.value;
112013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
112113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_bool->state = bool->state;
11225722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	new_bool->flags = bool->flags;
112313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
112413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
112513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
112613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
112713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
112813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
112913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
113013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
113113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *level = (level_datum_t *) datum, *new_level = NULL;
113213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = (char *)key, *new_id = NULL;
113313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
113413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_LEVELS)) {
113513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
113613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
113713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
113813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
113913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
114013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying sensitivity level %s", id);
114113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
114213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level = (level_datum_t *) malloc(sizeof(level_datum_t));
114313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_level)
114413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
114513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_init(new_level);
114613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t));
114713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_level->level)
114813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
114913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_level_init(new_level->level);
115013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
115113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id)
115213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
115313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
115413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_level_cpy(new_level->level, level->level)) {
115513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
115613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
115713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_level->isalias = level->isalias;
115813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_levels.nprim++;
115913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
116013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_insert(state->out->p_levels.table,
116113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_key_t) new_id,
116213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_datum_t) new_level)) {
116313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
116413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
116513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
116613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
116713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
116813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
116913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_level != NULL && new_level->level != NULL) {
117013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_level_destroy(new_level->level);
117113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(new_level->level);
117213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
117313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_destroy(new_level);
117413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_level);
117513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
117613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
117713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
117813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
118013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
118113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
118213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = (expand_state_t *) data;
118313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL;
118413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = (char *)key, *new_id = NULL;
118513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!is_id_enabled(id, state->base, SYM_CATS)) {
118713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* identifier's scope is not enabled */
118813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
118913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
119013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
119213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "copying category attribute %s", id);
119313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t));
119513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_cat)
119613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
119713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_init(new_cat);
119813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_id = strdup(id);
119913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_id)
120013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
120113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
120213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat->s.value = cat->s.value;
120313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cat->isalias = cat->isalias;
120413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->out->p_cats.nprim++;
120513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_insert(state->out->p_cats.table,
120613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) {
120713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out_of_mem;
120813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
120913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
121113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out_of_mem:
121313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
121413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_destroy(new_cat);
121513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_cat);
121613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
121713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
121813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
121913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules)
122113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
122213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
122313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_t *cur_allow, *n, *l;
122413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_rule_t *cur;
122513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t roles, new_roles;
122613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
122713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* start at the end of the list */
122913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (l = state->out->role_allow; l && l->next; l = l->next) ;
123013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
123113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = rules;
123213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
123313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&roles);
123413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&new_roles);
123513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12363592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
123713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
123813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
123913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
124013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12413592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) {
124213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
124313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
124413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
124513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&roles, snode, i) {
124713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
124813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
124913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&new_roles, tnode, j) {
125013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
125113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
125213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* check for duplicates */
125313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cur_allow = state->out->role_allow;
125413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				while (cur_allow) {
125513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if ((cur_allow->role == i + 1) &&
125613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (cur_allow->new_role == j + 1))
125713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						break;
125813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					cur_allow = cur_allow->next;
125913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
126013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur_allow)
126113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
126213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n = (role_allow_t *)
126313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    malloc(sizeof(role_allow_t));
126413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n) {
126513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
126613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
126713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
126813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				memset(n, 0, sizeof(role_allow_t));
126913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->role = i + 1;
127013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->new_role = j + 1;
127113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (l) {
127213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					l->next = n;
127313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
127413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state->out->role_allow = n;
127513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
127613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l = n;
127713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
127813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
127913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
128013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&roles);
128113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&new_roles);
128213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
128313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
128413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
128513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
128613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
128713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
128813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
128913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
129013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
12916db9b74210197f792a52038abbd10e946e99e49dHarry Ciao	unsigned int i, j, k;
129213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_t *n, *l, *cur_trans;
129313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_rule_t *cur;
129413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t roles, types;
12956db9b74210197f792a52038abbd10e946e99e49dHarry Ciao	ebitmap_node_t *rnode, *tnode, *cnode;
129613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
129713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* start at the end of the list */
129813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (l = state->out->role_tr; l && l->next; l = l->next) ;
129913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
130013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = rules;
130113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
130213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&roles);
130313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&types);
130413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13053592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
130613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
130713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
130813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
130913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set
131013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->out, state->typemap, &cur->types, &types, 1)) {
131113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
131213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
131313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
131413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&roles, rnode, i) {
131513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(rnode, i))
131613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
131713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&types, tnode, j) {
131813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
131913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
13206db9b74210197f792a52038abbd10e946e99e49dHarry Ciao				ebitmap_for_each_bit(&cur->classes, cnode, k) {
13216db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					if (!ebitmap_node_get_bit(cnode, k))
13226db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						continue;
13236db9b74210197f792a52038abbd10e946e99e49dHarry Ciao
13246db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					cur_trans = state->out->role_tr;
13256db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					while (cur_trans) {
13261867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris						unsigned int mapped_role;
13271867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris
13281867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris						mapped_role = state->rolemap[cur->new_role - 1];
13291867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris
13306db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						if ((cur_trans->role ==
13316db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								i + 1) &&
13326db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						    (cur_trans->type ==
13336db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								j + 1) &&
13346db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						    (cur_trans->tclass ==
13356db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								k + 1)) {
13361867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris							if (cur_trans->new_role == mapped_role) {
13376db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								break;
13386db9b74210197f792a52038abbd10e946e99e49dHarry Ciao							} else {
13396db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								ERR(state->handle,
13401867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris									"Conflicting role trans rule %s %s : %s { %s vs %s }",
13416db9b74210197f792a52038abbd10e946e99e49dHarry Ciao									state->out->p_role_val_to_name[i],
13426db9b74210197f792a52038abbd10e946e99e49dHarry Ciao									state->out->p_type_val_to_name[j],
13436db9b74210197f792a52038abbd10e946e99e49dHarry Ciao									state->out->p_class_val_to_name[k],
13441867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris									state->out->p_role_val_to_name[mapped_role - 1],
13451867652e5424e867cea542a9311ccdc5fa9ec835Eric Paris									state->out->p_role_val_to_name[cur_trans->new_role - 1]);
13466db9b74210197f792a52038abbd10e946e99e49dHarry Ciao								return -1;
13476db9b74210197f792a52038abbd10e946e99e49dHarry Ciao							}
134813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						}
13496db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						cur_trans = cur_trans->next;
135013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
13516db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					if (cur_trans)
13526db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						continue;
13536db9b74210197f792a52038abbd10e946e99e49dHarry Ciao
13546db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					n = (role_trans_t *)
13556db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						malloc(sizeof(role_trans_t));
13566db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					if (!n) {
13576db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						ERR(state->handle,
13586db9b74210197f792a52038abbd10e946e99e49dHarry Ciao							"Out of memory!");
13596db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						return -1;
13606db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					}
13616db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					memset(n, 0, sizeof(role_trans_t));
13626db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					n->role = i + 1;
13636db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					n->type = j + 1;
13646db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					n->tclass = k + 1;
13656db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					n->new_role = state->rolemap
13666db9b74210197f792a52038abbd10e946e99e49dHarry Ciao							[cur->new_role - 1];
13676db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					if (l)
13686db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						l->next = n;
13696db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					else
13706db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						state->out->role_tr = n;
13716db9b74210197f792a52038abbd10e946e99e49dHarry Ciao
13726db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					l = n;
137313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
137413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
137513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
137613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&roles);
137813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&types);
137913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
138013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
138113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
138213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
138313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
138413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13856eeb71538ea29b639ac7549831cd1aa4da32722aEric Parisstatic int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
13866eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris{
13876eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	unsigned int i, j;
13888fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	filename_trans_t key, *new_trans;
13898fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	filename_trans_datum_t *otype;
13906eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	filename_trans_rule_t *cur_rule;
13916eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	ebitmap_t stypes, ttypes;
13926eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	ebitmap_node_t *snode, *tnode;
13938fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	int rc;
13946eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
13956eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	cur_rule = rules;
13966eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	while (cur_rule) {
13970a778ba601d68ef91304f90c101b5dc67d433e04Eric Paris		uint32_t mapped_otype;
13980a778ba601d68ef91304f90c101b5dc67d433e04Eric Paris
13996eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		ebitmap_init(&stypes);
14006eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		ebitmap_init(&ttypes);
14016eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14026eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (expand_convert_type_set(state->out, state->typemap,
14036eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					    &cur_rule->stypes, &stypes, 1)) {
14046eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			ERR(state->handle, "Out of memory!");
14056eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			return -1;
14066eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		}
14076eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14086eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (expand_convert_type_set(state->out, state->typemap,
14096eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					    &cur_rule->ttypes, &ttypes, 1)) {
14106eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			ERR(state->handle, "Out of memory!");
14116eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			return -1;
14126eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		}
14136eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14140a778ba601d68ef91304f90c101b5dc67d433e04Eric Paris		mapped_otype = state->typemap[cur_rule->otype - 1];
14150a778ba601d68ef91304f90c101b5dc67d433e04Eric Paris
14166eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		ebitmap_for_each_bit(&stypes, snode, i) {
14176eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			if (!ebitmap_node_get_bit(snode, i))
14186eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				continue;
14196eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			ebitmap_for_each_bit(&ttypes, tnode, j) {
14206eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				if (!ebitmap_node_get_bit(tnode, j))
14216eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					continue;
14226eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14238fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				key.stype = i + 1;
14248fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				key.ttype = j + 1;
14258fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				key.tclass = cur_rule->tclass;
14268fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				key.name = cur_rule->name;
14278fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				otype = hashtab_search(state->out->filename_trans,
14288fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley						       (hashtab_key_t) &key);
14298fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				if (otype) {
14308fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					/* duplicate rule, ignore */
14318fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					if (otype->otype == mapped_otype)
14328fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley						continue;
14339e746d6a693c2090694407c218300cfa4b8469a0Stephen Smalley
14348fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\":  %s vs %s",
14358fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    state->out->p_type_val_to_name[i],
14368fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    state->out->p_type_val_to_name[j],
14378fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    state->out->p_class_val_to_name[cur_rule->tclass - 1],
14388fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    cur_rule->name,
14398fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    state->out->p_type_val_to_name[otype->otype - 1],
14408fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					    state->out->p_type_val_to_name[mapped_otype - 1]);
14418fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					return -1;
14426eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				}
14436eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14448fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				new_trans = calloc(1, sizeof(*new_trans));
14456eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				if (!new_trans) {
14466eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					ERR(state->handle, "Out of memory!");
14476eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					return -1;
14486eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				}
14496eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14506eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				new_trans->name = strdup(cur_rule->name);
14516eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				if (!new_trans->name) {
14526eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					ERR(state->handle, "Out of memory!");
14536eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris					return -1;
14546eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				}
14556eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				new_trans->stype = i + 1;
14566eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				new_trans->ttype = j + 1;
14576eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				new_trans->tclass = cur_rule->tclass;
14588fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley
14598fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				otype = calloc(1, sizeof(*otype));
14608fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				if (!otype) {
14618fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					ERR(state->handle, "Out of memory!");
14628fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					return -1;
14638fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				}
14648fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				otype->otype = mapped_otype;
14658fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley
14668fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				rc = hashtab_insert(state->out->filename_trans,
14678fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley						    (hashtab_key_t)new_trans,
14688fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley						    otype);
14698fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				if (rc) {
14708fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					ERR(state->handle, "Out of memory!");
14718fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley					return -1;
14728fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley				}
14736eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			}
14746eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		}
14756eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14766eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		ebitmap_destroy(&stypes);
14776eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		ebitmap_destroy(&ttypes);
14786eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14796eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		cur_rule = cur_rule->next;
14806eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	}
14816eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	return 0;
14826eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris}
14836eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
148413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
148513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      mls_semantic_range_t * trange,
148613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      expand_state_t * state)
148713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
14888fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	range_trans_t *rt = NULL, key;
14898fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	mls_range_t *r, *exp_range = NULL;
149013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc = -1;
149113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14928fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	exp_range = calloc(1, sizeof(*exp_range));
14938fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	if (!exp_range) {
14948fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		ERR(state->handle, "Out of memory!");
14958fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		return -1;
14968fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	}
14978fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley
14988fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	if (mls_semantic_range_expand(trange, exp_range, state->out,
149913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				      state->handle))
15008fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		goto err;
150113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
150213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check for duplicates/conflicts */
15038fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	key.source_type = stype;
15048fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	key.target_type = ttype;
15058fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	key.target_class = tclass;
15068fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	r = hashtab_search(state->out->range_tr, (hashtab_key_t) &key);
15078fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	if (r) {
15088fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		if (mls_range_eq(r, exp_range)) {
15098fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley			/* duplicate, ignore */
15108fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley			mls_range_destroy(exp_range);
15118fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley			free(exp_range);
15128fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley			return 0;
151313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
15148fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley
15158fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		/* conflict */
15168fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		ERR(state->handle,
15178fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		    "Conflicting range trans rule %s %s : %s",
15188fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		    state->out->p_type_val_to_name[stype - 1],
15198fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		    state->out->p_type_val_to_name[ttype - 1],
15208fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		    state->out->p_class_val_to_name[tclass - 1]);
15218fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		goto err;
152213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
152313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15248fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	rt = calloc(1, sizeof(*rt));
152513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!rt) {
152613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
15278fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		goto err;
152813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
152913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->source_type = stype;
153013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->target_type = ttype;
153113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rt->target_class = tclass;
15328fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley
15338fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	rc = hashtab_insert(state->out->range_tr, (hashtab_key_t) rt,
15348fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley			    exp_range);
15358fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	if (rc) {
153613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
15378fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		goto err;
153813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15398fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	}
154013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15418fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	return 0;
15428fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalleyerr:
15438fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	free(rt);
15448fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	if (exp_range) {
15458fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		mls_range_destroy(exp_range);
15468fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley		free(exp_range);
15478fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	}
15488fdb2255215a1f1488b613737b5fbffb873d8376Stephen Smalley	return -1;
154913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
155013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
155113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_range_trans(expand_state_t * state,
155213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      range_trans_rule_t * rules)
155313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
155413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j, k;
155513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_trans_rule_t *rule;
155613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
155713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
155813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode, *cnode;
155913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
156113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "expanding range transitions");
156213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (rule = rules; rule; rule = rule->next) {
156413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&stypes);
156513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&ttypes);
156613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the type sets */
156813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set(state->out, state->typemap,
156913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    &rule->stypes, &stypes, 1)) {
157013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
157113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
157213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
157313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_convert_type_set(state->out, state->typemap,
157413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    &rule->ttypes, &ttypes, 1)) {
157513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_destroy(&stypes);
157613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
157713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
157813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
157913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
158013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* loop on source type */
158113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&stypes, snode, i) {
158213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
158313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
158413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* loop on target type */
158513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ebitmap_for_each_bit(&ttypes, tnode, j) {
158613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!ebitmap_node_get_bit(tnode, j))
158713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
158813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* loop on target class */
158913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ebitmap_for_each_bit(&rule->tclasses, cnode, k) {
159013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!ebitmap_node_get_bit(cnode, k))
159113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
159213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
159313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (exp_rangetr_helper(i + 1,
159413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       j + 1,
159513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       k + 1,
159613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       &rule->trange,
159713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       state)) {
159813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						ebitmap_destroy(&stypes);
159913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						ebitmap_destroy(&ttypes);
160013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						return -1;
160113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
160213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
160313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
160413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
160513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
160613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&stypes);
160713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_destroy(&ttypes);
160813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
160913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
161113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
161213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Search for an AV tab node within a hash table with the given key.
161413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * If the node does not exist, create it and return it; otherwise
161513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * return the pre-existing one.
161613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle*/
161713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
161813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   avtab_t * avtab, avtab_key_t * key,
161980bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep				   cond_av_list_t ** cond,
16205862ac5dfe3bcfc5ff1aa40b5585899b993ae446William Roberts				   av_extended_perms_t *xperms)
162113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
162213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
162313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t avdatum;
162413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *nl;
1625915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	int match = 0;
162613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1627915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	/* AVTAB_XPERMS entries are not necessarily unique */
1628915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	if (key->specified & AVTAB_XPERMS) {
162980bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		node = avtab_search_node(avtab, key);
163080bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		while (node) {
1631915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep			if ((node->datum.xperms->specified == xperms->specified) &&
1632915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep				(node->datum.xperms->driver == xperms->driver)) {
1633915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep				match = 1;
163480bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep				break;
163580bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			}
163680bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			node = avtab_search_node_next(node, key->specified);
163780bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		}
1638915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep		if (!match)
163980bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			node = NULL;
164080bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep	} else {
164180bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		node = avtab_search_node(avtab, key);
164280bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep	}
164313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
164413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* If this is for conditional policies, keep searching in case
164513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   the node is part of my conditional avtab. */
164613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond) {
164713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (node) {
164813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (node->parse_context == cond)
164913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
165013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node = avtab_search_node_next(node, key->specified);
165113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
165213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
165313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
165413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!node) {
165513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(&avdatum, 0, sizeof avdatum);
1656be96f05182ffd934eb20776c52a88df6e51fe6dfWilliam Roberts		/*
1657be96f05182ffd934eb20776c52a88df6e51fe6dfWilliam Roberts		 * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
1658be96f05182ffd934eb20776c52a88df6e51fe6dfWilliam Roberts		 * others. Initialize the data accordingly.
1659be96f05182ffd934eb20776c52a88df6e51fe6dfWilliam Roberts		 */
1660be96f05182ffd934eb20776c52a88df6e51fe6dfWilliam Roberts		avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0;
166113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this is used to get the node - insertion is actually unique */
166213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(avtab, key, &avdatum);
166313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
166413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle, "hash table overflow");
166513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return NULL;
166613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
166713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cond) {
166813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->parse_context = cond;
166913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t));
167013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!nl) {
167113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(handle, "Memory error");
167213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return NULL;
167313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
167413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(nl, 0, sizeof(cond_av_list_t));
167513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl->node = node;
167613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			nl->next = *cond;
167713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*cond = nl;
167813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
167913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
168013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
168113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return node;
168213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
168313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1684dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Robertsstatic uint32_t avrule_to_avtab_spec(uint32_t specification)
1685dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts{
1686dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	return (specification == AVRULE_DONTAUDIT) ?
1687dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		AVTAB_AUDITDENY : specification;
1688dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts}
1689dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
169013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_SUCCESS   1
169113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_CONFLICT  0
169213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPAND_RULE_ERROR    -1
169313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
169413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_terule_helper(sepol_handle_t * handle,
169513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policydb_t * p, uint32_t * typemap,
169613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t specified, cond_av_list_t ** cond,
169713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cond_av_list_t ** other, uint32_t stype,
169813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t ttype, class_perm_node_t * perms,
169913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				avtab_t * avtab, int enabled)
170013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
170113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t avkey;
170213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avdatump;
170313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
170413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur;
170513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int conflict;
17064129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts	uint32_t oldtype = 0;
17074129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts
17084129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts	if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) {
17094129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts		ERR(handle, "Invalid specification: %"PRIu32"\n", specified);
17104129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts		return EXPAND_RULE_ERROR;
171113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
171213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17134129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts	avkey.specified = avrule_to_avtab_spec(specified);
17144129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts	avkey.source_type = stype + 1;
17154129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts	avkey.target_type = ttype + 1;
17164129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts
171713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = perms;
171813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
171913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		uint32_t remapped_data =
172013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    typemap ? typemap[cur->data - 1] : cur->data;
1721ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman		avkey.target_class = cur->tclass;
172213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
172313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		conflict = 0;
172413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* check to see if the expanded TE already exists --
172513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * either in the global scope or in another
172613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * conditional AV tab */
172713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_search_node(&p->te_avtab, &avkey);
172813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (node) {
172913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			conflict = 1;
173013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
173113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node = avtab_search_node(&p->te_cond_avtab, &avkey);
173213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (node && node->parse_context != other) {
173313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				conflict = 2;
173413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
173513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
173613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
173713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (conflict) {
173813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump = &node->datum;
173913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (specified & AVRULE_TRANSITION) {
174013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
174113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (specified & AVRULE_MEMBER) {
174213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
174313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (specified & AVRULE_CHANGE) {
174413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				oldtype = avdatump->data;
174513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
174613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
174713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (oldtype == remapped_data) {
174813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* if the duplicate is inside the same scope (eg., unconditional
174913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 * or in same conditional then ignore it */
175013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if ((conflict == 1 && cond == NULL)
175113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    || node->parse_context == cond)
175213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return EXPAND_RULE_SUCCESS;
175313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(handle, "duplicate TE rule for %s %s:%s %s",
175413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[avkey.source_type -
175513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  1],
175613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[avkey.target_type -
175713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							  1],
175813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_class_val_to_name[avkey.target_class -
175913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   1],
176013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    p->p_type_val_to_name[oldtype - 1]);
176113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return EXPAND_RULE_CONFLICT;
176213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
176313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle,
176413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "conflicting TE rule for (%s, %s:%s):  old was %s, new is %s",
176513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[avkey.source_type - 1],
176613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[avkey.target_type - 1],
176713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_class_val_to_name[avkey.target_class - 1],
176813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[oldtype - 1],
176913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->p_type_val_to_name[remapped_data - 1]);
177013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return EXPAND_RULE_CONFLICT;
177113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
177213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17735862ac5dfe3bcfc5ff1aa40b5585899b993ae446William Roberts		node = find_avtab_node(handle, avtab, &avkey, cond, NULL);
177413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node)
177513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
177613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (enabled) {
177713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified |= AVTAB_ENABLED;
177813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
177913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified &= ~AVTAB_ENABLED;
178013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
178113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avdatump = &node->datum;
17834129eb499db070a001b9bb4d5286f5699db7d85fWilliam Roberts		avdatump->data = remapped_data;
178413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
178613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
178713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
178913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
179013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1791dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts/* 0 for success -1 indicates failure */
1792dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Robertsstatic int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump,
1793dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			   av_extended_perms_t * extended_perms)
1794dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts{
1795dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	unsigned int i;
1796dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
1797dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	avtab_extended_perms_t *xperms = avdatump->xperms;
1798dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	if (!xperms) {
1799dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		xperms = (avtab_extended_perms_t *)
1800dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			calloc(1, sizeof(avtab_extended_perms_t));
1801dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		if (!xperms) {
1802dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			ERR(handle, "Out of memory!");
1803dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			return -1;
1804dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		}
1805dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		avdatump->xperms = xperms;
1806dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	}
1807dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
1808dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	switch (extended_perms->specified) {
1809dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	case AVRULE_XPERMS_IOCTLFUNCTION:
1810dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION;
1811dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		break;
1812dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	case AVRULE_XPERMS_IOCTLDRIVER:
1813dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		xperms->specified = AVTAB_XPERMS_IOCTLDRIVER;
1814dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		break;
1815dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	default:
1816dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		return -1;
1817dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	}
1818dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
1819dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	xperms->driver = extended_perms->driver;
1820dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
1821dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		xperms->perms[i] |= extended_perms->perms[i];
1822dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
1823dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	return 0;
1824dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts}
1825dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
182613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avrule_helper(sepol_handle_t * handle,
182713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t specified,
182813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cond_av_list_t ** cond,
182913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				uint32_t stype, uint32_t ttype,
183013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				class_perm_node_t * perms, avtab_t * avtab,
1831915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep				int enabled, av_extended_perms_t *extended_perms)
183213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
183313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t avkey;
183413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avdatump;
183513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
183613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur;
183713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1838dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	/* bail early if dontaudit's are disabled and it's a dontaudit rule */
1839dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	if ((specified & (AVRULE_DONTAUDIT|AVRULE_XPERMS_DONTAUDIT))
1840dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	     && handle && handle->disable_dontaudit)
184180bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			return EXPAND_RULE_SUCCESS;
1842dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts
1843dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	avkey.source_type = stype + 1;
1844dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	avkey.target_type = ttype + 1;
1845dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts	avkey.specified = avrule_to_avtab_spec(specified);
184613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
184713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = perms;
184813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
1849ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman		avkey.target_class = cur->tclass;
185013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18515862ac5dfe3bcfc5ff1aa40b5585899b993ae446William Roberts		node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms);
185213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node)
185313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return EXPAND_RULE_ERROR;
185413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (enabled) {
185513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified |= AVTAB_ENABLED;
185613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
185713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->key.specified &= ~AVTAB_ENABLED;
185813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
185913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
186013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avdatump = &node->datum;
1861dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		switch (specified) {
1862dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_ALLOWED:
1863dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_AUDITALLOW:
1864dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_NEVERALLOW:
186513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data |= cur->data;
1866dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			break;
1867dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_DONTAUDIT:
1868dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			avdatump->data &= ~cur->data;
1869dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			break;
1870dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_AUDITDENY:
187113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* Since a '0' in an auditdeny mask represents
187213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * a permission we do NOT want to audit
187313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * (dontaudit), we use the '&' operand to
187413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * ensure that all '0's in the mask are
187513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * retained (much unlike the allow and
187613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * auditallow cases).
187713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 */
187813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avdatump->data &= cur->data;
1879dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			break;
1880dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_XPERMS_ALLOWED:
1881dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_XPERMS_AUDITALLOW:
1882dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_XPERMS_DONTAUDIT:
1883dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		case AVRULE_XPERMS_NEVERALLOW:
1884dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			if (allocate_xperms(handle, avdatump, extended_perms))
1885dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts				return EXPAND_RULE_ERROR;
1886dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			break;
1887dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts		default:
1888dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			ERR(handle, "Unknown specification: %"PRIu32"\n", specified);
1889dcd473d5ae0a9f81c272a30e9e39a28cda8fc586William Roberts			return EXPAND_RULE_ERROR;
189013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
189113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
189213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
189313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
189413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
189513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
189613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
189713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_rule_helper(sepol_handle_t * handle,
189813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      policydb_t * p, uint32_t * typemap,
189913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avrule_t * source_rule, avtab_t * dest_avtab,
190013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      cond_av_list_t ** cond, cond_av_list_t ** other,
190113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      int enabled,
190213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      ebitmap_t * stypes, ebitmap_t * ttypes)
190313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
190413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
190513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
190613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
190713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
190813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(stypes, snode, i) {
190913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
191013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
191113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (source_rule->flags & RULE_SELF) {
1912915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep			if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
1913c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				retval = expand_avrule_helper(handle, source_rule->specified,
1914c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      cond, i, i, source_rule->perms,
1915915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep							      dest_avtab, enabled, source_rule->xperms);
1916c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				if (retval != EXPAND_RULE_SUCCESS)
191713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
191813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
1919c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				retval = expand_terule_helper(handle, p, typemap,
1920c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      source_rule->specified, cond,
1921c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      other, i, i, source_rule->perms,
1922c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      dest_avtab, enabled);
1923c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				if (retval != EXPAND_RULE_SUCCESS)
192413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
192513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
192613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
192713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(ttypes, tnode, j) {
192813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
192913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
1930915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep			if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
1931c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				retval = expand_avrule_helper(handle, source_rule->specified,
1932c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      cond, i, j, source_rule->perms,
1933915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep							      dest_avtab, enabled, source_rule->xperms);
1934c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				if (retval != EXPAND_RULE_SUCCESS)
193513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
193613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
1937c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				retval = expand_terule_helper(handle, p, typemap,
1938c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      source_rule->specified, cond,
1939c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      other, i, j, source_rule->perms,
1940c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris							      dest_avtab, enabled);
1941c43f5b1d34d9cbdc767254046d9b7e0ab47b866dEric Paris				if (retval != EXPAND_RULE_SUCCESS)
194213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return retval;
194313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
194413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
194513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
194613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
194713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return EXPAND_RULE_SUCCESS;
194813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
194913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
195113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Expand a rule into a given avtab - checking for conflicting type
195213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * rules in the destination policy.  Return EXPAND_RULE_SUCCESS on
195313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * success, EXPAND_RULE_CONFLICT if the rule conflicts with something
195413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * (and hence was not added), or EXPAND_RULE_ERROR on error.
195513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
195613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int convert_and_expand_rule(sepol_handle_t * handle,
195713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   policydb_t * dest_pol, uint32_t * typemap,
195813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   avrule_t * source_rule, avtab_t * dest_avtab,
195913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   cond_av_list_t ** cond,
196013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   cond_av_list_t ** other, int enabled,
196113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   int do_neverallow)
196213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
196313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
196413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
196513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned char alwaysexpand;
196613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
196713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW)
196813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_SUCCESS;
19690ca5562e9782cd078030d486be9e8dc3190a8ccfRichard Haines	if (!do_neverallow && source_rule->specified & AVRULE_XPERMS_NEVERALLOW)
197099fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		return EXPAND_RULE_SUCCESS;
197113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&stypes);
197313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&ttypes);
197413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Force expansion for type rules and for self rules. */
197613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	alwaysexpand = ((source_rule->specified & AVRULE_TYPE) ||
197713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			(source_rule->flags & RULE_SELF));
197813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
198013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand))
198113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_ERROR;
198213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
198313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand))
198413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return EXPAND_RULE_ERROR;
198513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
198613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = expand_rule_helper(handle, dest_pol, typemap,
198713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    source_rule, dest_avtab,
198813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    cond, other, enabled, &stypes, &ttypes);
198913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
199013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
199113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
199213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
199313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
199413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules,
199513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 avtab_t * dest_avtab, cond_av_list_t ** list,
199613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 cond_av_list_t ** other, uint32_t * typemap,
199713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 int enabled, expand_state_t * state)
199813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
199913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *cur;
200013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
200113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = source_rules;
200213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
200313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (convert_and_expand_rule(state->handle, dest_pol,
200413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    typemap, cur, dest_avtab,
200513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    list, other, enabled,
200613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    0) != EXPAND_RULE_SUCCESS) {
200713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
200813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
200913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
201113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
201213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
201413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
201513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_node_map_bools(expand_state_t * state, cond_node_t * cn)
201713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
201813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_expr_t *cur;
201913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
202013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
202113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = cn->expr;
202213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
202313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cur->bool)
202413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur->bool = state->boolmap[cur->bool - 1];
202513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
202613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
202713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
202813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++)
202913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1];
203013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
203113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize_expr(state->out, cn)) {
203213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error while normalizing conditional");
203313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
203413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
203513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
203613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
203713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
203813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
203913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* copy the nodes in *reverse* order -- the result is that the last
204013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * given conditional appears first in the policy, so as to match the
204113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * behavior of the upstream compiler */
204213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_node_copy(expand_state_t * state, cond_node_t * cn)
204313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
204413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_t *new_cond, *tmp;
204513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
204613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cn == NULL) {
204713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
204813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
204913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_node_copy(state, cn->next)) {
205013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
205113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
20525722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao
20535722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	/* If current cond_node_t is of tunable, its effective branch
20545722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	 * has been appended to its home decl->avrules list during link
20555722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	 * and now we should just skip it. */
20565722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao	if (cn->flags & COND_NODE_FLAGS_TUNABLE)
20575722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao		return 0;
20585722d765c756ac8dc52c52077f9311b8886fe8daHarry Ciao
205913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize_expr(state->base, cn)) {
206013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error while normalizing conditional");
206113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
206213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
206313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
206413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* create a new temporary conditional node with the booleans
206513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * mapped */
206613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmp = cond_node_create(state->base, cn);
206713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!tmp) {
206813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory");
206913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
207013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
207113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_node_map_bools(state, tmp)) {
2073afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		cond_node_destroy(tmp);
2074afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		free(tmp);
207513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Error mapping booleans");
207613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
207713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
207813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_cond = cond_node_search(state->out, state->out->cond_list, tmp);
208013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_cond) {
208113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cond_node_destroy(tmp);
208213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(tmp);
208313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
208413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
208513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
208613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_destroy(tmp);
208713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(tmp);
208813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
208913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_avrule_list_copy
209013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, cn->avtrue_list, &state->out->te_cond_avtab,
209113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_cond->true_list, &new_cond->false_list, state->typemap,
209213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     new_cond->cur_state, state))
209313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
209413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_avrule_list_copy
209513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state->out, cn->avfalse_list, &state->out->te_cond_avtab,
209613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     &new_cond->false_list, &new_cond->true_list, state->typemap,
209713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     !new_cond->cur_state, state))
209813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
209913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
210113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
210213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int context_copy(context_struct_t * dst, context_struct_t * src,
210413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			expand_state_t * state)
210513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
210613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->user = state->usermap[src->user - 1];
210713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->role = state->rolemap[src->role - 1];
210813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->type = state->typemap[src->type - 1];
210913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return mls_context_cpy(dst, src);
211013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
211113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2112505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzistatic int ocontext_copy_xen(expand_state_t *state)
211313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
2114505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	unsigned int i;
211513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *n, *l;
211613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
211713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < OCON_NUM; i++) {
211813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		l = NULL;
211913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (c = state->base->ocontexts[i]; c; c = c->next) {
212013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			n = malloc(sizeof(ocontext_t));
212113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!n) {
212213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
212313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
212413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
212513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(n, 0, sizeof(ocontext_t));
2126505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			if (l)
212713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l->next = n;
2128505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			else
212913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				state->out->ocontexts[i] = n;
2130505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			l = n;
2131505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			switch (i) {
2132505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			case OCON_XEN_ISID:
21331f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito				if (c->context[0].user == 0) {
21341f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					ERR(state->handle,
21351f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					    "Missing context for %s initial sid",
21361f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					    c->u.name);
21371f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					return -1;
21381f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito				}
2139505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->sid[0] = c->sid[0];
2140505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				break;
2141505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			case OCON_XEN_PIRQ:
2142505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.pirq = c->u.pirq;
2143505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				break;
2144505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			case OCON_XEN_IOPORT:
2145505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.ioport.low_ioport = c->u.ioport.low_ioport;
2146505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.ioport.high_ioport =
2147505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi					c->u.ioport.high_ioport;
2148505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				break;
2149505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			case OCON_XEN_IOMEM:
2150505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.iomem.low_iomem  = c->u.iomem.low_iomem;
2151505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.iomem.high_iomem = c->u.iomem.high_iomem;
2152505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				break;
2153505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			case OCON_XEN_PCIDEVICE:
2154505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				n->u.device = c->u.device;
2155505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				break;
2156f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf			case OCON_XEN_DEVICETREE:
2157f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf				n->u.name = strdup(c->u.name);
2158f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf				if (!n->u.name) {
2159f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf					ERR(state->handle, "Out of memory!");
2160f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf					return -1;
2161f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf				}
2162f0290677091e7eee4a3724a2a86ede9e11f93802Daniel De Graaf				break;
2163505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			default:
2164505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				/* shouldn't get here */
2165505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				ERR(state->handle, "Unknown ocontext");
2166505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				return -1;
2167505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			}
2168e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito			if (context_copy(&n->context[0], &c->context[0],
2169e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito				state)) {
2170e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito				ERR(state->handle, "Out of memory!");
2171e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito				return -1;
2172e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito			}
2173505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		}
2174505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	}
2175505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	return 0;
2176505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi}
2177505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi
2178505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzistatic int ocontext_copy_selinux(expand_state_t *state)
2179505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi{
2180505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	unsigned int i, j;
2181505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	ocontext_t *c, *n, *l;
2182505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi
2183505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	for (i = 0; i < OCON_NUM; i++) {
2184505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		l = NULL;
2185505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		for (c = state->base->ocontexts[i]; c; c = c->next) {
2186505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			n = malloc(sizeof(ocontext_t));
2187505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			if (!n) {
2188505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				ERR(state->handle, "Out of memory!");
2189505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				return -1;
219013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
2191505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			memset(n, 0, sizeof(ocontext_t));
2192505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			if (l)
2193505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				l->next = n;
2194505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi			else
2195505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				state->out->ocontexts[i] = n;
219613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			l = n;
219713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			switch (i) {
219813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_ISID:
21991f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito				if (c->context[0].user == 0) {
22001f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					ERR(state->handle,
22011f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					    "Missing context for %s initial sid",
22021f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					    c->u.name);
22031f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito					return -1;
22041f3bca77e04687afb87a7a4e034298c9c955919bChris PeBenito				}
220513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->sid[0] = c->sid[0];
220613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
220713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_FS:	/* FALLTHROUGH */
220813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NETIF:
220913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.name = strdup(c->u.name);
221013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n->u.name) {
221113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
221213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
221313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
221413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (context_copy
221513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (&n->context[1], &c->context[1], state)) {
221613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
221713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
221813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
221913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
222013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_PORT:
222113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.protocol = c->u.port.protocol;
222213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.low_port = c->u.port.low_port;
222313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.port.high_port = c->u.port.high_port;
222413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
222513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NODE:
222613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.node.addr = c->u.node.addr;
222713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.node.mask = c->u.node.mask;
222813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
222913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_FSUSE:
223013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->v.behavior = c->v.behavior;
223113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				n->u.name = strdup(c->u.name);
223213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!n->u.name) {
223313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle, "Out of memory!");
223413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
223513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
223613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
223713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			case OCON_NODE6:
223813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				for (j = 0; j < 4; j++)
223913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					n->u.node6.addr[j] = c->u.node6.addr[j];
224013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				for (j = 0; j < 4; j++)
224113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					n->u.node6.mask[j] = c->u.node6.mask[j];
224213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
224313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			default:
224413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* shouldn't get here */
2245505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				ERR(state->handle, "Unknown ocontext");
2246505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi				return -1;
224713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
2248e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito			if (context_copy(&n->context[0], &c->context[0], state)) {
2249e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito				ERR(state->handle, "Out of memory!");
2250e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito				return -1;
2251e26b58b08e92f823ff2f7e20ffd3124b7c5f8ccfChris PeBenito			}
225213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
225313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
225413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
225513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
225613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2257505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzistatic int ocontext_copy(expand_state_t *state, uint32_t target)
2258505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi{
2259505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	int rc = -1;
2260505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	switch (target) {
2261505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	case SEPOL_TARGET_SELINUX:
2262505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		rc = ocontext_copy_selinux(state);
2263505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		break;
2264505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	case SEPOL_TARGET_XEN:
2265505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		rc = ocontext_copy_xen(state);
2266505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		break;
2267505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	default:
2268505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		ERR(state->handle, "Unknown target");
2269505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi		return -1;
2270505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	}
2271505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	return rc;
2272505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi}
2273505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi
227413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int genfs_copy(expand_state_t * state)
227513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
227613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *newc, *l;
227713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genfs_t *genfs, *newgenfs, *end;
227813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	end = NULL;
228013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (genfs = state->base->genfs; genfs; genfs = genfs->next) {
228113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newgenfs = malloc(sizeof(genfs_t));
228213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!newgenfs) {
228313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
228413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
228513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
228613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(newgenfs, 0, sizeof(genfs_t));
228713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newgenfs->fstype = strdup(genfs->fstype);
228813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!newgenfs->fstype) {
2289afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			free(newgenfs);
229013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
229113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
229213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
2293afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		if (!end)
2294afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			state->out->genfs = newgenfs;
2295afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		else
2296afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			end->next = newgenfs;
2297afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		end = newgenfs;
229813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
229913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		l = NULL;
230013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (c = genfs->head; c; c = c->next) {
230113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc = malloc(sizeof(ocontext_t));
230213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!newc) {
230313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
230413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
230513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
230613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			memset(newc, 0, sizeof(ocontext_t));
230713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc->u.name = strdup(c->u.name);
230813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!newc->u.name) {
230913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory!");
2310afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris				free(newc);
231113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
231213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
231313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newc->v.sclass = c->v.sclass;
231413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_copy(&newc->context[0], &c->context[0], state);
231513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (l)
231613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				l->next = newc;
231713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			else
231813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				newgenfs->head = newc;
231913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			l = newc;
232013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
232113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
232213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
232313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
232413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
232513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_attr_map(hashtab_key_t key
232613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 __attribute__ ((unused)), hashtab_datum_t datum,
232713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 void *ptr)
232813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
232913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type;
233013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t *state = ptr;
233113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p = state->out;
233213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
233313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
233488d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter	int value;
233513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
233613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
233788d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter	value = type->s.value;
233888d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter
233913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor == TYPE_ATTRIB) {
234088d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter		if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) {
234188d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter			goto oom;
234213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
234313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&type->types, tnode, i) {
234413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, i))
234513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
234688d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter			if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) {
234788d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter				goto oom;
234813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
234913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
235088d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter	} else {
235188d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter		if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) {
235288d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter			goto oom;
235388d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter		}
235413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
235588d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter
235613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
235788d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter
235888d09b69795de11401355d2fcc6459bdc3f8a8a6James Carteroom:
235988d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter	ERR(state->handle, "Out of memory!");
236088d09b69795de11401355d2fcc6459bdc3f8a8a6James Carter	return -1;
236113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
236213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
236313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy.
236413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * this should not be called until after all the blocks have been processed and the attributes in target policy
236513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * are complete. */
236613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_convert_type_set(policydb_t * p, uint32_t * typemap,
236713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    type_set_t * set, ebitmap_t * types,
236813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    unsigned char alwaysexpand)
236913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
237013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_t tmpset;
237113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_init(&tmpset);
237313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&set->types, &tmpset.types, typemap))
237513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
237613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (map_ebitmap(&set->negset, &tmpset.negset, typemap))
237813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
237913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmpset.flags = set->flags;
238113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_expand(&tmpset, types, p, alwaysexpand))
238313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
238413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_destroy(&tmpset);
238613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
238713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
238813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
238913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2390eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle/* Expand a rule into a given avtab - checking for conflicting type
2391eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle * rules.  Return 1 on success, 0 if the rule conflicts with something
2392eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle * (and hence was not added), or -1 on error. */
2393eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindleint expand_rule(sepol_handle_t * handle,
2394eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		policydb_t * source_pol,
2395eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		avrule_t * source_rule, avtab_t * dest_avtab,
2396eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		cond_av_list_t ** cond, cond_av_list_t ** other, int enabled)
2397eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle{
2398eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	int retval;
2399eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	ebitmap_t stypes, ttypes;
2400eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle
240199fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	if ((source_rule->specified & AVRULE_NEVERALLOW)
240299fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		|| (source_rule->specified & AVRULE_XPERMS_NEVERALLOW))
2403eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		return 1;
2404eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle
2405eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	ebitmap_init(&stypes);
2406eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	ebitmap_init(&ttypes);
2407eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle
2408eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1))
2409eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		return -1;
2410eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1))
2411eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle		return -1;
2412eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	retval = expand_rule_helper(handle, source_pol, NULL,
2413eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle				    source_rule, dest_avtab,
2414eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle				    cond, other, enabled, &stypes, &ttypes);
2415eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	ebitmap_destroy(&stypes);
2416eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	ebitmap_destroy(&ttypes);
2417eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle	return retval;
2418eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle}
2419eeb520a0453ccc3d51770c4281125086e91c4ff7Joshua Brindle
24203592ebea1a5beb390a520c09747d3699867af9deHarry Ciao/* Expand a role set into an ebitmap containing the roles.
24213592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * This handles the attribute and flags.
24223592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * Attribute expansion depends on if the rolemap is available.
24233592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * During module compile the rolemap is not available, the
24243592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * possible duplicates of a regular role and the role attribute
24253592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * the regular role belongs to could be properly handled by
24263592ebea1a5beb390a520c09747d3699867af9deHarry Ciao * copy_role_trans and copy_role_allow.
24273592ebea1a5beb390a520c09747d3699867af9deHarry Ciao */
24283592ebea1a5beb390a520c09747d3699867af9deHarry Ciaoint role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap)
242913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
243013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
243113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *rnode;
24323592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_t mapped_roles, roles;
24333592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	policydb_t *p = out;
24343592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	role_datum_t *role;
243513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
243613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(r);
243713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
243813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (x->flags & ROLE_STAR) {
243986bad3dbf981b7d645d41e4c93649dcf782b1a6fNicolas Iooss		for (i = 0; i < p->p_roles.nprim; i++)
244013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(r, i, 1))
244113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
244213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
244313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
244413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24453592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_init(&mapped_roles);
24463592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_init(&roles);
24473592ebea1a5beb390a520c09747d3699867af9deHarry Ciao
244813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rolemap) {
24493592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		assert(base != NULL);
24503592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		ebitmap_for_each_bit(&x->roles, rnode, i) {
24513592ebea1a5beb390a520c09747d3699867af9deHarry Ciao			if (ebitmap_node_get_bit(rnode, i)) {
24523592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				/* take advantage of p_role_val_to_struct[]
24533592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				 * of the base module */
24543592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				role = base->role_val_to_struct[i];
24553592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				assert(role != NULL);
24563592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				if (role->flavor == ROLE_ATTRIB) {
24573592ebea1a5beb390a520c09747d3699867af9deHarry Ciao					if (ebitmap_union(&roles,
24583592ebea1a5beb390a520c09747d3699867af9deHarry Ciao							  &role->roles))
24593592ebea1a5beb390a520c09747d3699867af9deHarry Ciao						goto bad;
24603592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				} else {
24613592ebea1a5beb390a520c09747d3699867af9deHarry Ciao					if (ebitmap_set_bit(&roles, i, 1))
24623592ebea1a5beb390a520c09747d3699867af9deHarry Ciao						goto bad;
24633592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				}
24643592ebea1a5beb390a520c09747d3699867af9deHarry Ciao			}
24653592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		}
24663592ebea1a5beb390a520c09747d3699867af9deHarry Ciao		if (map_ebitmap(&roles, &mapped_roles, rolemap))
24673592ebea1a5beb390a520c09747d3699867af9deHarry Ciao			goto bad;
246813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
246913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_cpy(&mapped_roles, &x->roles))
24703592ebea1a5beb390a520c09747d3699867af9deHarry Ciao			goto bad;
247113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
247213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
247313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&mapped_roles, rnode, i) {
247413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(rnode, i)) {
247513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(r, i, 1))
24763592ebea1a5beb390a520c09747d3699867af9deHarry Ciao				goto bad;
247713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
247813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
247913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
248013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&mapped_roles);
24813592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_destroy(&roles);
248213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
248313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* if role is to be complimented, invert the entire bitmap here */
248413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (x->flags & ROLE_COMP) {
248513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < ebitmap_length(r); i++) {
248613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(r, i)) {
248713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(r, i, 0))
248813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
248913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
249013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(r, i, 1))
249113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
249213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
249313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
249413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
249513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
24963592ebea1a5beb390a520c09747d3699867af9deHarry Ciao
24973592ebea1a5beb390a520c09747d3699867af9deHarry Ciaobad:
24983592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_destroy(&mapped_roles);
24993592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	ebitmap_destroy(&roles);
25003592ebea1a5beb390a520c09747d3699867af9deHarry Ciao	return -1;
250113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
250213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
250313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Expand a type set into an ebitmap containing the types. This
250413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * handles the negset, attributes, and flags.
250513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Attribute expansion depends on several factors:
250613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - if alwaysexpand is 1, then they will be expanded,
250713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - if the type set has a negset or flags, then they will be expanded,
250813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * - otherwise, they will not be expanded.
250913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
251013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p,
251113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    unsigned char alwaysexpand)
251213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
251313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
251413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t types, neg_types;
251513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
25168e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	int rc =-1;
251713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
251813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&types);
251913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(t);
252013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
252113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (alwaysexpand || ebitmap_length(&set->negset) || set->flags) {
252213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* First go through the types and OR all the attributes to types */
252313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&set->types, tnode, i) {
252413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_node_get_bit(tnode, i)) {
25256e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts
25266e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts				/*
25276e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts				 * invalid policies might have more types set in the ebitmap than
25286e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts				 * what's available in the type_val_to_struct mapping
25296e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts				 */
25306e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts				if (i > p->p_types.nprim - 1)
25318e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts					goto err_types;
25326e7d04ac0b01f34716941736f356d88a6f4ea6a1William Roberts
25338b4ad4fde577548a286a7c571ba4585cc11cfcd8William Roberts				if (!p->type_val_to_struct[i]) {
25348b4ad4fde577548a286a7c571ba4585cc11cfcd8William Roberts					goto err_types;
25358b4ad4fde577548a286a7c571ba4585cc11cfcd8William Roberts				}
25368b4ad4fde577548a286a7c571ba4585cc11cfcd8William Roberts
253713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (p->type_val_to_struct[i]->flavor ==
253813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    TYPE_ATTRIB) {
253913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_union
254013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (&types,
254113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     &p->type_val_to_struct[i]->
254213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     types)) {
25438e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts						goto err_types;
254413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
254513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
254613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (ebitmap_set_bit(&types, i, 1)) {
25478e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts						goto err_types;
254813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
254913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
255013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
255113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
255213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
255313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* No expansion of attributes, just copy the set as is. */
255413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_cpy(&types, &set->types))
25558e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts			goto err_types;
255613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
255713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
255813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Now do the same thing for negset */
255913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&neg_types);
256013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&set->negset, tnode, i) {
256113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)) {
256213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
256313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
256413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_union
256513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (&neg_types,
256613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     &p->type_val_to_struct[i]->types)) {
25678e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts					goto err_neg;
256813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
256913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
257013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(&neg_types, i, 1)) {
25718e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts					goto err_neg;
257213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
257313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
257413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
257513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
257613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
257713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set->flags & TYPE_STAR) {
257813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* set all types not in neg_types */
257913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < p->p_types.nprim; i++) {
258013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(&neg_types, i))
258113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
258213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
258313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
258413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
258513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(t, i, 1))
25868e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts				goto err_neg;
258713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
258813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
258913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
259013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
259113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&types, tnode, i) {
259213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)
259313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    && (!ebitmap_get_bit(&neg_types, i)))
259413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit(t, i, 1))
25958e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts				goto err_neg;
259613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
259713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
259813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set->flags & TYPE_COMP) {
259913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < p->p_types.nprim; i++) {
260013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (p->type_val_to_struct[i] &&
260113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
260213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(!ebitmap_get_bit(t, i));
260313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
260413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
260513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_get_bit(t, i)) {
260613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(t, i, 0))
26078e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts					goto err_neg;
260813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
260913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit(t, i, 1))
26108e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts					goto err_neg;
261113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
261213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
261313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
261413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26158e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	  out:
26168e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	rc = 0;
261713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26188e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	  err_neg:
261913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&neg_types);
26208e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	  err_types:
26218e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	ebitmap_destroy(&types);
262213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26238e8a648e92ce1cd0c254459fcabb9dfa381a15bdWilliam Roberts	return rc;
262413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
262513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
262613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
262713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   avrule_t * source_rule)
262813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
262913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t stypes, ttypes;
263013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *avrule;
263113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur_perm, *new_perm, *tail_perm;
263299fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	av_extended_perms_t *xperms = NULL;
263313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
263413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&stypes);
263513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&ttypes);
263613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
263713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
263813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->stypes, &stypes, 1))
263913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
264013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (expand_convert_type_set
264113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1))
264213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
264313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
264413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule = (avrule_t *) malloc(sizeof(avrule_t));
264513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!avrule)
264613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
264713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
264813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_init(avrule);
264999fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	avrule->specified = source_rule->specified;
265013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule->line = source_rule->line;
265113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule->flags = source_rule->flags;
2652ef24ade029329a6e9981bd1de2ba7b9ea48e1c79Stephen Smalley	avrule->source_line = source_rule->source_line;
2653a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley	if (source_rule->source_filename) {
2654a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley		avrule->source_filename = strdup(source_rule->source_filename);
2655a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley		if (!avrule->source_filename)
2656a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley			goto err;
2657a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley	}
265813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
265913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&avrule->stypes.types, &stypes))
266013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
266113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
266213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&avrule->ttypes.types, &ttypes))
266313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
266413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
266513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur_perm = source_rule->perms;
266613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail_perm = NULL;
266713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur_perm) {
266813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_perm =
266913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
267013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_perm)
267113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
267213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		class_perm_node_init(new_perm);
2673ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman		new_perm->tclass = cur_perm->tclass;
2674ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman		assert(new_perm->tclass);
267513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
267613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* once we have modules with permissions we'll need to map the permissions (and classes) */
267713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_perm->data = cur_perm->data;
267813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
267913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!avrule->perms)
268013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avrule->perms = new_perm;
268113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
268213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (tail_perm)
268313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail_perm->next = new_perm;
268413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail_perm = new_perm;
268513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_perm = cur_perm->next;
268613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
268713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
268899fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	/* copy over extended permissions */
268999fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	if (source_rule->xperms) {
269099fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		xperms = calloc(1, sizeof(av_extended_perms_t));
269199fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		if (!xperms)
269299fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep			goto err;
269399fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t));
269499fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep		avrule->xperms = xperms;
269599fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	}
269699fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep
269713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* just prepend the avrule to the first branch; it'll never be
269813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   written to disk */
269913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!dest_pol->global->branch_list->avrules)
270013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_pol->global->branch_list->avrules = avrule;
270113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else {
270213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule->next = dest_pol->global->branch_list->avrules;
270313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_pol->global->branch_list->avrules = avrule;
270413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
270513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
270613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
270713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
270813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
270913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
271013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
271113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
271213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&stypes);
271313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&ttypes);
271413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&avrule->stypes.types);
271513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&avrule->ttypes.types);
271613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur_perm = avrule->perms;
271713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur_perm) {
271813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail_perm = cur_perm->next;
271913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(cur_perm);
272013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_perm = tail_perm;
272113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
272299fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep	free(xperms);
272313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(avrule);
272413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
272513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
272613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
272713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
272813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow
272913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * rules are copied or expanded as per the settings in the state object; all
273013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * other AV rules are expanded.  If neverallow rules are expanded, they are not
273113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * copied, otherwise they are copied for later use by the assertion checker.
273213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
273313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_and_expand_avrule_block(expand_state_t * state)
273413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
273513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *curblock = state->base->global;
273613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *prevblock;
273713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = -1;
273813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
273913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) {
274013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		ERR(state->handle, "Out of Memory!");
274113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		return -1;
274213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	}
274313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
274413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) {
274513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		ERR(state->handle, "Out of Memory!");
274613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 		return -1;
274713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 	}
274813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
274913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (curblock) {
275013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = curblock->enabled;
275113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_t *cur_avrule;
275213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
275313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (decl == NULL) {
275413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* nothing was enabled within this block */
275513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cont;
275613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
275713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
275813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy role allows and role trans */
275913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_role_allows(state, decl->role_allow_rules) != 0 ||
276013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    copy_role_trans(state, decl->role_tr_rules) != 0) {
276113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
276213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
276313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27646eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (expand_filename_trans(state, decl->filename_trans_rules))
27656eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			goto cleanup;
27666eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
276713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* expand the range transition rules */
276813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (expand_range_trans(state, decl->range_tr_rules))
276913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
277013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
277113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy rules */
277213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_avrule = decl->avrules;
277313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur_avrule != NULL) {
277413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!(state->expand_neverallow)
277599fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep			    && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) {
277613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* copy this over directly so that assertions are checked later */
277713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (copy_neverallow
277813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (state->out, state->typemap, cur_avrule))
277913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
278013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "Error while copying neverallow.");
278113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
278299fc177b5af4e1e8855d42d2d01cb93ac7f9d14bJeff Vander Stoep				if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))
278313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state->out->unsupported_format = 1;
278413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (convert_and_expand_rule
278513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (state->handle, state->out, state->typemap,
278613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     cur_avrule, &state->out->te_avtab, NULL,
278713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     NULL, 0,
278813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     state->expand_neverallow) !=
278913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    EXPAND_RULE_SUCCESS) {
279013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto cleanup;
279113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
279213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
279313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur_avrule = cur_avrule->next;
279413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
279513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
279613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy conditional rules */
279713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cond_node_copy(state, decl->cond_list))
279813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
279913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
280013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cont:
280113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		prevblock = curblock;
280213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		curblock = curblock->next;
280313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
280413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->handle && state->handle->expand_consume_base) {
280513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* set base top avrule block in case there
280613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 			 * is an error condition and the policy needs
280713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 			 * to be destroyed */
280813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->base->global = curblock;
280913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avrule_block_destroy(prevblock);
281013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
281113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
281213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
281313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
281413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
281513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
281613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
281713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
281813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
281913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
282013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This function allows external users of the library (such as setools) to
282113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * expand only the avrules and optionally perform expansion of neverallow rules
282213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * or expand into the same policy for analysis purposes.
282313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
282413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_module_avrules(sepol_handle_t * handle, policydb_t * base,
282513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  policydb_t * out, uint32_t * typemap,
282613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  uint32_t * boolmap, uint32_t * rolemap,
282713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  uint32_t * usermap, int verbose,
282813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  int expand_neverallow)
282913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
283013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t state;
283113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
283213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_init(&state);
283313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
283413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.base = base;
283513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out = out;
283613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.typemap = typemap;
283713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.boolmap = boolmap;
283813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.rolemap = rolemap;
283913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.usermap = usermap;
284013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.handle = handle;
284113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.verbose = verbose;
284213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.expand_neverallow = expand_neverallow;
284313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
284413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return copy_and_expand_avrule_block(&state);
284513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
284613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28479f709e6bab863036950644a7dd470d50663b558bHarry Ciaostatic void discard_tunables(sepol_handle_t *sh, policydb_t *pol)
2848ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao{
2849ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	avrule_block_t *block;
2850ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	avrule_decl_t *decl;
2851ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	cond_node_t *cur_node;
2852ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	cond_expr_t *cur_expr;
28539f709e6bab863036950644a7dd470d50663b558bHarry Ciao	int cur_state, preserve_tunables = 0;
2854ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	avrule_t *tail, *to_be_appended;
2855ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
28569f709e6bab863036950644a7dd470d50663b558bHarry Ciao	if (sh && sh->preserve_tunables)
28579f709e6bab863036950644a7dd470d50663b558bHarry Ciao		preserve_tunables = 1;
28589f709e6bab863036950644a7dd470d50663b558bHarry Ciao
2859ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	/* Iterate through all cond_node of all enabled decls, if a cond_node
28609f709e6bab863036950644a7dd470d50663b558bHarry Ciao	 * is about tunable, calculate its state value and concatenate one of
28619f709e6bab863036950644a7dd470d50663b558bHarry Ciao	 * its avrule list to the current decl->avrules list. On the other
28629f709e6bab863036950644a7dd470d50663b558bHarry Ciao	 * hand, the disabled unused branch of a tunable would be discarded.
2863ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 *
2864ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * Note, such tunable cond_node would be skipped over in expansion,
2865ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * so we won't have to worry about removing it from decl->cond_list
2866ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * here :-)
2867ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 *
28689f709e6bab863036950644a7dd470d50663b558bHarry Ciao	 * If tunables are requested to be preserved then they would be
28699f709e6bab863036950644a7dd470d50663b558bHarry Ciao	 * "transformed" as booleans by having their TUNABLE flag cleared.
2870ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 */
2871ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	for (block = pol->global; block != NULL; block = block->next) {
2872ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		decl = block->enabled;
2873ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		if (decl == NULL || decl->enabled == 0)
2874ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			continue;
2875ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2876ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		tail = decl->avrules;
2877ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		while (tail && tail->next)
2878ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			tail = tail->next;
2879ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2880ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		for (cur_node = decl->cond_list; cur_node != NULL;
2881ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		     cur_node = cur_node->next) {
28829f709e6bab863036950644a7dd470d50663b558bHarry Ciao			int booleans, tunables, i;
2883ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			cond_bool_datum_t *booldatum;
28849f709e6bab863036950644a7dd470d50663b558bHarry Ciao			cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH];
2885ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2886ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			booleans = tunables = 0;
28879f709e6bab863036950644a7dd470d50663b558bHarry Ciao			memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH);
2888ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2889ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			for (cur_expr = cur_node->expr; cur_expr != NULL;
2890ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			     cur_expr = cur_expr->next) {
2891ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				if (cur_expr->expr_type != COND_BOOL)
2892ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					continue;
2893ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				booldatum = pol->bool_val_to_struct[cur_expr->bool - 1];
2894ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE)
28959f709e6bab863036950644a7dd470d50663b558bHarry Ciao					tmp[tunables++] = booldatum;
2896ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				else
2897ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					booleans++;
2898ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			}
2899ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2900ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			/* bool_copy_callback() at link phase has ensured
2901ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			 * that no mixture of tunables and booleans in one
29029f709e6bab863036950644a7dd470d50663b558bHarry Ciao			 * expression. However, this would be broken by the
29039f709e6bab863036950644a7dd470d50663b558bHarry Ciao			 * request to preserve tunables */
29049f709e6bab863036950644a7dd470d50663b558bHarry Ciao			if (!preserve_tunables)
29059f709e6bab863036950644a7dd470d50663b558bHarry Ciao				assert(!(booleans && tunables));
2906ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
29079f709e6bab863036950644a7dd470d50663b558bHarry Ciao			if (booleans || preserve_tunables) {
2908ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE;
29099f709e6bab863036950644a7dd470d50663b558bHarry Ciao				if (tunables) {
29109f709e6bab863036950644a7dd470d50663b558bHarry Ciao					for (i = 0; i < tunables; i++)
29119f709e6bab863036950644a7dd470d50663b558bHarry Ciao						tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE;
29129f709e6bab863036950644a7dd470d50663b558bHarry Ciao				}
2913ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			} else {
2914ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				cur_node->flags |= COND_NODE_FLAGS_TUNABLE;
2915ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				cur_state = cond_evaluate_expr(pol, cur_node->expr);
2916ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				if (cur_state == -1) {
2917ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					printf("Expression result was "
2918ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					       "undefined, skipping all"
2919ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					       "rules\n");
2920ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					continue;
2921ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				}
2922ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2923ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				to_be_appended = (cur_state == 1) ?
2924ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					cur_node->avtrue_list : cur_node->avfalse_list;
2925ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2926ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				if (tail)
2927ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					tail->next = to_be_appended;
2928ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				else
2929ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					tail = decl->avrules = to_be_appended;
2930ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2931ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				/* Now that the effective branch has been
2932ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				 * appended, neutralize its original pointer */
2933ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				if (cur_state == 1)
2934ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					cur_node->avtrue_list = NULL;
2935ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				else
2936ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					cur_node->avfalse_list = NULL;
2937ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
2938ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				/* Update the tail of decl->avrules for
2939ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				 * further concatenation */
2940ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao				while (tail && tail->next)
2941ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao					tail = tail->next;
2942ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao			}
2943ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao		}
2944ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	}
2945ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao}
2946ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
294713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Linking should always be done before calling expand, even if
294813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * there is only a base since all optionals are dealt with at link time
294913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the base passed in should be indexed and avrule blocks should be
295013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * enabled.
295113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
295213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_module(sepol_handle_t * handle,
295313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		  policydb_t * base, policydb_t * out, int verbose, int check)
295413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
295513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = -1;
295613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
295713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_t state;
295813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *curblock;
295913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2960ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	/* Append tunable's avtrue_list or avfalse_list to the avrules list
2961ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * of its home decl depending on its state value, so that the effect
2962ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * rules of a tunable would be added to te_avtab permanently. Whereas
2963ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * the disabled unused branch would be discarded.
2964ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 *
2965ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * Originally this function is called at the very end of link phase,
2966ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * however, we need to keep the linked policy intact for analysis
2967ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao	 * purpose. */
29689f709e6bab863036950644a7dd470d50663b558bHarry Ciao	discard_tunables(handle, base);
2969ad5951fcb142cf9c2e899d3d99ce35b729b66b4cHarry Ciao
297013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expand_state_init(&state);
297113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
297213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.verbose = verbose;
297313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.typemap = NULL;
297413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.base = base;
297513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out = out;
297613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.handle = handle;
297713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
297813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base->policy_type != POLICY_BASE) {
297913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Target of expand was not a base policy.");
298013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
298113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
298213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
298313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->policy_type = POLICY_KERN;
298413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->policyvers = POLICYDB_VERSION_MAX;
298513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
298613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Copy mls state from base to out */
298713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	out->mls = base->mls;
298813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	out->handle_unknown = base->handle_unknown;
298913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2990505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	/* Copy target from base to out */
2991505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	out->target_platform = base->target_platform;
2992505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi
299313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Copy policy capabilities */
299413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_cpy(&out->policycaps, &base->policycaps)) {
299513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
299613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
299713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
299813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
299913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((state.typemap =
300013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     (uint32_t *) calloc(state.base->p_types.nprim,
300113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 sizeof(uint32_t))) == NULL) {
300213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
300313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
300413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
300513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
300613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t));
300713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.boolmap) {
300813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
300913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
301013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
301113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
301213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t));
301313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.rolemap) {
301413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
301513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
301613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
301713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
301813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t));
301913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.usermap) {
302013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
302113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
302213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
302313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
302413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* order is important - types must be first */
302513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
302613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy types */
302713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) {
302813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
302913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
303013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
303113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* convert attribute type sets */
303213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
303313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_types.table, attr_convert_callback, &state)) {
303413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
303513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
303613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
303713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy commons */
303813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
303913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_commons.table, common_copy_callback, &state)) {
304013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
304113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
304213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
304313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy classes, note, this does not copy constraints, constraints can't be
304413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * copied until after all the blocks have been processed and attributes are complete */
304513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
304613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_classes.table, class_copy_callback, &state)) {
304713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
304813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
304913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3050f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	/* copy type bounds */
3051f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(state.base->p_types.table,
3052f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			type_bounds_copy_callback, &state))
3053f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		goto cleanup;
3054f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
305513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy aliases */
305613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state))
305713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
305813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
305913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* index here so that type indexes are available for role_copy_callback */
306013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
306113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
306213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
306313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
306413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
306513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy roles */
306613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
306713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
3068f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(state.base->p_roles.table,
3069f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			role_bounds_copy_callback, &state))
3070f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		goto cleanup;
3071d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	/* escalate the type_set_t in a role attribute to all regular roles
3072d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	 * that belongs to it. */
3073d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao	if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
3074d4d90eceeba902874252fd7c1b9384fc5b1605d4Harry Ciao		goto cleanup;
307513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
307613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy MLS's sensitivity level and categories - this needs to be done
307713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * before expanding users (they need to be indexed too) */
307813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
307913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
308013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
308113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
308213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
308313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
308413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
308513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
308613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
308713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy users */
308813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
308913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
3090f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(state.base->p_users.table,
3091f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			user_bounds_copy_callback, &state))
3092f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		goto cleanup;
309313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
309413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy bools */
309513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
309613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
309713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
309813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_classes(out)) {
309913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out classes");
310013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
310113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
310213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(handle, out, verbose)) {
310313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error while indexing out symbols");
310413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
310513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
310613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
310713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* loop through all decls and union attributes, roles, users */
310813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (curblock = state.base->global; curblock != NULL;
310913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     curblock = curblock->next) {
311013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = curblock->enabled;
311113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
311213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (decl == NULL) {
311313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* nothing was enabled within this block */
311413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
311513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
311613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
311713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* convert attribute type sets */
311813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
311913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_types.table, attr_convert_callback, &state)) {
312013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
312113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
312213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
312313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy roles */
312413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
312513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_roles.table, role_copy_callback, &state))
312613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
312713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
312813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* copy users */
312913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
313013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (decl->p_users.table, user_copy_callback, &state))
313113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
313213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
313313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
313413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
313513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* remap role dominates bitmaps */
313613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) {
313713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
313813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
313913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
314013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (copy_and_expand_avrule_block(&state) < 0) {
314113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Error during expand");
314213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
314313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
314413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
314513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy constraints */
314613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map
314713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (state.base->p_classes.table, constraint_copy_callback, &state)) {
314813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
314913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
315013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
315113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_optimize_lists(state.out->cond_list);
3152afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	if (evaluate_conds(state.out))
3153afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		goto cleanup;
315413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
315513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy ocontexts */
3156505c75aad7f16e0db9ccfeb04eaa70f242e6b060Paul Nuzzi	if (ocontext_copy(&state, out->target_platform))
315713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
315813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
315913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy genfs */
316013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (genfs_copy(&state))
316113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
316213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
316313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Build the type<->attribute maps and remove attributes. */
316413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->attr_type_map = malloc(state.out->p_types.nprim *
316513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					  sizeof(ebitmap_t));
316613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.out->type_attr_map = malloc(state.out->p_types.nprim *
316713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					  sizeof(ebitmap_t));
316813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!state.out->attr_type_map || !state.out->type_attr_map) {
316913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
317013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
317113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
317213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < state.out->p_types.nprim; i++) {
317313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&state.out->type_attr_map[i]);
317413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(&state.out->attr_type_map[i]);
317513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* add the type itself as the degenerate case */
317613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) {
317713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(handle, "Out of memory!");
317813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
317913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
318013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
318113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (hashtab_map(state.out->p_types.table, type_attr_map, &state))
318213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
318313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (check) {
318413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hierarchy_check_constraints(handle, state.out))
318513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
318613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
318713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (check_assertions
318813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (handle, state.out,
318913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     state.out->global->branch_list->avrules))
319013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 goto cleanup;
319113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
319213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
319313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
319413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
319513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
319613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.typemap);
319713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.boolmap);
319813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.rolemap);
319913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.usermap);
320013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
320113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
320213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
320313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
320413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
320513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
320613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avd;
3207915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	avtab_extended_perms_t *xperms;
320880bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep	unsigned int i;
3209915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	unsigned int match = 0;
321080bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep
3211915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	if (k->specified & AVTAB_XPERMS) {
321280bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		/*
3213915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep		 * AVTAB_XPERMS entries are not necessarily unique.
3214915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep		 * find node with matching xperms
321580bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		 */
321680bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		node = avtab_search_node(a, k);
321780bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		while (node) {
3218915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep			if ((node->datum.xperms->specified == d->xperms->specified) &&
3219915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep				(node->datum.xperms->driver == d->xperms->driver)) {
3220915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep				match = 1;
322180bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep				break;
322280bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			}
322380bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			node = avtab_search_node_next(node, k->specified);
322480bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		}
3225915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep		if (!match)
322680bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			node = NULL;
322780bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep	} else {
322880bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		node = avtab_search_node(a, k);
322913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
323013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
323180bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep	if (!node || ((k->specified & AVTAB_ENABLED) !=
323280bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep			(node->key.specified & AVTAB_ENABLED))) {
323313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(a, k, d);
323413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
323513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
323613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
323713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
323813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
323913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
324013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
324113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avd = &node->datum;
3242915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	xperms = node->datum.xperms;
324313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (k->specified & ~AVTAB_ENABLED) {
324413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_ALLOWED:
324513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITALLOW:
324613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data |= d->data;
324713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
324813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITDENY:
324913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data &= d->data;
325013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
3251915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	case AVTAB_XPERMS_ALLOWED:
3252915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	case AVTAB_XPERMS_AUDITALLOW:
3253915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep	case AVTAB_XPERMS_DONTAUDIT:
3254915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep		for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
3255915fa8f08f4f9a4c437ee8280a4e641872ea59ddJeff Vander Stoep			xperms->perms[i] |= d->xperms->perms[i];
325680bc7ee8faaddfa7a650994fa82a57f41a9e7475Jeff Vander Stoep		break;
325713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
325813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Type conflict!");
325913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
326013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
326113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
326213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
326313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
326413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
326513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestruct expand_avtab_data {
326613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_t *expa;
326713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p;
326813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
326913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
327013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
327113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args)
327213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
327313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct expand_avtab_data *ptr = args;
327413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_t *expa = ptr->expa;
327513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p = ptr->p;
327613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
327713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
327813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
327913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
328013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
328113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
328213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t newkey;
328313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
328413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
328513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.target_class = k->target_class;
328613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.specified = k->specified;
328713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3288678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
328913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Both are individual types, no expansion required. */
329013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return expand_avtab_insert(expa, k, d);
329113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
329213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3293678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (stype && stype->flavor != TYPE_ATTRIB) {
329413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Source is an individual type, target is an attribute. */
329513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.source_type = k->source_type;
329613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
329713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
329813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
329913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
330013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
330113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
330213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
330313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
330413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
330513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
330613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3307678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (ttype && ttype->flavor != TYPE_ATTRIB) {
330813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Target is an individual type, source is an attribute. */
330913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.target_type = k->target_type;
331013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(sattr, snode, i) {
331113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
331213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
331313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
331413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
331513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
331613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
331713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
331813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
331913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
332013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
332113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Both source and target type are attributes. */
332213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(sattr, snode, i) {
332313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
332413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
332513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
332613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
332713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
332813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
332913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
333013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_avtab_insert(expa, &newkey, d);
333113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
333213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
333313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
333413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
333513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
333613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
333713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
333813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
333913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa)
334013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
334113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct expand_avtab_data data;
334213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
334313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
334413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Out of memory!");
334513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
334613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
334713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
334813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data.expa = expa;
334913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data.p = p;
335013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return avtab_map(a, expand_avtab_node, &data);
335113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
335213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
335313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int expand_cond_insert(cond_av_list_t ** l,
335413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avtab_t * expa,
335513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      avtab_key_t * k, avtab_datum_t * d)
335613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
335713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
335813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *avd;
335913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *nl;
336013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
336113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	node = avtab_search_node(expa, k);
336213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!node ||
336313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (k->specified & AVTAB_ENABLED) !=
336413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (node->key.specified & AVTAB_ENABLED)) {
336513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = avtab_insert_nonunique(expa, k, d);
336613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!node) {
336713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
336813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
336913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
337013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node->parse_context = (void *)1;
337113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl = (cond_av_list_t *) malloc(sizeof(*nl));
337213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!nl) {
337313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(NULL, "Out of memory!");
337413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
337513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
337613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(nl, 0, sizeof(*nl));
337713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl->node = node;
337813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nl->next = *l;
337913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*l = nl;
338013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
338113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
338213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
338313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avd = &node->datum;
338413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (k->specified & ~AVTAB_ENABLED) {
338513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_ALLOWED:
338613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITALLOW:
338713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data |= d->data;
338813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
338913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case AVTAB_AUDITDENY:
339013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avd->data &= d->data;
339113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
339213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
339313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Type conflict!");
339413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
339513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
339613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
339713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
339813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
339913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
340013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_cond_av_node(policydb_t * p,
340113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			avtab_ptr_t node,
340213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cond_av_list_t ** newl, avtab_t * expa)
340313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
340413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t *k = &node->key;
340513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_datum_t *d = &node->datum;
340613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
340713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
340813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
340913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
341013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *snode, *tnode;
341113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
341213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_key_t newkey;
341313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
341413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
341513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.target_class = k->target_class;
341613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	newkey.specified = k->specified;
341713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3418678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
341913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Both are individual types, no expansion required. */
342013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return expand_cond_insert(newl, expa, k, d);
342113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
342213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3423678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (stype && stype->flavor != TYPE_ATTRIB) {
342413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Source is an individual type, target is an attribute. */
342513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.source_type = k->source_type;
342613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
342713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
342813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
342913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
343013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
343113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
343213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
343313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
343413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
343513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
343613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3437678ec5df790b0ff3c9dbb041be670a5916838e29Stephen Smalley	if (ttype && ttype->flavor != TYPE_ATTRIB) {
343813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Target is an individual type, source is an attribute. */
343913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newkey.target_type = k->target_type;
344013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(sattr, snode, i) {
344113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(snode, i))
344213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
344313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
344413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
344513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
344613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
344713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
344813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
344913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
345013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
345113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Both source and target type are attributes. */
345213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(sattr, snode, i) {
345313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!ebitmap_node_get_bit(snode, i))
345413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
345513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(tattr, tnode, j) {
345613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(tnode, j))
345713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
345813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.source_type = i + 1;
345913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newkey.target_type = j + 1;
346013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = expand_cond_insert(newl, expa, &newkey, d);
346113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc)
346213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
346313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
346413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
346513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
346613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
346713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
346813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
346913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint expand_cond_av_list(policydb_t * p, cond_av_list_t * l,
347013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cond_av_list_t ** newl, avtab_t * expa)
347113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
347213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_av_list_t *cur;
347313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avtab_ptr_t node;
347413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
347513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
347613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
347713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(NULL, "Out of memory!");
347813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
347913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
348013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
348113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*newl = NULL;
348213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cur = l; cur; cur = cur->next) {
348313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = cur->node;
348413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = expand_cond_av_node(p, node, newl, expa);
348513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc)
348613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return rc;
348713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
348813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
348913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
349013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
3491