113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	    Joshua Brindle <jbrindle@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *          Jason Tang <jtang@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 <sepol/policydb/policydb.h>
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/conditional.h>
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/hashtab.h>
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/avrule_block.h>
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/link.h>
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/util.h>
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdarg.h>
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <assert.h>
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#undef min
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define min(a,b) (((a) < (b)) ? (a) : (b))
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct policy_module {
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *policy;
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t num_decls;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *map[SYM_NUM];
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *avdecl_map;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t **perm_map;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *perm_map_len;
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* a pointer to within the base module's avrule_block chain to
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * where this module's global now resides */
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *base_global;
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} policy_module_t;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct link_state {
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int verbose;
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *base;
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *last_avrule_block, *last_base_avrule_block;
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t next_decl_id, current_decl_id;
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* temporary variables, used during hashtab_map() calls */
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *cur;
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *cur_mod_name;
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *dest_decl;
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *src_class, *dest_class;
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *dest_class_name;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char dest_class_req;	/* flag indicating the class was not declared */
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t symbol_num;
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* used to report the name of the module if dependancy error occurs */
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t **decl_to_mod;
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* error reporting fields */
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_handle_t *handle;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} link_state_t;
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct missing_requirement {
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t symbol_type;
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t symbol_value;
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t perm_value;
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} missing_requirement_t;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic const char *symtab_names[SYM_NUM] = {
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	"common", "class", "role", "type/attribute", "user",
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	"bool", "level", "category"
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Deallocates all elements within a module, but NOT the policydb_t
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * structure within, as well as the pointer itself. */
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void policy_module_destroy(policy_module_t * mod)
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mod == NULL) {
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return;
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(mod->map[i]);
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; mod->perm_map != NULL && i < mod->policy->p_classes.nprim;
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     i++) {
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(mod->perm_map[i]);
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mod->perm_map);
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mod->perm_map_len);
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mod->avdecl_map);
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mod);
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/***** functions that copy identifiers from a module to base *****/
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Note: there is currently no scoping for permissions, which causes some
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * strange side-effects. The current approach is this:
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * a) perm is required and the class _and_ perm are declared in base: only add a mapping.
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * b) perm is required and the class and perm are _not_ declared in base: simply add the permissions
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    to the object class. This means that the requirements for the decl are the union of the permissions
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    required for all decls, but who cares.
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * c) perm is required, the class is declared in base, but the perm is not present. Nothing we can do
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    here because we can't mark a single permission as required, so we bail with a requirement error
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    _even_ if we are in an optional.
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * A is correct behavior, b is wrong but not too bad, c is totall wrong for optionals. Fixing this requires
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * a format change.
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    void *data)
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *perm_id = key, *new_id = NULL;
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perm, *new_perm = NULL, *dest_perm;
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *src_class = state->src_class;
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *dest_class = state->dest_class;
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *mod = state->cur;
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t sclassi = src_class->s.value - 1;
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm = (perm_datum_t *) datum;
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dest_perm = hashtab_search(dest_class->permissions.table, perm_id);
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (dest_perm == NULL && dest_class->comdatum != NULL) {
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dest_perm =
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_search(dest_class->comdatum->permissions.table,
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   perm_id);
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (dest_perm == NULL) {
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* If the object class was not declared in the base, add the perm
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * to the object class. */
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->dest_class_req) {
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* If the class was required (not declared), insert the new permission */
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_id = strdup(perm_id);
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_id == NULL) {
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Memory error");
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_perm =
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (perm_datum_t *) calloc(1, sizeof(perm_datum_t));
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_perm == NULL) {
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Memory error");
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = hashtab_insert(dest_class->permissions.table,
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     (hashtab_key_t) new_id,
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     (hashtab_datum_t) new_perm);
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ret) {
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle,
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "could not insert permission into class\n");
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_perm->s.value = dest_class->permissions.nprim + 1;
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			dest_perm = new_perm;
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* this is case c from above */
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "Module %s depends on permission %s in class %s, not satisfied",
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name, perm_id,
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->dest_class_name);
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_EREQ;
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* build the mapping for permissions encompassing this class.
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * unlike symbols, the permission map translates between
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * module permission bit to target permission bit.  that bit
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * may have originated from the class -or- it could be from
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * the class's common parent.*/
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (perm->s.value > mod->perm_map_len[sclassi]) {
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		uint32_t *newmap = calloc(perm->s.value, sizeof(*newmap));
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (newmap == NULL) {
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(newmap, mod->perm_map[sclassi],
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       mod->perm_map_len[sclassi] * sizeof(*newmap));
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(mod->perm_map[sclassi]);
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mod->perm_map[sclassi] = newmap;
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mod->perm_map_len[sclassi] = perm->s.value;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mod->perm_map[sclassi][perm->s.value - 1] = dest_perm->s.value;
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_perm);
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Parisstatic int class_copy_default_new_object(link_state_t *state,
20909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris					 class_datum_t *olddatum,
21009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris					 class_datum_t *newdatum)
21109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris{
21209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_user) {
21309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
21409c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default user definitions");
21509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
21609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
21709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_user = olddatum->default_user;
21809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
21909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_role) {
22009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
22109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default role definitions");
22209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
22309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
22409c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_role = olddatum->default_role;
22509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
226693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris	if (olddatum->default_type) {
227693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
228693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris			ERR(state->handle, "Found conflicting default type definitions");
229693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris			return SEPOL_ENOTSUP;
230693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		}
231693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris		newdatum->default_type = olddatum->default_type;
232693f5241fdd5ae7e89d4312b85443c0fc1b1a57dEric Paris	}
23309c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (olddatum->default_range) {
23409c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
23509c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			ERR(state->handle, "Found conflicting default range definitions");
23609c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris			return SEPOL_ENOTSUP;
23709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		}
23809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		newdatum->default_range = olddatum->default_range;
23909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	}
24009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	return 0;
24109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris}
24209c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_datum_t *cladatum, *new_class = NULL;
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope = NULL;
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cladatum = (class_datum_t *) datum;
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->dest_class_req = 0;
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_class = hashtab_search(state->base->p_classes.table, id);
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* If there is not an object class already in the base symtab that means
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * that either a) a module is trying to declare a new object class (which
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * the compiler should prevent) or b) an object class was required that is
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * not in the base.
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 */
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_class == NULL) {
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope =
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_search(state->cur->policy->p_classes_scope.table,
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   id);
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (scope == NULL) {
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = SEPOL_ERR;
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (scope->scope == SCOPE_DECL) {
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* disallow declarations in modules */
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Modules may not yet declare new classes.",
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name);
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = SEPOL_ENOTSUP;
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* It would be nice to error early here because the requirement is
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * not met, but we cannot because the decl might be optional (in which
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * case we should record the requirement so that it is just turned
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * off). Note: this will break horribly if modules can declare object
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * classes because the class numbers will be all wrong (i.e., they
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * might be assigned in the order they were required rather than the
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * current scheme which ensures correct numbering by ordering the
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * declarations properly). This can't be fixed until some infrastructure
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * for querying the object class numbers is in place. */
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->dest_class_req = 1;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_class =
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (class_datum_t *) calloc(1, sizeof(class_datum_t));
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_class == NULL) {
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Memory error\n");
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (symtab_init
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&new_class->permissions, PERM_SYMTAB_SIZE)) {
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_id = strdup(id);
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_id == NULL) {
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Memory error\n");
30292788715dc793f805b0ae56844216b844a34ea22Alice Chu				symtab_destroy(&new_class->permissions);
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = hashtab_insert(state->base->p_classes.table,
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     (hashtab_key_t) new_id,
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     (hashtab_datum_t) new_class);
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ret) {
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle,
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "could not insert new class into symtab");
31292788715dc793f805b0ae56844216b844a34ea22Alice Chu				symtab_destroy(&new_class->permissions);
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto err;
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_class->s.value = ++(state->base->p_classes.nprim);
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_CLASSES][cladatum->s.value - 1] =
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    new_class->s.value;
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy permissions */
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->src_class = cladatum;
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->dest_class = new_class;
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->dest_class_name = (char *)key;
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32709c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	/* copy default new object rules */
32809c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	ret = class_copy_default_new_object(state, cladatum, new_class);
32909c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris	if (ret)
33009c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris		return ret;
33109c783c9a36cd47216df827c5d2c21ec8cd613e2Eric Paris
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret =
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    hashtab_map(cladatum->permissions.table, permission_copy_callback,
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state);
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret != 0) {
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return ret;
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_class);
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role, *base_role, *new_role = NULL;
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role = (role_datum_t *) datum;
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_role = hashtab_search(state->base->p_roles.table, id);
357bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao	if (base_role != NULL) {
358bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		/* role already exists.  check that it is what this
359bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		 * module expected.  duplicate declarations (e.g., two
360bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		 * modules both declare role foo_r) is checked during
361bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		 * scope_copy_callback(). */
362bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		if (role->flavor == ROLE_ATTRIB
363bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		    && base_role->flavor != ROLE_ATTRIB) {
364bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			ERR(state->handle,
365bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			    "%s: Expected %s to be a role attribute, but it was already declared as a regular role.",
366bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			    state->cur_mod_name, id);
367bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			return -1;
368bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		} else if (role->flavor != ROLE_ATTRIB
369bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			   && base_role->flavor == ROLE_ATTRIB) {
370bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			ERR(state->handle,
371bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			    "%s: Expected %s to be a regular role, but it was already declared as a role attribute.",
372bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			    state->cur_mod_name, id);
373bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			return -1;
374bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		}
375bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao	} else {
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->verbose)
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			INFO(state->handle, "copying role %s", id);
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_role =
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (role_datum_t *) malloc(sizeof(*new_role))) == NULL) {
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_datum_init(new_role);
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
389bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		/* new_role's dominates, types and roles field will be copied
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * during role_fix_callback() */
391bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		new_role->flavor = role->flavor;
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role->s.value = state->base->p_roles.nprim + 1;
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->base->p_roles.table,
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_role);
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->p_roles.nprim++;
40113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_role = new_role;
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl) {
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = NULL;
40613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_role = malloc(sizeof(*new_role))) == NULL) {
40713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
40913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_datum_init(new_role);
410bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		new_role->flavor = base_role->flavor;
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_role->s.value = base_role->s.value;
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_insert
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->dest_decl->p_roles.table, new_id, new_role)) {
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->dest_decl->p_roles.nprim++;
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_ROLES][role->s.value - 1] = base_role->s.value;
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_destroy(new_role);
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_role);
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Copy types and attributes from a module into the base module. The
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * attributes are copied, but the types that make up this attribute
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * are delayed type_fix_callback(). */
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *base_type, *new_type = NULL;
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((type->flavor == TYPE_TYPE && !type->primary)
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || type->flavor == TYPE_ALIAS) {
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* aliases are handled later, in alias_copy_callback() */
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_type = hashtab_search(state->base->p_types.table, id);
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_type != NULL) {
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* type already exists.  check that it is what this
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * module expected.  duplicate declarations (e.g., two
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * modules both declare type foo_t) is checked during
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * scope_copy_callback(). */
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (type->flavor == TYPE_ATTRIB
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    && base_type->flavor != TYPE_ATTRIB) {
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Expected %s to be an attribute, but it was already declared as a type.",
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name, id);
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (type->flavor != TYPE_ATTRIB
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   && base_type->flavor == TYPE_ATTRIB) {
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Expected %s to be a type, but it was already declared as an attribute.",
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name, id);
46813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* permissive should pass to the base type */
47113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type->flags |= (type->flags & TYPE_FLAGS_PERMISSIVE);
47213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
47313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->verbose)
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			INFO(state->handle, "copying type %s", id);
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_type =
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->primary = type->primary;
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flags = type->flags;
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flavor = type->flavor;
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* for attributes, the writing of new_type->types is
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   done in type_fix_callback() */
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->s.value = state->base->p_types.nprim + 1;
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->base->p_types.table,
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_type);
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->p_types.nprim++;
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type = new_type;
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl) {
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = NULL;
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_type = calloc(1, sizeof(*new_type))) == NULL) {
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->primary = type->primary;
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flavor = type->flavor;
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flags = type->flags;
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->s.value = base_type->s.value;
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_insert
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->dest_decl->p_types.table, new_id, new_type)) {
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->dest_decl->p_types.nprim++;
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_TYPES][type->s.value - 1] = base_type->s.value;
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_type);
52813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
53013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
53213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
53313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
53413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
53513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
53613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user, *base_user, *new_user = NULL;
53713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
53813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user = (user_datum_t *) datum;
54013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_user = hashtab_search(state->base->p_users.table, id);
54213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_user == NULL) {
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->verbose)
54413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			INFO(state->handle, "copying user %s", id);
54513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
54713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
54813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
54913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_user =
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (user_datum_t *) malloc(sizeof(*new_user))) == NULL) {
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
55313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
55413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user_datum_init(new_user);
55513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* new_users's roles and MLS fields will be copied during
55613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		   user_fix_callback(). */
55713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user->s.value = state->base->p_users.nprim + 1;
55913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
56013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->base->p_users.table,
56113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
56213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_user);
56313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
56413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
56513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
56613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->p_users.nprim++;
56713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_user = new_user;
56813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
56913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
57013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl) {
57113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_id = NULL;
57213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_user = malloc(sizeof(*new_user))) == NULL) {
57313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
57413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
57513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user_datum_init(new_user);
57613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_user->s.value = base_user->s.value;
57713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
57813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
57913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
58013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_insert
58113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->dest_decl->p_users.table, new_id, new_user)) {
58213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
58313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
58413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->dest_decl->p_users.nprim++;
58513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
58613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
58713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_USERS][user->s.value - 1] = base_user->s.value;
58813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
58913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
59013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
59113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
59213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_destroy(new_user);
59313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
59413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_user);
59513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
59613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
59713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
59813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
59913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
60013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
60113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
60213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
60313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_bool_datum_t *booldatum, *base_bool, *new_bool = NULL;
60413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
6053df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle	scope_datum_t *scope;
60613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
60713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	booldatum = (cond_bool_datum_t *) datum;
60813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
60913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_bool = hashtab_search(state->base->p_bools.table, id);
61013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_bool == NULL) {
61113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->verbose)
61213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			INFO(state->handle, "copying boolean %s", id);
61313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
61513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
61613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
61713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_bool =
61913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (cond_bool_datum_t *) malloc(sizeof(*new_bool))) == NULL) {
62013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
62113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
62213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_bool->s.value = state->base->p_bools.nprim + 1;
62313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
62413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->base->p_bools.table,
62513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
62613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_bool);
62713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
62813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
62913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
63013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->p_bools.nprim++;
63113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_bool = new_bool;
632d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao		base_bool->flags = booldatum->flags;
633c046d974c5513c5bc1c29f964177e2fac4004544Thomas Hurd		base_bool->state = booldatum->state;
634d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao	} else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) !=
635d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao		   (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) {
636d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			/* A mismatch between boolean/tunable declaration
637d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			 * and usage(for example a boolean used in the
638d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			 * tunable_policy() or vice versa).
639d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			 *
640d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			 * This is not allowed and bail out with errors */
641d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			ERR(state->handle,
642d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			    "%s: Mismatch between boolean/tunable definition "
643d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			    "and usage for %s", state->cur_mod_name, id);
644d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao			return -1;
64513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
64613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6473df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle	/* Get the scope info for this boolean to see if this is the declaration,
6483df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle 	 * if so set the state */
6493df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle	scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
6503df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle	if (!scope)
6513df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle		return SEPOL_ERR;
652d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao	if (scope->scope == SCOPE_DECL) {
6533df79fc5ebf08a35aaa095b2ee3fd24b3ece6ae5Joshua Brindle		base_bool->state = booldatum->state;
654d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao		/* Only the declaration rather than requirement
655d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao		 * decides if it is a boolean or tunable. */
656d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao		base_bool->flags = booldatum->flags;
657d9d583759595e522a0ebfb56f74ee2a274d48d19Harry Ciao	}
65813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value;
65913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
66013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
66213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
66313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_destroy_bool(new_id, new_bool, NULL);
66413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
66513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
66613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
66813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      void *data)
66913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
67013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key;
67113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level_datum_t *level, *base_level;
67213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
67313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope;
67413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
67513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level = (level_datum_t *) datum;
67613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
67713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_level = hashtab_search(state->base->p_levels.table, id);
67813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!base_level) {
67913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope =
68013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_search(state->cur->policy->p_sens_scope.table, id);
68113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!scope)
68213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ERR;
68313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (scope->scope == SCOPE_DECL) {
68413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* disallow declarations in modules */
68513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
68613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Modules may not declare new sensitivities.",
68713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name);
68813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ENOTSUP;
689afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		} else if (scope->scope == SCOPE_REQ) {
69013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* unmet requirement */
69113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
69213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Sensitivity %s not declared by base.",
69313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name, id);
69413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ENOTSUP;
695afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		} else {
696afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			ERR(state->handle,
697afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			    "%s: has an unknown scope: %d\n",
698afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			    state->cur_mod_name, scope->scope);
699afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return SEPOL_ENOTSUP;
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_LEVELS][level->level->sens - 1] =
70413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    base_level->level->sens;
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
70913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
71013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     void *data)
71113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
71213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key;
71313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat_datum_t *cat, *base_cat;
71413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
71513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope;
71613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cat = (cat_datum_t *) datum;
71813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
71913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_cat = hashtab_search(state->base->p_cats.table, id);
72013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!base_cat) {
721afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		scope = hashtab_search(state->cur->policy->p_cat_scope.table, id);
72213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!scope)
72313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ERR;
72413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (scope->scope == SCOPE_DECL) {
72513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* disallow declarations in modules */
72613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
72713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Modules may not declare new categories.",
72813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name);
72913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ENOTSUP;
730afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		} else if (scope->scope == SCOPE_REQ) {
73113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* unmet requirement */
73213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
73313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Category %s not declared by base.",
73413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name, id);
73513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return SEPOL_ENOTSUP;
736afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		} else {
737afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			/* unknown scope?  malformed policy? */
738afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			ERR(state->handle,
739afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			    "%s: has an unknown scope: %d\n",
740afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			    state->cur_mod_name, scope->scope);
741afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return SEPOL_ENOTSUP;
74213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
74313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
74413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value;
74613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
74813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
74913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
75013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int (*copy_callback_f[SYM_NUM]) (hashtab_key_t key,
75113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					hashtab_datum_t datum, void *datap) = {
75213cd4c8960688af11ad23b4c946149015c80d54Joshua BrindleNULL, class_copy_callback, role_copy_callback, type_copy_callback,
75313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    user_copy_callback, bool_copy_callback, sens_copy_callback,
75413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    cat_copy_callback};
75513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
756f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle/*
757f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle * The boundaries have to be copied after the types/roles/users are copied,
758f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle * because it refers hashtab to lookup destinated objects.
759f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle */
760f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int type_bounds_copy_callback(hashtab_key_t key,
761f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
762f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
763f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	link_state_t *state = (link_state_t *) data;
764f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	type_datum_t *type = (type_datum_t *) datum;
765f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	type_datum_t *dest;
766f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
767f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
768f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!type->bounds)
769f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
770f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
771f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->cur->map[SYM_TYPES][type->bounds - 1];
772f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
773f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->base->p_types.table, key);
774f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
775f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
776f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "Type lookup failed for %s", (char *)key);
777f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
778f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
779f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
780f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
781f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "Inconsistent boundary for %s", (char *)key);
782f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
783f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
784f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
785f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
786f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
787f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
788f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
789f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int role_bounds_copy_callback(hashtab_key_t key,
790f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
791f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
792f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	link_state_t *state = (link_state_t *) data;
793f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	role_datum_t *role = (role_datum_t *) datum;
794f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	role_datum_t *dest;
795f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
796f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
797f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!role->bounds)
798f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
799f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
800f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->cur->map[SYM_ROLES][role->bounds - 1];
801f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
802f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->base->p_roles.table, key);
803f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
804f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
805f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "Role lookup failed for %s", (char *)key);
806f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
807f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
808f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
809f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
810f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "Inconsistent boundary for %s", (char *)key);
811f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
812f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
813f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
814f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
815f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
816f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
817f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
818f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindlestatic int user_bounds_copy_callback(hashtab_key_t key,
819f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle				     hashtab_datum_t datum, void *data)
820f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle{
821f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	link_state_t *state = (link_state_t *) data;
822f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	user_datum_t *user = (user_datum_t *) datum;
823f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	user_datum_t *dest;
824f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	uint32_t bounds_val;
825f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
826f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!user->bounds)
827f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return 0;
828f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
829f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	bounds_val = state->cur->map[SYM_USERS][user->bounds - 1];
830f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
831f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest = hashtab_search(state->base->p_users.table, key);
832f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (!dest) {
833f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
834f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "User lookup failed for %s", (char *)key);
835f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
836f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
837f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (dest->bounds != 0 && dest->bounds != bounds_val) {
838f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		ERR(state->handle,
839f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		    "Inconsistent boundary for %s", (char *)key);
840f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
841f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	}
842f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	dest->bounds = bounds_val;
843f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
844f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	return 0;
845f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle}
846f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* The aliases have to be copied after the types and attributes to be
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * certain that the base symbol table will have the type that the
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * alias refers. Otherwise, we won't be able to find the type value
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * for the alias. We can't depend on the declaration ordering because
85113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * of the hash table.
85213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
85613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL, *target_id;
85713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *base_type, *new_type = NULL, *target_type;
85813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *mod = state->cur;
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int primval;
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* there are 2 kinds of aliases. Ones with their own value (TYPE_ALIAS)
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * and ones with the value of their primary (TYPE_TYPE && type->primary = 0)
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 */
86613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (type->flavor == TYPE_ALIAS
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     || (type->flavor == TYPE_TYPE && !type->primary))) {
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* ignore types and attributes -- they were handled in
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * type_copy_callback() */
87113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
87213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor == TYPE_ALIAS)
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		primval = type->primary;
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		primval = type->s.value;
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	target_id = mod->policy->p_type_val_to_name[primval - 1];
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	target_type = hashtab_search(state->base->p_types.table, target_id);
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (target_type == NULL) {
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "%s: Could not find type %s for alias %s.",
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    state->cur_mod_name, target_id, id);
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
88513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!strcmp(id, target_id)) {
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "%s: Self aliasing of %s.",
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    state->cur_mod_name, id);
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	target_type->flags |= (type->flags & TYPE_FLAGS_PERMISSIVE);
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_type = hashtab_search(state->base->p_types.table, id);
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_type == NULL) {
89713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (state->verbose)
89813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			INFO(state->handle, "copying alias %s", id);
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_type =
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
90213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
90313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
90413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* the linked copy always has TYPE_ALIAS style aliases */
90513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->primary = target_type->s.value;
90613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flags = target_type->flags;
90713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->flavor = TYPE_ALIAS;
90813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_type->s.value = state->base->p_types.nprim + 1;
90913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
91013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
91113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
91213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_insert
91313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (state->base->p_types.table, new_id, new_type)) {
91413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->p_types.nprim++;
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type = new_type;
91813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* if this already exists and isn't an alias it was required by another module (or base)
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * and inserted into the hashtable as a type, fix it up now */
92213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (base_type->flavor == TYPE_ALIAS) {
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* error checking */
92513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(base_type->primary == target_type->s.value);
92613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(base_type->primary ==
92713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       mod->map[SYM_TYPES][primval - 1]);
92813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_TYPES][type->s.value - 1] ==
92913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       base_type->primary);
93013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
93113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
93213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (base_type->flavor == TYPE_ATTRIB) {
93413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
93513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s is an alias of an attribute, not allowed", id);
93613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
93713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
93813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type->flavor = TYPE_ALIAS;
94013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type->primary = target_type->s.value;
94113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_type->flags |= (target_type->flags & TYPE_FLAGS_PERMISSIVE);
94213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* the aliases map points from its value to its primary so when this module
94513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * references this type the value it gets back from the map is the primary */
94613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mod->map[SYM_TYPES][type->s.value - 1] = base_type->primary;
94713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
94813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
94913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
95113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
95213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_id);
95313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_type);
95413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
95513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
95613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*********** callbacks that fix bitmaps ***********/
95813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_set_convert(type_set_t * types, type_set_t * dst,
96013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    policy_module_t * mod, link_state_t * state
96113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    __attribute__ ((unused)))
96213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
96313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
96413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
96513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&types->types, tnode, i) {
96613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)) {
96713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_TYPES][i]);
96813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
96913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&dst->types, mod->map[SYM_TYPES][i] - 1, 1)) {
97013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
97113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
97213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
97313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
97413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&types->negset, tnode, i) {
97513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)) {
97613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_TYPES][i]);
97713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
97813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&dst->negset, mod->map[SYM_TYPES][i] - 1, 1)) {
97913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
98013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
98113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
98213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
98313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->flags = types->flags;
98413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
98513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
98613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
98713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
98813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
98913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* OR 2 typemaps together and at the same time map the src types to
99113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the correct values in the dst typeset.
99213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
99313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_set_or_convert(type_set_t * types, type_set_t * dst,
99413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       policy_module_t * mod, link_state_t * state)
99513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
99613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_t ts_tmp;
99713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_init(&ts_tmp);
99913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_convert(types, &ts_tmp, mod, state) == -1) {
100013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
100113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
100213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_or_eq(dst, &ts_tmp)) {
100313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
100413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
100513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_destroy(&ts_tmp);
100613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
100713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
100813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
100913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
101013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_set_destroy(&ts_tmp);
101113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
101213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
101313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
101413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_set_or_convert(role_set_t * roles, role_set_t * dst,
101513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       policy_module_t * mod, link_state_t * state)
101613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
101713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
101813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t tmp;
101913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *rnode;
102013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
102113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&tmp);
102213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&roles->roles, rnode, i) {
102313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(rnode, i)) {
102413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_ROLES][i]);
102513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
102613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&tmp, mod->map[SYM_ROLES][i] - 1, 1)) {
102713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
102813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
102913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
103013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
103113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&dst->roles, &tmp)) {
103213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
103313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
103413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->flags |= roles->flags;
103513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp);
103613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
103713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
103813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
103913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&tmp);
104013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
104113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
104213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst,
104413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     policy_module_t * mod, link_state_t * state)
104513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
104613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mls_semantic_cat_t *src_cat, *new_cat;
104713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
104813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!mod->policy->mls)
104913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
105013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Required not declared. */
105213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!src->sens)
105313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
105413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(mod->map[SYM_LEVELS][src->sens - 1]);
105613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dst->sens = mod->map[SYM_LEVELS][src->sens - 1];
105713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
105813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (src_cat = src->cat; src_cat; src_cat = src_cat->next) {
105913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_cat =
106013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
106113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_cat) {
106213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory");
106313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
106413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
106513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_semantic_cat_init(new_cat);
106613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
106713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_cat->next = dst->cat;
106813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dst->cat = new_cat;
106913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
107013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(mod->map[SYM_CATS][src_cat->low - 1]);
107113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1];
107213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		assert(mod->map[SYM_CATS][src_cat->high - 1]);
107313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1];
107413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
107513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
107613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
107713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
107813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
107913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * dst,
108013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     policy_module_t * mod, link_state_t * state)
108113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
108213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
108313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = mls_level_convert(&src->level[0], &dst->level[0], mod, state);
108413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
108513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return ret;
108613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = mls_level_convert(&src->level[1], &dst->level[1], mod, state);
108713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
108813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return ret;
108913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
109013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
109113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
109213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
109313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     void *data)
109413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
109513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
109613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key;
109713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_datum_t *role, *dest_role = NULL;
109813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
109913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t e_tmp;
110013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *mod = state->cur;
110113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *rnode;
110213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t role_tab;
110313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
110413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role = (role_datum_t *) datum;
110513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl == NULL)
110613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_tab = state->base->p_roles.table;
110713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
110813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_tab = state->dest_decl->p_roles.table;
110913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
111013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dest_role = hashtab_search(role_tab, id);
111113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(dest_role != NULL);
111213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
111313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose) {
111413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "fixing role %s", id);
111513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
111613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
111713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&e_tmp);
111813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&role->dominates, rnode, i) {
111913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(rnode, i)) {
112013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_ROLES][i]);
112113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
112213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) {
112313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
112413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
112513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
112613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
112713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&dest_role->dominates, &e_tmp)) {
112813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
112913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
113013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type_set_or_convert(&role->types, &dest_role->types, mod, state)) {
113113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
113213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
113313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&e_tmp);
1134bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao
1135bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao	if (role->flavor == ROLE_ATTRIB) {
1136bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		ebitmap_init(&e_tmp);
1137bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		ebitmap_for_each_bit(&role->roles, rnode, i) {
1138bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			if (ebitmap_node_get_bit(rnode, i)) {
1139bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao				assert(mod->map[SYM_ROLES][i]);
1140bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao				if (ebitmap_set_bit
1141bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao				    (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) {
1142bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao					goto cleanup;
1143bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao				}
1144bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			}
1145bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		}
1146bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		if (ebitmap_union(&dest_role->roles, &e_tmp)) {
1147bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao			goto cleanup;
1148bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		}
1149bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao		ebitmap_destroy(&e_tmp);
1150bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao	}
1151bff13595230dbd41692a98482ff3323078ae7d03Harry Ciao
115213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
115313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
115413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
115513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
115613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&e_tmp);
115713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
115813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
115913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
116013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
116113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     void *data)
116213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
116313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
116413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key;
116513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type_datum_t *type, *new_type = NULL;
116613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
116713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t e_tmp;
116813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *mod = state->cur;
116913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *tnode;
117013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	symtab_t *typetab;
117113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = (type_datum_t *) datum;
117313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl == NULL)
117513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		typetab = &state->base->p_types;
117613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
117713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		typetab = &state->dest_decl->p_types;
117813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* only fix attributes */
118013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (type->flavor != TYPE_ATTRIB) {
118113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
118213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_type = hashtab_search(typetab->table, id);
118513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(new_type != NULL && new_type->flavor == TYPE_ATTRIB);
118613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose) {
118813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "fixing attribute %s", id);
118913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
119013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_init(&e_tmp);
119213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_for_each_bit(&type->types, tnode, i) {
119313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ebitmap_node_get_bit(tnode, i)) {
119413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(mod->map[SYM_TYPES][i]);
119513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_set_bit
119613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (&e_tmp, mod->map[SYM_TYPES][i] - 1, 1)) {
119713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
119813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
119913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
120013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
120113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ebitmap_union(&new_type->types, &e_tmp)) {
120213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
120313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
120413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&e_tmp);
120513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
120613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
120713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
120813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
120913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_destroy(&e_tmp);
121013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
121113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
121213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
121413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     void *data)
121513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
121613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key;
121713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_datum_t *user, *new_user = NULL;
121813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
121913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t *mod = state->cur;
122013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	symtab_t *usertab;
122113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user = (user_datum_t *) datum;
122313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->dest_decl == NULL)
122513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		usertab = &state->base->p_users;
122613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
122713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		usertab = &state->dest_decl->p_users;
122813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_user = hashtab_search(usertab->table, id);
123013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(new_user != NULL);
123113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
123213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose) {
123313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "fixing user %s", id);
123413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
123513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
123613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (role_set_or_convert(&user->roles, &new_user->roles, mod, state)) {
123713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
123813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
123913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_range_convert(&user->range, &new_user->range, mod, state))
124113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
124213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod, state))
124413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
124513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
124713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
124913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
125013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
125113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
125213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
125313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int (*fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
125413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       void *datap) = {
125513cd4c8960688af11ad23b4c946149015c80d54Joshua BrindleNULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback,
125613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    NULL, NULL, NULL};
125713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
125813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*********** functions that copy AV rules ***********/
125913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_avrule_list(avrule_t * list, avrule_t ** dst,
126113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    policy_module_t * module, link_state_t * state)
126213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
126313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
126413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_t *cur, *new_rule = NULL, *tail;
126513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	class_perm_node_t *cur_perm, *new_perm, *tail_perm = NULL;
126613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail = *dst;
126813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (tail && tail->next) {
126913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = tail->next;
127013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
127113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
127213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = list;
127313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
127413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_rule = (avrule_t *) malloc(sizeof(avrule_t))) == NULL) {
127513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
127613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
127713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_init(new_rule);
127813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
127913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule->specified = cur->specified;
128013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule->flags = cur->flags;
128113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (type_set_convert
128213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (&cur->stypes, &new_rule->stypes, module, state) == -1
128313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || type_set_convert(&cur->ttypes, &new_rule->ttypes, module,
128413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state) == -1) {
128513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
128613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
128713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
128813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur_perm = cur->perms;
128913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail_perm = NULL;
129013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur_perm) {
129113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if ((new_perm = (class_perm_node_t *)
129213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     malloc(sizeof(class_perm_node_t))) == NULL) {
129313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
129413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
129513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_perm_node_init(new_perm);
129613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1297ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman			new_perm->tclass =
1298ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman			    module->map[SYM_CLASSES][cur_perm->tclass - 1];
1299ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman			assert(new_perm->tclass);
130013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
130113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_rule->specified & AVRULE_AV) {
130213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				for (i = 0;
130313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     i <
1304ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman				     module->perm_map_len[cur_perm->tclass - 1];
130513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     i++) {
130613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!(cur_perm->data & (1U << i)))
130713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
130813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					new_perm->data |=
130913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (1U <<
131013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     (module->
1311ed7a6ba24ad3241e696fa7bc9bb56bb4f373147bdcashman					      perm_map[cur_perm->tclass - 1][i] -
131213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      1));
131313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
131413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
131513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				new_perm->data =
131613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    module->map[SYM_TYPES][cur_perm->data - 1];
131713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
131813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
131913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_rule->perms == NULL) {
132013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				new_rule->perms = new_perm;
132113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
132292788715dc793f805b0ae56844216b844a34ea22Alice Chu				assert(tail_perm);
132313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				tail_perm->next = new_perm;
132413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
132513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail_perm = new_perm;
132613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur_perm = cur_perm->next;
132713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
132813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule->line = cur->line;
1329ef24ade029329a6e9981bd1de2ba7b9ea48e1c79Stephen Smalley		new_rule->source_line = cur->source_line;
1330a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley		if (cur->source_filename) {
1331a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley			new_rule->source_filename = strdup(cur->source_filename);
1332a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley			if (!new_rule->source_filename)
1333a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley				goto cleanup;
1334a80a48cb1907162b1fce8f0af38d062fca39a635Stephen Smalley		}
133513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
133613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
133713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
133813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*dst == NULL) {
133913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_rule;
134013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
134113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail->next = new_rule;
134213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
134313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = new_rule;
134413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
134513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
134613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
134713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
134813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
134913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_destroy(new_rule);
135013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_rule);
135113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
135213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
135313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
135413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_trans_list(role_trans_rule_t * list,
135513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				role_trans_rule_t ** dst,
135613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policy_module_t * module, link_state_t * state)
135713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
135813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_rule_t *cur, *new_rule = NULL, *tail;
13596db9b74210197f792a52038abbd10e946e99e49dHarry Ciao	unsigned int i;
13606db9b74210197f792a52038abbd10e946e99e49dHarry Ciao	ebitmap_node_t *cnode;
136113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
136213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = list;
136313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail = *dst;
136413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (tail && tail->next) {
136513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = tail->next;
136613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
136713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
136813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_rule =
136913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (role_trans_rule_t *) malloc(sizeof(role_trans_rule_t))) ==
137013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    NULL) {
137113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
137213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
137313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_trans_rule_init(new_rule);
137413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (role_set_or_convert
137613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (&cur->roles, &new_rule->roles, module, state)
137713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || type_set_or_convert(&cur->types, &new_rule->types,
137813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   module, state)) {
137913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
138013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
138113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13826db9b74210197f792a52038abbd10e946e99e49dHarry Ciao		ebitmap_for_each_bit(&cur->classes, cnode, i) {
13836db9b74210197f792a52038abbd10e946e99e49dHarry Ciao			if (ebitmap_node_get_bit(cnode, i)) {
13846db9b74210197f792a52038abbd10e946e99e49dHarry Ciao				assert(module->map[SYM_CLASSES][i]);
13856db9b74210197f792a52038abbd10e946e99e49dHarry Ciao				if (ebitmap_set_bit(&new_rule->classes,
13866db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						    module->
13876db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						    map[SYM_CLASSES][i] - 1,
13886db9b74210197f792a52038abbd10e946e99e49dHarry Ciao						    1)) {
13896db9b74210197f792a52038abbd10e946e99e49dHarry Ciao					goto cleanup;
13906db9b74210197f792a52038abbd10e946e99e49dHarry Ciao				}
13916db9b74210197f792a52038abbd10e946e99e49dHarry Ciao			}
13926db9b74210197f792a52038abbd10e946e99e49dHarry Ciao		}
13936db9b74210197f792a52038abbd10e946e99e49dHarry Ciao
139413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1];
139513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
139613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*dst == NULL) {
139713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_rule;
139813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
139913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail->next = new_rule;
140013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
140113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = new_rule;
140213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
140313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
140413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
140513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
140613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
140713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_trans_rule_list_destroy(new_rule);
140813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
140913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
141013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_role_allow_list(role_allow_rule_t * list,
141213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				role_allow_rule_t ** dst,
141313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policy_module_t * module, link_state_t * state)
141413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
141513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_rule_t *cur, *new_rule = NULL, *tail;
141613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
141713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = list;
141813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail = *dst;
141913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (tail && tail->next) {
142013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = tail->next;
142113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
142213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
142313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
142413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_rule =
142513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (role_allow_rule_t *) malloc(sizeof(role_allow_rule_t))) ==
142613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    NULL) {
142713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
142813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
142913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		role_allow_rule_init(new_rule);
143013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
143113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (role_set_or_convert
143213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (&cur->roles, &new_rule->roles, module, state)
143313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || role_set_or_convert(&cur->new_roles,
143413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   &new_rule->new_roles, module,
143513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   state)) {
143613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
143713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
143813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*dst == NULL) {
143913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_rule;
144013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
144113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail->next = new_rule;
144213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
144313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = new_rule;
144413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
144513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
144613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
144713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
144813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
144913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	role_allow_rule_list_destroy(new_rule);
145013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
145113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
145213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14536eeb71538ea29b639ac7549831cd1aa4da32722aEric Parisstatic int copy_filename_trans_list(filename_trans_rule_t * list,
14546eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				    filename_trans_rule_t ** dst,
14556eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				    policy_module_t * module,
14566eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				    link_state_t * state)
14576eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris{
14586eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	filename_trans_rule_t *cur, *new_rule, *tail;
14596eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14606eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	cur = list;
14616eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	tail = *dst;
14626eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	while (tail && tail->next)
14636eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		tail = tail->next;
14646eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14656eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	while (cur) {
14666eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		new_rule = malloc(sizeof(*new_rule));
14676eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (!new_rule)
14686eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			goto err;
14696eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14706eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		filename_trans_rule_init(new_rule);
14716eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14726eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (*dst == NULL)
14736eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			*dst = new_rule;
14746eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		else
14756eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			tail->next = new_rule;
14766eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		tail = new_rule;
14776eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14786eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		new_rule->name = strdup(cur->name);
14796eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (!new_rule->name)
14806eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			goto err;
14816eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14826eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module, state) ||
14836eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		    type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module, state))
14846eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris			goto err;
14856eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14866eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1];
14876eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		new_rule->otype = module->map[SYM_TYPES][cur->otype - 1];
14886eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
14896eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		cur = cur->next;
14906eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	}
14916eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	return 0;
14926eeb71538ea29b639ac7549831cd1aa4da32722aEric Pariserr:
14936eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	ERR(state->handle, "Out of memory!");
14946eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	return -1;
14956eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris}
14966eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
149713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_range_trans_list(range_trans_rule_t * rules,
149813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 range_trans_rule_t ** dst,
149913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				 policy_module_t * mod, link_state_t * state)
150013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
150113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_trans_rule_t *rule, *new_rule = NULL;
150213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
150313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *cnode;
150413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
150513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (rule = rules; rule; rule = rule->next) {
150613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule =
150713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t));
150813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_rule)
150913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
151013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
151113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		range_trans_rule_init(new_rule);
151213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
151313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_rule->next = *dst;
151413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*dst = new_rule;
151513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
151613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (type_set_convert(&rule->stypes, &new_rule->stypes,
151713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     mod, state))
151813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
151913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
152013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (type_set_convert(&rule->ttypes, &new_rule->ttypes,
152113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     mod, state))
152213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
152313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
152413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(&rule->tclasses, cnode, i) {
152513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_node_get_bit(cnode, i)) {
152613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(mod->map[SYM_CLASSES][i]);
152713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit
152813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (&new_rule->tclasses,
152913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     mod->map[SYM_CLASSES][i] - 1, 1)) {
153013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto cleanup;
153113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
153213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
153313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
153413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
153513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state))
153613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
153713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
153813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
153913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
154013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
154113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
154213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	range_trans_rule_list_destroy(new_rule);
154313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
154413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
154513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
154613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_cond_list(cond_node_t * list, cond_node_t ** dst,
154713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  policy_module_t * module, link_state_t * state)
154813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
154913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned i;
155013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_t *cur, *new_node = NULL, *tail;
155113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_expr_t *cur_expr;
155213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tail = *dst;
155313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (tail && tail->next)
155413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = tail->next;
155513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
155613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = list;
155713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur) {
155813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_node = (cond_node_t *) malloc(sizeof(cond_node_t));
155913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_node) {
156013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
156113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
156213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(new_node, 0, sizeof(cond_node_t));
156313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
156413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_node->cur_state = cur->cur_state;
156513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_node->expr = cond_copy_expr(cur->expr);
156613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!new_node->expr)
156713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
156813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* go back through and remap the expression */
156913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (cur_expr = new_node->expr; cur_expr != NULL;
157013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     cur_expr = cur_expr->next) {
157113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* expression nodes don't have a bool value of 0 - don't map them */
157213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (cur_expr->expr_type != COND_BOOL)
157313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
157413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(module->map[SYM_BOOLS][cur_expr->bool - 1] != 0);
157513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur_expr->bool =
157613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    module->map[SYM_BOOLS][cur_expr->bool - 1];
157713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
157813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_node->nbools = cur->nbools;
157913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* FIXME should COND_MAX_BOOLS be used here? */
158013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < min(cur->nbools, COND_MAX_BOOLS); i++) {
158113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			uint32_t remapped_id =
158213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    module->map[SYM_BOOLS][cur->bool_ids[i] - 1];
158313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(remapped_id != 0);
158413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_node->bool_ids[i] = remapped_id;
158513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
158613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_node->expr_pre_comp = cur->expr_pre_comp;
158713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
158813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_avrule_list
158913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (cur->avtrue_list, &new_node->avtrue_list, module, state)
159013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || copy_avrule_list(cur->avfalse_list,
159113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					&new_node->avfalse_list, module,
159213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state)) {
159313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
159413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
159513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
159613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*dst == NULL) {
159713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*dst = new_node;
159813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
159913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			tail->next = new_node;
160013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
160113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		tail = new_node;
160213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
160313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
160413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
160513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
160613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
160713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cond_node_destroy(new_node);
160813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(new_node);
160913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
161013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
161213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*********** functions that copy avrule_decls from module to base ***********/
161413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
161513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_identifiers(link_state_t * state, symtab_t * src_symtab,
161613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    avrule_decl_t * dest_decl)
161713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
161813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i, ret;
161913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
162013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->dest_decl = dest_decl;
162113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
162213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_callback_f[i] != NULL) {
162313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret =
162413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    hashtab_map(src_symtab[i].table, copy_callback_f[i],
162513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					state);
162613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ret) {
162713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return ret;
162813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
162913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
163013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
163113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1632f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(src_symtab[SYM_TYPES].table,
1633f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			type_bounds_copy_callback, state))
1634f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
1635f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
1636f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(src_symtab[SYM_TYPES].table,
1637f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			alias_copy_callback, state))
1638f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
1639f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
1640f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(src_symtab[SYM_ROLES].table,
1641f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			role_bounds_copy_callback, state))
1642f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle		return -1;
1643f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle
1644f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle	if (hashtab_map(src_symtab[SYM_USERS].table,
1645f470207454f5f6ce539aa543e5168a07d667254bJoshua Brindle			user_bounds_copy_callback, state))
164613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
164713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
164813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then fix bitmaps associated with those newly copied identifiers */
164913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
165013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fix_callback_f[i] != NULL &&
165113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_map(src_symtab[i].table, fix_callback_f[i],
165213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				state)) {
165313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
165413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
165513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
165613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
165713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
165813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
165913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_scope_index(scope_index_t * src, scope_index_t * dest,
166013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    policy_module_t * module, link_state_t * state)
166113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
166213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
166313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t largest_mapped_class_value = 0;
166413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *node;
166513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy the scoping information for this avrule decl block */
166613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
166713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_t *srcmap = src->scope + i;
166813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_t *destmap = dest->scope + i;
166913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (copy_callback_f[i] == NULL) {
167013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
167113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
167213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(srcmap, node, j) {
167313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_node_get_bit(node, j)) {
167413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				assert(module->map[i][j] != 0);
167513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (ebitmap_set_bit
167613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    (destmap, module->map[i][j] - 1, 1) != 0) {
167713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
167813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto cleanup;
167913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
168013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (i == SYM_CLASSES &&
168113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    largest_mapped_class_value <
168213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    module->map[SYM_CLASSES][j]) {
168313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					largest_mapped_class_value =
168413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    module->map[SYM_CLASSES][j];
168513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
168613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
168713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
168813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
168913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
169013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* next copy the enabled permissions data  */
169113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((dest->class_perms_map = malloc(largest_mapped_class_value *
169213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    sizeof(*dest->class_perms_map))) ==
169313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    NULL) {
169413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
169513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
169613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < largest_mapped_class_value; i++) {
169713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_init(dest->class_perms_map + i);
169813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
169913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	dest->class_perms_len = largest_mapped_class_value;
170013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < src->class_perms_len; i++) {
170113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_t *srcmap = src->class_perms_map + i;
170213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_t *destmap =
170313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    dest->class_perms_map + module->map[SYM_CLASSES][i] - 1;
170413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(srcmap, node, j) {
170513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (ebitmap_node_get_bit(node, j) &&
170613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    ebitmap_set_bit(destmap, module->perm_map[i][j] - 1,
170713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    1)) {
170813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
170913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
171013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
171113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
171213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
171313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
171413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
171513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
171613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
171713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
171813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
171913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
172013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_avrule_decl(link_state_t * state, policy_module_t * module,
172113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    avrule_decl_t * src_decl, avrule_decl_t * dest_decl)
172213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
172313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
172413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
172513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy all of the RBAC and TE rules */
172613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (copy_avrule_list
172713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (src_decl->avrules, &dest_decl->avrules, module, state) == -1
172813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || copy_role_trans_list(src_decl->role_tr_rules,
172913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    &dest_decl->role_tr_rules, module,
173013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    state) == -1
173113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || copy_role_allow_list(src_decl->role_allow_rules,
173213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    &dest_decl->role_allow_rules, module,
173313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    state) == -1
173413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || copy_cond_list(src_decl->cond_list, &dest_decl->cond_list,
173513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      module, state) == -1) {
173613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
173713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
173813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17396eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris	if (copy_filename_trans_list(src_decl->filename_trans_rules,
17406eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				     &dest_decl->filename_trans_rules,
17416eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris				     module, state))
17426eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris		return -1;
17436eeb71538ea29b639ac7549831cd1aa4da32722aEric Paris
174413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (copy_range_trans_list(src_decl->range_tr_rules,
174513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				  &dest_decl->range_tr_rules, module, state))
174613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
174713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
174813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* finally copy any identifiers local to this declaration */
174913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = copy_identifiers(state, src_decl->symtab, dest_decl);
175013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret < 0) {
175113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return ret;
175213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
175313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
175413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then copy required and declared scope indices here */
175513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (copy_scope_index(&src_decl->required, &dest_decl->required,
175613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     module, state) == -1 ||
175713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    copy_scope_index(&src_decl->declared, &dest_decl->declared,
175813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     module, state) == -1) {
175913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
176013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
176113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
176213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
176313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
176413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
176513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_avrule_block(link_state_t * state, policy_module_t * module,
176613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     avrule_block_t * block)
176713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
176813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *new_block = avrule_block_create();
176913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl, *last_decl = NULL;
177013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
177113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
177213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (new_block == NULL) {
177313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
177413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = -1;
177513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
177613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
177713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
177813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	new_block->flags = block->flags;
177913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (decl = block->branch_list; decl != NULL; decl = decl->next) {
178113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *new_decl =
178213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    avrule_decl_create(state->next_decl_id);
178313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (new_decl == NULL) {
178413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
178513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = -1;
178613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
178713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
178813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
178913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (module->policy->name != NULL) {
179013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_decl->module_name = strdup(module->policy->name);
179113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (new_decl->module_name == NULL) {
179213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle, "Out of memory\n");
179392788715dc793f805b0ae56844216b844a34ea22Alice Chu				avrule_decl_destroy(new_decl);
179413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = -1;
179513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
179613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
179713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
179813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
179913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (last_decl == NULL) {
180013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			new_block->branch_list = new_decl;
180113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
180213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			last_decl->next = new_decl;
180313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
180413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		last_decl = new_decl;
180513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->base->decl_val_to_struct[state->next_decl_id - 1] =
180613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    new_decl;
180713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->decl_to_mod[state->next_decl_id] = module->policy;
180813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
180913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		module->avdecl_map[decl->decl_id] = new_decl->decl_id;
181013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
181113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = copy_avrule_decl(state, module, decl, new_decl);
181213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
181392788715dc793f805b0ae56844216b844a34ea22Alice Chu			avrule_decl_destroy(new_decl);
181413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
181513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
181613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
181713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->next_decl_id++;
181813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
181913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->last_avrule_block->next = new_block;
182013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->last_avrule_block = new_block;
182113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
182213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
182313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
182413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_list_destroy(new_block);
182513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
182613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
182713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
182813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
182913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       void *data)
183013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
183113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
183213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
183313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id = key, *new_id = NULL;
183413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope, *base_scope;
183513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t *state = (link_state_t *) data;
183613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t symbol_num = state->symbol_num;
183713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *avdecl_map = state->cur->avdecl_map;
183813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
183913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope = (scope_datum_t *) datum;
184013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
184113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check if the base already has a scope entry */
184213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_scope = hashtab_search(state->base->scope[symbol_num].table, id);
184313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_scope == NULL) {
184413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		scope_datum_t *new_scope;
184513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_id = strdup(id)) == NULL) {
184613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
184713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
184813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
184913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((new_scope =
185013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (scope_datum_t *) calloc(1, sizeof(*new_scope))) == NULL) {
185113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
185213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
185313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
185413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = hashtab_insert(state->base->scope[symbol_num].table,
185513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_key_t) new_id,
185613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     (hashtab_datum_t) new_scope);
185713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
185813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_id);
185913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(new_scope);
186013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
186113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
186213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_scope->scope = SCOPE_REQ;	/* this is reset further down */
186313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_scope = new_scope;
186413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
186513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_DECL) {
186613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this module declared symbol, so overwrite the old
186713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * list with the new decl ids */
186813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_scope->scope = SCOPE_DECL;
186913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(base_scope->decl_ids);
187013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_scope->decl_ids = NULL;
187113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_scope->decl_ids_len = 0;
187213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < scope->decl_ids_len; i++) {
187313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
187413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids_len,
187513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids) == -1) {
187613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
187713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
187813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
187913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (base_scope->scope == SCOPE_DECL && scope->scope == SCOPE_REQ) {
188013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this module depended on a symbol that now exists,
188113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * so don't do anything */
188213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_REQ) {
188313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* symbol is still required, so add to the list */
188413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < scope->decl_ids_len; i++) {
188513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
188613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids_len,
188713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids) == -1) {
188813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
188913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
189013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
189113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
189213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* this module declared a symbol, and it was already
189313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * declared.  only roles and users may be multiply
189413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 * declared; for all others this is an error. */
189513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (symbol_num != SYM_ROLES && symbol_num != SYM_USERS) {
189613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle,
189713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%s: Duplicate declaration in module: %s %s",
189813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    state->cur_mod_name,
189913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    symtab_names[state->symbol_num], id);
190013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
190113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
190213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (i = 0; i < scope->decl_ids_len; i++) {
190313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
190413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids_len,
190513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       &base_scope->decl_ids) == -1) {
190613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
190713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
190813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
190913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
191013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
191113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
191313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(state->handle, "Out of memory!");
191413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
191513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
191613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
191713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Copy a module over to a base, remapping all values within.  After
191813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * all identifiers and rules are done, copy the scoping information.
191913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This is when it checks for duplicate declarations. */
192013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int copy_module(link_state_t * state, policy_module_t * module)
192113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
192213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i, ret;
192313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *cur;
192413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur = module;
192513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->cur_mod_name = module->policy->name;
192613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
192713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* first copy all of the identifiers */
192813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = copy_identifiers(state, module->policy->symtab, NULL);
192913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
193013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return ret;
193113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
193213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
193313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* next copy all of the avrule blocks */
193413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cur = module->policy->global; cur != NULL; cur = cur->next) {
193513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = copy_avrule_block(state, module, cur);
193613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
193713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return ret;
193813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
193913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
194013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
194113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then copy the scoping tables */
194213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
194313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->symbol_num = i;
194413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (hashtab_map
194513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (module->policy->scope[i].table, scope_copy_callback,
194613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     state)) {
194713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
194813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
194913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
195013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
195213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
195313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/***** functions that check requirements and enable blocks in a module ******/
195513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* borrowed from checkpolicy.c */
195713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
195813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestruct find_perm_arg {
195913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int valuep;
196013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_key_t key;
196113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
196213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
196313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg)
196413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
196513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
196613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct find_perm_arg *arg = varg;
196713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
196813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	perm_datum_t *perdatum = (perm_datum_t *) datum;
196913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (arg->valuep == perdatum->s.value) {
197013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		arg->key = key;
197113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 1;
197213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
197313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
197513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
197613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
197713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Check if the requirements are met for a single declaration.  If all
197813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * are met return 1.  For the first requirement found to be missing,
197913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * if 'missing_sym_num' and 'missing_value' are both not NULL then
198013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * write to them the symbol number and value for the missing
198113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * declaration.  Then return 0 to indicate a missing declaration.
198213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Note that if a declaration had no requirement at all (e.g., an ELSE
198313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * block) this returns 1. */
198413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int is_decl_requires_met(link_state_t * state,
198513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				avrule_decl_t * decl,
198613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				struct missing_requirement *req)
198713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
198813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* (This algorithm is very unoptimized.  It performs many
198913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * redundant checks.  A very obvious improvement is to cache
199013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * which symbols have been verified, so that they do not need
199113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * to be re-checked.) */
199213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
199313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *bitmap;
199413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id, *perm_id;
199513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *pol = state->base;
199613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *node;
199713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
199813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check that all symbols have been satisfied */
199913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
200013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (i == SYM_CLASSES) {
200113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* classes will be checked during permissions
200213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * checking phase below */
200313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
200413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
200513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		bitmap = &decl->required.scope[i];
200613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(bitmap, node, j) {
200713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(node, j)) {
200813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
200913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
201013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
201113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* check base's scope table */
201213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			id = pol->sym_val_to_name[i][j];
201313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!is_id_enabled(id, state->base, i)) {
201413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				/* this symbol was not found */
201513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (req != NULL) {
201613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req->symbol_type = i;
201713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req->symbol_value = j + 1;
201813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
201913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return 0;
202013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
202113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
202213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
202313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check that all classes and permissions have been satisfied */
202413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < decl->required.class_perms_len; i++) {
202513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
202613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		bitmap = decl->required.class_perms_map + i;
202713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ebitmap_for_each_bit(bitmap, node, j) {
202813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			struct find_perm_arg fparg;
202913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			class_datum_t *cladatum;
203013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			uint32_t perm_value = j + 1;
2031afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			int rc;
203213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			scope_datum_t *scope;
203313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
203413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!ebitmap_node_get_bit(node, j)) {
203513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
203613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
203713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			id = pol->p_class_val_to_name[i];
203813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cladatum = pol->class_val_to_struct[i];
203913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
204013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			scope =
204113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    hashtab_search(state->base->p_classes_scope.table,
204213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   id);
204313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (scope == NULL) {
204413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state->handle,
204513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "Could not find scope information for class %s",
204613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    id);
204713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
204813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
204913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
205013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fparg.valuep = perm_value;
205113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fparg.key = NULL;
205213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2053afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			(void)hashtab_map(cladatum->permissions.table, find_perm,
205413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    &fparg);
2055afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			if (fparg.key == NULL && cladatum->comdatum != NULL) {
2056afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris				rc = hashtab_map(cladatum->comdatum->permissions.table,
2057afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris						 find_perm, &fparg);
2058afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris				assert(rc == 1);
2059afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			}
206013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			perm_id = fparg.key;
206113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
206213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(perm_id != NULL);
206313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!is_perm_enabled(id, perm_id, state->base)) {
206413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (req != NULL) {
206513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req->symbol_type = SYM_CLASSES;
206613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req->symbol_value = i + 1;
206713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req->perm_value = perm_value;
206813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
206913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return 0;
207013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
207113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
207213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
207313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* all requirements have been met */
207513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 1;
207613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
207713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
207813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int debug_requirements(link_state_t * state, policydb_t * p)
207913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
208013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
208113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *cur;
208213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	missing_requirement_t req;
2083afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	memset(&req, 0, sizeof(req));
208413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
208513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cur = p->global; cur != NULL; cur = cur->next) {
208613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (cur->enabled != NULL)
208713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
208813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
208913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = is_decl_requires_met(state, cur->branch_list, &req);
209013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret < 0) {
209113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return ret;
209213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else if (ret == 0) {
209314c0564641e6c8be386f117c2b0f09434121226fNicolas Iooss			const char *mod_name = cur->branch_list->module_name ?
209413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    cur->branch_list->module_name : "BASE";
209513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (req.symbol_type == SYM_CLASSES) {
209613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				struct find_perm_arg fparg;
209713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
209813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				class_datum_t *cladatum;
2099afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris				cladatum = p->class_val_to_struct[req.symbol_value - 1];
210013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				fparg.valuep = req.perm_value;
210213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				fparg.key = NULL;
2103afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris				(void)hashtab_map(cladatum->permissions.table,
2104afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris						  find_perm, &fparg);
210513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
210613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur->flags & AVRULE_OPTIONAL) {
210713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
210813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "%s[%d]'s optional requirements were not met: class %s, permission %s",
210913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    mod_name, cur->branch_list->decl_id,
2110afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris					    p->p_class_val_to_name[req.symbol_value - 1],
211113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    fparg.key);
211213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
211313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
211413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "%s[%d]'s global requirements were not met: class %s, permission %s",
211513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    mod_name, cur->branch_list->decl_id,
2116afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris					    p->p_class_val_to_name[req.symbol_value - 1],
211713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    fparg.key);
211813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
211913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
212013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cur->flags & AVRULE_OPTIONAL) {
212113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
212213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "%s[%d]'s optional requirements were not met: %s %s",
212313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    mod_name, cur->branch_list->decl_id,
212413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    symtab_names[req.symbol_type],
212513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    p->sym_val_to_name[req.
212613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       symbol_type][req.
212713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    symbol_value
212813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    -
212913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    1]);
213013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				} else {
213113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ERR(state->handle,
213213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    "%s[%d]'s global requirements were not met: %s %s",
213313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    mod_name, cur->branch_list->decl_id,
213413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    symtab_names[req.symbol_type],
213513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    p->sym_val_to_name[req.
213613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       symbol_type][req.
213713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    symbol_value
213813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    -
213913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									    1]);
214013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
214113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
214213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
214313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
214413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
214513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
214613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
214713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void print_missing_requirements(link_state_t * state,
214813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       avrule_block_t * cur,
214913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       missing_requirement_t * req)
215013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
215113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p = state->base;
215214c0564641e6c8be386f117c2b0f09434121226fNicolas Iooss	const char *mod_name = cur->branch_list->module_name ?
215313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    cur->branch_list->module_name : "BASE";
215413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (req->symbol_type == SYM_CLASSES) {
215613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		struct find_perm_arg fparg;
215813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
215913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		class_datum_t *cladatum;
216013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cladatum = p->class_val_to_struct[req->symbol_value - 1];
216113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
216213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fparg.valuep = req->perm_value;
216313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fparg.key = NULL;
2164afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		(void)hashtab_map(cladatum->permissions.table, find_perm, &fparg);
216513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
216613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle,
216713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "%s's global requirements were not met: class %s, permission %s",
216813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    mod_name,
216913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    p->p_class_val_to_name[req->symbol_value - 1], fparg.key);
217013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
217113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle,
217213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "%s's global requirements were not met: %s %s",
217313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    mod_name,
217413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    symtab_names[req->symbol_type],
2175afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		    p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]);
217613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
217713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
217813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
217913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Enable all of the avrule_decl blocks for the policy. This simple
218013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * algorithm is the following:
218113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
218213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 1) Enable all of the non-else avrule_decls for all blocks.
218313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 2) Iterate through the non-else decls looking for decls whose requirements
218413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    are not met.
218513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    2a) If the decl is non-optional, return immediately with an error.
218613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    2b) If the decl is optional, disable the block and mark changed = 1
218713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 3) If changed == 1 goto 2.
218813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 4) Iterate through all blocks looking for those that have no enabled
218913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *    decl. If the block has an else decl, enable.
219013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
219113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This will correctly handle all dependencies, including mutual and
219213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * cicular. The only downside is that it is slow.
219313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
219413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int enable_avrules(link_state_t * state, policydb_t * pol)
219513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
219613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int changed = 1;
219713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *block;
219813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl;
219913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	missing_requirement_t req;
220013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret = 0, rc;
220113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
220213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose) {
220313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		INFO(state->handle, "Determining which avrules to enable.");
220413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
220513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
220613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* 1) enable all of the non-else blocks */
220713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (block = pol->global; block != NULL; block = block->next) {
220813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		block->enabled = block->branch_list;
220913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		block->enabled->enabled = 1;
221013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (decl = block->branch_list->next; decl != NULL;
221113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     decl = decl->next)
221213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			decl->enabled = 0;
221313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
221413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
221513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* 2) Iterate */
221613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (changed) {
221713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		changed = 0;
221813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (block = pol->global; block != NULL; block = block->next) {
221913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (block->enabled == NULL) {
222013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				continue;
222113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
222213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			decl = block->branch_list;
222313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (state->verbose) {
222414c0564641e6c8be386f117c2b0f09434121226fNicolas Iooss				const char *mod_name = decl->module_name ?
222513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    decl->module_name : "BASE";
222613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				INFO(state->handle, "check module %s decl %d\n",
222713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     mod_name, decl->decl_id);
222813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
222913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = is_decl_requires_met(state, decl, &req);
223013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
223113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ret = SEPOL_ERR;
223213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto out;
223313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (rc == 0) {
223413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				decl->enabled = 0;
223513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				block->enabled = NULL;
223613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				changed = 1;
223713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!(block->flags & AVRULE_OPTIONAL)) {
223813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					print_missing_requirements(state, block,
223913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								   &req);
224013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ret = SEPOL_EREQ;
224113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto out;
224213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
224313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
224413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
224513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
224613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
224713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* 4) else handling
224813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 *
224913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * Iterate through all of the blocks skipping the first (which is the
225013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * global block, is required to be present, and cannot have an else).
225113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * If the block is disabled and has an else decl, enable that.
225213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 *
225313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * This code assumes that the second block in the branch list is the else
225413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * block. This is currently supported by the compiler.
225513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 */
225613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (block = pol->global->next; block != NULL; block = block->next) {
225713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (block->enabled == NULL) {
225813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (block->branch_list->next != NULL) {
225913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				block->enabled = block->branch_list->next;
226013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				block->branch_list->next->enabled = 1;
226113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
226213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
226313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
226413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
226513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
226613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (state->verbose)
226713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		debug_requirements(state, pol);
226813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
226913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
227013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
227113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*********** the main linking functions ***********/
227313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
227413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Given a module's policy, normalize all conditional expressions
227513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * within.  Return 0 on success, -1 on error. */
227613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int cond_normalize(policydb_t * p)
227713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
227813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *block;
227913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (block = p->global; block != NULL; block = block->next) {
228013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl;
228113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (decl = block->branch_list; decl != NULL; decl = decl->next) {
228213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cond_list_t *cond = decl->cond_list;
228313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			while (cond) {
228413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (cond_normalize_expr(p, cond) < 0)
228513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return -1;
228613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cond = cond->next;
228713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
228813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
228913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
229013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
229113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
229213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
229313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Allocate space for the various remapping arrays. */
229413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int prepare_module(link_state_t * state, policy_module_t * module)
229513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
229613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;
229713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t items, num_decls = 0;
229813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *cur;
229913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
230013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* allocate the maps */
230113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < SYM_NUM; i++) {
230213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		items = module->policy->symtab[i].nprim;
230313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((module->map[i] =
230413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (uint32_t *) calloc(items,
230513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					 sizeof(*module->map[i]))) == NULL) {
230613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state->handle, "Out of memory!");
230713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
230813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
230913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
231013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
231113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* allocate the permissions remap here */
231213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	items = module->policy->p_classes.nprim;
231313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((module->perm_map_len =
231413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     calloc(items, sizeof(*module->perm_map_len))) == NULL) {
231513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
231613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
231713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
231813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((module->perm_map =
231913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     calloc(items, sizeof(*module->perm_map))) == NULL) {
232013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
232113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
232213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
232313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
232413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* allocate a map for avrule_decls */
232513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (cur = module->policy->global; cur != NULL; cur = cur->next) {
232613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl;
232713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
232813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (decl->decl_id > num_decls) {
232913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				num_decls = decl->decl_id;
233013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
233113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
233213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
233313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	num_decls++;
233413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((module->avdecl_map = calloc(num_decls, sizeof(uint32_t))) == NULL) {
233513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
233613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
233713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
233813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	module->num_decls = num_decls;
233913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
234013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* normalize conditionals within */
234113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize(module->policy) < 0) {
234213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle,
234313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "Error while normalizing conditionals within the module %s.",
234413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    module->policy->name);
234513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
234613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
234713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
234813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
234913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
235013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int prepare_base(link_state_t * state, uint32_t num_mod_decls)
235113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
235213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *cur = state->base->global;
235313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(cur != NULL);
235413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->next_decl_id = 0;
235513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
235613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* iterate through all of the declarations in the base, to
235713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   determine what the next decl_id should be */
235813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur != NULL) {
235913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl;
236013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
236113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (decl->decl_id > state->next_decl_id) {
236213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				state->next_decl_id = decl->decl_id;
236313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
236413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
236513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state->last_avrule_block = cur;
236613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
236713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
236813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->last_base_avrule_block = state->last_avrule_block;
236913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state->next_decl_id++;
237013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
237113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* allocate the table mapping from base's decl_id to its
237213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * avrule_decls and set the initial mappings */
237313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state->base->decl_val_to_struct);
237413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((state->base->decl_val_to_struct =
237513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     calloc(state->next_decl_id + num_mod_decls,
237613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    sizeof(*(state->base->decl_val_to_struct)))) == NULL) {
237713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
237813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
237913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
238013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* This allocates the decl block to module mapping used for error reporting */
238113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((state->decl_to_mod = calloc(state->next_decl_id + num_mod_decls,
238213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					 sizeof(*(state->decl_to_mod)))) ==
238313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    NULL) {
238413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle, "Out of memory!");
238513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
238613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
238713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cur = state->base->global;
238813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (cur != NULL) {
238913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		avrule_decl_t *decl = cur->branch_list;
239013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (decl != NULL) {
239113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->base->decl_val_to_struct[decl->decl_id - 1] =
239213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    decl;
239313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			state->decl_to_mod[decl->decl_id] = state->base;
239413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			decl = decl->next;
239513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
239613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = cur->next;
239713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
239813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
239913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* normalize conditionals within */
240013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (cond_normalize(state->base) < 0) {
240113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state->handle,
240213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "Error while normalizing conditionals within the base module.");
240313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
240413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
240513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
240613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
240713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2408c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciaostatic int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum,
2409c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				  void * data)
2410c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao{
2411c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	char *id;
2412c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	role_datum_t *role, *sub_attr;
2413c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	link_state_t *state;
2414c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	unsigned int i;
2415c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	ebitmap_node_t *rnode;
2416c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2417c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	id = key;
2418c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	role = (role_datum_t *)datum;
2419c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	state = (link_state_t *)data;
2420c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2421c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (strcmp(id, OBJECT_R) == 0){
2422c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		/* object_r is never a role attribute by far */
2423c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		return 0;
2424c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2425c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2426c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (role->flavor != ROLE_ATTRIB)
2427c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		return 0;
2428c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2429c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (state->verbose)
2430c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		INFO(state->handle, "expanding role attribute %s", id);
2431c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2432c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciaorestart:
2433c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	ebitmap_for_each_bit(&role->roles, rnode, i) {
2434c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		if (ebitmap_node_get_bit(rnode, i)) {
2435c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			sub_attr = state->base->role_val_to_struct[i];
2436c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			if (sub_attr->flavor != ROLE_ATTRIB)
2437c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				continue;
2438c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2439c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			/* remove the sub role attribute from the parent
2440c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			 * role attribute's roles ebitmap */
2441c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			if (ebitmap_set_bit(&role->roles, i, 0))
2442c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				return -1;
2443c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2444c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			/* loop dependency of role attributes */
2445c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			if (sub_attr->s.value == role->s.value)
2446c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				continue;
2447c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2448c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			/* now go on to expand a sub role attribute
2449c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			 * by escalating its roles ebitmap */
2450c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			if (ebitmap_union(&role->roles, &sub_attr->roles)) {
2451c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				ERR(state->handle, "Out of memory!");
2452c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				return -1;
2453c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			}
2454c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2455c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			/* sub_attr->roles may contain other role attributes,
2456c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			 * re-scan the parent role attribute's roles ebitmap */
2457c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			goto restart;
2458c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		}
2459c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2460c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2461c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	return 0;
2462c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao}
2463c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2464c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao/* For any role attribute in a declaration's local symtab[SYM_ROLES] table,
2465c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao * copy its roles ebitmap into its duplicate's in the base->p_roles.table.
2466c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao */
2467c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciaostatic int populate_decl_roleattributes(hashtab_key_t key,
2468c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao					hashtab_datum_t datum,
2469c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao					void *data)
2470c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao{
2471c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	char *id = key;
2472c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	role_datum_t *decl_role, *base_role;
2473c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	link_state_t *state = (link_state_t *)data;
2474c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2475c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	decl_role = (role_datum_t *)datum;
2476c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2477c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (strcmp(id, OBJECT_R) == 0) {
2478c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		/* object_r is never a role attribute by far */
2479c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		return 0;
2480c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2481c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2482c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (decl_role->flavor != ROLE_ATTRIB)
2483c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		return 0;
2484c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2485c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table,
2486c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao						   id);
2487c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB);
2488c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2489c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (ebitmap_union(&base_role->roles, &decl_role->roles)) {
2490c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		ERR(state->handle, "Out of memory!");
2491c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		return -1;
2492c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2493c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2494c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	return 0;
2495c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao}
2496c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2497c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciaostatic int populate_roleattributes(link_state_t *state, policydb_t *pol)
2498c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao{
2499c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	avrule_block_t *block;
2500c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	avrule_decl_t *decl;
2501c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2502c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (state->verbose)
2503c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		INFO(state->handle, "Populating role-attribute relationship "
2504c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			    "from enabled declarations' local symtab.");
2505c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2506c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	/* Iterate through all of the blocks skipping the first(which is the
2507c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * global block, is required to be present and can't have an else).
2508c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * If the block is disabled or not having an enabled decl, skip it.
2509c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 */
2510c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	for (block = pol->global->next; block != NULL; block = block->next)
2511c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	{
2512c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		decl = block->enabled;
2513c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		if (decl == NULL || decl->enabled == 0)
2514c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			continue;
2515c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2516c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		if (hashtab_map(decl->symtab[SYM_ROLES].table,
2517c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao				populate_decl_roleattributes, state))
2518c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			return -1;
2519c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2520c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2521c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	return 0;
2522c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao}
2523c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
252413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Link a set of modules into a base module. This process is somewhat
252513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * similar to an actual compiler: it requires a set of order dependent
252613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * steps.  The base and every module must have been indexed prior to
252713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * calling this function.
252813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
252913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint link_modules(sepol_handle_t * handle,
253013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		 policydb_t * b, policydb_t ** mods, int len, int verbose)
253113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
253213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i, ret, retval = -1;
253313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_module_t **modules = NULL;
253413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	link_state_t state;
253513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t num_mod_decls = 0;
253613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
253713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(&state, 0, sizeof(state));
253813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.base = b;
253913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.verbose = verbose;
254013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	state.handle = handle;
254113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
254213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (b->policy_type != POLICY_BASE) {
254313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state.handle, "Target of link was not a base policy.");
254413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
254513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
254613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
254713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* first allocate some space to hold the maps from module
254813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * symbol's value to the destination symbol value; then do
254913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * other preparation work */
255013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((modules =
255113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     (policy_module_t **) calloc(len, sizeof(*modules))) == NULL) {
255213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state.handle, "Out of memory!");
255313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
255413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
255513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < len; i++) {
255613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mods[i]->policy_type != POLICY_MOD) {
255713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state.handle,
255813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "Tried to link in a policy that was not a module.");
255913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
256013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
256113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
256213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mods[i]->mls != b->mls) {
256313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (b->mls)
256413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state.handle,
256513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "Tried to link in a non-MLS module with an MLS base.");
256613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			else
256713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(state.handle,
256813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "Tried to link in an MLS module with a non-MLS base.");
256913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
257013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
257113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
257213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((modules[i] =
257313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     (policy_module_t *) calloc(1,
257413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						sizeof(policy_module_t))) ==
257513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    NULL) {
257613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(state.handle, "Out of memory!");
257713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
257813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
257913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		modules[i]->policy = mods[i];
258013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (prepare_module(&state, modules[i]) == -1) {
258113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
258213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
258313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		num_mod_decls += modules[i]->num_decls;
258413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
258513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (prepare_base(&state, num_mod_decls) == -1) {
258613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
258713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
258813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
258913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy all types, declared and required */
259013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < len; i++) {
259113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state.cur = modules[i];
259213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state.cur_mod_name = modules[i]->policy->name;
259313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret =
259413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    hashtab_map(modules[i]->policy->p_types.table,
259513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				type_copy_callback, &state);
259613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
259713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			retval = ret;
259813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
259913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
260013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
260113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
260213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* then copy everything else, including aliases, and fixup attributes */
260313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < len; i++) {
260413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state.cur = modules[i];
260513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state.cur_mod_name = modules[i]->policy->name;
260613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret =
260713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    copy_identifiers(&state, modules[i]->policy->symtab, NULL);
260813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
260913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			retval = ret;
261013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
261113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
261213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
261313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
261413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(state.handle, state.base, 0)) {
261513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state.handle, "Error while indexing others");
261613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
261713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
261813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
261913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* copy and remap the module's data over to base */
262013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < len; i++) {
262113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		state.cur = modules[i];
262213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = copy_module(&state, modules[i]);
262313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (ret) {
262413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			retval = ret;
262513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
262613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
262713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
262813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
262913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* re-index base, for symbols were added to symbol tables  */
263013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_classes(state.base)) {
263113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state.handle, "Error while indexing classes");
263213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
263313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
263413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_index_others(state.handle, state.base, 0)) {
263513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(state.handle, "Error while indexing others");
263613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
263713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
263813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
263913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (enable_avrules(&state, state.base)) {
264013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		retval = SEPOL_EREQ;
264113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
264213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
264313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2644c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	/* Now that all role attribute's roles ebitmap have been settled,
2645c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * escalate sub role attribute's roles ebitmap into that of parent.
2646c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 *
2647c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * First, since some role-attribute relationships could be recorded
2648c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * in some decl's local symtab(see get_local_role()), we need to
2649c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	 * populate them up to the base.p_roles table. */
2650c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (populate_roleattributes(&state, state.base)) {
2651c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		retval = SEPOL_EREQ;
2652c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		goto cleanup;
2653c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	}
2654c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
2655c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	/* Now do the escalation. */
2656c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao	if (hashtab_map(state.base->p_roles.table, expand_role_attributes,
2657c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao			&state))
2658c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao		goto cleanup;
2659c3f5d75c3234ea2b03c7eba9eb18b550efcc1605Harry Ciao
266013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
266113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
266213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; modules != NULL && i < len; i++) {
266313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		policy_module_destroy(modules[i]);
266413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
266513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(modules);
266613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(state.decl_to_mod);
266713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
266813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
2669