xref: /aosp_15_r20/external/selinux/libsepol/src/link.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Authors: Karl MacMillan <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker  *	    Joshua Brindle <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker  *          Jason Tang <[email protected]>
4*2d543d20SAndroid Build Coastguard Worker  *
5*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2004-2005 Tresys Technology, LLC
6*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2007 Red Hat, Inc.
7*2d543d20SAndroid Build Coastguard Worker  *
8*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
9*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
10*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
11*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
12*2d543d20SAndroid Build Coastguard Worker  *
13*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
14*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
17*2d543d20SAndroid Build Coastguard Worker  *
18*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
19*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
20*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21*2d543d20SAndroid Build Coastguard Worker  */
22*2d543d20SAndroid Build Coastguard Worker 
23*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
24*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
25*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/hashtab.h>
26*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/avrule_block.h>
27*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/link.h>
28*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/util.h>
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
31*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
32*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
33*2d543d20SAndroid Build Coastguard Worker #include <string.h>
34*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
35*2d543d20SAndroid Build Coastguard Worker 
36*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
37*2d543d20SAndroid Build Coastguard Worker #include "private.h"
38*2d543d20SAndroid Build Coastguard Worker 
39*2d543d20SAndroid Build Coastguard Worker #undef min
40*2d543d20SAndroid Build Coastguard Worker #define min(a,b) (((a) < (b)) ? (a) : (b))
41*2d543d20SAndroid Build Coastguard Worker 
42*2d543d20SAndroid Build Coastguard Worker typedef struct policy_module {
43*2d543d20SAndroid Build Coastguard Worker 	policydb_t *policy;
44*2d543d20SAndroid Build Coastguard Worker 	uint32_t num_decls;
45*2d543d20SAndroid Build Coastguard Worker 	uint32_t *map[SYM_NUM];
46*2d543d20SAndroid Build Coastguard Worker 	uint32_t *avdecl_map;
47*2d543d20SAndroid Build Coastguard Worker 	uint32_t **perm_map;
48*2d543d20SAndroid Build Coastguard Worker 	uint32_t *perm_map_len;
49*2d543d20SAndroid Build Coastguard Worker 
50*2d543d20SAndroid Build Coastguard Worker 	/* a pointer to within the base module's avrule_block chain to
51*2d543d20SAndroid Build Coastguard Worker 	 * where this module's global now resides */
52*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *base_global;
53*2d543d20SAndroid Build Coastguard Worker } policy_module_t;
54*2d543d20SAndroid Build Coastguard Worker 
55*2d543d20SAndroid Build Coastguard Worker typedef struct link_state {
56*2d543d20SAndroid Build Coastguard Worker 	int verbose;
57*2d543d20SAndroid Build Coastguard Worker 	policydb_t *base;
58*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *last_avrule_block, *last_base_avrule_block;
59*2d543d20SAndroid Build Coastguard Worker 	uint32_t next_decl_id, current_decl_id;
60*2d543d20SAndroid Build Coastguard Worker 
61*2d543d20SAndroid Build Coastguard Worker 	/* temporary variables, used during hashtab_map() calls */
62*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *cur;
63*2d543d20SAndroid Build Coastguard Worker 	char *cur_mod_name;
64*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *dest_decl;
65*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *src_class, *dest_class;
66*2d543d20SAndroid Build Coastguard Worker 	char *dest_class_name;
67*2d543d20SAndroid Build Coastguard Worker 	char dest_class_req;	/* flag indicating the class was not declared */
68*2d543d20SAndroid Build Coastguard Worker 	uint32_t symbol_num;
69*2d543d20SAndroid Build Coastguard Worker 	/* used to report the name of the module if dependency error occurs */
70*2d543d20SAndroid Build Coastguard Worker 	policydb_t **decl_to_mod;
71*2d543d20SAndroid Build Coastguard Worker 
72*2d543d20SAndroid Build Coastguard Worker 	/* error reporting fields */
73*2d543d20SAndroid Build Coastguard Worker 	sepol_handle_t *handle;
74*2d543d20SAndroid Build Coastguard Worker } link_state_t;
75*2d543d20SAndroid Build Coastguard Worker 
76*2d543d20SAndroid Build Coastguard Worker typedef struct missing_requirement {
77*2d543d20SAndroid Build Coastguard Worker 	uint32_t symbol_type;
78*2d543d20SAndroid Build Coastguard Worker 	uint32_t symbol_value;
79*2d543d20SAndroid Build Coastguard Worker 	uint32_t perm_value;
80*2d543d20SAndroid Build Coastguard Worker } missing_requirement_t;
81*2d543d20SAndroid Build Coastguard Worker 
82*2d543d20SAndroid Build Coastguard Worker static const char * const symtab_names[SYM_NUM] = {
83*2d543d20SAndroid Build Coastguard Worker 	"common", "class", "role", "type/attribute", "user",
84*2d543d20SAndroid Build Coastguard Worker 	"bool", "level", "category"
85*2d543d20SAndroid Build Coastguard Worker };
86*2d543d20SAndroid Build Coastguard Worker 
87*2d543d20SAndroid Build Coastguard Worker /* Deallocates all elements within a module, but NOT the policydb_t
88*2d543d20SAndroid Build Coastguard Worker  * structure within, as well as the pointer itself. */
policy_module_destroy(policy_module_t * mod)89*2d543d20SAndroid Build Coastguard Worker static void policy_module_destroy(policy_module_t * mod)
90*2d543d20SAndroid Build Coastguard Worker {
91*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
92*2d543d20SAndroid Build Coastguard Worker 	if (mod == NULL) {
93*2d543d20SAndroid Build Coastguard Worker 		return;
94*2d543d20SAndroid Build Coastguard Worker 	}
95*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
96*2d543d20SAndroid Build Coastguard Worker 		free(mod->map[i]);
97*2d543d20SAndroid Build Coastguard Worker 	}
98*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; mod->perm_map != NULL && i < mod->policy->p_classes.nprim;
99*2d543d20SAndroid Build Coastguard Worker 	     i++) {
100*2d543d20SAndroid Build Coastguard Worker 		free(mod->perm_map[i]);
101*2d543d20SAndroid Build Coastguard Worker 	}
102*2d543d20SAndroid Build Coastguard Worker 	free(mod->perm_map);
103*2d543d20SAndroid Build Coastguard Worker 	free(mod->perm_map_len);
104*2d543d20SAndroid Build Coastguard Worker 	free(mod->avdecl_map);
105*2d543d20SAndroid Build Coastguard Worker 	free(mod);
106*2d543d20SAndroid Build Coastguard Worker }
107*2d543d20SAndroid Build Coastguard Worker 
108*2d543d20SAndroid Build Coastguard Worker /***** functions that copy identifiers from a module to base *****/
109*2d543d20SAndroid Build Coastguard Worker 
110*2d543d20SAndroid Build Coastguard Worker /* Note: there is currently no scoping for permissions, which causes some
111*2d543d20SAndroid Build Coastguard Worker  * strange side-effects. The current approach is this:
112*2d543d20SAndroid Build Coastguard Worker  *
113*2d543d20SAndroid Build Coastguard Worker  * a) perm is required and the class _and_ perm are declared in base: only add a mapping.
114*2d543d20SAndroid Build Coastguard Worker  * b) perm is required and the class and perm are _not_ declared in base: simply add the permissions
115*2d543d20SAndroid Build Coastguard Worker  *    to the object class. This means that the requirements for the decl are the union of the permissions
116*2d543d20SAndroid Build Coastguard Worker  *    required for all decls, but who cares.
117*2d543d20SAndroid Build Coastguard Worker  * c) perm is required, the class is declared in base, but the perm is not present. Nothing we can do
118*2d543d20SAndroid Build Coastguard Worker  *    here because we can't mark a single permission as required, so we bail with a requirement error
119*2d543d20SAndroid Build Coastguard Worker  *    _even_ if we are in an optional.
120*2d543d20SAndroid Build Coastguard Worker  *
121*2d543d20SAndroid Build Coastguard Worker  * A is correct behavior, b is wrong but not too bad, c is totall wrong for optionals. Fixing this requires
122*2d543d20SAndroid Build Coastguard Worker  * a format change.
123*2d543d20SAndroid Build Coastguard Worker  */
permission_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)124*2d543d20SAndroid Build Coastguard Worker static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
125*2d543d20SAndroid Build Coastguard Worker 				    void *data)
126*2d543d20SAndroid Build Coastguard Worker {
127*2d543d20SAndroid Build Coastguard Worker 	char *perm_id = key, *new_id = NULL;
128*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perm, *new_perm = NULL, *dest_perm;
129*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
130*2d543d20SAndroid Build Coastguard Worker 
131*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *src_class = state->src_class;
132*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *dest_class = state->dest_class;
133*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *mod = state->cur;
134*2d543d20SAndroid Build Coastguard Worker 	uint32_t sclassi = src_class->s.value - 1;
135*2d543d20SAndroid Build Coastguard Worker 	int ret;
136*2d543d20SAndroid Build Coastguard Worker 
137*2d543d20SAndroid Build Coastguard Worker 	perm = (perm_datum_t *) datum;
138*2d543d20SAndroid Build Coastguard Worker 	dest_perm = hashtab_search(dest_class->permissions.table, perm_id);
139*2d543d20SAndroid Build Coastguard Worker 	if (dest_perm == NULL && dest_class->comdatum != NULL) {
140*2d543d20SAndroid Build Coastguard Worker 		dest_perm =
141*2d543d20SAndroid Build Coastguard Worker 		    hashtab_search(dest_class->comdatum->permissions.table,
142*2d543d20SAndroid Build Coastguard Worker 				   perm_id);
143*2d543d20SAndroid Build Coastguard Worker 	}
144*2d543d20SAndroid Build Coastguard Worker 
145*2d543d20SAndroid Build Coastguard Worker 	if (dest_perm == NULL) {
146*2d543d20SAndroid Build Coastguard Worker 		/* If the object class was not declared in the base, add the perm
147*2d543d20SAndroid Build Coastguard Worker 		 * to the object class. */
148*2d543d20SAndroid Build Coastguard Worker 		if (state->dest_class_req) {
149*2d543d20SAndroid Build Coastguard Worker 			/* If the class was required (not declared), insert the new permission */
150*2d543d20SAndroid Build Coastguard Worker 			new_id = strdup(perm_id);
151*2d543d20SAndroid Build Coastguard Worker 			if (new_id == NULL) {
152*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle, "Memory error");
153*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
154*2d543d20SAndroid Build Coastguard Worker 				goto err;
155*2d543d20SAndroid Build Coastguard Worker 			}
156*2d543d20SAndroid Build Coastguard Worker 			new_perm =
157*2d543d20SAndroid Build Coastguard Worker 			    (perm_datum_t *) calloc(1, sizeof(perm_datum_t));
158*2d543d20SAndroid Build Coastguard Worker 			if (new_perm == NULL) {
159*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle, "Memory error");
160*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
161*2d543d20SAndroid Build Coastguard Worker 				goto err;
162*2d543d20SAndroid Build Coastguard Worker 			}
163*2d543d20SAndroid Build Coastguard Worker 			ret = hashtab_insert(dest_class->permissions.table,
164*2d543d20SAndroid Build Coastguard Worker 					     (hashtab_key_t) new_id,
165*2d543d20SAndroid Build Coastguard Worker 					     (hashtab_datum_t) new_perm);
166*2d543d20SAndroid Build Coastguard Worker 			if (ret) {
167*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle,
168*2d543d20SAndroid Build Coastguard Worker 				    "could not insert permission into class");
169*2d543d20SAndroid Build Coastguard Worker 				goto err;
170*2d543d20SAndroid Build Coastguard Worker 			}
171*2d543d20SAndroid Build Coastguard Worker 			new_perm->s.value = dest_class->permissions.nprim + 1;
172*2d543d20SAndroid Build Coastguard Worker 			dest_perm = new_perm;
173*2d543d20SAndroid Build Coastguard Worker 		} else {
174*2d543d20SAndroid Build Coastguard Worker 			/* this is case c from above */
175*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
176*2d543d20SAndroid Build Coastguard Worker 			    "Module %s depends on permission %s in class %s, not satisfied",
177*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, perm_id,
178*2d543d20SAndroid Build Coastguard Worker 			    state->dest_class_name);
179*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_EREQ;
180*2d543d20SAndroid Build Coastguard Worker 		}
181*2d543d20SAndroid Build Coastguard Worker 	}
182*2d543d20SAndroid Build Coastguard Worker 
183*2d543d20SAndroid Build Coastguard Worker 	/* build the mapping for permissions encompassing this class.
184*2d543d20SAndroid Build Coastguard Worker 	 * unlike symbols, the permission map translates between
185*2d543d20SAndroid Build Coastguard Worker 	 * module permission bit to target permission bit.  that bit
186*2d543d20SAndroid Build Coastguard Worker 	 * may have originated from the class -or- it could be from
187*2d543d20SAndroid Build Coastguard Worker 	 * the class's common parent.*/
188*2d543d20SAndroid Build Coastguard Worker 	if (perm->s.value > mod->perm_map_len[sclassi]) {
189*2d543d20SAndroid Build Coastguard Worker 		uint32_t *newmap = calloc(perm->s.value, sizeof(*newmap));
190*2d543d20SAndroid Build Coastguard Worker 		if (newmap == NULL) {
191*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Out of memory!");
192*2d543d20SAndroid Build Coastguard Worker 			return -1;
193*2d543d20SAndroid Build Coastguard Worker 		}
194*2d543d20SAndroid Build Coastguard Worker 		if (mod->perm_map_len[sclassi] > 0) {
195*2d543d20SAndroid Build Coastguard Worker 			memcpy(newmap, mod->perm_map[sclassi], mod->perm_map_len[sclassi] * sizeof(*newmap));
196*2d543d20SAndroid Build Coastguard Worker 		}
197*2d543d20SAndroid Build Coastguard Worker 		free(mod->perm_map[sclassi]);
198*2d543d20SAndroid Build Coastguard Worker 		mod->perm_map[sclassi] = newmap;
199*2d543d20SAndroid Build Coastguard Worker 		mod->perm_map_len[sclassi] = perm->s.value;
200*2d543d20SAndroid Build Coastguard Worker 	}
201*2d543d20SAndroid Build Coastguard Worker 	mod->perm_map[sclassi][perm->s.value - 1] = dest_perm->s.value;
202*2d543d20SAndroid Build Coastguard Worker 
203*2d543d20SAndroid Build Coastguard Worker 	return 0;
204*2d543d20SAndroid Build Coastguard Worker       err:
205*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
206*2d543d20SAndroid Build Coastguard Worker 	free(new_perm);
207*2d543d20SAndroid Build Coastguard Worker 	return ret;
208*2d543d20SAndroid Build Coastguard Worker }
209*2d543d20SAndroid Build Coastguard Worker 
class_copy_default_new_object(link_state_t * state,class_datum_t * olddatum,class_datum_t * newdatum)210*2d543d20SAndroid Build Coastguard Worker static int class_copy_default_new_object(link_state_t *state,
211*2d543d20SAndroid Build Coastguard Worker 					 class_datum_t *olddatum,
212*2d543d20SAndroid Build Coastguard Worker 					 class_datum_t *newdatum)
213*2d543d20SAndroid Build Coastguard Worker {
214*2d543d20SAndroid Build Coastguard Worker 	if (olddatum->default_user) {
215*2d543d20SAndroid Build Coastguard Worker 		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
216*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Found conflicting default user definitions");
217*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
218*2d543d20SAndroid Build Coastguard Worker 		}
219*2d543d20SAndroid Build Coastguard Worker 		newdatum->default_user = olddatum->default_user;
220*2d543d20SAndroid Build Coastguard Worker 	}
221*2d543d20SAndroid Build Coastguard Worker 	if (olddatum->default_role) {
222*2d543d20SAndroid Build Coastguard Worker 		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
223*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Found conflicting default role definitions");
224*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
225*2d543d20SAndroid Build Coastguard Worker 		}
226*2d543d20SAndroid Build Coastguard Worker 		newdatum->default_role = olddatum->default_role;
227*2d543d20SAndroid Build Coastguard Worker 	}
228*2d543d20SAndroid Build Coastguard Worker 	if (olddatum->default_type) {
229*2d543d20SAndroid Build Coastguard Worker 		if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
230*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Found conflicting default type definitions");
231*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
232*2d543d20SAndroid Build Coastguard Worker 		}
233*2d543d20SAndroid Build Coastguard Worker 		newdatum->default_type = olddatum->default_type;
234*2d543d20SAndroid Build Coastguard Worker 	}
235*2d543d20SAndroid Build Coastguard Worker 	if (olddatum->default_range) {
236*2d543d20SAndroid Build Coastguard Worker 		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
237*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Found conflicting default range definitions");
238*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
239*2d543d20SAndroid Build Coastguard Worker 		}
240*2d543d20SAndroid Build Coastguard Worker 		newdatum->default_range = olddatum->default_range;
241*2d543d20SAndroid Build Coastguard Worker 	}
242*2d543d20SAndroid Build Coastguard Worker 	return 0;
243*2d543d20SAndroid Build Coastguard Worker }
244*2d543d20SAndroid Build Coastguard Worker 
class_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)245*2d543d20SAndroid Build Coastguard Worker static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
246*2d543d20SAndroid Build Coastguard Worker 			       void *data)
247*2d543d20SAndroid Build Coastguard Worker {
248*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
249*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum, *new_class = NULL;
250*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
251*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope = NULL;
252*2d543d20SAndroid Build Coastguard Worker 	int ret;
253*2d543d20SAndroid Build Coastguard Worker 
254*2d543d20SAndroid Build Coastguard Worker 	cladatum = (class_datum_t *) datum;
255*2d543d20SAndroid Build Coastguard Worker 	state->dest_class_req = 0;
256*2d543d20SAndroid Build Coastguard Worker 
257*2d543d20SAndroid Build Coastguard Worker 	new_class = hashtab_search(state->base->p_classes.table, id);
258*2d543d20SAndroid Build Coastguard Worker 	/* If there is not an object class already in the base symtab that means
259*2d543d20SAndroid Build Coastguard Worker 	 * that either a) a module is trying to declare a new object class (which
260*2d543d20SAndroid Build Coastguard Worker 	 * the compiler should prevent) or b) an object class was required that is
261*2d543d20SAndroid Build Coastguard Worker 	 * not in the base.
262*2d543d20SAndroid Build Coastguard Worker 	 */
263*2d543d20SAndroid Build Coastguard Worker 	if (new_class == NULL) {
264*2d543d20SAndroid Build Coastguard Worker 		scope =
265*2d543d20SAndroid Build Coastguard Worker 		    hashtab_search(state->cur->policy->p_classes_scope.table,
266*2d543d20SAndroid Build Coastguard Worker 				   id);
267*2d543d20SAndroid Build Coastguard Worker 		if (scope == NULL) {
268*2d543d20SAndroid Build Coastguard Worker 			ret = SEPOL_ERR;
269*2d543d20SAndroid Build Coastguard Worker 			goto err;
270*2d543d20SAndroid Build Coastguard Worker 		}
271*2d543d20SAndroid Build Coastguard Worker 		if (scope->scope == SCOPE_DECL) {
272*2d543d20SAndroid Build Coastguard Worker 			/* disallow declarations in modules */
273*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
274*2d543d20SAndroid Build Coastguard Worker 			    "%s: Modules may not yet declare new classes.",
275*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name);
276*2d543d20SAndroid Build Coastguard Worker 			ret = SEPOL_ENOTSUP;
277*2d543d20SAndroid Build Coastguard Worker 			goto err;
278*2d543d20SAndroid Build Coastguard Worker 		} else {
279*2d543d20SAndroid Build Coastguard Worker 			/* It would be nice to error early here because the requirement is
280*2d543d20SAndroid Build Coastguard Worker 			 * not met, but we cannot because the decl might be optional (in which
281*2d543d20SAndroid Build Coastguard Worker 			 * case we should record the requirement so that it is just turned
282*2d543d20SAndroid Build Coastguard Worker 			 * off). Note: this will break horribly if modules can declare object
283*2d543d20SAndroid Build Coastguard Worker 			 * classes because the class numbers will be all wrong (i.e., they
284*2d543d20SAndroid Build Coastguard Worker 			 * might be assigned in the order they were required rather than the
285*2d543d20SAndroid Build Coastguard Worker 			 * current scheme which ensures correct numbering by ordering the
286*2d543d20SAndroid Build Coastguard Worker 			 * declarations properly). This can't be fixed until some infrastructure
287*2d543d20SAndroid Build Coastguard Worker 			 * for querying the object class numbers is in place. */
288*2d543d20SAndroid Build Coastguard Worker 			state->dest_class_req = 1;
289*2d543d20SAndroid Build Coastguard Worker 			new_class =
290*2d543d20SAndroid Build Coastguard Worker 			    (class_datum_t *) calloc(1, sizeof(class_datum_t));
291*2d543d20SAndroid Build Coastguard Worker 			if (new_class == NULL) {
292*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle, "Memory error");
293*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
294*2d543d20SAndroid Build Coastguard Worker 				goto err;
295*2d543d20SAndroid Build Coastguard Worker 			}
296*2d543d20SAndroid Build Coastguard Worker 			if (symtab_init
297*2d543d20SAndroid Build Coastguard Worker 			    (&new_class->permissions, PERM_SYMTAB_SIZE)) {
298*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
299*2d543d20SAndroid Build Coastguard Worker 				goto err;
300*2d543d20SAndroid Build Coastguard Worker 			}
301*2d543d20SAndroid Build Coastguard Worker 			new_id = strdup(id);
302*2d543d20SAndroid Build Coastguard Worker 			if (new_id == NULL) {
303*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle, "Memory error");
304*2d543d20SAndroid Build Coastguard Worker 				symtab_destroy(&new_class->permissions);
305*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
306*2d543d20SAndroid Build Coastguard Worker 				goto err;
307*2d543d20SAndroid Build Coastguard Worker 			}
308*2d543d20SAndroid Build Coastguard Worker 			ret = hashtab_insert(state->base->p_classes.table,
309*2d543d20SAndroid Build Coastguard Worker 					     (hashtab_key_t) new_id,
310*2d543d20SAndroid Build Coastguard Worker 					     (hashtab_datum_t) new_class);
311*2d543d20SAndroid Build Coastguard Worker 			if (ret) {
312*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle,
313*2d543d20SAndroid Build Coastguard Worker 				    "could not insert new class into symtab");
314*2d543d20SAndroid Build Coastguard Worker 				symtab_destroy(&new_class->permissions);
315*2d543d20SAndroid Build Coastguard Worker 				goto err;
316*2d543d20SAndroid Build Coastguard Worker 			}
317*2d543d20SAndroid Build Coastguard Worker 			new_class->s.value = ++(state->base->p_classes.nprim);
318*2d543d20SAndroid Build Coastguard Worker 		}
319*2d543d20SAndroid Build Coastguard Worker 	}
320*2d543d20SAndroid Build Coastguard Worker 
321*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_CLASSES][cladatum->s.value - 1] =
322*2d543d20SAndroid Build Coastguard Worker 	    new_class->s.value;
323*2d543d20SAndroid Build Coastguard Worker 
324*2d543d20SAndroid Build Coastguard Worker 	/* copy permissions */
325*2d543d20SAndroid Build Coastguard Worker 	state->src_class = cladatum;
326*2d543d20SAndroid Build Coastguard Worker 	state->dest_class = new_class;
327*2d543d20SAndroid Build Coastguard Worker 	state->dest_class_name = (char *)key;
328*2d543d20SAndroid Build Coastguard Worker 
329*2d543d20SAndroid Build Coastguard Worker 	/* copy default new object rules */
330*2d543d20SAndroid Build Coastguard Worker 	ret = class_copy_default_new_object(state, cladatum, new_class);
331*2d543d20SAndroid Build Coastguard Worker 	if (ret)
332*2d543d20SAndroid Build Coastguard Worker 		return ret;
333*2d543d20SAndroid Build Coastguard Worker 
334*2d543d20SAndroid Build Coastguard Worker 	ret =
335*2d543d20SAndroid Build Coastguard Worker 	    hashtab_map(cladatum->permissions.table, permission_copy_callback,
336*2d543d20SAndroid Build Coastguard Worker 			state);
337*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
338*2d543d20SAndroid Build Coastguard Worker 		return ret;
339*2d543d20SAndroid Build Coastguard Worker 	}
340*2d543d20SAndroid Build Coastguard Worker 
341*2d543d20SAndroid Build Coastguard Worker 	return 0;
342*2d543d20SAndroid Build Coastguard Worker       err:
343*2d543d20SAndroid Build Coastguard Worker 	free(new_class);
344*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
345*2d543d20SAndroid Build Coastguard Worker 	return ret;
346*2d543d20SAndroid Build Coastguard Worker }
347*2d543d20SAndroid Build Coastguard Worker 
role_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)348*2d543d20SAndroid Build Coastguard Worker static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
349*2d543d20SAndroid Build Coastguard Worker 			      void *data)
350*2d543d20SAndroid Build Coastguard Worker {
351*2d543d20SAndroid Build Coastguard Worker 	int ret;
352*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
353*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role, *base_role, *new_role = NULL;
354*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
355*2d543d20SAndroid Build Coastguard Worker 
356*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *) datum;
357*2d543d20SAndroid Build Coastguard Worker 
358*2d543d20SAndroid Build Coastguard Worker 	base_role = hashtab_search(state->base->p_roles.table, id);
359*2d543d20SAndroid Build Coastguard Worker 	if (base_role != NULL) {
360*2d543d20SAndroid Build Coastguard Worker 		/* role already exists.  check that it is what this
361*2d543d20SAndroid Build Coastguard Worker 		 * module expected.  duplicate declarations (e.g., two
362*2d543d20SAndroid Build Coastguard Worker 		 * modules both declare role foo_r) is checked during
363*2d543d20SAndroid Build Coastguard Worker 		 * scope_copy_callback(). */
364*2d543d20SAndroid Build Coastguard Worker 		if (role->flavor == ROLE_ATTRIB
365*2d543d20SAndroid Build Coastguard Worker 		    && base_role->flavor != ROLE_ATTRIB) {
366*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
367*2d543d20SAndroid Build Coastguard Worker 			    "%s: Expected %s to be a role attribute, but it was already declared as a regular role.",
368*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
369*2d543d20SAndroid Build Coastguard Worker 			return -1;
370*2d543d20SAndroid Build Coastguard Worker 		} else if (role->flavor != ROLE_ATTRIB
371*2d543d20SAndroid Build Coastguard Worker 			   && base_role->flavor == ROLE_ATTRIB) {
372*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
373*2d543d20SAndroid Build Coastguard Worker 			    "%s: Expected %s to be a regular role, but it was already declared as a role attribute.",
374*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
375*2d543d20SAndroid Build Coastguard Worker 			return -1;
376*2d543d20SAndroid Build Coastguard Worker 		}
377*2d543d20SAndroid Build Coastguard Worker 	} else {
378*2d543d20SAndroid Build Coastguard Worker 		if (state->verbose)
379*2d543d20SAndroid Build Coastguard Worker 			INFO(state->handle, "copying role %s", id);
380*2d543d20SAndroid Build Coastguard Worker 
381*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
382*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
383*2d543d20SAndroid Build Coastguard Worker 		}
384*2d543d20SAndroid Build Coastguard Worker 
385*2d543d20SAndroid Build Coastguard Worker 		if ((new_role =
386*2d543d20SAndroid Build Coastguard Worker 		     (role_datum_t *) malloc(sizeof(*new_role))) == NULL) {
387*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
388*2d543d20SAndroid Build Coastguard Worker 		}
389*2d543d20SAndroid Build Coastguard Worker 		role_datum_init(new_role);
390*2d543d20SAndroid Build Coastguard Worker 
391*2d543d20SAndroid Build Coastguard Worker 		/* new_role's dominates, types and roles field will be copied
392*2d543d20SAndroid Build Coastguard Worker 		 * during role_fix_callback() */
393*2d543d20SAndroid Build Coastguard Worker 		new_role->flavor = role->flavor;
394*2d543d20SAndroid Build Coastguard Worker 		new_role->s.value = state->base->p_roles.nprim + 1;
395*2d543d20SAndroid Build Coastguard Worker 
396*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(state->base->p_roles.table,
397*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) new_id,
398*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) new_role);
399*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
400*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
401*2d543d20SAndroid Build Coastguard Worker 		}
402*2d543d20SAndroid Build Coastguard Worker 		state->base->p_roles.nprim++;
403*2d543d20SAndroid Build Coastguard Worker 		base_role = new_role;
404*2d543d20SAndroid Build Coastguard Worker 	}
405*2d543d20SAndroid Build Coastguard Worker 
406*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl) {
407*2d543d20SAndroid Build Coastguard Worker 		new_id = NULL;
408*2d543d20SAndroid Build Coastguard Worker 		if ((new_role = malloc(sizeof(*new_role))) == NULL) {
409*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
410*2d543d20SAndroid Build Coastguard Worker 		}
411*2d543d20SAndroid Build Coastguard Worker 		role_datum_init(new_role);
412*2d543d20SAndroid Build Coastguard Worker 		new_role->flavor = base_role->flavor;
413*2d543d20SAndroid Build Coastguard Worker 		new_role->s.value = base_role->s.value;
414*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
415*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
416*2d543d20SAndroid Build Coastguard Worker 		}
417*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_insert
418*2d543d20SAndroid Build Coastguard Worker 		    (state->dest_decl->p_roles.table, new_id, new_role)) {
419*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
420*2d543d20SAndroid Build Coastguard Worker 		}
421*2d543d20SAndroid Build Coastguard Worker 		state->dest_decl->p_roles.nprim++;
422*2d543d20SAndroid Build Coastguard Worker 	}
423*2d543d20SAndroid Build Coastguard Worker 
424*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_ROLES][role->s.value - 1] = base_role->s.value;
425*2d543d20SAndroid Build Coastguard Worker 	return 0;
426*2d543d20SAndroid Build Coastguard Worker 
427*2d543d20SAndroid Build Coastguard Worker       cleanup:
428*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
429*2d543d20SAndroid Build Coastguard Worker 	role_datum_destroy(new_role);
430*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
431*2d543d20SAndroid Build Coastguard Worker 	free(new_role);
432*2d543d20SAndroid Build Coastguard Worker 	return -1;
433*2d543d20SAndroid Build Coastguard Worker }
434*2d543d20SAndroid Build Coastguard Worker 
435*2d543d20SAndroid Build Coastguard Worker /* Copy types and attributes from a module into the base module. The
436*2d543d20SAndroid Build Coastguard Worker  * attributes are copied, but the types that make up this attribute
437*2d543d20SAndroid Build Coastguard Worker  * are delayed type_fix_callback(). */
type_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)438*2d543d20SAndroid Build Coastguard Worker static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
439*2d543d20SAndroid Build Coastguard Worker 			      void *data)
440*2d543d20SAndroid Build Coastguard Worker {
441*2d543d20SAndroid Build Coastguard Worker 	int ret;
442*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
443*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *type, *base_type, *new_type = NULL;
444*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
445*2d543d20SAndroid Build Coastguard Worker 
446*2d543d20SAndroid Build Coastguard Worker 	type = (type_datum_t *) datum;
447*2d543d20SAndroid Build Coastguard Worker 	if ((type->flavor == TYPE_TYPE && !type->primary)
448*2d543d20SAndroid Build Coastguard Worker 	    || type->flavor == TYPE_ALIAS) {
449*2d543d20SAndroid Build Coastguard Worker 		/* aliases are handled later, in alias_copy_callback() */
450*2d543d20SAndroid Build Coastguard Worker 		return 0;
451*2d543d20SAndroid Build Coastguard Worker 	}
452*2d543d20SAndroid Build Coastguard Worker 
453*2d543d20SAndroid Build Coastguard Worker 	base_type = hashtab_search(state->base->p_types.table, id);
454*2d543d20SAndroid Build Coastguard Worker 	if (base_type != NULL) {
455*2d543d20SAndroid Build Coastguard Worker 		/* type already exists.  check that it is what this
456*2d543d20SAndroid Build Coastguard Worker 		 * module expected.  duplicate declarations (e.g., two
457*2d543d20SAndroid Build Coastguard Worker 		 * modules both declare type foo_t) is checked during
458*2d543d20SAndroid Build Coastguard Worker 		 * scope_copy_callback(). */
459*2d543d20SAndroid Build Coastguard Worker 		if (type->flavor == TYPE_ATTRIB
460*2d543d20SAndroid Build Coastguard Worker 		    && base_type->flavor != TYPE_ATTRIB) {
461*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
462*2d543d20SAndroid Build Coastguard Worker 			    "%s: Expected %s to be an attribute, but it was already declared as a type.",
463*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
464*2d543d20SAndroid Build Coastguard Worker 			return -1;
465*2d543d20SAndroid Build Coastguard Worker 		} else if (type->flavor != TYPE_ATTRIB
466*2d543d20SAndroid Build Coastguard Worker 			   && base_type->flavor == TYPE_ATTRIB) {
467*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
468*2d543d20SAndroid Build Coastguard Worker 			    "%s: Expected %s to be a type, but it was already declared as an attribute.",
469*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
470*2d543d20SAndroid Build Coastguard Worker 			return -1;
471*2d543d20SAndroid Build Coastguard Worker 		}
472*2d543d20SAndroid Build Coastguard Worker 
473*2d543d20SAndroid Build Coastguard Worker 		base_type->flags |= type->flags;
474*2d543d20SAndroid Build Coastguard Worker 	} else {
475*2d543d20SAndroid Build Coastguard Worker 		if (state->verbose)
476*2d543d20SAndroid Build Coastguard Worker 			INFO(state->handle, "copying type %s", id);
477*2d543d20SAndroid Build Coastguard Worker 
478*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
479*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
480*2d543d20SAndroid Build Coastguard Worker 		}
481*2d543d20SAndroid Build Coastguard Worker 
482*2d543d20SAndroid Build Coastguard Worker 		if ((new_type =
483*2d543d20SAndroid Build Coastguard Worker 		     (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
484*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
485*2d543d20SAndroid Build Coastguard Worker 		}
486*2d543d20SAndroid Build Coastguard Worker 		new_type->primary = type->primary;
487*2d543d20SAndroid Build Coastguard Worker 		new_type->flags = type->flags;
488*2d543d20SAndroid Build Coastguard Worker 		new_type->flavor = type->flavor;
489*2d543d20SAndroid Build Coastguard Worker 		/* for attributes, the writing of new_type->types is
490*2d543d20SAndroid Build Coastguard Worker 		   done in type_fix_callback() */
491*2d543d20SAndroid Build Coastguard Worker 
492*2d543d20SAndroid Build Coastguard Worker 		new_type->s.value = state->base->p_types.nprim + 1;
493*2d543d20SAndroid Build Coastguard Worker 
494*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(state->base->p_types.table,
495*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) new_id,
496*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) new_type);
497*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
498*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
499*2d543d20SAndroid Build Coastguard Worker 		}
500*2d543d20SAndroid Build Coastguard Worker 		state->base->p_types.nprim++;
501*2d543d20SAndroid Build Coastguard Worker 		base_type = new_type;
502*2d543d20SAndroid Build Coastguard Worker 	}
503*2d543d20SAndroid Build Coastguard Worker 
504*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl) {
505*2d543d20SAndroid Build Coastguard Worker 		new_id = NULL;
506*2d543d20SAndroid Build Coastguard Worker 		if ((new_type = calloc(1, sizeof(*new_type))) == NULL) {
507*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
508*2d543d20SAndroid Build Coastguard Worker 		}
509*2d543d20SAndroid Build Coastguard Worker 		new_type->primary = type->primary;
510*2d543d20SAndroid Build Coastguard Worker 		new_type->flavor = type->flavor;
511*2d543d20SAndroid Build Coastguard Worker 		new_type->flags = type->flags;
512*2d543d20SAndroid Build Coastguard Worker 		new_type->s.value = base_type->s.value;
513*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
514*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
515*2d543d20SAndroid Build Coastguard Worker 		}
516*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_insert
517*2d543d20SAndroid Build Coastguard Worker 		    (state->dest_decl->p_types.table, new_id, new_type)) {
518*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
519*2d543d20SAndroid Build Coastguard Worker 		}
520*2d543d20SAndroid Build Coastguard Worker 		state->dest_decl->p_types.nprim++;
521*2d543d20SAndroid Build Coastguard Worker 	}
522*2d543d20SAndroid Build Coastguard Worker 
523*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_TYPES][type->s.value - 1] = base_type->s.value;
524*2d543d20SAndroid Build Coastguard Worker 	return 0;
525*2d543d20SAndroid Build Coastguard Worker 
526*2d543d20SAndroid Build Coastguard Worker       cleanup:
527*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
528*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
529*2d543d20SAndroid Build Coastguard Worker 	free(new_type);
530*2d543d20SAndroid Build Coastguard Worker 	return -1;
531*2d543d20SAndroid Build Coastguard Worker }
532*2d543d20SAndroid Build Coastguard Worker 
user_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)533*2d543d20SAndroid Build Coastguard Worker static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
534*2d543d20SAndroid Build Coastguard Worker 			      void *data)
535*2d543d20SAndroid Build Coastguard Worker {
536*2d543d20SAndroid Build Coastguard Worker 	int ret;
537*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
538*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *user, *base_user, *new_user = NULL;
539*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
540*2d543d20SAndroid Build Coastguard Worker 
541*2d543d20SAndroid Build Coastguard Worker 	user = (user_datum_t *) datum;
542*2d543d20SAndroid Build Coastguard Worker 
543*2d543d20SAndroid Build Coastguard Worker 	base_user = hashtab_search(state->base->p_users.table, id);
544*2d543d20SAndroid Build Coastguard Worker 	if (base_user == NULL) {
545*2d543d20SAndroid Build Coastguard Worker 		if (state->verbose)
546*2d543d20SAndroid Build Coastguard Worker 			INFO(state->handle, "copying user %s", id);
547*2d543d20SAndroid Build Coastguard Worker 
548*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
549*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
550*2d543d20SAndroid Build Coastguard Worker 		}
551*2d543d20SAndroid Build Coastguard Worker 
552*2d543d20SAndroid Build Coastguard Worker 		if ((new_user =
553*2d543d20SAndroid Build Coastguard Worker 		     (user_datum_t *) malloc(sizeof(*new_user))) == NULL) {
554*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
555*2d543d20SAndroid Build Coastguard Worker 		}
556*2d543d20SAndroid Build Coastguard Worker 		user_datum_init(new_user);
557*2d543d20SAndroid Build Coastguard Worker 		/* new_users's roles and MLS fields will be copied during
558*2d543d20SAndroid Build Coastguard Worker 		   user_fix_callback(). */
559*2d543d20SAndroid Build Coastguard Worker 
560*2d543d20SAndroid Build Coastguard Worker 		new_user->s.value = state->base->p_users.nprim + 1;
561*2d543d20SAndroid Build Coastguard Worker 
562*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(state->base->p_users.table,
563*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) new_id,
564*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) new_user);
565*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
566*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
567*2d543d20SAndroid Build Coastguard Worker 		}
568*2d543d20SAndroid Build Coastguard Worker 		state->base->p_users.nprim++;
569*2d543d20SAndroid Build Coastguard Worker 		base_user = new_user;
570*2d543d20SAndroid Build Coastguard Worker 	}
571*2d543d20SAndroid Build Coastguard Worker 
572*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl) {
573*2d543d20SAndroid Build Coastguard Worker 		new_id = NULL;
574*2d543d20SAndroid Build Coastguard Worker 		if ((new_user = malloc(sizeof(*new_user))) == NULL) {
575*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
576*2d543d20SAndroid Build Coastguard Worker 		}
577*2d543d20SAndroid Build Coastguard Worker 		user_datum_init(new_user);
578*2d543d20SAndroid Build Coastguard Worker 		new_user->s.value = base_user->s.value;
579*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
580*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
581*2d543d20SAndroid Build Coastguard Worker 		}
582*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_insert
583*2d543d20SAndroid Build Coastguard Worker 		    (state->dest_decl->p_users.table, new_id, new_user)) {
584*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
585*2d543d20SAndroid Build Coastguard Worker 		}
586*2d543d20SAndroid Build Coastguard Worker 		state->dest_decl->p_users.nprim++;
587*2d543d20SAndroid Build Coastguard Worker 	}
588*2d543d20SAndroid Build Coastguard Worker 
589*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_USERS][user->s.value - 1] = base_user->s.value;
590*2d543d20SAndroid Build Coastguard Worker 	return 0;
591*2d543d20SAndroid Build Coastguard Worker 
592*2d543d20SAndroid Build Coastguard Worker       cleanup:
593*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
594*2d543d20SAndroid Build Coastguard Worker 	user_datum_destroy(new_user);
595*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
596*2d543d20SAndroid Build Coastguard Worker 	free(new_user);
597*2d543d20SAndroid Build Coastguard Worker 	return -1;
598*2d543d20SAndroid Build Coastguard Worker }
599*2d543d20SAndroid Build Coastguard Worker 
bool_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)600*2d543d20SAndroid Build Coastguard Worker static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
601*2d543d20SAndroid Build Coastguard Worker 			      void *data)
602*2d543d20SAndroid Build Coastguard Worker {
603*2d543d20SAndroid Build Coastguard Worker 	int ret;
604*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
605*2d543d20SAndroid Build Coastguard Worker 	cond_bool_datum_t *booldatum, *base_bool, *new_bool = NULL;
606*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
607*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope;
608*2d543d20SAndroid Build Coastguard Worker 
609*2d543d20SAndroid Build Coastguard Worker 	booldatum = (cond_bool_datum_t *) datum;
610*2d543d20SAndroid Build Coastguard Worker 
611*2d543d20SAndroid Build Coastguard Worker 	base_bool = hashtab_search(state->base->p_bools.table, id);
612*2d543d20SAndroid Build Coastguard Worker 	if (base_bool == NULL) {
613*2d543d20SAndroid Build Coastguard Worker 		if (state->verbose)
614*2d543d20SAndroid Build Coastguard Worker 			INFO(state->handle, "copying boolean %s", id);
615*2d543d20SAndroid Build Coastguard Worker 
616*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
617*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
618*2d543d20SAndroid Build Coastguard Worker 		}
619*2d543d20SAndroid Build Coastguard Worker 
620*2d543d20SAndroid Build Coastguard Worker 		if ((new_bool =
621*2d543d20SAndroid Build Coastguard Worker 		     (cond_bool_datum_t *) malloc(sizeof(*new_bool))) == NULL) {
622*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
623*2d543d20SAndroid Build Coastguard Worker 		}
624*2d543d20SAndroid Build Coastguard Worker 		new_bool->s.value = state->base->p_bools.nprim + 1;
625*2d543d20SAndroid Build Coastguard Worker 
626*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(state->base->p_bools.table,
627*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) new_id,
628*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) new_bool);
629*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
630*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
631*2d543d20SAndroid Build Coastguard Worker 		}
632*2d543d20SAndroid Build Coastguard Worker 		state->base->p_bools.nprim++;
633*2d543d20SAndroid Build Coastguard Worker 		base_bool = new_bool;
634*2d543d20SAndroid Build Coastguard Worker 		base_bool->flags = booldatum->flags;
635*2d543d20SAndroid Build Coastguard Worker 		base_bool->state = booldatum->state;
636*2d543d20SAndroid Build Coastguard Worker 	} else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) !=
637*2d543d20SAndroid Build Coastguard Worker 		   (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) {
638*2d543d20SAndroid Build Coastguard Worker 			/* A mismatch between boolean/tunable declaration
639*2d543d20SAndroid Build Coastguard Worker 			 * and usage(for example a boolean used in the
640*2d543d20SAndroid Build Coastguard Worker 			 * tunable_policy() or vice versa).
641*2d543d20SAndroid Build Coastguard Worker 			 *
642*2d543d20SAndroid Build Coastguard Worker 			 * This is not allowed and bail out with errors */
643*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
644*2d543d20SAndroid Build Coastguard Worker 			    "%s: Mismatch between boolean/tunable definition "
645*2d543d20SAndroid Build Coastguard Worker 			    "and usage for %s", state->cur_mod_name, id);
646*2d543d20SAndroid Build Coastguard Worker 			return -1;
647*2d543d20SAndroid Build Coastguard Worker 	}
648*2d543d20SAndroid Build Coastguard Worker 
649*2d543d20SAndroid Build Coastguard Worker 	/* Get the scope info for this boolean to see if this is the declaration,
650*2d543d20SAndroid Build Coastguard Worker  	 * if so set the state */
651*2d543d20SAndroid Build Coastguard Worker 	scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
652*2d543d20SAndroid Build Coastguard Worker 	if (!scope)
653*2d543d20SAndroid Build Coastguard Worker 		return SEPOL_ERR;
654*2d543d20SAndroid Build Coastguard Worker 	if (scope->scope == SCOPE_DECL) {
655*2d543d20SAndroid Build Coastguard Worker 		base_bool->state = booldatum->state;
656*2d543d20SAndroid Build Coastguard Worker 		/* Only the declaration rather than requirement
657*2d543d20SAndroid Build Coastguard Worker 		 * decides if it is a boolean or tunable. */
658*2d543d20SAndroid Build Coastguard Worker 		base_bool->flags = booldatum->flags;
659*2d543d20SAndroid Build Coastguard Worker 	}
660*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value;
661*2d543d20SAndroid Build Coastguard Worker 	return 0;
662*2d543d20SAndroid Build Coastguard Worker 
663*2d543d20SAndroid Build Coastguard Worker       cleanup:
664*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
665*2d543d20SAndroid Build Coastguard Worker 	cond_destroy_bool(new_id, new_bool, NULL);
666*2d543d20SAndroid Build Coastguard Worker 	return -1;
667*2d543d20SAndroid Build Coastguard Worker }
668*2d543d20SAndroid Build Coastguard Worker 
sens_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)669*2d543d20SAndroid Build Coastguard Worker static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
670*2d543d20SAndroid Build Coastguard Worker 			      void *data)
671*2d543d20SAndroid Build Coastguard Worker {
672*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
673*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *level, *base_level;
674*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
675*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope;
676*2d543d20SAndroid Build Coastguard Worker 
677*2d543d20SAndroid Build Coastguard Worker 	level = (level_datum_t *) datum;
678*2d543d20SAndroid Build Coastguard Worker 
679*2d543d20SAndroid Build Coastguard Worker 	base_level = hashtab_search(state->base->p_levels.table, id);
680*2d543d20SAndroid Build Coastguard Worker 	if (!base_level) {
681*2d543d20SAndroid Build Coastguard Worker 		scope =
682*2d543d20SAndroid Build Coastguard Worker 		    hashtab_search(state->cur->policy->p_sens_scope.table, id);
683*2d543d20SAndroid Build Coastguard Worker 		if (!scope)
684*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ERR;
685*2d543d20SAndroid Build Coastguard Worker 		if (scope->scope == SCOPE_DECL) {
686*2d543d20SAndroid Build Coastguard Worker 			/* disallow declarations in modules */
687*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
688*2d543d20SAndroid Build Coastguard Worker 			    "%s: Modules may not declare new sensitivities.",
689*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name);
690*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
691*2d543d20SAndroid Build Coastguard Worker 		} else if (scope->scope == SCOPE_REQ) {
692*2d543d20SAndroid Build Coastguard Worker 			/* unmet requirement */
693*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
694*2d543d20SAndroid Build Coastguard Worker 			    "%s: Sensitivity %s not declared by base.",
695*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
696*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
697*2d543d20SAndroid Build Coastguard Worker 		} else {
698*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
699*2d543d20SAndroid Build Coastguard Worker 			    "%s: has an unknown scope: %d",
700*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, scope->scope);
701*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
702*2d543d20SAndroid Build Coastguard Worker 		}
703*2d543d20SAndroid Build Coastguard Worker 	}
704*2d543d20SAndroid Build Coastguard Worker 
705*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_LEVELS][level->level->sens - 1] =
706*2d543d20SAndroid Build Coastguard Worker 	    base_level->level->sens;
707*2d543d20SAndroid Build Coastguard Worker 
708*2d543d20SAndroid Build Coastguard Worker 	return 0;
709*2d543d20SAndroid Build Coastguard Worker }
710*2d543d20SAndroid Build Coastguard Worker 
cat_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)711*2d543d20SAndroid Build Coastguard Worker static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
712*2d543d20SAndroid Build Coastguard Worker 			     void *data)
713*2d543d20SAndroid Build Coastguard Worker {
714*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
715*2d543d20SAndroid Build Coastguard Worker 	cat_datum_t *cat, *base_cat;
716*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
717*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope;
718*2d543d20SAndroid Build Coastguard Worker 
719*2d543d20SAndroid Build Coastguard Worker 	cat = (cat_datum_t *) datum;
720*2d543d20SAndroid Build Coastguard Worker 
721*2d543d20SAndroid Build Coastguard Worker 	base_cat = hashtab_search(state->base->p_cats.table, id);
722*2d543d20SAndroid Build Coastguard Worker 	if (!base_cat) {
723*2d543d20SAndroid Build Coastguard Worker 		scope = hashtab_search(state->cur->policy->p_cat_scope.table, id);
724*2d543d20SAndroid Build Coastguard Worker 		if (!scope)
725*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ERR;
726*2d543d20SAndroid Build Coastguard Worker 		if (scope->scope == SCOPE_DECL) {
727*2d543d20SAndroid Build Coastguard Worker 			/* disallow declarations in modules */
728*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
729*2d543d20SAndroid Build Coastguard Worker 			    "%s: Modules may not declare new categories.",
730*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name);
731*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
732*2d543d20SAndroid Build Coastguard Worker 		} else if (scope->scope == SCOPE_REQ) {
733*2d543d20SAndroid Build Coastguard Worker 			/* unmet requirement */
734*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
735*2d543d20SAndroid Build Coastguard Worker 			    "%s: Category %s not declared by base.",
736*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, id);
737*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
738*2d543d20SAndroid Build Coastguard Worker 		} else {
739*2d543d20SAndroid Build Coastguard Worker 			/* unknown scope?  malformed policy? */
740*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
741*2d543d20SAndroid Build Coastguard Worker 			    "%s: has an unknown scope: %d",
742*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name, scope->scope);
743*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_ENOTSUP;
744*2d543d20SAndroid Build Coastguard Worker 		}
745*2d543d20SAndroid Build Coastguard Worker 	}
746*2d543d20SAndroid Build Coastguard Worker 
747*2d543d20SAndroid Build Coastguard Worker 	state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value;
748*2d543d20SAndroid Build Coastguard Worker 
749*2d543d20SAndroid Build Coastguard Worker 	return 0;
750*2d543d20SAndroid Build Coastguard Worker }
751*2d543d20SAndroid Build Coastguard Worker 
752*2d543d20SAndroid Build Coastguard Worker static int (*const copy_callback_f[SYM_NUM]) (hashtab_key_t key,
753*2d543d20SAndroid Build Coastguard Worker 					hashtab_datum_t datum, void *datap) = {
754*2d543d20SAndroid Build Coastguard Worker NULL, class_copy_callback, role_copy_callback, type_copy_callback,
755*2d543d20SAndroid Build Coastguard Worker 	    user_copy_callback, bool_copy_callback, sens_copy_callback,
756*2d543d20SAndroid Build Coastguard Worker 	    cat_copy_callback};
757*2d543d20SAndroid Build Coastguard Worker 
758*2d543d20SAndroid Build Coastguard Worker /*
759*2d543d20SAndroid Build Coastguard Worker  * The boundaries have to be copied after the types/roles/users are copied,
760*2d543d20SAndroid Build Coastguard Worker  * because it refers hashtab to lookup destinated objects.
761*2d543d20SAndroid Build Coastguard Worker  */
type_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)762*2d543d20SAndroid Build Coastguard Worker static int type_bounds_copy_callback(hashtab_key_t key,
763*2d543d20SAndroid Build Coastguard Worker 				     hashtab_datum_t datum, void *data)
764*2d543d20SAndroid Build Coastguard Worker {
765*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
766*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *type = (type_datum_t *) datum;
767*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *dest;
768*2d543d20SAndroid Build Coastguard Worker 	uint32_t bounds_val;
769*2d543d20SAndroid Build Coastguard Worker 
770*2d543d20SAndroid Build Coastguard Worker 	if (!type->bounds)
771*2d543d20SAndroid Build Coastguard Worker 		return 0;
772*2d543d20SAndroid Build Coastguard Worker 
773*2d543d20SAndroid Build Coastguard Worker 	bounds_val = state->cur->map[SYM_TYPES][type->bounds - 1];
774*2d543d20SAndroid Build Coastguard Worker 
775*2d543d20SAndroid Build Coastguard Worker 	dest = hashtab_search(state->base->p_types.table, key);
776*2d543d20SAndroid Build Coastguard Worker 	if (!dest) {
777*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
778*2d543d20SAndroid Build Coastguard Worker 		    "Type lookup failed for %s", (char *)key);
779*2d543d20SAndroid Build Coastguard Worker 		return -1;
780*2d543d20SAndroid Build Coastguard Worker 	}
781*2d543d20SAndroid Build Coastguard Worker 	if (dest->bounds != 0 && dest->bounds != bounds_val) {
782*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
783*2d543d20SAndroid Build Coastguard Worker 		    "Inconsistent boundary for %s", (char *)key);
784*2d543d20SAndroid Build Coastguard Worker 		return -1;
785*2d543d20SAndroid Build Coastguard Worker 	}
786*2d543d20SAndroid Build Coastguard Worker 	dest->bounds = bounds_val;
787*2d543d20SAndroid Build Coastguard Worker 
788*2d543d20SAndroid Build Coastguard Worker 	return 0;
789*2d543d20SAndroid Build Coastguard Worker }
790*2d543d20SAndroid Build Coastguard Worker 
role_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)791*2d543d20SAndroid Build Coastguard Worker static int role_bounds_copy_callback(hashtab_key_t key,
792*2d543d20SAndroid Build Coastguard Worker 				     hashtab_datum_t datum, void *data)
793*2d543d20SAndroid Build Coastguard Worker {
794*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
795*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role = (role_datum_t *) datum;
796*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *dest;
797*2d543d20SAndroid Build Coastguard Worker 	uint32_t bounds_val;
798*2d543d20SAndroid Build Coastguard Worker 
799*2d543d20SAndroid Build Coastguard Worker 	if (!role->bounds)
800*2d543d20SAndroid Build Coastguard Worker 		return 0;
801*2d543d20SAndroid Build Coastguard Worker 
802*2d543d20SAndroid Build Coastguard Worker 	bounds_val = state->cur->map[SYM_ROLES][role->bounds - 1];
803*2d543d20SAndroid Build Coastguard Worker 
804*2d543d20SAndroid Build Coastguard Worker 	dest = hashtab_search(state->base->p_roles.table, key);
805*2d543d20SAndroid Build Coastguard Worker 	if (!dest) {
806*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
807*2d543d20SAndroid Build Coastguard Worker 		    "Role lookup failed for %s", (char *)key);
808*2d543d20SAndroid Build Coastguard Worker 		return -1;
809*2d543d20SAndroid Build Coastguard Worker 	}
810*2d543d20SAndroid Build Coastguard Worker 	if (dest->bounds != 0 && dest->bounds != bounds_val) {
811*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
812*2d543d20SAndroid Build Coastguard Worker 		    "Inconsistent boundary for %s", (char *)key);
813*2d543d20SAndroid Build Coastguard Worker 		return -1;
814*2d543d20SAndroid Build Coastguard Worker 	}
815*2d543d20SAndroid Build Coastguard Worker 	dest->bounds = bounds_val;
816*2d543d20SAndroid Build Coastguard Worker 
817*2d543d20SAndroid Build Coastguard Worker 	return 0;
818*2d543d20SAndroid Build Coastguard Worker }
819*2d543d20SAndroid Build Coastguard Worker 
user_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)820*2d543d20SAndroid Build Coastguard Worker static int user_bounds_copy_callback(hashtab_key_t key,
821*2d543d20SAndroid Build Coastguard Worker 				     hashtab_datum_t datum, void *data)
822*2d543d20SAndroid Build Coastguard Worker {
823*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
824*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *user = (user_datum_t *) datum;
825*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *dest;
826*2d543d20SAndroid Build Coastguard Worker 	uint32_t bounds_val;
827*2d543d20SAndroid Build Coastguard Worker 
828*2d543d20SAndroid Build Coastguard Worker 	if (!user->bounds)
829*2d543d20SAndroid Build Coastguard Worker 		return 0;
830*2d543d20SAndroid Build Coastguard Worker 
831*2d543d20SAndroid Build Coastguard Worker 	bounds_val = state->cur->map[SYM_USERS][user->bounds - 1];
832*2d543d20SAndroid Build Coastguard Worker 
833*2d543d20SAndroid Build Coastguard Worker 	dest = hashtab_search(state->base->p_users.table, key);
834*2d543d20SAndroid Build Coastguard Worker 	if (!dest) {
835*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
836*2d543d20SAndroid Build Coastguard Worker 		    "User lookup failed for %s", (char *)key);
837*2d543d20SAndroid Build Coastguard Worker 		return -1;
838*2d543d20SAndroid Build Coastguard Worker 	}
839*2d543d20SAndroid Build Coastguard Worker 	if (dest->bounds != 0 && dest->bounds != bounds_val) {
840*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
841*2d543d20SAndroid Build Coastguard Worker 		    "Inconsistent boundary for %s", (char *)key);
842*2d543d20SAndroid Build Coastguard Worker 		return -1;
843*2d543d20SAndroid Build Coastguard Worker 	}
844*2d543d20SAndroid Build Coastguard Worker 	dest->bounds = bounds_val;
845*2d543d20SAndroid Build Coastguard Worker 
846*2d543d20SAndroid Build Coastguard Worker 	return 0;
847*2d543d20SAndroid Build Coastguard Worker }
848*2d543d20SAndroid Build Coastguard Worker 
849*2d543d20SAndroid Build Coastguard Worker /* The aliases have to be copied after the types and attributes to be
850*2d543d20SAndroid Build Coastguard Worker  * certain that the base symbol table will have the type that the
851*2d543d20SAndroid Build Coastguard Worker  * alias refers. Otherwise, we won't be able to find the type value
852*2d543d20SAndroid Build Coastguard Worker  * for the alias. We can't depend on the declaration ordering because
853*2d543d20SAndroid Build Coastguard Worker  * of the hash table.
854*2d543d20SAndroid Build Coastguard Worker  */
alias_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)855*2d543d20SAndroid Build Coastguard Worker static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
856*2d543d20SAndroid Build Coastguard Worker 			       void *data)
857*2d543d20SAndroid Build Coastguard Worker {
858*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL, *target_id;
859*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *type, *base_type, *new_type = NULL, *target_type;
860*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
861*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *mod = state->cur;
862*2d543d20SAndroid Build Coastguard Worker 	int primval;
863*2d543d20SAndroid Build Coastguard Worker 
864*2d543d20SAndroid Build Coastguard Worker 	type = (type_datum_t *) datum;
865*2d543d20SAndroid Build Coastguard Worker 	/* there are 2 kinds of aliases. Ones with their own value (TYPE_ALIAS)
866*2d543d20SAndroid Build Coastguard Worker 	 * and ones with the value of their primary (TYPE_TYPE && type->primary = 0)
867*2d543d20SAndroid Build Coastguard Worker 	 */
868*2d543d20SAndroid Build Coastguard Worker 	if (!
869*2d543d20SAndroid Build Coastguard Worker 	    (type->flavor == TYPE_ALIAS
870*2d543d20SAndroid Build Coastguard Worker 	     || (type->flavor == TYPE_TYPE && !type->primary))) {
871*2d543d20SAndroid Build Coastguard Worker 		/* ignore types and attributes -- they were handled in
872*2d543d20SAndroid Build Coastguard Worker 		 * type_copy_callback() */
873*2d543d20SAndroid Build Coastguard Worker 		return 0;
874*2d543d20SAndroid Build Coastguard Worker 	}
875*2d543d20SAndroid Build Coastguard Worker 
876*2d543d20SAndroid Build Coastguard Worker 	if (type->flavor == TYPE_ALIAS)
877*2d543d20SAndroid Build Coastguard Worker 		primval = type->primary;
878*2d543d20SAndroid Build Coastguard Worker 	else
879*2d543d20SAndroid Build Coastguard Worker 		primval = type->s.value;
880*2d543d20SAndroid Build Coastguard Worker 
881*2d543d20SAndroid Build Coastguard Worker 	target_id = mod->policy->p_type_val_to_name[primval - 1];
882*2d543d20SAndroid Build Coastguard Worker 	target_type = hashtab_search(state->base->p_types.table, target_id);
883*2d543d20SAndroid Build Coastguard Worker 	if (target_type == NULL) {
884*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "%s: Could not find type %s for alias %s.",
885*2d543d20SAndroid Build Coastguard Worker 		    state->cur_mod_name, target_id, id);
886*2d543d20SAndroid Build Coastguard Worker 		return -1;
887*2d543d20SAndroid Build Coastguard Worker 	}
888*2d543d20SAndroid Build Coastguard Worker 
889*2d543d20SAndroid Build Coastguard Worker 	if (!strcmp(id, target_id)) {
890*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "%s: Self aliasing of %s.",
891*2d543d20SAndroid Build Coastguard Worker 		    state->cur_mod_name, id);
892*2d543d20SAndroid Build Coastguard Worker 		return -1;
893*2d543d20SAndroid Build Coastguard Worker 	}
894*2d543d20SAndroid Build Coastguard Worker 
895*2d543d20SAndroid Build Coastguard Worker 	target_type->flags |= type->flags;
896*2d543d20SAndroid Build Coastguard Worker 
897*2d543d20SAndroid Build Coastguard Worker 	base_type = hashtab_search(state->base->p_types.table, id);
898*2d543d20SAndroid Build Coastguard Worker 	if (base_type == NULL) {
899*2d543d20SAndroid Build Coastguard Worker 		if (state->verbose)
900*2d543d20SAndroid Build Coastguard Worker 			INFO(state->handle, "copying alias %s", id);
901*2d543d20SAndroid Build Coastguard Worker 
902*2d543d20SAndroid Build Coastguard Worker 		if ((new_type =
903*2d543d20SAndroid Build Coastguard Worker 		     (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
904*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
905*2d543d20SAndroid Build Coastguard Worker 		}
906*2d543d20SAndroid Build Coastguard Worker 		/* the linked copy always has TYPE_ALIAS style aliases */
907*2d543d20SAndroid Build Coastguard Worker 		new_type->primary = target_type->s.value;
908*2d543d20SAndroid Build Coastguard Worker 		new_type->flags = target_type->flags;
909*2d543d20SAndroid Build Coastguard Worker 		new_type->flavor = TYPE_ALIAS;
910*2d543d20SAndroid Build Coastguard Worker 		new_type->s.value = state->base->p_types.nprim + 1;
911*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
912*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
913*2d543d20SAndroid Build Coastguard Worker 		}
914*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_insert
915*2d543d20SAndroid Build Coastguard Worker 		    (state->base->p_types.table, new_id, new_type)) {
916*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
917*2d543d20SAndroid Build Coastguard Worker 		}
918*2d543d20SAndroid Build Coastguard Worker 		state->base->p_types.nprim++;
919*2d543d20SAndroid Build Coastguard Worker 		base_type = new_type;
920*2d543d20SAndroid Build Coastguard Worker 	} else {
921*2d543d20SAndroid Build Coastguard Worker 
922*2d543d20SAndroid Build Coastguard Worker 		/* if this already exists and isn't an alias it was required by another module (or base)
923*2d543d20SAndroid Build Coastguard Worker 		 * and inserted into the hashtable as a type, fix it up now */
924*2d543d20SAndroid Build Coastguard Worker 
925*2d543d20SAndroid Build Coastguard Worker 		if (base_type->flavor == TYPE_ALIAS) {
926*2d543d20SAndroid Build Coastguard Worker 			/* error checking */
927*2d543d20SAndroid Build Coastguard Worker 			assert(base_type->primary == target_type->s.value);
928*2d543d20SAndroid Build Coastguard Worker 			assert(base_type->primary ==
929*2d543d20SAndroid Build Coastguard Worker 			       mod->map[SYM_TYPES][primval - 1]);
930*2d543d20SAndroid Build Coastguard Worker 			assert(mod->map[SYM_TYPES][type->s.value - 1] ==
931*2d543d20SAndroid Build Coastguard Worker 			       base_type->primary);
932*2d543d20SAndroid Build Coastguard Worker 			return 0;
933*2d543d20SAndroid Build Coastguard Worker 		}
934*2d543d20SAndroid Build Coastguard Worker 
935*2d543d20SAndroid Build Coastguard Worker 		if (base_type->flavor == TYPE_ATTRIB) {
936*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
937*2d543d20SAndroid Build Coastguard Worker 			    "%s is an alias of an attribute, not allowed", id);
938*2d543d20SAndroid Build Coastguard Worker 			return -1;
939*2d543d20SAndroid Build Coastguard Worker 		}
940*2d543d20SAndroid Build Coastguard Worker 
941*2d543d20SAndroid Build Coastguard Worker 		base_type->flavor = TYPE_ALIAS;
942*2d543d20SAndroid Build Coastguard Worker 		base_type->primary = target_type->s.value;
943*2d543d20SAndroid Build Coastguard Worker 		base_type->flags |= target_type->flags;
944*2d543d20SAndroid Build Coastguard Worker 
945*2d543d20SAndroid Build Coastguard Worker 	}
946*2d543d20SAndroid Build Coastguard Worker 	/* the aliases map points from its value to its primary so when this module
947*2d543d20SAndroid Build Coastguard Worker 	 * references this type the value it gets back from the map is the primary */
948*2d543d20SAndroid Build Coastguard Worker 	mod->map[SYM_TYPES][type->s.value - 1] = base_type->primary;
949*2d543d20SAndroid Build Coastguard Worker 
950*2d543d20SAndroid Build Coastguard Worker 	return 0;
951*2d543d20SAndroid Build Coastguard Worker 
952*2d543d20SAndroid Build Coastguard Worker       cleanup:
953*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
954*2d543d20SAndroid Build Coastguard Worker 	free(new_id);
955*2d543d20SAndroid Build Coastguard Worker 	free(new_type);
956*2d543d20SAndroid Build Coastguard Worker 	return -1;
957*2d543d20SAndroid Build Coastguard Worker }
958*2d543d20SAndroid Build Coastguard Worker 
959*2d543d20SAndroid Build Coastguard Worker /*********** callbacks that fix bitmaps ***********/
960*2d543d20SAndroid Build Coastguard Worker 
ebitmap_convert(const ebitmap_t * src,ebitmap_t * dst,const uint32_t * map)961*2d543d20SAndroid Build Coastguard Worker static int ebitmap_convert(const ebitmap_t *src, ebitmap_t *dst, const uint32_t *map)
962*2d543d20SAndroid Build Coastguard Worker {
963*2d543d20SAndroid Build Coastguard Worker 	unsigned int bit;
964*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
965*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(src, node, bit) {
966*2d543d20SAndroid Build Coastguard Worker 		assert(map[bit]);
967*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(dst, map[bit] - 1, 1))
968*2d543d20SAndroid Build Coastguard Worker 			return -1;
969*2d543d20SAndroid Build Coastguard Worker 	}
970*2d543d20SAndroid Build Coastguard Worker 
971*2d543d20SAndroid Build Coastguard Worker 	return 0;
972*2d543d20SAndroid Build Coastguard Worker }
973*2d543d20SAndroid Build Coastguard Worker 
type_set_convert(const type_set_t * types,type_set_t * dst,const policy_module_t * mod)974*2d543d20SAndroid Build Coastguard Worker static int type_set_convert(const type_set_t * types, type_set_t * dst,
975*2d543d20SAndroid Build Coastguard Worker 			    const policy_module_t * mod)
976*2d543d20SAndroid Build Coastguard Worker {
977*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_convert(&types->types, &dst->types, mod->map[SYM_TYPES]))
978*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
979*2d543d20SAndroid Build Coastguard Worker 
980*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_convert(&types->negset, &dst->negset, mod->map[SYM_TYPES]))
981*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
982*2d543d20SAndroid Build Coastguard Worker 
983*2d543d20SAndroid Build Coastguard Worker 	dst->flags = types->flags;
984*2d543d20SAndroid Build Coastguard Worker 	return 0;
985*2d543d20SAndroid Build Coastguard Worker 
986*2d543d20SAndroid Build Coastguard Worker       cleanup:
987*2d543d20SAndroid Build Coastguard Worker 	return -1;
988*2d543d20SAndroid Build Coastguard Worker }
989*2d543d20SAndroid Build Coastguard Worker 
990*2d543d20SAndroid Build Coastguard Worker /* OR 2 typemaps together and at the same time map the src types to
991*2d543d20SAndroid Build Coastguard Worker  * the correct values in the dst typeset.
992*2d543d20SAndroid Build Coastguard Worker  */
type_set_or_convert(const type_set_t * types,type_set_t * dst,const policy_module_t * mod)993*2d543d20SAndroid Build Coastguard Worker static int type_set_or_convert(const type_set_t * types, type_set_t * dst,
994*2d543d20SAndroid Build Coastguard Worker 			       const policy_module_t * mod)
995*2d543d20SAndroid Build Coastguard Worker {
996*2d543d20SAndroid Build Coastguard Worker 	type_set_t ts_tmp;
997*2d543d20SAndroid Build Coastguard Worker 
998*2d543d20SAndroid Build Coastguard Worker 	type_set_init(&ts_tmp);
999*2d543d20SAndroid Build Coastguard Worker 	if (type_set_convert(types, &ts_tmp, mod) == -1) {
1000*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1001*2d543d20SAndroid Build Coastguard Worker 	}
1002*2d543d20SAndroid Build Coastguard Worker 	if (type_set_or_eq(dst, &ts_tmp)) {
1003*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1004*2d543d20SAndroid Build Coastguard Worker 	}
1005*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&ts_tmp);
1006*2d543d20SAndroid Build Coastguard Worker 	return 0;
1007*2d543d20SAndroid Build Coastguard Worker 
1008*2d543d20SAndroid Build Coastguard Worker       cleanup:
1009*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&ts_tmp);
1010*2d543d20SAndroid Build Coastguard Worker 	return -1;
1011*2d543d20SAndroid Build Coastguard Worker }
1012*2d543d20SAndroid Build Coastguard Worker 
role_set_or_convert(role_set_t * roles,role_set_t * dst,policy_module_t * mod,link_state_t * state)1013*2d543d20SAndroid Build Coastguard Worker static int role_set_or_convert(role_set_t * roles, role_set_t * dst,
1014*2d543d20SAndroid Build Coastguard Worker 			       policy_module_t * mod, link_state_t * state)
1015*2d543d20SAndroid Build Coastguard Worker {
1016*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tmp;
1017*2d543d20SAndroid Build Coastguard Worker 
1018*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&tmp);
1019*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_convert(&roles->roles, &tmp, mod->map[SYM_ROLES]))
1020*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1021*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_union(&dst->roles, &tmp)) {
1022*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1023*2d543d20SAndroid Build Coastguard Worker 	}
1024*2d543d20SAndroid Build Coastguard Worker 	dst->flags |= roles->flags;
1025*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tmp);
1026*2d543d20SAndroid Build Coastguard Worker 	return 0;
1027*2d543d20SAndroid Build Coastguard Worker       cleanup:
1028*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1029*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tmp);
1030*2d543d20SAndroid Build Coastguard Worker 	return -1;
1031*2d543d20SAndroid Build Coastguard Worker }
1032*2d543d20SAndroid Build Coastguard Worker 
mls_level_convert(mls_semantic_level_t * src,mls_semantic_level_t * dst,policy_module_t * mod,link_state_t * state)1033*2d543d20SAndroid Build Coastguard Worker static int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst,
1034*2d543d20SAndroid Build Coastguard Worker 			     policy_module_t * mod, link_state_t * state)
1035*2d543d20SAndroid Build Coastguard Worker {
1036*2d543d20SAndroid Build Coastguard Worker 	mls_semantic_cat_t *src_cat, *new_cat;
1037*2d543d20SAndroid Build Coastguard Worker 
1038*2d543d20SAndroid Build Coastguard Worker 	if (!mod->policy->mls)
1039*2d543d20SAndroid Build Coastguard Worker 		return 0;
1040*2d543d20SAndroid Build Coastguard Worker 
1041*2d543d20SAndroid Build Coastguard Worker 	/* Required not declared. */
1042*2d543d20SAndroid Build Coastguard Worker 	if (!src->sens)
1043*2d543d20SAndroid Build Coastguard Worker 		return 0;
1044*2d543d20SAndroid Build Coastguard Worker 
1045*2d543d20SAndroid Build Coastguard Worker 	assert(mod->map[SYM_LEVELS][src->sens - 1]);
1046*2d543d20SAndroid Build Coastguard Worker 	dst->sens = mod->map[SYM_LEVELS][src->sens - 1];
1047*2d543d20SAndroid Build Coastguard Worker 
1048*2d543d20SAndroid Build Coastguard Worker 	for (src_cat = src->cat; src_cat; src_cat = src_cat->next) {
1049*2d543d20SAndroid Build Coastguard Worker 		new_cat =
1050*2d543d20SAndroid Build Coastguard Worker 		    (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
1051*2d543d20SAndroid Build Coastguard Worker 		if (!new_cat) {
1052*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Out of memory");
1053*2d543d20SAndroid Build Coastguard Worker 			return -1;
1054*2d543d20SAndroid Build Coastguard Worker 		}
1055*2d543d20SAndroid Build Coastguard Worker 		mls_semantic_cat_init(new_cat);
1056*2d543d20SAndroid Build Coastguard Worker 
1057*2d543d20SAndroid Build Coastguard Worker 		new_cat->next = dst->cat;
1058*2d543d20SAndroid Build Coastguard Worker 		dst->cat = new_cat;
1059*2d543d20SAndroid Build Coastguard Worker 
1060*2d543d20SAndroid Build Coastguard Worker 		assert(mod->map[SYM_CATS][src_cat->low - 1]);
1061*2d543d20SAndroid Build Coastguard Worker 		dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1];
1062*2d543d20SAndroid Build Coastguard Worker 		assert(mod->map[SYM_CATS][src_cat->high - 1]);
1063*2d543d20SAndroid Build Coastguard Worker 		dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1];
1064*2d543d20SAndroid Build Coastguard Worker 	}
1065*2d543d20SAndroid Build Coastguard Worker 
1066*2d543d20SAndroid Build Coastguard Worker 	return 0;
1067*2d543d20SAndroid Build Coastguard Worker }
1068*2d543d20SAndroid Build Coastguard Worker 
mls_range_convert(mls_semantic_range_t * src,mls_semantic_range_t * dst,policy_module_t * mod,link_state_t * state)1069*2d543d20SAndroid Build Coastguard Worker static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * dst,
1070*2d543d20SAndroid Build Coastguard Worker 			     policy_module_t * mod, link_state_t * state)
1071*2d543d20SAndroid Build Coastguard Worker {
1072*2d543d20SAndroid Build Coastguard Worker 	int ret;
1073*2d543d20SAndroid Build Coastguard Worker 	ret = mls_level_convert(&src->level[0], &dst->level[0], mod, state);
1074*2d543d20SAndroid Build Coastguard Worker 	if (ret)
1075*2d543d20SAndroid Build Coastguard Worker 		return ret;
1076*2d543d20SAndroid Build Coastguard Worker 	ret = mls_level_convert(&src->level[1], &dst->level[1], mod, state);
1077*2d543d20SAndroid Build Coastguard Worker 	if (ret)
1078*2d543d20SAndroid Build Coastguard Worker 		return ret;
1079*2d543d20SAndroid Build Coastguard Worker 	return 0;
1080*2d543d20SAndroid Build Coastguard Worker }
1081*2d543d20SAndroid Build Coastguard Worker 
role_fix_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1082*2d543d20SAndroid Build Coastguard Worker static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1083*2d543d20SAndroid Build Coastguard Worker 			     void *data)
1084*2d543d20SAndroid Build Coastguard Worker {
1085*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
1086*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role, *dest_role = NULL;
1087*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
1088*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e_tmp;
1089*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *mod = state->cur;
1090*2d543d20SAndroid Build Coastguard Worker 	hashtab_t role_tab;
1091*2d543d20SAndroid Build Coastguard Worker 
1092*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *) datum;
1093*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl == NULL)
1094*2d543d20SAndroid Build Coastguard Worker 		role_tab = state->base->p_roles.table;
1095*2d543d20SAndroid Build Coastguard Worker 	else
1096*2d543d20SAndroid Build Coastguard Worker 		role_tab = state->dest_decl->p_roles.table;
1097*2d543d20SAndroid Build Coastguard Worker 
1098*2d543d20SAndroid Build Coastguard Worker 	dest_role = hashtab_search(role_tab, id);
1099*2d543d20SAndroid Build Coastguard Worker 	assert(dest_role != NULL);
1100*2d543d20SAndroid Build Coastguard Worker 
1101*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose) {
1102*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "fixing role %s", id);
1103*2d543d20SAndroid Build Coastguard Worker 	}
1104*2d543d20SAndroid Build Coastguard Worker 
1105*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_tmp);
1106*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_convert(&role->dominates, &e_tmp, mod->map[SYM_ROLES]))
1107*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1108*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_union(&dest_role->dominates, &e_tmp)) {
1109*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1110*2d543d20SAndroid Build Coastguard Worker 	}
1111*2d543d20SAndroid Build Coastguard Worker 	if (type_set_or_convert(&role->types, &dest_role->types, mod)) {
1112*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1113*2d543d20SAndroid Build Coastguard Worker 	}
1114*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tmp);
1115*2d543d20SAndroid Build Coastguard Worker 
1116*2d543d20SAndroid Build Coastguard Worker 	if (role->flavor == ROLE_ATTRIB) {
1117*2d543d20SAndroid Build Coastguard Worker 		ebitmap_init(&e_tmp);
1118*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_convert(&role->roles, &e_tmp, mod->map[SYM_ROLES]))
1119*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1120*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_union(&dest_role->roles, &e_tmp)) {
1121*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1122*2d543d20SAndroid Build Coastguard Worker 		}
1123*2d543d20SAndroid Build Coastguard Worker 		ebitmap_destroy(&e_tmp);
1124*2d543d20SAndroid Build Coastguard Worker 	}
1125*2d543d20SAndroid Build Coastguard Worker 
1126*2d543d20SAndroid Build Coastguard Worker 	return 0;
1127*2d543d20SAndroid Build Coastguard Worker 
1128*2d543d20SAndroid Build Coastguard Worker       cleanup:
1129*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1130*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tmp);
1131*2d543d20SAndroid Build Coastguard Worker 	return -1;
1132*2d543d20SAndroid Build Coastguard Worker }
1133*2d543d20SAndroid Build Coastguard Worker 
type_fix_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1134*2d543d20SAndroid Build Coastguard Worker static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1135*2d543d20SAndroid Build Coastguard Worker 			     void *data)
1136*2d543d20SAndroid Build Coastguard Worker {
1137*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
1138*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *type, *new_type = NULL;
1139*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
1140*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e_tmp;
1141*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *mod = state->cur;
1142*2d543d20SAndroid Build Coastguard Worker 	symtab_t *typetab;
1143*2d543d20SAndroid Build Coastguard Worker 
1144*2d543d20SAndroid Build Coastguard Worker 	type = (type_datum_t *) datum;
1145*2d543d20SAndroid Build Coastguard Worker 
1146*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl == NULL)
1147*2d543d20SAndroid Build Coastguard Worker 		typetab = &state->base->p_types;
1148*2d543d20SAndroid Build Coastguard Worker 	else
1149*2d543d20SAndroid Build Coastguard Worker 		typetab = &state->dest_decl->p_types;
1150*2d543d20SAndroid Build Coastguard Worker 
1151*2d543d20SAndroid Build Coastguard Worker 	/* only fix attributes */
1152*2d543d20SAndroid Build Coastguard Worker 	if (type->flavor != TYPE_ATTRIB) {
1153*2d543d20SAndroid Build Coastguard Worker 		return 0;
1154*2d543d20SAndroid Build Coastguard Worker 	}
1155*2d543d20SAndroid Build Coastguard Worker 
1156*2d543d20SAndroid Build Coastguard Worker 	new_type = hashtab_search(typetab->table, id);
1157*2d543d20SAndroid Build Coastguard Worker 	assert(new_type != NULL && new_type->flavor == TYPE_ATTRIB);
1158*2d543d20SAndroid Build Coastguard Worker 
1159*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose) {
1160*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "fixing attribute %s", id);
1161*2d543d20SAndroid Build Coastguard Worker 	}
1162*2d543d20SAndroid Build Coastguard Worker 
1163*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_tmp);
1164*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_convert(&type->types, &e_tmp, mod->map[SYM_TYPES]))
1165*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1166*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_union(&new_type->types, &e_tmp)) {
1167*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1168*2d543d20SAndroid Build Coastguard Worker 	}
1169*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tmp);
1170*2d543d20SAndroid Build Coastguard Worker 	return 0;
1171*2d543d20SAndroid Build Coastguard Worker 
1172*2d543d20SAndroid Build Coastguard Worker       cleanup:
1173*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1174*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tmp);
1175*2d543d20SAndroid Build Coastguard Worker 	return -1;
1176*2d543d20SAndroid Build Coastguard Worker }
1177*2d543d20SAndroid Build Coastguard Worker 
user_fix_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1178*2d543d20SAndroid Build Coastguard Worker static int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1179*2d543d20SAndroid Build Coastguard Worker 			     void *data)
1180*2d543d20SAndroid Build Coastguard Worker {
1181*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
1182*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *user, *new_user = NULL;
1183*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
1184*2d543d20SAndroid Build Coastguard Worker 	policy_module_t *mod = state->cur;
1185*2d543d20SAndroid Build Coastguard Worker 	symtab_t *usertab;
1186*2d543d20SAndroid Build Coastguard Worker 
1187*2d543d20SAndroid Build Coastguard Worker 	user = (user_datum_t *) datum;
1188*2d543d20SAndroid Build Coastguard Worker 
1189*2d543d20SAndroid Build Coastguard Worker 	if (state->dest_decl == NULL)
1190*2d543d20SAndroid Build Coastguard Worker 		usertab = &state->base->p_users;
1191*2d543d20SAndroid Build Coastguard Worker 	else
1192*2d543d20SAndroid Build Coastguard Worker 		usertab = &state->dest_decl->p_users;
1193*2d543d20SAndroid Build Coastguard Worker 
1194*2d543d20SAndroid Build Coastguard Worker 	new_user = hashtab_search(usertab->table, id);
1195*2d543d20SAndroid Build Coastguard Worker 	assert(new_user != NULL);
1196*2d543d20SAndroid Build Coastguard Worker 
1197*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose) {
1198*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "fixing user %s", id);
1199*2d543d20SAndroid Build Coastguard Worker 	}
1200*2d543d20SAndroid Build Coastguard Worker 
1201*2d543d20SAndroid Build Coastguard Worker 	if (role_set_or_convert(&user->roles, &new_user->roles, mod, state)) {
1202*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1203*2d543d20SAndroid Build Coastguard Worker 	}
1204*2d543d20SAndroid Build Coastguard Worker 
1205*2d543d20SAndroid Build Coastguard Worker 	if (mls_range_convert(&user->range, &new_user->range, mod, state))
1206*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1207*2d543d20SAndroid Build Coastguard Worker 
1208*2d543d20SAndroid Build Coastguard Worker 	if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod, state))
1209*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1210*2d543d20SAndroid Build Coastguard Worker 
1211*2d543d20SAndroid Build Coastguard Worker 	return 0;
1212*2d543d20SAndroid Build Coastguard Worker 
1213*2d543d20SAndroid Build Coastguard Worker       cleanup:
1214*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1215*2d543d20SAndroid Build Coastguard Worker 	return -1;
1216*2d543d20SAndroid Build Coastguard Worker }
1217*2d543d20SAndroid Build Coastguard Worker 
1218*2d543d20SAndroid Build Coastguard Worker static int (*const fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1219*2d543d20SAndroid Build Coastguard Worker 				       void *datap) = {
1220*2d543d20SAndroid Build Coastguard Worker NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback,
1221*2d543d20SAndroid Build Coastguard Worker 	    NULL, NULL, NULL};
1222*2d543d20SAndroid Build Coastguard Worker 
1223*2d543d20SAndroid Build Coastguard Worker /*********** functions that copy AV rules ***********/
1224*2d543d20SAndroid Build Coastguard Worker 
copy_avrule_list(avrule_t * list,avrule_t ** dst,policy_module_t * module,link_state_t * state)1225*2d543d20SAndroid Build Coastguard Worker static int copy_avrule_list(avrule_t * list, avrule_t ** dst,
1226*2d543d20SAndroid Build Coastguard Worker 			    policy_module_t * module, link_state_t * state)
1227*2d543d20SAndroid Build Coastguard Worker {
1228*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
1229*2d543d20SAndroid Build Coastguard Worker 	avrule_t *cur, *new_rule = NULL, *tail;
1230*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *cur_perm, *new_perm, *tail_perm = NULL;
1231*2d543d20SAndroid Build Coastguard Worker 
1232*2d543d20SAndroid Build Coastguard Worker 	tail = *dst;
1233*2d543d20SAndroid Build Coastguard Worker 	while (tail && tail->next) {
1234*2d543d20SAndroid Build Coastguard Worker 		tail = tail->next;
1235*2d543d20SAndroid Build Coastguard Worker 	}
1236*2d543d20SAndroid Build Coastguard Worker 
1237*2d543d20SAndroid Build Coastguard Worker 	cur = list;
1238*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1239*2d543d20SAndroid Build Coastguard Worker 		if ((new_rule = (avrule_t *) malloc(sizeof(avrule_t))) == NULL) {
1240*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1241*2d543d20SAndroid Build Coastguard Worker 		}
1242*2d543d20SAndroid Build Coastguard Worker 		avrule_init(new_rule);
1243*2d543d20SAndroid Build Coastguard Worker 
1244*2d543d20SAndroid Build Coastguard Worker 		new_rule->specified = cur->specified;
1245*2d543d20SAndroid Build Coastguard Worker 		new_rule->flags = cur->flags;
1246*2d543d20SAndroid Build Coastguard Worker 		if (type_set_convert
1247*2d543d20SAndroid Build Coastguard Worker 		    (&cur->stypes, &new_rule->stypes, module) == -1
1248*2d543d20SAndroid Build Coastguard Worker 		    || type_set_convert(&cur->ttypes, &new_rule->ttypes, module) == -1) {
1249*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1250*2d543d20SAndroid Build Coastguard Worker 		}
1251*2d543d20SAndroid Build Coastguard Worker 
1252*2d543d20SAndroid Build Coastguard Worker 		cur_perm = cur->perms;
1253*2d543d20SAndroid Build Coastguard Worker 		tail_perm = NULL;
1254*2d543d20SAndroid Build Coastguard Worker 		while (cur_perm) {
1255*2d543d20SAndroid Build Coastguard Worker 			if ((new_perm = (class_perm_node_t *)
1256*2d543d20SAndroid Build Coastguard Worker 			     malloc(sizeof(class_perm_node_t))) == NULL) {
1257*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1258*2d543d20SAndroid Build Coastguard Worker 			}
1259*2d543d20SAndroid Build Coastguard Worker 			class_perm_node_init(new_perm);
1260*2d543d20SAndroid Build Coastguard Worker 
1261*2d543d20SAndroid Build Coastguard Worker 			new_perm->tclass =
1262*2d543d20SAndroid Build Coastguard Worker 			    module->map[SYM_CLASSES][cur_perm->tclass - 1];
1263*2d543d20SAndroid Build Coastguard Worker 			assert(new_perm->tclass);
1264*2d543d20SAndroid Build Coastguard Worker 
1265*2d543d20SAndroid Build Coastguard Worker 			if (new_rule->specified & AVRULE_AV) {
1266*2d543d20SAndroid Build Coastguard Worker 				for (i = 0;
1267*2d543d20SAndroid Build Coastguard Worker 				     i <
1268*2d543d20SAndroid Build Coastguard Worker 				     module->perm_map_len[cur_perm->tclass - 1];
1269*2d543d20SAndroid Build Coastguard Worker 				     i++) {
1270*2d543d20SAndroid Build Coastguard Worker 					if (!(cur_perm->data & (UINT32_C(1) << i)))
1271*2d543d20SAndroid Build Coastguard Worker 						continue;
1272*2d543d20SAndroid Build Coastguard Worker 					new_perm->data |=
1273*2d543d20SAndroid Build Coastguard Worker 					    (UINT32_C(1) <<
1274*2d543d20SAndroid Build Coastguard Worker 					     (module->
1275*2d543d20SAndroid Build Coastguard Worker 					      perm_map[cur_perm->tclass - 1][i] -
1276*2d543d20SAndroid Build Coastguard Worker 					      1));
1277*2d543d20SAndroid Build Coastguard Worker 				}
1278*2d543d20SAndroid Build Coastguard Worker 			} else {
1279*2d543d20SAndroid Build Coastguard Worker 				new_perm->data =
1280*2d543d20SAndroid Build Coastguard Worker 				    module->map[SYM_TYPES][cur_perm->data - 1];
1281*2d543d20SAndroid Build Coastguard Worker 			}
1282*2d543d20SAndroid Build Coastguard Worker 
1283*2d543d20SAndroid Build Coastguard Worker 			if (new_rule->perms == NULL) {
1284*2d543d20SAndroid Build Coastguard Worker 				new_rule->perms = new_perm;
1285*2d543d20SAndroid Build Coastguard Worker 			} else {
1286*2d543d20SAndroid Build Coastguard Worker 				assert(tail_perm);
1287*2d543d20SAndroid Build Coastguard Worker 				tail_perm->next = new_perm;
1288*2d543d20SAndroid Build Coastguard Worker 			}
1289*2d543d20SAndroid Build Coastguard Worker 			tail_perm = new_perm;
1290*2d543d20SAndroid Build Coastguard Worker 			cur_perm = cur_perm->next;
1291*2d543d20SAndroid Build Coastguard Worker 		}
1292*2d543d20SAndroid Build Coastguard Worker 
1293*2d543d20SAndroid Build Coastguard Worker 		if (cur->xperms) {
1294*2d543d20SAndroid Build Coastguard Worker 			new_rule->xperms = calloc(1, sizeof(*new_rule->xperms));
1295*2d543d20SAndroid Build Coastguard Worker 			if (!new_rule->xperms)
1296*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1297*2d543d20SAndroid Build Coastguard Worker 			memcpy(new_rule->xperms, cur->xperms,
1298*2d543d20SAndroid Build Coastguard Worker 			       sizeof(*new_rule->xperms));
1299*2d543d20SAndroid Build Coastguard Worker 		}
1300*2d543d20SAndroid Build Coastguard Worker 
1301*2d543d20SAndroid Build Coastguard Worker 		new_rule->line = cur->line;
1302*2d543d20SAndroid Build Coastguard Worker 		new_rule->source_line = cur->source_line;
1303*2d543d20SAndroid Build Coastguard Worker 		if (cur->source_filename) {
1304*2d543d20SAndroid Build Coastguard Worker 			new_rule->source_filename = strdup(cur->source_filename);
1305*2d543d20SAndroid Build Coastguard Worker 			if (!new_rule->source_filename)
1306*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1307*2d543d20SAndroid Build Coastguard Worker 		}
1308*2d543d20SAndroid Build Coastguard Worker 
1309*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1310*2d543d20SAndroid Build Coastguard Worker 
1311*2d543d20SAndroid Build Coastguard Worker 		if (*dst == NULL) {
1312*2d543d20SAndroid Build Coastguard Worker 			*dst = new_rule;
1313*2d543d20SAndroid Build Coastguard Worker 		} else {
1314*2d543d20SAndroid Build Coastguard Worker 			tail->next = new_rule;
1315*2d543d20SAndroid Build Coastguard Worker 		}
1316*2d543d20SAndroid Build Coastguard Worker 		tail = new_rule;
1317*2d543d20SAndroid Build Coastguard Worker 	}
1318*2d543d20SAndroid Build Coastguard Worker 
1319*2d543d20SAndroid Build Coastguard Worker 	return 0;
1320*2d543d20SAndroid Build Coastguard Worker       cleanup:
1321*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1322*2d543d20SAndroid Build Coastguard Worker 	avrule_destroy(new_rule);
1323*2d543d20SAndroid Build Coastguard Worker 	free(new_rule);
1324*2d543d20SAndroid Build Coastguard Worker 	return -1;
1325*2d543d20SAndroid Build Coastguard Worker }
1326*2d543d20SAndroid Build Coastguard Worker 
copy_role_trans_list(role_trans_rule_t * list,role_trans_rule_t ** dst,policy_module_t * module,link_state_t * state)1327*2d543d20SAndroid Build Coastguard Worker static int copy_role_trans_list(role_trans_rule_t * list,
1328*2d543d20SAndroid Build Coastguard Worker 				role_trans_rule_t ** dst,
1329*2d543d20SAndroid Build Coastguard Worker 				policy_module_t * module, link_state_t * state)
1330*2d543d20SAndroid Build Coastguard Worker {
1331*2d543d20SAndroid Build Coastguard Worker 	role_trans_rule_t *cur, *new_rule = NULL, *tail;
1332*2d543d20SAndroid Build Coastguard Worker 
1333*2d543d20SAndroid Build Coastguard Worker 	cur = list;
1334*2d543d20SAndroid Build Coastguard Worker 	tail = *dst;
1335*2d543d20SAndroid Build Coastguard Worker 	while (tail && tail->next) {
1336*2d543d20SAndroid Build Coastguard Worker 		tail = tail->next;
1337*2d543d20SAndroid Build Coastguard Worker 	}
1338*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1339*2d543d20SAndroid Build Coastguard Worker 		if ((new_rule =
1340*2d543d20SAndroid Build Coastguard Worker 		     (role_trans_rule_t *) malloc(sizeof(role_trans_rule_t))) ==
1341*2d543d20SAndroid Build Coastguard Worker 		    NULL) {
1342*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1343*2d543d20SAndroid Build Coastguard Worker 		}
1344*2d543d20SAndroid Build Coastguard Worker 		role_trans_rule_init(new_rule);
1345*2d543d20SAndroid Build Coastguard Worker 
1346*2d543d20SAndroid Build Coastguard Worker 		if (role_set_or_convert
1347*2d543d20SAndroid Build Coastguard Worker 		    (&cur->roles, &new_rule->roles, module, state)
1348*2d543d20SAndroid Build Coastguard Worker 		    || type_set_or_convert(&cur->types, &new_rule->types,
1349*2d543d20SAndroid Build Coastguard Worker 					   module)) {
1350*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1351*2d543d20SAndroid Build Coastguard Worker 		}
1352*2d543d20SAndroid Build Coastguard Worker 
1353*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_convert(&cur->classes, &new_rule->classes, module->map[SYM_CLASSES]))
1354*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1355*2d543d20SAndroid Build Coastguard Worker 
1356*2d543d20SAndroid Build Coastguard Worker 		new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1];
1357*2d543d20SAndroid Build Coastguard Worker 
1358*2d543d20SAndroid Build Coastguard Worker 		if (*dst == NULL) {
1359*2d543d20SAndroid Build Coastguard Worker 			*dst = new_rule;
1360*2d543d20SAndroid Build Coastguard Worker 		} else {
1361*2d543d20SAndroid Build Coastguard Worker 			tail->next = new_rule;
1362*2d543d20SAndroid Build Coastguard Worker 		}
1363*2d543d20SAndroid Build Coastguard Worker 		tail = new_rule;
1364*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1365*2d543d20SAndroid Build Coastguard Worker 	}
1366*2d543d20SAndroid Build Coastguard Worker 	return 0;
1367*2d543d20SAndroid Build Coastguard Worker       cleanup:
1368*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1369*2d543d20SAndroid Build Coastguard Worker 	role_trans_rule_list_destroy(new_rule);
1370*2d543d20SAndroid Build Coastguard Worker 	return -1;
1371*2d543d20SAndroid Build Coastguard Worker }
1372*2d543d20SAndroid Build Coastguard Worker 
copy_role_allow_list(role_allow_rule_t * list,role_allow_rule_t ** dst,policy_module_t * module,link_state_t * state)1373*2d543d20SAndroid Build Coastguard Worker static int copy_role_allow_list(role_allow_rule_t * list,
1374*2d543d20SAndroid Build Coastguard Worker 				role_allow_rule_t ** dst,
1375*2d543d20SAndroid Build Coastguard Worker 				policy_module_t * module, link_state_t * state)
1376*2d543d20SAndroid Build Coastguard Worker {
1377*2d543d20SAndroid Build Coastguard Worker 	role_allow_rule_t *cur, *new_rule = NULL, *tail;
1378*2d543d20SAndroid Build Coastguard Worker 
1379*2d543d20SAndroid Build Coastguard Worker 	cur = list;
1380*2d543d20SAndroid Build Coastguard Worker 	tail = *dst;
1381*2d543d20SAndroid Build Coastguard Worker 	while (tail && tail->next) {
1382*2d543d20SAndroid Build Coastguard Worker 		tail = tail->next;
1383*2d543d20SAndroid Build Coastguard Worker 	}
1384*2d543d20SAndroid Build Coastguard Worker 
1385*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1386*2d543d20SAndroid Build Coastguard Worker 		if ((new_rule =
1387*2d543d20SAndroid Build Coastguard Worker 		     (role_allow_rule_t *) malloc(sizeof(role_allow_rule_t))) ==
1388*2d543d20SAndroid Build Coastguard Worker 		    NULL) {
1389*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1390*2d543d20SAndroid Build Coastguard Worker 		}
1391*2d543d20SAndroid Build Coastguard Worker 		role_allow_rule_init(new_rule);
1392*2d543d20SAndroid Build Coastguard Worker 
1393*2d543d20SAndroid Build Coastguard Worker 		if (role_set_or_convert
1394*2d543d20SAndroid Build Coastguard Worker 		    (&cur->roles, &new_rule->roles, module, state)
1395*2d543d20SAndroid Build Coastguard Worker 		    || role_set_or_convert(&cur->new_roles,
1396*2d543d20SAndroid Build Coastguard Worker 					   &new_rule->new_roles, module,
1397*2d543d20SAndroid Build Coastguard Worker 					   state)) {
1398*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1399*2d543d20SAndroid Build Coastguard Worker 		}
1400*2d543d20SAndroid Build Coastguard Worker 		if (*dst == NULL) {
1401*2d543d20SAndroid Build Coastguard Worker 			*dst = new_rule;
1402*2d543d20SAndroid Build Coastguard Worker 		} else {
1403*2d543d20SAndroid Build Coastguard Worker 			tail->next = new_rule;
1404*2d543d20SAndroid Build Coastguard Worker 		}
1405*2d543d20SAndroid Build Coastguard Worker 		tail = new_rule;
1406*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1407*2d543d20SAndroid Build Coastguard Worker 	}
1408*2d543d20SAndroid Build Coastguard Worker 	return 0;
1409*2d543d20SAndroid Build Coastguard Worker       cleanup:
1410*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1411*2d543d20SAndroid Build Coastguard Worker 	role_allow_rule_list_destroy(new_rule);
1412*2d543d20SAndroid Build Coastguard Worker 	return -1;
1413*2d543d20SAndroid Build Coastguard Worker }
1414*2d543d20SAndroid Build Coastguard Worker 
copy_filename_trans_list(filename_trans_rule_t * list,filename_trans_rule_t ** dst,policy_module_t * module,link_state_t * state)1415*2d543d20SAndroid Build Coastguard Worker static int copy_filename_trans_list(filename_trans_rule_t * list,
1416*2d543d20SAndroid Build Coastguard Worker 				    filename_trans_rule_t ** dst,
1417*2d543d20SAndroid Build Coastguard Worker 				    policy_module_t * module,
1418*2d543d20SAndroid Build Coastguard Worker 				    link_state_t * state)
1419*2d543d20SAndroid Build Coastguard Worker {
1420*2d543d20SAndroid Build Coastguard Worker 	filename_trans_rule_t *cur, *new_rule, *tail;
1421*2d543d20SAndroid Build Coastguard Worker 
1422*2d543d20SAndroid Build Coastguard Worker 	cur = list;
1423*2d543d20SAndroid Build Coastguard Worker 	tail = *dst;
1424*2d543d20SAndroid Build Coastguard Worker 	while (tail && tail->next)
1425*2d543d20SAndroid Build Coastguard Worker 		tail = tail->next;
1426*2d543d20SAndroid Build Coastguard Worker 
1427*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1428*2d543d20SAndroid Build Coastguard Worker 		new_rule = malloc(sizeof(*new_rule));
1429*2d543d20SAndroid Build Coastguard Worker 		if (!new_rule)
1430*2d543d20SAndroid Build Coastguard Worker 			goto err;
1431*2d543d20SAndroid Build Coastguard Worker 
1432*2d543d20SAndroid Build Coastguard Worker 		filename_trans_rule_init(new_rule);
1433*2d543d20SAndroid Build Coastguard Worker 
1434*2d543d20SAndroid Build Coastguard Worker 		if (*dst == NULL)
1435*2d543d20SAndroid Build Coastguard Worker 			*dst = new_rule;
1436*2d543d20SAndroid Build Coastguard Worker 		else
1437*2d543d20SAndroid Build Coastguard Worker 			tail->next = new_rule;
1438*2d543d20SAndroid Build Coastguard Worker 		tail = new_rule;
1439*2d543d20SAndroid Build Coastguard Worker 
1440*2d543d20SAndroid Build Coastguard Worker 		new_rule->name = strdup(cur->name);
1441*2d543d20SAndroid Build Coastguard Worker 		if (!new_rule->name)
1442*2d543d20SAndroid Build Coastguard Worker 			goto err;
1443*2d543d20SAndroid Build Coastguard Worker 
1444*2d543d20SAndroid Build Coastguard Worker 		if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) ||
1445*2d543d20SAndroid Build Coastguard Worker 		    type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module))
1446*2d543d20SAndroid Build Coastguard Worker 			goto err;
1447*2d543d20SAndroid Build Coastguard Worker 
1448*2d543d20SAndroid Build Coastguard Worker 		new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1];
1449*2d543d20SAndroid Build Coastguard Worker 		new_rule->otype = module->map[SYM_TYPES][cur->otype - 1];
1450*2d543d20SAndroid Build Coastguard Worker 		new_rule->flags = cur->flags;
1451*2d543d20SAndroid Build Coastguard Worker 
1452*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1453*2d543d20SAndroid Build Coastguard Worker 	}
1454*2d543d20SAndroid Build Coastguard Worker 	return 0;
1455*2d543d20SAndroid Build Coastguard Worker err:
1456*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1457*2d543d20SAndroid Build Coastguard Worker 	return -1;
1458*2d543d20SAndroid Build Coastguard Worker }
1459*2d543d20SAndroid Build Coastguard Worker 
copy_range_trans_list(range_trans_rule_t * rules,range_trans_rule_t ** dst,policy_module_t * mod,link_state_t * state)1460*2d543d20SAndroid Build Coastguard Worker static int copy_range_trans_list(range_trans_rule_t * rules,
1461*2d543d20SAndroid Build Coastguard Worker 				 range_trans_rule_t ** dst,
1462*2d543d20SAndroid Build Coastguard Worker 				 policy_module_t * mod, link_state_t * state)
1463*2d543d20SAndroid Build Coastguard Worker {
1464*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_t *rule, *new_rule = NULL;
1465*2d543d20SAndroid Build Coastguard Worker 
1466*2d543d20SAndroid Build Coastguard Worker 	for (rule = rules; rule; rule = rule->next) {
1467*2d543d20SAndroid Build Coastguard Worker 		new_rule =
1468*2d543d20SAndroid Build Coastguard Worker 		    (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t));
1469*2d543d20SAndroid Build Coastguard Worker 		if (!new_rule)
1470*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1471*2d543d20SAndroid Build Coastguard Worker 
1472*2d543d20SAndroid Build Coastguard Worker 		range_trans_rule_init(new_rule);
1473*2d543d20SAndroid Build Coastguard Worker 
1474*2d543d20SAndroid Build Coastguard Worker 		new_rule->next = *dst;
1475*2d543d20SAndroid Build Coastguard Worker 		*dst = new_rule;
1476*2d543d20SAndroid Build Coastguard Worker 
1477*2d543d20SAndroid Build Coastguard Worker 		if (type_set_convert(&rule->stypes, &new_rule->stypes,
1478*2d543d20SAndroid Build Coastguard Worker 				     mod))
1479*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1480*2d543d20SAndroid Build Coastguard Worker 
1481*2d543d20SAndroid Build Coastguard Worker 		if (type_set_convert(&rule->ttypes, &new_rule->ttypes,
1482*2d543d20SAndroid Build Coastguard Worker 				     mod))
1483*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1484*2d543d20SAndroid Build Coastguard Worker 
1485*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_convert(&rule->tclasses, &new_rule->tclasses, mod->map[SYM_CLASSES]))
1486*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1487*2d543d20SAndroid Build Coastguard Worker 
1488*2d543d20SAndroid Build Coastguard Worker 		if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state))
1489*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1490*2d543d20SAndroid Build Coastguard Worker 	}
1491*2d543d20SAndroid Build Coastguard Worker 	return 0;
1492*2d543d20SAndroid Build Coastguard Worker 
1493*2d543d20SAndroid Build Coastguard Worker       cleanup:
1494*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1495*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_list_destroy(new_rule);
1496*2d543d20SAndroid Build Coastguard Worker 	return -1;
1497*2d543d20SAndroid Build Coastguard Worker }
1498*2d543d20SAndroid Build Coastguard Worker 
copy_cond_list(cond_node_t * list,cond_node_t ** dst,policy_module_t * module,link_state_t * state)1499*2d543d20SAndroid Build Coastguard Worker static int copy_cond_list(cond_node_t * list, cond_node_t ** dst,
1500*2d543d20SAndroid Build Coastguard Worker 			  policy_module_t * module, link_state_t * state)
1501*2d543d20SAndroid Build Coastguard Worker {
1502*2d543d20SAndroid Build Coastguard Worker 	unsigned i;
1503*2d543d20SAndroid Build Coastguard Worker 	cond_node_t *cur, *new_node = NULL, *tail;
1504*2d543d20SAndroid Build Coastguard Worker 	cond_expr_t *cur_expr;
1505*2d543d20SAndroid Build Coastguard Worker 	tail = *dst;
1506*2d543d20SAndroid Build Coastguard Worker 	while (tail && tail->next)
1507*2d543d20SAndroid Build Coastguard Worker 		tail = tail->next;
1508*2d543d20SAndroid Build Coastguard Worker 
1509*2d543d20SAndroid Build Coastguard Worker 	cur = list;
1510*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1511*2d543d20SAndroid Build Coastguard Worker 		new_node = (cond_node_t *) malloc(sizeof(cond_node_t));
1512*2d543d20SAndroid Build Coastguard Worker 		if (!new_node) {
1513*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1514*2d543d20SAndroid Build Coastguard Worker 		}
1515*2d543d20SAndroid Build Coastguard Worker 		memset(new_node, 0, sizeof(cond_node_t));
1516*2d543d20SAndroid Build Coastguard Worker 
1517*2d543d20SAndroid Build Coastguard Worker 		new_node->cur_state = cur->cur_state;
1518*2d543d20SAndroid Build Coastguard Worker 		new_node->expr = cond_copy_expr(cur->expr);
1519*2d543d20SAndroid Build Coastguard Worker 		if (!new_node->expr)
1520*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1521*2d543d20SAndroid Build Coastguard Worker 		/* go back through and remap the expression */
1522*2d543d20SAndroid Build Coastguard Worker 		for (cur_expr = new_node->expr; cur_expr != NULL;
1523*2d543d20SAndroid Build Coastguard Worker 		     cur_expr = cur_expr->next) {
1524*2d543d20SAndroid Build Coastguard Worker 			/* expression nodes don't have a bool value of 0 - don't map them */
1525*2d543d20SAndroid Build Coastguard Worker 			if (cur_expr->expr_type != COND_BOOL)
1526*2d543d20SAndroid Build Coastguard Worker 				continue;
1527*2d543d20SAndroid Build Coastguard Worker 			assert(module->map[SYM_BOOLS][cur_expr->boolean - 1] != 0);
1528*2d543d20SAndroid Build Coastguard Worker 			cur_expr->boolean =
1529*2d543d20SAndroid Build Coastguard Worker 			    module->map[SYM_BOOLS][cur_expr->boolean - 1];
1530*2d543d20SAndroid Build Coastguard Worker 		}
1531*2d543d20SAndroid Build Coastguard Worker 		new_node->nbools = cur->nbools;
1532*2d543d20SAndroid Build Coastguard Worker 		/* FIXME should COND_MAX_BOOLS be used here? */
1533*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < min(cur->nbools, COND_MAX_BOOLS); i++) {
1534*2d543d20SAndroid Build Coastguard Worker 			uint32_t remapped_id =
1535*2d543d20SAndroid Build Coastguard Worker 			    module->map[SYM_BOOLS][cur->bool_ids[i] - 1];
1536*2d543d20SAndroid Build Coastguard Worker 			assert(remapped_id != 0);
1537*2d543d20SAndroid Build Coastguard Worker 			new_node->bool_ids[i] = remapped_id;
1538*2d543d20SAndroid Build Coastguard Worker 		}
1539*2d543d20SAndroid Build Coastguard Worker 		new_node->expr_pre_comp = cur->expr_pre_comp;
1540*2d543d20SAndroid Build Coastguard Worker 
1541*2d543d20SAndroid Build Coastguard Worker 		if (copy_avrule_list
1542*2d543d20SAndroid Build Coastguard Worker 		    (cur->avtrue_list, &new_node->avtrue_list, module, state)
1543*2d543d20SAndroid Build Coastguard Worker 		    || copy_avrule_list(cur->avfalse_list,
1544*2d543d20SAndroid Build Coastguard Worker 					&new_node->avfalse_list, module,
1545*2d543d20SAndroid Build Coastguard Worker 					state)) {
1546*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1547*2d543d20SAndroid Build Coastguard Worker 		}
1548*2d543d20SAndroid Build Coastguard Worker 
1549*2d543d20SAndroid Build Coastguard Worker 		if (*dst == NULL) {
1550*2d543d20SAndroid Build Coastguard Worker 			*dst = new_node;
1551*2d543d20SAndroid Build Coastguard Worker 		} else {
1552*2d543d20SAndroid Build Coastguard Worker 			tail->next = new_node;
1553*2d543d20SAndroid Build Coastguard Worker 		}
1554*2d543d20SAndroid Build Coastguard Worker 		tail = new_node;
1555*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1556*2d543d20SAndroid Build Coastguard Worker 	}
1557*2d543d20SAndroid Build Coastguard Worker 	return 0;
1558*2d543d20SAndroid Build Coastguard Worker       cleanup:
1559*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1560*2d543d20SAndroid Build Coastguard Worker 	cond_node_destroy(new_node);
1561*2d543d20SAndroid Build Coastguard Worker 	free(new_node);
1562*2d543d20SAndroid Build Coastguard Worker 	return -1;
1563*2d543d20SAndroid Build Coastguard Worker 
1564*2d543d20SAndroid Build Coastguard Worker }
1565*2d543d20SAndroid Build Coastguard Worker 
1566*2d543d20SAndroid Build Coastguard Worker /*********** functions that copy avrule_decls from module to base ***********/
1567*2d543d20SAndroid Build Coastguard Worker 
copy_identifiers(link_state_t * state,symtab_t * src_symtab,avrule_decl_t * dest_decl)1568*2d543d20SAndroid Build Coastguard Worker static int copy_identifiers(link_state_t * state, symtab_t * src_symtab,
1569*2d543d20SAndroid Build Coastguard Worker 			    avrule_decl_t * dest_decl)
1570*2d543d20SAndroid Build Coastguard Worker {
1571*2d543d20SAndroid Build Coastguard Worker 	int i, ret;
1572*2d543d20SAndroid Build Coastguard Worker 
1573*2d543d20SAndroid Build Coastguard Worker 	state->dest_decl = dest_decl;
1574*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
1575*2d543d20SAndroid Build Coastguard Worker 		if (copy_callback_f[i] != NULL) {
1576*2d543d20SAndroid Build Coastguard Worker 			ret =
1577*2d543d20SAndroid Build Coastguard Worker 			    hashtab_map(src_symtab[i].table, copy_callback_f[i],
1578*2d543d20SAndroid Build Coastguard Worker 					state);
1579*2d543d20SAndroid Build Coastguard Worker 			if (ret) {
1580*2d543d20SAndroid Build Coastguard Worker 				return ret;
1581*2d543d20SAndroid Build Coastguard Worker 			}
1582*2d543d20SAndroid Build Coastguard Worker 		}
1583*2d543d20SAndroid Build Coastguard Worker 	}
1584*2d543d20SAndroid Build Coastguard Worker 
1585*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(src_symtab[SYM_TYPES].table,
1586*2d543d20SAndroid Build Coastguard Worker 			type_bounds_copy_callback, state))
1587*2d543d20SAndroid Build Coastguard Worker 		return -1;
1588*2d543d20SAndroid Build Coastguard Worker 
1589*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(src_symtab[SYM_TYPES].table,
1590*2d543d20SAndroid Build Coastguard Worker 			alias_copy_callback, state))
1591*2d543d20SAndroid Build Coastguard Worker 		return -1;
1592*2d543d20SAndroid Build Coastguard Worker 
1593*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(src_symtab[SYM_ROLES].table,
1594*2d543d20SAndroid Build Coastguard Worker 			role_bounds_copy_callback, state))
1595*2d543d20SAndroid Build Coastguard Worker 		return -1;
1596*2d543d20SAndroid Build Coastguard Worker 
1597*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(src_symtab[SYM_USERS].table,
1598*2d543d20SAndroid Build Coastguard Worker 			user_bounds_copy_callback, state))
1599*2d543d20SAndroid Build Coastguard Worker 		return -1;
1600*2d543d20SAndroid Build Coastguard Worker 
1601*2d543d20SAndroid Build Coastguard Worker 	/* then fix bitmaps associated with those newly copied identifiers */
1602*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
1603*2d543d20SAndroid Build Coastguard Worker 		if (fix_callback_f[i] != NULL &&
1604*2d543d20SAndroid Build Coastguard Worker 		    hashtab_map(src_symtab[i].table, fix_callback_f[i],
1605*2d543d20SAndroid Build Coastguard Worker 				state)) {
1606*2d543d20SAndroid Build Coastguard Worker 			return -1;
1607*2d543d20SAndroid Build Coastguard Worker 		}
1608*2d543d20SAndroid Build Coastguard Worker 	}
1609*2d543d20SAndroid Build Coastguard Worker 	return 0;
1610*2d543d20SAndroid Build Coastguard Worker }
1611*2d543d20SAndroid Build Coastguard Worker 
copy_scope_index(scope_index_t * src,scope_index_t * dest,policy_module_t * module,link_state_t * state)1612*2d543d20SAndroid Build Coastguard Worker static int copy_scope_index(scope_index_t * src, scope_index_t * dest,
1613*2d543d20SAndroid Build Coastguard Worker 			    policy_module_t * module, link_state_t * state)
1614*2d543d20SAndroid Build Coastguard Worker {
1615*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j;
1616*2d543d20SAndroid Build Coastguard Worker 	uint32_t largest_mapped_class_value = 0;
1617*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
1618*2d543d20SAndroid Build Coastguard Worker 	/* copy the scoping information for this avrule decl block */
1619*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
1620*2d543d20SAndroid Build Coastguard Worker 		ebitmap_t *srcmap = src->scope + i;
1621*2d543d20SAndroid Build Coastguard Worker 		ebitmap_t *destmap = dest->scope + i;
1622*2d543d20SAndroid Build Coastguard Worker 		if (copy_callback_f[i] == NULL) {
1623*2d543d20SAndroid Build Coastguard Worker 			continue;
1624*2d543d20SAndroid Build Coastguard Worker 		}
1625*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(srcmap, node, j) {
1626*2d543d20SAndroid Build Coastguard Worker 			assert(module->map[i][j] != 0);
1627*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_set_bit
1628*2d543d20SAndroid Build Coastguard Worker 			    (destmap, module->map[i][j] - 1, 1) != 0) {
1629*2d543d20SAndroid Build Coastguard Worker 
1630*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1631*2d543d20SAndroid Build Coastguard Worker 			}
1632*2d543d20SAndroid Build Coastguard Worker 			if (i == SYM_CLASSES &&
1633*2d543d20SAndroid Build Coastguard Worker 			    largest_mapped_class_value <
1634*2d543d20SAndroid Build Coastguard Worker 			    module->map[SYM_CLASSES][j]) {
1635*2d543d20SAndroid Build Coastguard Worker 				largest_mapped_class_value =
1636*2d543d20SAndroid Build Coastguard Worker 				    module->map[SYM_CLASSES][j];
1637*2d543d20SAndroid Build Coastguard Worker 			}
1638*2d543d20SAndroid Build Coastguard Worker 		}
1639*2d543d20SAndroid Build Coastguard Worker 	}
1640*2d543d20SAndroid Build Coastguard Worker 
1641*2d543d20SAndroid Build Coastguard Worker 	/* next copy the enabled permissions data  */
1642*2d543d20SAndroid Build Coastguard Worker 	if ((dest->class_perms_map = calloc(largest_mapped_class_value,
1643*2d543d20SAndroid Build Coastguard Worker 					    sizeof(*dest->class_perms_map))) == NULL) {
1644*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1645*2d543d20SAndroid Build Coastguard Worker 	}
1646*2d543d20SAndroid Build Coastguard Worker 	dest->class_perms_len = largest_mapped_class_value;
1647*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < src->class_perms_len; i++) {
1648*2d543d20SAndroid Build Coastguard Worker 		const ebitmap_t *srcmap = src->class_perms_map + i;
1649*2d543d20SAndroid Build Coastguard Worker 		ebitmap_t *destmap =
1650*2d543d20SAndroid Build Coastguard Worker 		    dest->class_perms_map + module->map[SYM_CLASSES][i] - 1;
1651*2d543d20SAndroid Build Coastguard Worker 
1652*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_convert(srcmap, destmap, module->perm_map[i]))
1653*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1654*2d543d20SAndroid Build Coastguard Worker 	}
1655*2d543d20SAndroid Build Coastguard Worker 
1656*2d543d20SAndroid Build Coastguard Worker 	return 0;
1657*2d543d20SAndroid Build Coastguard Worker 
1658*2d543d20SAndroid Build Coastguard Worker       cleanup:
1659*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1660*2d543d20SAndroid Build Coastguard Worker 	return -1;
1661*2d543d20SAndroid Build Coastguard Worker }
1662*2d543d20SAndroid Build Coastguard Worker 
copy_avrule_decl(link_state_t * state,policy_module_t * module,avrule_decl_t * src_decl,avrule_decl_t * dest_decl)1663*2d543d20SAndroid Build Coastguard Worker static int copy_avrule_decl(link_state_t * state, policy_module_t * module,
1664*2d543d20SAndroid Build Coastguard Worker 			    avrule_decl_t * src_decl, avrule_decl_t * dest_decl)
1665*2d543d20SAndroid Build Coastguard Worker {
1666*2d543d20SAndroid Build Coastguard Worker 	int ret;
1667*2d543d20SAndroid Build Coastguard Worker 
1668*2d543d20SAndroid Build Coastguard Worker 	/* copy all of the RBAC and TE rules */
1669*2d543d20SAndroid Build Coastguard Worker 	if (copy_avrule_list
1670*2d543d20SAndroid Build Coastguard Worker 	    (src_decl->avrules, &dest_decl->avrules, module, state) == -1
1671*2d543d20SAndroid Build Coastguard Worker 	    || copy_role_trans_list(src_decl->role_tr_rules,
1672*2d543d20SAndroid Build Coastguard Worker 				    &dest_decl->role_tr_rules, module,
1673*2d543d20SAndroid Build Coastguard Worker 				    state) == -1
1674*2d543d20SAndroid Build Coastguard Worker 	    || copy_role_allow_list(src_decl->role_allow_rules,
1675*2d543d20SAndroid Build Coastguard Worker 				    &dest_decl->role_allow_rules, module,
1676*2d543d20SAndroid Build Coastguard Worker 				    state) == -1
1677*2d543d20SAndroid Build Coastguard Worker 	    || copy_cond_list(src_decl->cond_list, &dest_decl->cond_list,
1678*2d543d20SAndroid Build Coastguard Worker 			      module, state) == -1) {
1679*2d543d20SAndroid Build Coastguard Worker 		return -1;
1680*2d543d20SAndroid Build Coastguard Worker 	}
1681*2d543d20SAndroid Build Coastguard Worker 
1682*2d543d20SAndroid Build Coastguard Worker 	if (copy_filename_trans_list(src_decl->filename_trans_rules,
1683*2d543d20SAndroid Build Coastguard Worker 				     &dest_decl->filename_trans_rules,
1684*2d543d20SAndroid Build Coastguard Worker 				     module, state))
1685*2d543d20SAndroid Build Coastguard Worker 		return -1;
1686*2d543d20SAndroid Build Coastguard Worker 
1687*2d543d20SAndroid Build Coastguard Worker 	if (copy_range_trans_list(src_decl->range_tr_rules,
1688*2d543d20SAndroid Build Coastguard Worker 				  &dest_decl->range_tr_rules, module, state))
1689*2d543d20SAndroid Build Coastguard Worker 		return -1;
1690*2d543d20SAndroid Build Coastguard Worker 
1691*2d543d20SAndroid Build Coastguard Worker 	/* finally copy any identifiers local to this declaration */
1692*2d543d20SAndroid Build Coastguard Worker 	ret = copy_identifiers(state, src_decl->symtab, dest_decl);
1693*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0) {
1694*2d543d20SAndroid Build Coastguard Worker 		return ret;
1695*2d543d20SAndroid Build Coastguard Worker 	}
1696*2d543d20SAndroid Build Coastguard Worker 
1697*2d543d20SAndroid Build Coastguard Worker 	/* then copy required and declared scope indices here */
1698*2d543d20SAndroid Build Coastguard Worker 	if (copy_scope_index(&src_decl->required, &dest_decl->required,
1699*2d543d20SAndroid Build Coastguard Worker 			     module, state) == -1 ||
1700*2d543d20SAndroid Build Coastguard Worker 	    copy_scope_index(&src_decl->declared, &dest_decl->declared,
1701*2d543d20SAndroid Build Coastguard Worker 			     module, state) == -1) {
1702*2d543d20SAndroid Build Coastguard Worker 		return -1;
1703*2d543d20SAndroid Build Coastguard Worker 	}
1704*2d543d20SAndroid Build Coastguard Worker 
1705*2d543d20SAndroid Build Coastguard Worker 	return 0;
1706*2d543d20SAndroid Build Coastguard Worker }
1707*2d543d20SAndroid Build Coastguard Worker 
copy_avrule_block(link_state_t * state,policy_module_t * module,avrule_block_t * block)1708*2d543d20SAndroid Build Coastguard Worker static int copy_avrule_block(link_state_t * state, policy_module_t * module,
1709*2d543d20SAndroid Build Coastguard Worker 			     avrule_block_t * block)
1710*2d543d20SAndroid Build Coastguard Worker {
1711*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *new_block = avrule_block_create();
1712*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *decl, *last_decl = NULL;
1713*2d543d20SAndroid Build Coastguard Worker 	int ret;
1714*2d543d20SAndroid Build Coastguard Worker 
1715*2d543d20SAndroid Build Coastguard Worker 	if (new_block == NULL) {
1716*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
1717*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
1718*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1719*2d543d20SAndroid Build Coastguard Worker 	}
1720*2d543d20SAndroid Build Coastguard Worker 
1721*2d543d20SAndroid Build Coastguard Worker 	new_block->flags = block->flags;
1722*2d543d20SAndroid Build Coastguard Worker 
1723*2d543d20SAndroid Build Coastguard Worker 	for (decl = block->branch_list; decl != NULL; decl = decl->next) {
1724*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *new_decl =
1725*2d543d20SAndroid Build Coastguard Worker 		    avrule_decl_create(state->next_decl_id);
1726*2d543d20SAndroid Build Coastguard Worker 		if (new_decl == NULL) {
1727*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Out of memory!");
1728*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
1729*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1730*2d543d20SAndroid Build Coastguard Worker 		}
1731*2d543d20SAndroid Build Coastguard Worker 
1732*2d543d20SAndroid Build Coastguard Worker 		if (module->policy->name != NULL) {
1733*2d543d20SAndroid Build Coastguard Worker 			new_decl->module_name = strdup(module->policy->name);
1734*2d543d20SAndroid Build Coastguard Worker 			if (new_decl->module_name == NULL) {
1735*2d543d20SAndroid Build Coastguard Worker 				ERR(state->handle, "Out of memory");
1736*2d543d20SAndroid Build Coastguard Worker 				avrule_decl_destroy(new_decl);
1737*2d543d20SAndroid Build Coastguard Worker 				ret = -1;
1738*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1739*2d543d20SAndroid Build Coastguard Worker 			}
1740*2d543d20SAndroid Build Coastguard Worker 		}
1741*2d543d20SAndroid Build Coastguard Worker 
1742*2d543d20SAndroid Build Coastguard Worker 		if (last_decl == NULL) {
1743*2d543d20SAndroid Build Coastguard Worker 			new_block->branch_list = new_decl;
1744*2d543d20SAndroid Build Coastguard Worker 		} else {
1745*2d543d20SAndroid Build Coastguard Worker 			last_decl->next = new_decl;
1746*2d543d20SAndroid Build Coastguard Worker 		}
1747*2d543d20SAndroid Build Coastguard Worker 		last_decl = new_decl;
1748*2d543d20SAndroid Build Coastguard Worker 		state->base->decl_val_to_struct[state->next_decl_id - 1] =
1749*2d543d20SAndroid Build Coastguard Worker 		    new_decl;
1750*2d543d20SAndroid Build Coastguard Worker 		state->decl_to_mod[state->next_decl_id] = module->policy;
1751*2d543d20SAndroid Build Coastguard Worker 
1752*2d543d20SAndroid Build Coastguard Worker 		module->avdecl_map[decl->decl_id] = new_decl->decl_id;
1753*2d543d20SAndroid Build Coastguard Worker 
1754*2d543d20SAndroid Build Coastguard Worker 		ret = copy_avrule_decl(state, module, decl, new_decl);
1755*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
1756*2d543d20SAndroid Build Coastguard Worker 			avrule_decl_destroy(new_decl);
1757*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1758*2d543d20SAndroid Build Coastguard Worker 		}
1759*2d543d20SAndroid Build Coastguard Worker 
1760*2d543d20SAndroid Build Coastguard Worker 		state->next_decl_id++;
1761*2d543d20SAndroid Build Coastguard Worker 	}
1762*2d543d20SAndroid Build Coastguard Worker 	state->last_avrule_block->next = new_block;
1763*2d543d20SAndroid Build Coastguard Worker 	state->last_avrule_block = new_block;
1764*2d543d20SAndroid Build Coastguard Worker 	return 0;
1765*2d543d20SAndroid Build Coastguard Worker 
1766*2d543d20SAndroid Build Coastguard Worker       cleanup:
1767*2d543d20SAndroid Build Coastguard Worker 	avrule_block_list_destroy(new_block);
1768*2d543d20SAndroid Build Coastguard Worker 	return ret;
1769*2d543d20SAndroid Build Coastguard Worker }
1770*2d543d20SAndroid Build Coastguard Worker 
scope_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1771*2d543d20SAndroid Build Coastguard Worker static int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
1772*2d543d20SAndroid Build Coastguard Worker 			       void *data)
1773*2d543d20SAndroid Build Coastguard Worker {
1774*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
1775*2d543d20SAndroid Build Coastguard Worker 	int ret;
1776*2d543d20SAndroid Build Coastguard Worker 	char *id = key, *new_id = NULL;
1777*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope, *base_scope;
1778*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *) data;
1779*2d543d20SAndroid Build Coastguard Worker 	uint32_t symbol_num = state->symbol_num;
1780*2d543d20SAndroid Build Coastguard Worker 	uint32_t *avdecl_map = state->cur->avdecl_map;
1781*2d543d20SAndroid Build Coastguard Worker 
1782*2d543d20SAndroid Build Coastguard Worker 	scope = (scope_datum_t *) datum;
1783*2d543d20SAndroid Build Coastguard Worker 
1784*2d543d20SAndroid Build Coastguard Worker 	/* check if the base already has a scope entry */
1785*2d543d20SAndroid Build Coastguard Worker 	base_scope = hashtab_search(state->base->scope[symbol_num].table, id);
1786*2d543d20SAndroid Build Coastguard Worker 	if (base_scope == NULL) {
1787*2d543d20SAndroid Build Coastguard Worker 		scope_datum_t *new_scope;
1788*2d543d20SAndroid Build Coastguard Worker 		if ((new_id = strdup(id)) == NULL) {
1789*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1790*2d543d20SAndroid Build Coastguard Worker 		}
1791*2d543d20SAndroid Build Coastguard Worker 
1792*2d543d20SAndroid Build Coastguard Worker 		if ((new_scope =
1793*2d543d20SAndroid Build Coastguard Worker 		     (scope_datum_t *) calloc(1, sizeof(*new_scope))) == NULL) {
1794*2d543d20SAndroid Build Coastguard Worker 			free(new_id);
1795*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1796*2d543d20SAndroid Build Coastguard Worker 		}
1797*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(state->base->scope[symbol_num].table,
1798*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) new_id,
1799*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) new_scope);
1800*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
1801*2d543d20SAndroid Build Coastguard Worker 			free(new_id);
1802*2d543d20SAndroid Build Coastguard Worker 			free(new_scope);
1803*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1804*2d543d20SAndroid Build Coastguard Worker 		}
1805*2d543d20SAndroid Build Coastguard Worker 		new_scope->scope = SCOPE_REQ;	/* this is reset further down */
1806*2d543d20SAndroid Build Coastguard Worker 		base_scope = new_scope;
1807*2d543d20SAndroid Build Coastguard Worker 	}
1808*2d543d20SAndroid Build Coastguard Worker 	if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_DECL) {
1809*2d543d20SAndroid Build Coastguard Worker 		/* this module declared symbol, so overwrite the old
1810*2d543d20SAndroid Build Coastguard Worker 		 * list with the new decl ids */
1811*2d543d20SAndroid Build Coastguard Worker 		base_scope->scope = SCOPE_DECL;
1812*2d543d20SAndroid Build Coastguard Worker 		free(base_scope->decl_ids);
1813*2d543d20SAndroid Build Coastguard Worker 		base_scope->decl_ids = NULL;
1814*2d543d20SAndroid Build Coastguard Worker 		base_scope->decl_ids_len = 0;
1815*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < scope->decl_ids_len; i++) {
1816*2d543d20SAndroid Build Coastguard Worker 			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1817*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids_len,
1818*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids) == -1) {
1819*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1820*2d543d20SAndroid Build Coastguard Worker 			}
1821*2d543d20SAndroid Build Coastguard Worker 		}
1822*2d543d20SAndroid Build Coastguard Worker 	} else if (base_scope->scope == SCOPE_DECL && scope->scope == SCOPE_REQ) {
1823*2d543d20SAndroid Build Coastguard Worker 		/* this module depended on a symbol that now exists,
1824*2d543d20SAndroid Build Coastguard Worker 		 * so don't do anything */
1825*2d543d20SAndroid Build Coastguard Worker 	} else if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_REQ) {
1826*2d543d20SAndroid Build Coastguard Worker 		/* symbol is still required, so add to the list */
1827*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < scope->decl_ids_len; i++) {
1828*2d543d20SAndroid Build Coastguard Worker 			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1829*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids_len,
1830*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids) == -1) {
1831*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1832*2d543d20SAndroid Build Coastguard Worker 			}
1833*2d543d20SAndroid Build Coastguard Worker 		}
1834*2d543d20SAndroid Build Coastguard Worker 	} else {
1835*2d543d20SAndroid Build Coastguard Worker 		/* this module declared a symbol, and it was already
1836*2d543d20SAndroid Build Coastguard Worker 		 * declared.  only roles and users may be multiply
1837*2d543d20SAndroid Build Coastguard Worker 		 * declared; for all others this is an error. */
1838*2d543d20SAndroid Build Coastguard Worker 		if (symbol_num != SYM_ROLES && symbol_num != SYM_USERS) {
1839*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
1840*2d543d20SAndroid Build Coastguard Worker 			    "%s: Duplicate declaration in module: %s %s",
1841*2d543d20SAndroid Build Coastguard Worker 			    state->cur_mod_name,
1842*2d543d20SAndroid Build Coastguard Worker 			    symtab_names[state->symbol_num], id);
1843*2d543d20SAndroid Build Coastguard Worker 			return -1;
1844*2d543d20SAndroid Build Coastguard Worker 		}
1845*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < scope->decl_ids_len; i++) {
1846*2d543d20SAndroid Build Coastguard Worker 			if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1847*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids_len,
1848*2d543d20SAndroid Build Coastguard Worker 				       &base_scope->decl_ids) == -1) {
1849*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1850*2d543d20SAndroid Build Coastguard Worker 			}
1851*2d543d20SAndroid Build Coastguard Worker 		}
1852*2d543d20SAndroid Build Coastguard Worker 	}
1853*2d543d20SAndroid Build Coastguard Worker 	return 0;
1854*2d543d20SAndroid Build Coastguard Worker 
1855*2d543d20SAndroid Build Coastguard Worker       cleanup:
1856*2d543d20SAndroid Build Coastguard Worker 	ERR(state->handle, "Out of memory!");
1857*2d543d20SAndroid Build Coastguard Worker 	return -1;
1858*2d543d20SAndroid Build Coastguard Worker }
1859*2d543d20SAndroid Build Coastguard Worker 
1860*2d543d20SAndroid Build Coastguard Worker /* Copy a module over to a base, remapping all values within.  After
1861*2d543d20SAndroid Build Coastguard Worker  * all identifiers and rules are done, copy the scoping information.
1862*2d543d20SAndroid Build Coastguard Worker  * This is when it checks for duplicate declarations. */
copy_module(link_state_t * state,policy_module_t * module)1863*2d543d20SAndroid Build Coastguard Worker static int copy_module(link_state_t * state, policy_module_t * module)
1864*2d543d20SAndroid Build Coastguard Worker {
1865*2d543d20SAndroid Build Coastguard Worker 	int i, ret;
1866*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *cur;
1867*2d543d20SAndroid Build Coastguard Worker 	state->cur = module;
1868*2d543d20SAndroid Build Coastguard Worker 	state->cur_mod_name = module->policy->name;
1869*2d543d20SAndroid Build Coastguard Worker 
1870*2d543d20SAndroid Build Coastguard Worker 	/* first copy all of the identifiers */
1871*2d543d20SAndroid Build Coastguard Worker 	ret = copy_identifiers(state, module->policy->symtab, NULL);
1872*2d543d20SAndroid Build Coastguard Worker 	if (ret) {
1873*2d543d20SAndroid Build Coastguard Worker 		return ret;
1874*2d543d20SAndroid Build Coastguard Worker 	}
1875*2d543d20SAndroid Build Coastguard Worker 
1876*2d543d20SAndroid Build Coastguard Worker 	/* next copy all of the avrule blocks */
1877*2d543d20SAndroid Build Coastguard Worker 	for (cur = module->policy->global; cur != NULL; cur = cur->next) {
1878*2d543d20SAndroid Build Coastguard Worker 		ret = copy_avrule_block(state, module, cur);
1879*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
1880*2d543d20SAndroid Build Coastguard Worker 			return ret;
1881*2d543d20SAndroid Build Coastguard Worker 		}
1882*2d543d20SAndroid Build Coastguard Worker 	}
1883*2d543d20SAndroid Build Coastguard Worker 
1884*2d543d20SAndroid Build Coastguard Worker 	/* then copy the scoping tables */
1885*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
1886*2d543d20SAndroid Build Coastguard Worker 		state->symbol_num = i;
1887*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_map
1888*2d543d20SAndroid Build Coastguard Worker 		    (module->policy->scope[i].table, scope_copy_callback,
1889*2d543d20SAndroid Build Coastguard Worker 		     state)) {
1890*2d543d20SAndroid Build Coastguard Worker 			return -1;
1891*2d543d20SAndroid Build Coastguard Worker 		}
1892*2d543d20SAndroid Build Coastguard Worker 	}
1893*2d543d20SAndroid Build Coastguard Worker 
1894*2d543d20SAndroid Build Coastguard Worker 	return 0;
1895*2d543d20SAndroid Build Coastguard Worker }
1896*2d543d20SAndroid Build Coastguard Worker 
1897*2d543d20SAndroid Build Coastguard Worker /***** functions that check requirements and enable blocks in a module ******/
1898*2d543d20SAndroid Build Coastguard Worker 
1899*2d543d20SAndroid Build Coastguard Worker /* borrowed from checkpolicy.c */
1900*2d543d20SAndroid Build Coastguard Worker 
1901*2d543d20SAndroid Build Coastguard Worker struct find_perm_arg {
1902*2d543d20SAndroid Build Coastguard Worker 	unsigned int valuep;
1903*2d543d20SAndroid Build Coastguard Worker 	hashtab_key_t key;
1904*2d543d20SAndroid Build Coastguard Worker };
1905*2d543d20SAndroid Build Coastguard Worker 
find_perm(hashtab_key_t key,hashtab_datum_t datum,void * varg)1906*2d543d20SAndroid Build Coastguard Worker static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg)
1907*2d543d20SAndroid Build Coastguard Worker {
1908*2d543d20SAndroid Build Coastguard Worker 
1909*2d543d20SAndroid Build Coastguard Worker 	struct find_perm_arg *arg = varg;
1910*2d543d20SAndroid Build Coastguard Worker 
1911*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum = (perm_datum_t *) datum;
1912*2d543d20SAndroid Build Coastguard Worker 	if (arg->valuep == perdatum->s.value) {
1913*2d543d20SAndroid Build Coastguard Worker 		arg->key = key;
1914*2d543d20SAndroid Build Coastguard Worker 		return 1;
1915*2d543d20SAndroid Build Coastguard Worker 	}
1916*2d543d20SAndroid Build Coastguard Worker 
1917*2d543d20SAndroid Build Coastguard Worker 	return 0;
1918*2d543d20SAndroid Build Coastguard Worker }
1919*2d543d20SAndroid Build Coastguard Worker 
1920*2d543d20SAndroid Build Coastguard Worker /* Check if the requirements are met for a single declaration.  If all
1921*2d543d20SAndroid Build Coastguard Worker  * are met return 1.  For the first requirement found to be missing,
1922*2d543d20SAndroid Build Coastguard Worker  * if 'missing_sym_num' and 'missing_value' are both not NULL then
1923*2d543d20SAndroid Build Coastguard Worker  * write to them the symbol number and value for the missing
1924*2d543d20SAndroid Build Coastguard Worker  * declaration.  Then return 0 to indicate a missing declaration.
1925*2d543d20SAndroid Build Coastguard Worker  * Note that if a declaration had no requirement at all (e.g., an ELSE
1926*2d543d20SAndroid Build Coastguard Worker  * block) this returns 1. */
is_decl_requires_met(link_state_t * state,const avrule_decl_t * decl,struct missing_requirement * req)1927*2d543d20SAndroid Build Coastguard Worker static int is_decl_requires_met(link_state_t * state,
1928*2d543d20SAndroid Build Coastguard Worker 				const avrule_decl_t * decl,
1929*2d543d20SAndroid Build Coastguard Worker 				struct missing_requirement *req)
1930*2d543d20SAndroid Build Coastguard Worker {
1931*2d543d20SAndroid Build Coastguard Worker 	/* (This algorithm is very unoptimized.  It performs many
1932*2d543d20SAndroid Build Coastguard Worker 	 * redundant checks.  A very obvious improvement is to cache
1933*2d543d20SAndroid Build Coastguard Worker 	 * which symbols have been verified, so that they do not need
1934*2d543d20SAndroid Build Coastguard Worker 	 * to be re-checked.) */
1935*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j;
1936*2d543d20SAndroid Build Coastguard Worker 	const ebitmap_t *bitmap;
1937*2d543d20SAndroid Build Coastguard Worker 	const char *id, *perm_id;
1938*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *pol = state->base;
1939*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
1940*2d543d20SAndroid Build Coastguard Worker 
1941*2d543d20SAndroid Build Coastguard Worker 	/* check that all symbols have been satisfied */
1942*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
1943*2d543d20SAndroid Build Coastguard Worker 		if (i == SYM_CLASSES) {
1944*2d543d20SAndroid Build Coastguard Worker 			/* classes will be checked during permissions
1945*2d543d20SAndroid Build Coastguard Worker 			 * checking phase below */
1946*2d543d20SAndroid Build Coastguard Worker 			continue;
1947*2d543d20SAndroid Build Coastguard Worker 		}
1948*2d543d20SAndroid Build Coastguard Worker 		bitmap = &decl->required.scope[i];
1949*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(bitmap, node, j) {
1950*2d543d20SAndroid Build Coastguard Worker 			/* check base's scope table */
1951*2d543d20SAndroid Build Coastguard Worker 			id = pol->sym_val_to_name[i][j];
1952*2d543d20SAndroid Build Coastguard Worker 			if (!is_id_enabled(id, state->base, i)) {
1953*2d543d20SAndroid Build Coastguard Worker 				/* this symbol was not found */
1954*2d543d20SAndroid Build Coastguard Worker 				if (req != NULL) {
1955*2d543d20SAndroid Build Coastguard Worker 					req->symbol_type = i;
1956*2d543d20SAndroid Build Coastguard Worker 					req->symbol_value = j + 1;
1957*2d543d20SAndroid Build Coastguard Worker 				}
1958*2d543d20SAndroid Build Coastguard Worker 				return 0;
1959*2d543d20SAndroid Build Coastguard Worker 			}
1960*2d543d20SAndroid Build Coastguard Worker 		}
1961*2d543d20SAndroid Build Coastguard Worker 	}
1962*2d543d20SAndroid Build Coastguard Worker 	/* check that all classes and permissions have been satisfied */
1963*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < decl->required.class_perms_len; i++) {
1964*2d543d20SAndroid Build Coastguard Worker 		const class_datum_t *cladatum = pol->class_val_to_struct[i];
1965*2d543d20SAndroid Build Coastguard Worker 		const scope_datum_t *scope;
1966*2d543d20SAndroid Build Coastguard Worker 
1967*2d543d20SAndroid Build Coastguard Worker 		bitmap = &decl->required.class_perms_map[i];
1968*2d543d20SAndroid Build Coastguard Worker 		id = pol->p_class_val_to_name[i];
1969*2d543d20SAndroid Build Coastguard Worker 
1970*2d543d20SAndroid Build Coastguard Worker 
1971*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_enabled(id, state->base, SYM_CLASSES)) {
1972*2d543d20SAndroid Build Coastguard Worker 			return 0;
1973*2d543d20SAndroid Build Coastguard Worker 		}
1974*2d543d20SAndroid Build Coastguard Worker 
1975*2d543d20SAndroid Build Coastguard Worker 		scope = hashtab_search(state->base->p_classes_scope.table, id);
1976*2d543d20SAndroid Build Coastguard Worker 		if (scope == NULL) {
1977*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle,
1978*2d543d20SAndroid Build Coastguard Worker 				"Could not find scope information for class %s",
1979*2d543d20SAndroid Build Coastguard Worker 				id);
1980*2d543d20SAndroid Build Coastguard Worker 			return -1;
1981*2d543d20SAndroid Build Coastguard Worker 		}
1982*2d543d20SAndroid Build Coastguard Worker 
1983*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(bitmap, node, j) {
1984*2d543d20SAndroid Build Coastguard Worker 			struct find_perm_arg fparg;
1985*2d543d20SAndroid Build Coastguard Worker 			uint32_t perm_value = j + 1;
1986*2d543d20SAndroid Build Coastguard Worker 			int rc;
1987*2d543d20SAndroid Build Coastguard Worker 
1988*2d543d20SAndroid Build Coastguard Worker 			fparg.valuep = perm_value;
1989*2d543d20SAndroid Build Coastguard Worker 			fparg.key = NULL;
1990*2d543d20SAndroid Build Coastguard Worker 
1991*2d543d20SAndroid Build Coastguard Worker 			(void)hashtab_map(cladatum->permissions.table, find_perm,
1992*2d543d20SAndroid Build Coastguard Worker 				    &fparg);
1993*2d543d20SAndroid Build Coastguard Worker 			if (fparg.key == NULL && cladatum->comdatum != NULL) {
1994*2d543d20SAndroid Build Coastguard Worker 				rc = hashtab_map(cladatum->comdatum->permissions.table,
1995*2d543d20SAndroid Build Coastguard Worker 						 find_perm, &fparg);
1996*2d543d20SAndroid Build Coastguard Worker 				assert(rc == 1);
1997*2d543d20SAndroid Build Coastguard Worker 			}
1998*2d543d20SAndroid Build Coastguard Worker 			perm_id = fparg.key;
1999*2d543d20SAndroid Build Coastguard Worker 
2000*2d543d20SAndroid Build Coastguard Worker 			assert(perm_id != NULL);
2001*2d543d20SAndroid Build Coastguard Worker 			if (!is_perm_existent(cladatum, perm_id)) {
2002*2d543d20SAndroid Build Coastguard Worker 				if (req != NULL) {
2003*2d543d20SAndroid Build Coastguard Worker 					req->symbol_type = SYM_CLASSES;
2004*2d543d20SAndroid Build Coastguard Worker 					req->symbol_value = i + 1;
2005*2d543d20SAndroid Build Coastguard Worker 					req->perm_value = perm_value;
2006*2d543d20SAndroid Build Coastguard Worker 				}
2007*2d543d20SAndroid Build Coastguard Worker 				return 0;
2008*2d543d20SAndroid Build Coastguard Worker 			}
2009*2d543d20SAndroid Build Coastguard Worker 		}
2010*2d543d20SAndroid Build Coastguard Worker 	}
2011*2d543d20SAndroid Build Coastguard Worker 
2012*2d543d20SAndroid Build Coastguard Worker 	/* all requirements have been met */
2013*2d543d20SAndroid Build Coastguard Worker 	return 1;
2014*2d543d20SAndroid Build Coastguard Worker }
2015*2d543d20SAndroid Build Coastguard Worker 
debug_requirements(link_state_t * state,policydb_t * p)2016*2d543d20SAndroid Build Coastguard Worker static int debug_requirements(link_state_t * state, policydb_t * p)
2017*2d543d20SAndroid Build Coastguard Worker {
2018*2d543d20SAndroid Build Coastguard Worker 	int ret;
2019*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *cur;
2020*2d543d20SAndroid Build Coastguard Worker 	missing_requirement_t req;
2021*2d543d20SAndroid Build Coastguard Worker 	memset(&req, 0, sizeof(req));
2022*2d543d20SAndroid Build Coastguard Worker 
2023*2d543d20SAndroid Build Coastguard Worker 	for (cur = p->global; cur != NULL; cur = cur->next) {
2024*2d543d20SAndroid Build Coastguard Worker 		if (cur->enabled != NULL || cur->branch_list == NULL)
2025*2d543d20SAndroid Build Coastguard Worker 			continue;
2026*2d543d20SAndroid Build Coastguard Worker 
2027*2d543d20SAndroid Build Coastguard Worker 		ret = is_decl_requires_met(state, cur->branch_list, &req);
2028*2d543d20SAndroid Build Coastguard Worker 		if (ret < 0) {
2029*2d543d20SAndroid Build Coastguard Worker 			return ret;
2030*2d543d20SAndroid Build Coastguard Worker 		} else if (ret == 0) {
2031*2d543d20SAndroid Build Coastguard Worker 			const char *mod_name = cur->branch_list->module_name ?
2032*2d543d20SAndroid Build Coastguard Worker 			    cur->branch_list->module_name : "BASE";
2033*2d543d20SAndroid Build Coastguard Worker 			if (req.symbol_type == SYM_CLASSES) {
2034*2d543d20SAndroid Build Coastguard Worker 				struct find_perm_arg fparg;
2035*2d543d20SAndroid Build Coastguard Worker 
2036*2d543d20SAndroid Build Coastguard Worker 				class_datum_t *cladatum;
2037*2d543d20SAndroid Build Coastguard Worker 				cladatum = p->class_val_to_struct[req.symbol_value - 1];
2038*2d543d20SAndroid Build Coastguard Worker 
2039*2d543d20SAndroid Build Coastguard Worker 				fparg.valuep = req.perm_value;
2040*2d543d20SAndroid Build Coastguard Worker 				fparg.key = NULL;
2041*2d543d20SAndroid Build Coastguard Worker 				(void)hashtab_map(cladatum->permissions.table,
2042*2d543d20SAndroid Build Coastguard Worker 						  find_perm, &fparg);
2043*2d543d20SAndroid Build Coastguard Worker 
2044*2d543d20SAndroid Build Coastguard Worker 				if (cur->flags & AVRULE_OPTIONAL) {
2045*2d543d20SAndroid Build Coastguard Worker 					ERR(state->handle,
2046*2d543d20SAndroid Build Coastguard Worker 					    "%s[%d]'s optional requirements were not met: class %s, permission %s",
2047*2d543d20SAndroid Build Coastguard Worker 					    mod_name, cur->branch_list->decl_id,
2048*2d543d20SAndroid Build Coastguard Worker 					    p->p_class_val_to_name[req.symbol_value - 1],
2049*2d543d20SAndroid Build Coastguard Worker 					    fparg.key);
2050*2d543d20SAndroid Build Coastguard Worker 				} else {
2051*2d543d20SAndroid Build Coastguard Worker 					ERR(state->handle,
2052*2d543d20SAndroid Build Coastguard Worker 					    "%s[%d]'s global requirements were not met: class %s, permission %s",
2053*2d543d20SAndroid Build Coastguard Worker 					    mod_name, cur->branch_list->decl_id,
2054*2d543d20SAndroid Build Coastguard Worker 					    p->p_class_val_to_name[req.symbol_value - 1],
2055*2d543d20SAndroid Build Coastguard Worker 					    fparg.key);
2056*2d543d20SAndroid Build Coastguard Worker 				}
2057*2d543d20SAndroid Build Coastguard Worker 			} else {
2058*2d543d20SAndroid Build Coastguard Worker 				if (cur->flags & AVRULE_OPTIONAL) {
2059*2d543d20SAndroid Build Coastguard Worker 					ERR(state->handle,
2060*2d543d20SAndroid Build Coastguard Worker 					    "%s[%d]'s optional requirements were not met: %s %s",
2061*2d543d20SAndroid Build Coastguard Worker 					    mod_name, cur->branch_list->decl_id,
2062*2d543d20SAndroid Build Coastguard Worker 					    symtab_names[req.symbol_type],
2063*2d543d20SAndroid Build Coastguard Worker 					    p->sym_val_to_name[req.
2064*2d543d20SAndroid Build Coastguard Worker 							       symbol_type][req.
2065*2d543d20SAndroid Build Coastguard Worker 									    symbol_value
2066*2d543d20SAndroid Build Coastguard Worker 									    -
2067*2d543d20SAndroid Build Coastguard Worker 									    1]);
2068*2d543d20SAndroid Build Coastguard Worker 				} else {
2069*2d543d20SAndroid Build Coastguard Worker 					ERR(state->handle,
2070*2d543d20SAndroid Build Coastguard Worker 					    "%s[%d]'s global requirements were not met: %s %s",
2071*2d543d20SAndroid Build Coastguard Worker 					    mod_name, cur->branch_list->decl_id,
2072*2d543d20SAndroid Build Coastguard Worker 					    symtab_names[req.symbol_type],
2073*2d543d20SAndroid Build Coastguard Worker 					    p->sym_val_to_name[req.
2074*2d543d20SAndroid Build Coastguard Worker 							       symbol_type][req.
2075*2d543d20SAndroid Build Coastguard Worker 									    symbol_value
2076*2d543d20SAndroid Build Coastguard Worker 									    -
2077*2d543d20SAndroid Build Coastguard Worker 									    1]);
2078*2d543d20SAndroid Build Coastguard Worker 				}
2079*2d543d20SAndroid Build Coastguard Worker 			}
2080*2d543d20SAndroid Build Coastguard Worker 		}
2081*2d543d20SAndroid Build Coastguard Worker 	}
2082*2d543d20SAndroid Build Coastguard Worker 	return 0;
2083*2d543d20SAndroid Build Coastguard Worker }
2084*2d543d20SAndroid Build Coastguard Worker 
print_missing_requirements(link_state_t * state,avrule_block_t * cur,missing_requirement_t * req)2085*2d543d20SAndroid Build Coastguard Worker static void print_missing_requirements(link_state_t * state,
2086*2d543d20SAndroid Build Coastguard Worker 				       avrule_block_t * cur,
2087*2d543d20SAndroid Build Coastguard Worker 				       missing_requirement_t * req)
2088*2d543d20SAndroid Build Coastguard Worker {
2089*2d543d20SAndroid Build Coastguard Worker 	policydb_t *p = state->base;
2090*2d543d20SAndroid Build Coastguard Worker 	const char *mod_name = cur->branch_list->module_name ?
2091*2d543d20SAndroid Build Coastguard Worker 	    cur->branch_list->module_name : "BASE";
2092*2d543d20SAndroid Build Coastguard Worker 
2093*2d543d20SAndroid Build Coastguard Worker 	if (req->symbol_type == SYM_CLASSES) {
2094*2d543d20SAndroid Build Coastguard Worker 
2095*2d543d20SAndroid Build Coastguard Worker 		struct find_perm_arg fparg;
2096*2d543d20SAndroid Build Coastguard Worker 
2097*2d543d20SAndroid Build Coastguard Worker 		class_datum_t *cladatum;
2098*2d543d20SAndroid Build Coastguard Worker 		cladatum = p->class_val_to_struct[req->symbol_value - 1];
2099*2d543d20SAndroid Build Coastguard Worker 
2100*2d543d20SAndroid Build Coastguard Worker 		fparg.valuep = req->perm_value;
2101*2d543d20SAndroid Build Coastguard Worker 		fparg.key = NULL;
2102*2d543d20SAndroid Build Coastguard Worker 		(void)hashtab_map(cladatum->permissions.table, find_perm, &fparg);
2103*2d543d20SAndroid Build Coastguard Worker 
2104*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
2105*2d543d20SAndroid Build Coastguard Worker 		    "%s's global requirements were not met: class %s, permission %s",
2106*2d543d20SAndroid Build Coastguard Worker 		    mod_name,
2107*2d543d20SAndroid Build Coastguard Worker 		    p->p_class_val_to_name[req->symbol_value - 1], fparg.key);
2108*2d543d20SAndroid Build Coastguard Worker 	} else {
2109*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
2110*2d543d20SAndroid Build Coastguard Worker 		    "%s's global requirements were not met: %s %s",
2111*2d543d20SAndroid Build Coastguard Worker 		    mod_name,
2112*2d543d20SAndroid Build Coastguard Worker 		    symtab_names[req->symbol_type],
2113*2d543d20SAndroid Build Coastguard Worker 		    p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]);
2114*2d543d20SAndroid Build Coastguard Worker 	}
2115*2d543d20SAndroid Build Coastguard Worker }
2116*2d543d20SAndroid Build Coastguard Worker 
2117*2d543d20SAndroid Build Coastguard Worker /* Enable all of the avrule_decl blocks for the policy. This simple
2118*2d543d20SAndroid Build Coastguard Worker  * algorithm is the following:
2119*2d543d20SAndroid Build Coastguard Worker  *
2120*2d543d20SAndroid Build Coastguard Worker  * 1) Enable all of the non-else avrule_decls for all blocks.
2121*2d543d20SAndroid Build Coastguard Worker  * 2) Iterate through the non-else decls looking for decls whose requirements
2122*2d543d20SAndroid Build Coastguard Worker  *    are not met.
2123*2d543d20SAndroid Build Coastguard Worker  *    2a) If the decl is non-optional, return immediately with an error.
2124*2d543d20SAndroid Build Coastguard Worker  *    2b) If the decl is optional, disable the block and mark changed = 1
2125*2d543d20SAndroid Build Coastguard Worker  * 3) If changed == 1 goto 2.
2126*2d543d20SAndroid Build Coastguard Worker  * 4) Iterate through all blocks looking for those that have no enabled
2127*2d543d20SAndroid Build Coastguard Worker  *    decl. If the block has an else decl, enable.
2128*2d543d20SAndroid Build Coastguard Worker  *
2129*2d543d20SAndroid Build Coastguard Worker  * This will correctly handle all dependencies, including mutual and
2130*2d543d20SAndroid Build Coastguard Worker  * circular. The only downside is that it is slow.
2131*2d543d20SAndroid Build Coastguard Worker  */
enable_avrules(link_state_t * state,policydb_t * pol)2132*2d543d20SAndroid Build Coastguard Worker static int enable_avrules(link_state_t * state, policydb_t * pol)
2133*2d543d20SAndroid Build Coastguard Worker {
2134*2d543d20SAndroid Build Coastguard Worker 	int changed = 1;
2135*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *block;
2136*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *decl;
2137*2d543d20SAndroid Build Coastguard Worker 	missing_requirement_t req;
2138*2d543d20SAndroid Build Coastguard Worker 	int ret = 0, rc;
2139*2d543d20SAndroid Build Coastguard Worker 
2140*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose) {
2141*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "Determining which avrules to enable.");
2142*2d543d20SAndroid Build Coastguard Worker 	}
2143*2d543d20SAndroid Build Coastguard Worker 
2144*2d543d20SAndroid Build Coastguard Worker 	/* 1) enable all of the non-else blocks */
2145*2d543d20SAndroid Build Coastguard Worker 	for (block = pol->global; block != NULL; block = block->next) {
2146*2d543d20SAndroid Build Coastguard Worker 		block->enabled = block->branch_list;
2147*2d543d20SAndroid Build Coastguard Worker 		if (!block->enabled) {
2148*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Global block has no avrules!");
2149*2d543d20SAndroid Build Coastguard Worker 			ret = SEPOL_ERR;
2150*2d543d20SAndroid Build Coastguard Worker 			goto out;
2151*2d543d20SAndroid Build Coastguard Worker 		}
2152*2d543d20SAndroid Build Coastguard Worker 		block->enabled->enabled = 1;
2153*2d543d20SAndroid Build Coastguard Worker 		for (decl = block->branch_list->next; decl != NULL;
2154*2d543d20SAndroid Build Coastguard Worker 		     decl = decl->next)
2155*2d543d20SAndroid Build Coastguard Worker 			decl->enabled = 0;
2156*2d543d20SAndroid Build Coastguard Worker 	}
2157*2d543d20SAndroid Build Coastguard Worker 
2158*2d543d20SAndroid Build Coastguard Worker 	/* 2) Iterate */
2159*2d543d20SAndroid Build Coastguard Worker 	while (changed) {
2160*2d543d20SAndroid Build Coastguard Worker 		changed = 0;
2161*2d543d20SAndroid Build Coastguard Worker 		for (block = pol->global; block != NULL; block = block->next) {
2162*2d543d20SAndroid Build Coastguard Worker 			if (block->enabled == NULL) {
2163*2d543d20SAndroid Build Coastguard Worker 				continue;
2164*2d543d20SAndroid Build Coastguard Worker 			}
2165*2d543d20SAndroid Build Coastguard Worker 			decl = block->branch_list;
2166*2d543d20SAndroid Build Coastguard Worker 			if (state->verbose) {
2167*2d543d20SAndroid Build Coastguard Worker 				const char *mod_name = decl->module_name ?
2168*2d543d20SAndroid Build Coastguard Worker 				    decl->module_name : "BASE";
2169*2d543d20SAndroid Build Coastguard Worker 				INFO(state->handle, "check module %s decl %d",
2170*2d543d20SAndroid Build Coastguard Worker 				     mod_name, decl->decl_id);
2171*2d543d20SAndroid Build Coastguard Worker 			}
2172*2d543d20SAndroid Build Coastguard Worker 			rc = is_decl_requires_met(state, decl, &req);
2173*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
2174*2d543d20SAndroid Build Coastguard Worker 				ret = SEPOL_ERR;
2175*2d543d20SAndroid Build Coastguard Worker 				goto out;
2176*2d543d20SAndroid Build Coastguard Worker 			} else if (rc == 0) {
2177*2d543d20SAndroid Build Coastguard Worker 				decl->enabled = 0;
2178*2d543d20SAndroid Build Coastguard Worker 				block->enabled = NULL;
2179*2d543d20SAndroid Build Coastguard Worker 				changed = 1;
2180*2d543d20SAndroid Build Coastguard Worker 				if (!(block->flags & AVRULE_OPTIONAL)) {
2181*2d543d20SAndroid Build Coastguard Worker 					print_missing_requirements(state, block,
2182*2d543d20SAndroid Build Coastguard Worker 								   &req);
2183*2d543d20SAndroid Build Coastguard Worker 					ret = SEPOL_EREQ;
2184*2d543d20SAndroid Build Coastguard Worker 					goto out;
2185*2d543d20SAndroid Build Coastguard Worker 				}
2186*2d543d20SAndroid Build Coastguard Worker 			}
2187*2d543d20SAndroid Build Coastguard Worker 		}
2188*2d543d20SAndroid Build Coastguard Worker 	}
2189*2d543d20SAndroid Build Coastguard Worker 
2190*2d543d20SAndroid Build Coastguard Worker 	/* 4) else handling
2191*2d543d20SAndroid Build Coastguard Worker 	 *
2192*2d543d20SAndroid Build Coastguard Worker 	 * Iterate through all of the blocks skipping the first (which is the
2193*2d543d20SAndroid Build Coastguard Worker 	 * global block, is required to be present, and cannot have an else).
2194*2d543d20SAndroid Build Coastguard Worker 	 * If the block is disabled and has an else decl, enable that.
2195*2d543d20SAndroid Build Coastguard Worker 	 *
2196*2d543d20SAndroid Build Coastguard Worker 	 * This code assumes that the second block in the branch list is the else
2197*2d543d20SAndroid Build Coastguard Worker 	 * block. This is currently supported by the compiler.
2198*2d543d20SAndroid Build Coastguard Worker 	 */
2199*2d543d20SAndroid Build Coastguard Worker 	for (block = pol->global->next; block != NULL; block = block->next) {
2200*2d543d20SAndroid Build Coastguard Worker 		if (block->enabled == NULL) {
2201*2d543d20SAndroid Build Coastguard Worker 			if (block->branch_list->next != NULL) {
2202*2d543d20SAndroid Build Coastguard Worker 				block->enabled = block->branch_list->next;
2203*2d543d20SAndroid Build Coastguard Worker 				block->branch_list->next->enabled = 1;
2204*2d543d20SAndroid Build Coastguard Worker 			}
2205*2d543d20SAndroid Build Coastguard Worker 		}
2206*2d543d20SAndroid Build Coastguard Worker 	}
2207*2d543d20SAndroid Build Coastguard Worker 
2208*2d543d20SAndroid Build Coastguard Worker       out:
2209*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose)
2210*2d543d20SAndroid Build Coastguard Worker 		debug_requirements(state, pol);
2211*2d543d20SAndroid Build Coastguard Worker 
2212*2d543d20SAndroid Build Coastguard Worker 	return ret;
2213*2d543d20SAndroid Build Coastguard Worker }
2214*2d543d20SAndroid Build Coastguard Worker 
2215*2d543d20SAndroid Build Coastguard Worker /*********** the main linking functions ***********/
2216*2d543d20SAndroid Build Coastguard Worker 
2217*2d543d20SAndroid Build Coastguard Worker /* Given a module's policy, normalize all conditional expressions
2218*2d543d20SAndroid Build Coastguard Worker  * within.  Return 0 on success, -1 on error. */
cond_normalize(policydb_t * p)2219*2d543d20SAndroid Build Coastguard Worker static int cond_normalize(policydb_t * p)
2220*2d543d20SAndroid Build Coastguard Worker {
2221*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *block;
2222*2d543d20SAndroid Build Coastguard Worker 	for (block = p->global; block != NULL; block = block->next) {
2223*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *decl;
2224*2d543d20SAndroid Build Coastguard Worker 		for (decl = block->branch_list; decl != NULL; decl = decl->next) {
2225*2d543d20SAndroid Build Coastguard Worker 			cond_list_t *cond = decl->cond_list;
2226*2d543d20SAndroid Build Coastguard Worker 			while (cond) {
2227*2d543d20SAndroid Build Coastguard Worker 				if (cond_normalize_expr(p, cond) < 0)
2228*2d543d20SAndroid Build Coastguard Worker 					return -1;
2229*2d543d20SAndroid Build Coastguard Worker 				cond = cond->next;
2230*2d543d20SAndroid Build Coastguard Worker 			}
2231*2d543d20SAndroid Build Coastguard Worker 		}
2232*2d543d20SAndroid Build Coastguard Worker 	}
2233*2d543d20SAndroid Build Coastguard Worker 	return 0;
2234*2d543d20SAndroid Build Coastguard Worker }
2235*2d543d20SAndroid Build Coastguard Worker 
2236*2d543d20SAndroid Build Coastguard Worker /* Allocate space for the various remapping arrays. */
prepare_module(link_state_t * state,policy_module_t * module)2237*2d543d20SAndroid Build Coastguard Worker static int prepare_module(link_state_t * state, policy_module_t * module)
2238*2d543d20SAndroid Build Coastguard Worker {
2239*2d543d20SAndroid Build Coastguard Worker 	int i;
2240*2d543d20SAndroid Build Coastguard Worker 	uint32_t items, num_decls = 0;
2241*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *cur;
2242*2d543d20SAndroid Build Coastguard Worker 
2243*2d543d20SAndroid Build Coastguard Worker 	/* allocate the maps */
2244*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
2245*2d543d20SAndroid Build Coastguard Worker 		items = module->policy->symtab[i].nprim;
2246*2d543d20SAndroid Build Coastguard Worker 		if ((module->map[i] =
2247*2d543d20SAndroid Build Coastguard Worker 		     (uint32_t *) calloc(items,
2248*2d543d20SAndroid Build Coastguard Worker 					 sizeof(*module->map[i]))) == NULL) {
2249*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Out of memory!");
2250*2d543d20SAndroid Build Coastguard Worker 			return -1;
2251*2d543d20SAndroid Build Coastguard Worker 		}
2252*2d543d20SAndroid Build Coastguard Worker 	}
2253*2d543d20SAndroid Build Coastguard Worker 
2254*2d543d20SAndroid Build Coastguard Worker 	/* allocate the permissions remap here */
2255*2d543d20SAndroid Build Coastguard Worker 	items = module->policy->p_classes.nprim;
2256*2d543d20SAndroid Build Coastguard Worker 	if ((module->perm_map_len =
2257*2d543d20SAndroid Build Coastguard Worker 	     calloc(items, sizeof(*module->perm_map_len))) == NULL) {
2258*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2259*2d543d20SAndroid Build Coastguard Worker 		return -1;
2260*2d543d20SAndroid Build Coastguard Worker 	}
2261*2d543d20SAndroid Build Coastguard Worker 	if ((module->perm_map =
2262*2d543d20SAndroid Build Coastguard Worker 	     calloc(items, sizeof(*module->perm_map))) == NULL) {
2263*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2264*2d543d20SAndroid Build Coastguard Worker 		return -1;
2265*2d543d20SAndroid Build Coastguard Worker 	}
2266*2d543d20SAndroid Build Coastguard Worker 
2267*2d543d20SAndroid Build Coastguard Worker 	/* allocate a map for avrule_decls */
2268*2d543d20SAndroid Build Coastguard Worker 	for (cur = module->policy->global; cur != NULL; cur = cur->next) {
2269*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *decl;
2270*2d543d20SAndroid Build Coastguard Worker 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2271*2d543d20SAndroid Build Coastguard Worker 			if (decl->decl_id > num_decls) {
2272*2d543d20SAndroid Build Coastguard Worker 				num_decls = decl->decl_id;
2273*2d543d20SAndroid Build Coastguard Worker 			}
2274*2d543d20SAndroid Build Coastguard Worker 		}
2275*2d543d20SAndroid Build Coastguard Worker 	}
2276*2d543d20SAndroid Build Coastguard Worker 	num_decls++;
2277*2d543d20SAndroid Build Coastguard Worker 	if ((module->avdecl_map = calloc(num_decls, sizeof(uint32_t))) == NULL) {
2278*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2279*2d543d20SAndroid Build Coastguard Worker 		return -1;
2280*2d543d20SAndroid Build Coastguard Worker 	}
2281*2d543d20SAndroid Build Coastguard Worker 	module->num_decls = num_decls;
2282*2d543d20SAndroid Build Coastguard Worker 
2283*2d543d20SAndroid Build Coastguard Worker 	/* normalize conditionals within */
2284*2d543d20SAndroid Build Coastguard Worker 	if (cond_normalize(module->policy) < 0) {
2285*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
2286*2d543d20SAndroid Build Coastguard Worker 		    "Error while normalizing conditionals within the module %s.",
2287*2d543d20SAndroid Build Coastguard Worker 		    module->policy->name);
2288*2d543d20SAndroid Build Coastguard Worker 		return -1;
2289*2d543d20SAndroid Build Coastguard Worker 	}
2290*2d543d20SAndroid Build Coastguard Worker 	return 0;
2291*2d543d20SAndroid Build Coastguard Worker }
2292*2d543d20SAndroid Build Coastguard Worker 
prepare_base(link_state_t * state,uint32_t num_mod_decls)2293*2d543d20SAndroid Build Coastguard Worker static int prepare_base(link_state_t * state, uint32_t num_mod_decls)
2294*2d543d20SAndroid Build Coastguard Worker {
2295*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *cur = state->base->global;
2296*2d543d20SAndroid Build Coastguard Worker 	assert(cur != NULL);
2297*2d543d20SAndroid Build Coastguard Worker 	state->next_decl_id = 0;
2298*2d543d20SAndroid Build Coastguard Worker 
2299*2d543d20SAndroid Build Coastguard Worker 	/* iterate through all of the declarations in the base, to
2300*2d543d20SAndroid Build Coastguard Worker 	   determine what the next decl_id should be */
2301*2d543d20SAndroid Build Coastguard Worker 	while (cur != NULL) {
2302*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *decl;
2303*2d543d20SAndroid Build Coastguard Worker 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2304*2d543d20SAndroid Build Coastguard Worker 			if (decl->decl_id > state->next_decl_id) {
2305*2d543d20SAndroid Build Coastguard Worker 				state->next_decl_id = decl->decl_id;
2306*2d543d20SAndroid Build Coastguard Worker 			}
2307*2d543d20SAndroid Build Coastguard Worker 		}
2308*2d543d20SAndroid Build Coastguard Worker 		state->last_avrule_block = cur;
2309*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
2310*2d543d20SAndroid Build Coastguard Worker 	}
2311*2d543d20SAndroid Build Coastguard Worker 	state->last_base_avrule_block = state->last_avrule_block;
2312*2d543d20SAndroid Build Coastguard Worker 	state->next_decl_id++;
2313*2d543d20SAndroid Build Coastguard Worker 
2314*2d543d20SAndroid Build Coastguard Worker 	/* allocate the table mapping from base's decl_id to its
2315*2d543d20SAndroid Build Coastguard Worker 	 * avrule_decls and set the initial mappings */
2316*2d543d20SAndroid Build Coastguard Worker 	free(state->base->decl_val_to_struct);
2317*2d543d20SAndroid Build Coastguard Worker 	if ((state->base->decl_val_to_struct =
2318*2d543d20SAndroid Build Coastguard Worker 	     calloc(state->next_decl_id + num_mod_decls,
2319*2d543d20SAndroid Build Coastguard Worker 		    sizeof(*(state->base->decl_val_to_struct)))) == NULL) {
2320*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2321*2d543d20SAndroid Build Coastguard Worker 		return -1;
2322*2d543d20SAndroid Build Coastguard Worker 	}
2323*2d543d20SAndroid Build Coastguard Worker 	/* This allocates the decl block to module mapping used for error reporting */
2324*2d543d20SAndroid Build Coastguard Worker 	if ((state->decl_to_mod = calloc(state->next_decl_id + num_mod_decls,
2325*2d543d20SAndroid Build Coastguard Worker 					 sizeof(*(state->decl_to_mod)))) ==
2326*2d543d20SAndroid Build Coastguard Worker 	    NULL) {
2327*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2328*2d543d20SAndroid Build Coastguard Worker 		return -1;
2329*2d543d20SAndroid Build Coastguard Worker 	}
2330*2d543d20SAndroid Build Coastguard Worker 	cur = state->base->global;
2331*2d543d20SAndroid Build Coastguard Worker 	while (cur != NULL) {
2332*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *decl = cur->branch_list;
2333*2d543d20SAndroid Build Coastguard Worker 		while (decl != NULL) {
2334*2d543d20SAndroid Build Coastguard Worker 			state->base->decl_val_to_struct[decl->decl_id - 1] =
2335*2d543d20SAndroid Build Coastguard Worker 			    decl;
2336*2d543d20SAndroid Build Coastguard Worker 			state->decl_to_mod[decl->decl_id] = state->base;
2337*2d543d20SAndroid Build Coastguard Worker 			decl = decl->next;
2338*2d543d20SAndroid Build Coastguard Worker 		}
2339*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
2340*2d543d20SAndroid Build Coastguard Worker 	}
2341*2d543d20SAndroid Build Coastguard Worker 
2342*2d543d20SAndroid Build Coastguard Worker 	/* normalize conditionals within */
2343*2d543d20SAndroid Build Coastguard Worker 	if (cond_normalize(state->base) < 0) {
2344*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle,
2345*2d543d20SAndroid Build Coastguard Worker 		    "Error while normalizing conditionals within the base module.");
2346*2d543d20SAndroid Build Coastguard Worker 		return -1;
2347*2d543d20SAndroid Build Coastguard Worker 	}
2348*2d543d20SAndroid Build Coastguard Worker 	return 0;
2349*2d543d20SAndroid Build Coastguard Worker }
2350*2d543d20SAndroid Build Coastguard Worker 
expand_role_attributes(hashtab_key_t key,hashtab_datum_t datum,void * data)2351*2d543d20SAndroid Build Coastguard Worker static int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum,
2352*2d543d20SAndroid Build Coastguard Worker 				  void * data)
2353*2d543d20SAndroid Build Coastguard Worker {
2354*2d543d20SAndroid Build Coastguard Worker 	char *id;
2355*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role, *sub_attr;
2356*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state;
2357*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2358*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *rnode;
2359*2d543d20SAndroid Build Coastguard Worker 
2360*2d543d20SAndroid Build Coastguard Worker 	id = key;
2361*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *)datum;
2362*2d543d20SAndroid Build Coastguard Worker 	state = (link_state_t *)data;
2363*2d543d20SAndroid Build Coastguard Worker 
2364*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, OBJECT_R) == 0){
2365*2d543d20SAndroid Build Coastguard Worker 		/* object_r is never a role attribute by far */
2366*2d543d20SAndroid Build Coastguard Worker 		return 0;
2367*2d543d20SAndroid Build Coastguard Worker 	}
2368*2d543d20SAndroid Build Coastguard Worker 
2369*2d543d20SAndroid Build Coastguard Worker 	if (role->flavor != ROLE_ATTRIB)
2370*2d543d20SAndroid Build Coastguard Worker 		return 0;
2371*2d543d20SAndroid Build Coastguard Worker 
2372*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose)
2373*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "expanding role attribute %s", id);
2374*2d543d20SAndroid Build Coastguard Worker 
2375*2d543d20SAndroid Build Coastguard Worker restart:
2376*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&role->roles, rnode, i) {
2377*2d543d20SAndroid Build Coastguard Worker 		sub_attr = state->base->role_val_to_struct[i];
2378*2d543d20SAndroid Build Coastguard Worker 		if (sub_attr->flavor != ROLE_ATTRIB)
2379*2d543d20SAndroid Build Coastguard Worker 			continue;
2380*2d543d20SAndroid Build Coastguard Worker 
2381*2d543d20SAndroid Build Coastguard Worker 		/* remove the sub role attribute from the parent
2382*2d543d20SAndroid Build Coastguard Worker 		 * role attribute's roles ebitmap */
2383*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&role->roles, i, 0))
2384*2d543d20SAndroid Build Coastguard Worker 			return -1;
2385*2d543d20SAndroid Build Coastguard Worker 
2386*2d543d20SAndroid Build Coastguard Worker 		/* loop dependency of role attributes */
2387*2d543d20SAndroid Build Coastguard Worker 		if (sub_attr->s.value == role->s.value)
2388*2d543d20SAndroid Build Coastguard Worker 			continue;
2389*2d543d20SAndroid Build Coastguard Worker 
2390*2d543d20SAndroid Build Coastguard Worker 		/* now go on to expand a sub role attribute
2391*2d543d20SAndroid Build Coastguard Worker 		 * by escalating its roles ebitmap */
2392*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_union(&role->roles, &sub_attr->roles)) {
2393*2d543d20SAndroid Build Coastguard Worker 			ERR(state->handle, "Out of memory!");
2394*2d543d20SAndroid Build Coastguard Worker 			return -1;
2395*2d543d20SAndroid Build Coastguard Worker 		}
2396*2d543d20SAndroid Build Coastguard Worker 
2397*2d543d20SAndroid Build Coastguard Worker 		/* sub_attr->roles may contain other role attributes,
2398*2d543d20SAndroid Build Coastguard Worker 		 * re-scan the parent role attribute's roles ebitmap */
2399*2d543d20SAndroid Build Coastguard Worker 		goto restart;
2400*2d543d20SAndroid Build Coastguard Worker 	}
2401*2d543d20SAndroid Build Coastguard Worker 
2402*2d543d20SAndroid Build Coastguard Worker 	return 0;
2403*2d543d20SAndroid Build Coastguard Worker }
2404*2d543d20SAndroid Build Coastguard Worker 
2405*2d543d20SAndroid Build Coastguard Worker /* For any role attribute in a declaration's local symtab[SYM_ROLES] table,
2406*2d543d20SAndroid Build Coastguard Worker  * copy its roles ebitmap into its duplicate's in the base->p_roles.table.
2407*2d543d20SAndroid Build Coastguard Worker  */
populate_decl_roleattributes(hashtab_key_t key,hashtab_datum_t datum,void * data)2408*2d543d20SAndroid Build Coastguard Worker static int populate_decl_roleattributes(hashtab_key_t key,
2409*2d543d20SAndroid Build Coastguard Worker 					hashtab_datum_t datum,
2410*2d543d20SAndroid Build Coastguard Worker 					void *data)
2411*2d543d20SAndroid Build Coastguard Worker {
2412*2d543d20SAndroid Build Coastguard Worker 	char *id = key;
2413*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *decl_role, *base_role;
2414*2d543d20SAndroid Build Coastguard Worker 	link_state_t *state = (link_state_t *)data;
2415*2d543d20SAndroid Build Coastguard Worker 
2416*2d543d20SAndroid Build Coastguard Worker 	decl_role = (role_datum_t *)datum;
2417*2d543d20SAndroid Build Coastguard Worker 
2418*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, OBJECT_R) == 0) {
2419*2d543d20SAndroid Build Coastguard Worker 		/* object_r is never a role attribute by far */
2420*2d543d20SAndroid Build Coastguard Worker 		return 0;
2421*2d543d20SAndroid Build Coastguard Worker 	}
2422*2d543d20SAndroid Build Coastguard Worker 
2423*2d543d20SAndroid Build Coastguard Worker 	if (decl_role->flavor != ROLE_ATTRIB)
2424*2d543d20SAndroid Build Coastguard Worker 		return 0;
2425*2d543d20SAndroid Build Coastguard Worker 
2426*2d543d20SAndroid Build Coastguard Worker 	base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table,
2427*2d543d20SAndroid Build Coastguard Worker 						   id);
2428*2d543d20SAndroid Build Coastguard Worker 	assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB);
2429*2d543d20SAndroid Build Coastguard Worker 
2430*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_union(&base_role->roles, &decl_role->roles)) {
2431*2d543d20SAndroid Build Coastguard Worker 		ERR(state->handle, "Out of memory!");
2432*2d543d20SAndroid Build Coastguard Worker 		return -1;
2433*2d543d20SAndroid Build Coastguard Worker 	}
2434*2d543d20SAndroid Build Coastguard Worker 
2435*2d543d20SAndroid Build Coastguard Worker 	return 0;
2436*2d543d20SAndroid Build Coastguard Worker }
2437*2d543d20SAndroid Build Coastguard Worker 
populate_roleattributes(link_state_t * state,policydb_t * pol)2438*2d543d20SAndroid Build Coastguard Worker static int populate_roleattributes(link_state_t *state, policydb_t *pol)
2439*2d543d20SAndroid Build Coastguard Worker {
2440*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *block;
2441*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *decl;
2442*2d543d20SAndroid Build Coastguard Worker 
2443*2d543d20SAndroid Build Coastguard Worker 	if (state->verbose)
2444*2d543d20SAndroid Build Coastguard Worker 		INFO(state->handle, "Populating role-attribute relationship "
2445*2d543d20SAndroid Build Coastguard Worker 			    "from enabled declarations' local symtab.");
2446*2d543d20SAndroid Build Coastguard Worker 
2447*2d543d20SAndroid Build Coastguard Worker 	/* Iterate through all of the blocks skipping the first(which is the
2448*2d543d20SAndroid Build Coastguard Worker 	 * global block, is required to be present and can't have an else).
2449*2d543d20SAndroid Build Coastguard Worker 	 * If the block is disabled or not having an enabled decl, skip it.
2450*2d543d20SAndroid Build Coastguard Worker 	 */
2451*2d543d20SAndroid Build Coastguard Worker 	for (block = pol->global->next; block != NULL; block = block->next)
2452*2d543d20SAndroid Build Coastguard Worker 	{
2453*2d543d20SAndroid Build Coastguard Worker 		decl = block->enabled;
2454*2d543d20SAndroid Build Coastguard Worker 		if (decl == NULL || decl->enabled == 0)
2455*2d543d20SAndroid Build Coastguard Worker 			continue;
2456*2d543d20SAndroid Build Coastguard Worker 
2457*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_map(decl->symtab[SYM_ROLES].table,
2458*2d543d20SAndroid Build Coastguard Worker 				populate_decl_roleattributes, state))
2459*2d543d20SAndroid Build Coastguard Worker 			return -1;
2460*2d543d20SAndroid Build Coastguard Worker 	}
2461*2d543d20SAndroid Build Coastguard Worker 
2462*2d543d20SAndroid Build Coastguard Worker 	return 0;
2463*2d543d20SAndroid Build Coastguard Worker }
2464*2d543d20SAndroid Build Coastguard Worker 
2465*2d543d20SAndroid Build Coastguard Worker /* Link a set of modules into a base module. This process is somewhat
2466*2d543d20SAndroid Build Coastguard Worker  * similar to an actual compiler: it requires a set of order dependent
2467*2d543d20SAndroid Build Coastguard Worker  * steps.  The base and every module must have been indexed prior to
2468*2d543d20SAndroid Build Coastguard Worker  * calling this function.
2469*2d543d20SAndroid Build Coastguard Worker  */
link_modules(sepol_handle_t * handle,policydb_t * b,policydb_t ** mods,int len,int verbose)2470*2d543d20SAndroid Build Coastguard Worker int link_modules(sepol_handle_t * handle,
2471*2d543d20SAndroid Build Coastguard Worker 		 policydb_t * b, policydb_t ** mods, int len, int verbose)
2472*2d543d20SAndroid Build Coastguard Worker {
2473*2d543d20SAndroid Build Coastguard Worker 	int i, ret, retval = -1;
2474*2d543d20SAndroid Build Coastguard Worker 	policy_module_t **modules = NULL;
2475*2d543d20SAndroid Build Coastguard Worker 	link_state_t state;
2476*2d543d20SAndroid Build Coastguard Worker 	uint32_t num_mod_decls = 0;
2477*2d543d20SAndroid Build Coastguard Worker 
2478*2d543d20SAndroid Build Coastguard Worker 	memset(&state, 0, sizeof(state));
2479*2d543d20SAndroid Build Coastguard Worker 	state.base = b;
2480*2d543d20SAndroid Build Coastguard Worker 	state.verbose = verbose;
2481*2d543d20SAndroid Build Coastguard Worker 	state.handle = handle;
2482*2d543d20SAndroid Build Coastguard Worker 
2483*2d543d20SAndroid Build Coastguard Worker 	if (b->policy_type != POLICY_BASE) {
2484*2d543d20SAndroid Build Coastguard Worker 		ERR(state.handle, "Target of link was not a base policy.");
2485*2d543d20SAndroid Build Coastguard Worker 		return -1;
2486*2d543d20SAndroid Build Coastguard Worker 	}
2487*2d543d20SAndroid Build Coastguard Worker 
2488*2d543d20SAndroid Build Coastguard Worker 	/* first allocate some space to hold the maps from module
2489*2d543d20SAndroid Build Coastguard Worker 	 * symbol's value to the destination symbol value; then do
2490*2d543d20SAndroid Build Coastguard Worker 	 * other preparation work */
2491*2d543d20SAndroid Build Coastguard Worker 	if ((modules =
2492*2d543d20SAndroid Build Coastguard Worker 	     (policy_module_t **) calloc(len, sizeof(*modules))) == NULL) {
2493*2d543d20SAndroid Build Coastguard Worker 		ERR(state.handle, "Out of memory!");
2494*2d543d20SAndroid Build Coastguard Worker 		return -1;
2495*2d543d20SAndroid Build Coastguard Worker 	}
2496*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < len; i++) {
2497*2d543d20SAndroid Build Coastguard Worker 		if (mods[i]->policy_type != POLICY_MOD) {
2498*2d543d20SAndroid Build Coastguard Worker 			ERR(state.handle,
2499*2d543d20SAndroid Build Coastguard Worker 			    "Tried to link in a policy that was not a module.");
2500*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2501*2d543d20SAndroid Build Coastguard Worker 		}
2502*2d543d20SAndroid Build Coastguard Worker 
2503*2d543d20SAndroid Build Coastguard Worker 		if (mods[i]->mls != b->mls) {
2504*2d543d20SAndroid Build Coastguard Worker 			if (b->mls)
2505*2d543d20SAndroid Build Coastguard Worker 				ERR(state.handle,
2506*2d543d20SAndroid Build Coastguard Worker 				    "Tried to link in a non-MLS module with an MLS base.");
2507*2d543d20SAndroid Build Coastguard Worker 			else
2508*2d543d20SAndroid Build Coastguard Worker 				ERR(state.handle,
2509*2d543d20SAndroid Build Coastguard Worker 				    "Tried to link in an MLS module with a non-MLS base.");
2510*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2511*2d543d20SAndroid Build Coastguard Worker 		}
2512*2d543d20SAndroid Build Coastguard Worker 
2513*2d543d20SAndroid Build Coastguard Worker 		if (mods[i]->policyvers > b->policyvers) {
2514*2d543d20SAndroid Build Coastguard Worker 			WARN(state.handle,
2515*2d543d20SAndroid Build Coastguard Worker 			     "Upgrading policy version from %u to %u", b->policyvers, mods[i]->policyvers);
2516*2d543d20SAndroid Build Coastguard Worker 			b->policyvers = mods[i]->policyvers;
2517*2d543d20SAndroid Build Coastguard Worker 		}
2518*2d543d20SAndroid Build Coastguard Worker 
2519*2d543d20SAndroid Build Coastguard Worker 		if ((modules[i] =
2520*2d543d20SAndroid Build Coastguard Worker 		     (policy_module_t *) calloc(1,
2521*2d543d20SAndroid Build Coastguard Worker 						sizeof(policy_module_t))) ==
2522*2d543d20SAndroid Build Coastguard Worker 		    NULL) {
2523*2d543d20SAndroid Build Coastguard Worker 			ERR(state.handle, "Out of memory!");
2524*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2525*2d543d20SAndroid Build Coastguard Worker 		}
2526*2d543d20SAndroid Build Coastguard Worker 		modules[i]->policy = mods[i];
2527*2d543d20SAndroid Build Coastguard Worker 		if (prepare_module(&state, modules[i]) == -1) {
2528*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2529*2d543d20SAndroid Build Coastguard Worker 		}
2530*2d543d20SAndroid Build Coastguard Worker 		num_mod_decls += modules[i]->num_decls;
2531*2d543d20SAndroid Build Coastguard Worker 	}
2532*2d543d20SAndroid Build Coastguard Worker 	if (prepare_base(&state, num_mod_decls) == -1) {
2533*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2534*2d543d20SAndroid Build Coastguard Worker 	}
2535*2d543d20SAndroid Build Coastguard Worker 
2536*2d543d20SAndroid Build Coastguard Worker 	/* copy and remap the module's data over to base */
2537*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < len; i++) {
2538*2d543d20SAndroid Build Coastguard Worker 		state.cur = modules[i];
2539*2d543d20SAndroid Build Coastguard Worker 		ret = copy_module(&state, modules[i]);
2540*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
2541*2d543d20SAndroid Build Coastguard Worker 			retval = ret;
2542*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2543*2d543d20SAndroid Build Coastguard Worker 		}
2544*2d543d20SAndroid Build Coastguard Worker 	}
2545*2d543d20SAndroid Build Coastguard Worker 
2546*2d543d20SAndroid Build Coastguard Worker 	/* re-index base, for symbols were added to symbol tables  */
2547*2d543d20SAndroid Build Coastguard Worker 	if (policydb_index_classes(state.base)) {
2548*2d543d20SAndroid Build Coastguard Worker 		ERR(state.handle, "Error while indexing classes");
2549*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2550*2d543d20SAndroid Build Coastguard Worker 	}
2551*2d543d20SAndroid Build Coastguard Worker 	if (policydb_index_others(state.handle, state.base, 0)) {
2552*2d543d20SAndroid Build Coastguard Worker 		ERR(state.handle, "Error while indexing others");
2553*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2554*2d543d20SAndroid Build Coastguard Worker 	}
2555*2d543d20SAndroid Build Coastguard Worker 
2556*2d543d20SAndroid Build Coastguard Worker 	if (enable_avrules(&state, state.base)) {
2557*2d543d20SAndroid Build Coastguard Worker 		retval = SEPOL_EREQ;
2558*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2559*2d543d20SAndroid Build Coastguard Worker 	}
2560*2d543d20SAndroid Build Coastguard Worker 
2561*2d543d20SAndroid Build Coastguard Worker 	/* Now that all role attribute's roles ebitmap have been settled,
2562*2d543d20SAndroid Build Coastguard Worker 	 * escalate sub role attribute's roles ebitmap into that of parent.
2563*2d543d20SAndroid Build Coastguard Worker 	 *
2564*2d543d20SAndroid Build Coastguard Worker 	 * First, since some role-attribute relationships could be recorded
2565*2d543d20SAndroid Build Coastguard Worker 	 * in some decl's local symtab(see get_local_role()), we need to
2566*2d543d20SAndroid Build Coastguard Worker 	 * populate them up to the base.p_roles table. */
2567*2d543d20SAndroid Build Coastguard Worker 	if (populate_roleattributes(&state, state.base)) {
2568*2d543d20SAndroid Build Coastguard Worker 		retval = SEPOL_EREQ;
2569*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2570*2d543d20SAndroid Build Coastguard Worker 	}
2571*2d543d20SAndroid Build Coastguard Worker 
2572*2d543d20SAndroid Build Coastguard Worker 	/* Now do the escalation. */
2573*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(state.base->p_roles.table, expand_role_attributes,
2574*2d543d20SAndroid Build Coastguard Worker 			&state))
2575*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2576*2d543d20SAndroid Build Coastguard Worker 
2577*2d543d20SAndroid Build Coastguard Worker 	retval = 0;
2578*2d543d20SAndroid Build Coastguard Worker       cleanup:
2579*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; modules != NULL && i < len; i++) {
2580*2d543d20SAndroid Build Coastguard Worker 		policy_module_destroy(modules[i]);
2581*2d543d20SAndroid Build Coastguard Worker 	}
2582*2d543d20SAndroid Build Coastguard Worker 	free(modules);
2583*2d543d20SAndroid Build Coastguard Worker 	free(state.decl_to_mod);
2584*2d543d20SAndroid Build Coastguard Worker 	return retval;
2585*2d543d20SAndroid Build Coastguard Worker }
2586