1*2d543d20SAndroid Build Coastguard Worker /* Authors: Karl MacMillan <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker * Jason Tang <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker * Joshua Brindle <[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 * Copyright (C) 2017 Mellanox Technologies, Inc.
8*2d543d20SAndroid Build Coastguard Worker *
9*2d543d20SAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or
10*2d543d20SAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
11*2d543d20SAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
12*2d543d20SAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
13*2d543d20SAndroid Build Coastguard Worker *
14*2d543d20SAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful,
15*2d543d20SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*2d543d20SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17*2d543d20SAndroid Build Coastguard Worker * Lesser General Public License for more details.
18*2d543d20SAndroid Build Coastguard Worker *
19*2d543d20SAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
20*2d543d20SAndroid Build Coastguard Worker * License along with this library; if not, write to the Free Software
21*2d543d20SAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22*2d543d20SAndroid Build Coastguard Worker */
23*2d543d20SAndroid Build Coastguard Worker
24*2d543d20SAndroid Build Coastguard Worker #include "context.h"
25*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
26*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
27*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/hashtab.h>
28*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/expand.h>
29*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/hierarchy.h>
30*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/avrule_block.h>
31*2d543d20SAndroid Build Coastguard Worker
32*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
33*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
34*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
35*2d543d20SAndroid Build Coastguard Worker #include <string.h>
36*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
37*2d543d20SAndroid Build Coastguard Worker #include <inttypes.h>
38*2d543d20SAndroid Build Coastguard Worker
39*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
40*2d543d20SAndroid Build Coastguard Worker #include "private.h"
41*2d543d20SAndroid Build Coastguard Worker
42*2d543d20SAndroid Build Coastguard Worker typedef struct expand_state {
43*2d543d20SAndroid Build Coastguard Worker int verbose;
44*2d543d20SAndroid Build Coastguard Worker uint32_t *typemap;
45*2d543d20SAndroid Build Coastguard Worker uint32_t *boolmap;
46*2d543d20SAndroid Build Coastguard Worker uint32_t *rolemap;
47*2d543d20SAndroid Build Coastguard Worker uint32_t *usermap;
48*2d543d20SAndroid Build Coastguard Worker policydb_t *base;
49*2d543d20SAndroid Build Coastguard Worker policydb_t *out;
50*2d543d20SAndroid Build Coastguard Worker sepol_handle_t *handle;
51*2d543d20SAndroid Build Coastguard Worker int expand_neverallow;
52*2d543d20SAndroid Build Coastguard Worker } expand_state_t;
53*2d543d20SAndroid Build Coastguard Worker
expand_state_init(expand_state_t * state)54*2d543d20SAndroid Build Coastguard Worker static void expand_state_init(expand_state_t * state)
55*2d543d20SAndroid Build Coastguard Worker {
56*2d543d20SAndroid Build Coastguard Worker memset(state, 0, sizeof(expand_state_t));
57*2d543d20SAndroid Build Coastguard Worker }
58*2d543d20SAndroid Build Coastguard Worker
map_ebitmap(ebitmap_t * src,ebitmap_t * dst,uint32_t * map)59*2d543d20SAndroid Build Coastguard Worker static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
60*2d543d20SAndroid Build Coastguard Worker {
61*2d543d20SAndroid Build Coastguard Worker unsigned int i;
62*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *tnode;
63*2d543d20SAndroid Build Coastguard Worker ebitmap_init(dst);
64*2d543d20SAndroid Build Coastguard Worker
65*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(src, tnode, i) {
66*2d543d20SAndroid Build Coastguard Worker if (!map[i])
67*2d543d20SAndroid Build Coastguard Worker continue;
68*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(dst, map[i] - 1, 1))
69*2d543d20SAndroid Build Coastguard Worker return -1;
70*2d543d20SAndroid Build Coastguard Worker }
71*2d543d20SAndroid Build Coastguard Worker return 0;
72*2d543d20SAndroid Build Coastguard Worker }
73*2d543d20SAndroid Build Coastguard Worker
ebitmap_expand_roles(policydb_t * p,ebitmap_t * roles)74*2d543d20SAndroid Build Coastguard Worker static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles)
75*2d543d20SAndroid Build Coastguard Worker {
76*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *node;
77*2d543d20SAndroid Build Coastguard Worker unsigned int bit;
78*2d543d20SAndroid Build Coastguard Worker role_datum_t *role;
79*2d543d20SAndroid Build Coastguard Worker ebitmap_t tmp;
80*2d543d20SAndroid Build Coastguard Worker
81*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&tmp);
82*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(roles, node, bit) {
83*2d543d20SAndroid Build Coastguard Worker role = p->role_val_to_struct[bit];
84*2d543d20SAndroid Build Coastguard Worker assert(role);
85*2d543d20SAndroid Build Coastguard Worker if (role->flavor != ROLE_ATTRIB) {
86*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&tmp, bit, 1)) {
87*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp);
88*2d543d20SAndroid Build Coastguard Worker return -1;
89*2d543d20SAndroid Build Coastguard Worker }
90*2d543d20SAndroid Build Coastguard Worker } else {
91*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&tmp, &role->roles)) {
92*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp);
93*2d543d20SAndroid Build Coastguard Worker return -1;
94*2d543d20SAndroid Build Coastguard Worker }
95*2d543d20SAndroid Build Coastguard Worker }
96*2d543d20SAndroid Build Coastguard Worker }
97*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(roles);
98*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(roles, &tmp)) {
99*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp);
100*2d543d20SAndroid Build Coastguard Worker return -1;
101*2d543d20SAndroid Build Coastguard Worker }
102*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp);
103*2d543d20SAndroid Build Coastguard Worker return 0;
104*2d543d20SAndroid Build Coastguard Worker }
105*2d543d20SAndroid Build Coastguard Worker
type_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)106*2d543d20SAndroid Build Coastguard Worker static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
107*2d543d20SAndroid Build Coastguard Worker void *data)
108*2d543d20SAndroid Build Coastguard Worker {
109*2d543d20SAndroid Build Coastguard Worker int ret;
110*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
111*2d543d20SAndroid Build Coastguard Worker type_datum_t *type, *new_type;
112*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
113*2d543d20SAndroid Build Coastguard Worker
114*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
115*2d543d20SAndroid Build Coastguard Worker type = (type_datum_t *) datum;
116*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
117*2d543d20SAndroid Build Coastguard Worker
118*2d543d20SAndroid Build Coastguard Worker if ((type->flavor == TYPE_TYPE && !type->primary)
119*2d543d20SAndroid Build Coastguard Worker || type->flavor == TYPE_ALIAS) {
120*2d543d20SAndroid Build Coastguard Worker /* aliases are handled later */
121*2d543d20SAndroid Build Coastguard Worker return 0;
122*2d543d20SAndroid Build Coastguard Worker }
123*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_TYPES)) {
124*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
125*2d543d20SAndroid Build Coastguard Worker return 0;
126*2d543d20SAndroid Build Coastguard Worker }
127*2d543d20SAndroid Build Coastguard Worker
128*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
129*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying type or attribute %s", id);
130*2d543d20SAndroid Build Coastguard Worker
131*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
132*2d543d20SAndroid Build Coastguard Worker if (new_id == NULL) {
133*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
134*2d543d20SAndroid Build Coastguard Worker return -1;
135*2d543d20SAndroid Build Coastguard Worker }
136*2d543d20SAndroid Build Coastguard Worker
137*2d543d20SAndroid Build Coastguard Worker new_type = (type_datum_t *) malloc(sizeof(type_datum_t));
138*2d543d20SAndroid Build Coastguard Worker if (!new_type) {
139*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
140*2d543d20SAndroid Build Coastguard Worker free(new_id);
141*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOMEM;
142*2d543d20SAndroid Build Coastguard Worker }
143*2d543d20SAndroid Build Coastguard Worker memset(new_type, 0, sizeof(type_datum_t));
144*2d543d20SAndroid Build Coastguard Worker
145*2d543d20SAndroid Build Coastguard Worker new_type->flavor = type->flavor;
146*2d543d20SAndroid Build Coastguard Worker new_type->flags = type->flags;
147*2d543d20SAndroid Build Coastguard Worker new_type->s.value = ++state->out->p_types.nprim;
148*2d543d20SAndroid Build Coastguard Worker if (new_type->s.value > UINT16_MAX) {
149*2d543d20SAndroid Build Coastguard Worker free(new_id);
150*2d543d20SAndroid Build Coastguard Worker free(new_type);
151*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "type space overflow");
152*2d543d20SAndroid Build Coastguard Worker return -1;
153*2d543d20SAndroid Build Coastguard Worker }
154*2d543d20SAndroid Build Coastguard Worker new_type->primary = 1;
155*2d543d20SAndroid Build Coastguard Worker state->typemap[type->s.value - 1] = new_type->s.value;
156*2d543d20SAndroid Build Coastguard Worker
157*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(state->out->p_types.table,
158*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
159*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_type);
160*2d543d20SAndroid Build Coastguard Worker if (ret) {
161*2d543d20SAndroid Build Coastguard Worker free(new_id);
162*2d543d20SAndroid Build Coastguard Worker free(new_type);
163*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
164*2d543d20SAndroid Build Coastguard Worker return -1;
165*2d543d20SAndroid Build Coastguard Worker }
166*2d543d20SAndroid Build Coastguard Worker
167*2d543d20SAndroid Build Coastguard Worker if (new_type->flags & TYPE_FLAGS_PERMISSIVE)
168*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) {
169*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
170*2d543d20SAndroid Build Coastguard Worker return -1;
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker
173*2d543d20SAndroid Build Coastguard Worker return 0;
174*2d543d20SAndroid Build Coastguard Worker }
175*2d543d20SAndroid Build Coastguard Worker
attr_convert_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)176*2d543d20SAndroid Build Coastguard Worker static int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum,
177*2d543d20SAndroid Build Coastguard Worker void *data)
178*2d543d20SAndroid Build Coastguard Worker {
179*2d543d20SAndroid Build Coastguard Worker char *id;
180*2d543d20SAndroid Build Coastguard Worker type_datum_t *type, *new_type;
181*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
182*2d543d20SAndroid Build Coastguard Worker ebitmap_t tmp_union;
183*2d543d20SAndroid Build Coastguard Worker
184*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
185*2d543d20SAndroid Build Coastguard Worker type = (type_datum_t *) datum;
186*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
187*2d543d20SAndroid Build Coastguard Worker
188*2d543d20SAndroid Build Coastguard Worker if (type->flavor != TYPE_ATTRIB)
189*2d543d20SAndroid Build Coastguard Worker return 0;
190*2d543d20SAndroid Build Coastguard Worker
191*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_TYPES)) {
192*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
193*2d543d20SAndroid Build Coastguard Worker return 0;
194*2d543d20SAndroid Build Coastguard Worker }
195*2d543d20SAndroid Build Coastguard Worker
196*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
197*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "converting attribute %s", id);
198*2d543d20SAndroid Build Coastguard Worker
199*2d543d20SAndroid Build Coastguard Worker new_type = hashtab_search(state->out->p_types.table, id);
200*2d543d20SAndroid Build Coastguard Worker if (!new_type) {
201*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "attribute %s vanished!", id);
202*2d543d20SAndroid Build Coastguard Worker return -1;
203*2d543d20SAndroid Build Coastguard Worker }
204*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&type->types, &tmp_union, state->typemap)) {
205*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "out of memory");
206*2d543d20SAndroid Build Coastguard Worker return -1;
207*2d543d20SAndroid Build Coastguard Worker }
208*2d543d20SAndroid Build Coastguard Worker
209*2d543d20SAndroid Build Coastguard Worker /* then union tmp_union onto &new_type->types */
210*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&new_type->types, &tmp_union)) {
211*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
212*2d543d20SAndroid Build Coastguard Worker return -1;
213*2d543d20SAndroid Build Coastguard Worker }
214*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union);
215*2d543d20SAndroid Build Coastguard Worker
216*2d543d20SAndroid Build Coastguard Worker return 0;
217*2d543d20SAndroid Build Coastguard Worker }
218*2d543d20SAndroid Build Coastguard Worker
perm_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)219*2d543d20SAndroid Build Coastguard Worker static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
220*2d543d20SAndroid Build Coastguard Worker void *data)
221*2d543d20SAndroid Build Coastguard Worker {
222*2d543d20SAndroid Build Coastguard Worker int ret;
223*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
224*2d543d20SAndroid Build Coastguard Worker symtab_t *s;
225*2d543d20SAndroid Build Coastguard Worker perm_datum_t *perm, *new_perm;
226*2d543d20SAndroid Build Coastguard Worker
227*2d543d20SAndroid Build Coastguard Worker id = key;
228*2d543d20SAndroid Build Coastguard Worker perm = (perm_datum_t *) datum;
229*2d543d20SAndroid Build Coastguard Worker s = (symtab_t *) data;
230*2d543d20SAndroid Build Coastguard Worker
231*2d543d20SAndroid Build Coastguard Worker new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t));
232*2d543d20SAndroid Build Coastguard Worker if (!new_perm) {
233*2d543d20SAndroid Build Coastguard Worker return -1;
234*2d543d20SAndroid Build Coastguard Worker }
235*2d543d20SAndroid Build Coastguard Worker memset(new_perm, 0, sizeof(perm_datum_t));
236*2d543d20SAndroid Build Coastguard Worker
237*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
238*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
239*2d543d20SAndroid Build Coastguard Worker free(new_perm);
240*2d543d20SAndroid Build Coastguard Worker return -1;
241*2d543d20SAndroid Build Coastguard Worker }
242*2d543d20SAndroid Build Coastguard Worker
243*2d543d20SAndroid Build Coastguard Worker new_perm->s.value = perm->s.value;
244*2d543d20SAndroid Build Coastguard Worker s->nprim++;
245*2d543d20SAndroid Build Coastguard Worker
246*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm);
247*2d543d20SAndroid Build Coastguard Worker if (ret) {
248*2d543d20SAndroid Build Coastguard Worker free(new_id);
249*2d543d20SAndroid Build Coastguard Worker free(new_perm);
250*2d543d20SAndroid Build Coastguard Worker return -1;
251*2d543d20SAndroid Build Coastguard Worker }
252*2d543d20SAndroid Build Coastguard Worker
253*2d543d20SAndroid Build Coastguard Worker return 0;
254*2d543d20SAndroid Build Coastguard Worker }
255*2d543d20SAndroid Build Coastguard Worker
common_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)256*2d543d20SAndroid Build Coastguard Worker static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
257*2d543d20SAndroid Build Coastguard Worker void *data)
258*2d543d20SAndroid Build Coastguard Worker {
259*2d543d20SAndroid Build Coastguard Worker int ret;
260*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
261*2d543d20SAndroid Build Coastguard Worker common_datum_t *common, *new_common;
262*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
263*2d543d20SAndroid Build Coastguard Worker
264*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
265*2d543d20SAndroid Build Coastguard Worker common = (common_datum_t *) datum;
266*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
267*2d543d20SAndroid Build Coastguard Worker
268*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
269*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying common %s", id);
270*2d543d20SAndroid Build Coastguard Worker
271*2d543d20SAndroid Build Coastguard Worker new_common = (common_datum_t *) malloc(sizeof(common_datum_t));
272*2d543d20SAndroid Build Coastguard Worker if (!new_common) {
273*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
274*2d543d20SAndroid Build Coastguard Worker return -1;
275*2d543d20SAndroid Build Coastguard Worker }
276*2d543d20SAndroid Build Coastguard Worker memset(new_common, 0, sizeof(common_datum_t));
277*2d543d20SAndroid Build Coastguard Worker if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) {
278*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
279*2d543d20SAndroid Build Coastguard Worker free(new_common);
280*2d543d20SAndroid Build Coastguard Worker return -1;
281*2d543d20SAndroid Build Coastguard Worker }
282*2d543d20SAndroid Build Coastguard Worker
283*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
284*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
285*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
286*2d543d20SAndroid Build Coastguard Worker /* free memory created by symtab_init first, then free new_common */
287*2d543d20SAndroid Build Coastguard Worker symtab_destroy(&new_common->permissions);
288*2d543d20SAndroid Build Coastguard Worker free(new_common);
289*2d543d20SAndroid Build Coastguard Worker return -1;
290*2d543d20SAndroid Build Coastguard Worker }
291*2d543d20SAndroid Build Coastguard Worker
292*2d543d20SAndroid Build Coastguard Worker new_common->s.value = common->s.value;
293*2d543d20SAndroid Build Coastguard Worker state->out->p_commons.nprim++;
294*2d543d20SAndroid Build Coastguard Worker
295*2d543d20SAndroid Build Coastguard Worker ret =
296*2d543d20SAndroid Build Coastguard Worker hashtab_insert(state->out->p_commons.table, new_id,
297*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_common);
298*2d543d20SAndroid Build Coastguard Worker if (ret) {
299*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
300*2d543d20SAndroid Build Coastguard Worker free(new_common);
301*2d543d20SAndroid Build Coastguard Worker free(new_id);
302*2d543d20SAndroid Build Coastguard Worker return -1;
303*2d543d20SAndroid Build Coastguard Worker }
304*2d543d20SAndroid Build Coastguard Worker
305*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
306*2d543d20SAndroid Build Coastguard Worker (common->permissions.table, perm_copy_callback,
307*2d543d20SAndroid Build Coastguard Worker &new_common->permissions)) {
308*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
309*2d543d20SAndroid Build Coastguard Worker return -1;
310*2d543d20SAndroid Build Coastguard Worker }
311*2d543d20SAndroid Build Coastguard Worker
312*2d543d20SAndroid Build Coastguard Worker return 0;
313*2d543d20SAndroid Build Coastguard Worker }
314*2d543d20SAndroid Build Coastguard Worker
constraint_node_clone(constraint_node_t ** dst,constraint_node_t * src,expand_state_t * state)315*2d543d20SAndroid Build Coastguard Worker static int constraint_node_clone(constraint_node_t ** dst,
316*2d543d20SAndroid Build Coastguard Worker constraint_node_t * src,
317*2d543d20SAndroid Build Coastguard Worker expand_state_t * state)
318*2d543d20SAndroid Build Coastguard Worker {
319*2d543d20SAndroid Build Coastguard Worker constraint_node_t *new_con = NULL, *last_new_con = NULL;
320*2d543d20SAndroid Build Coastguard Worker constraint_expr_t *new_expr = NULL;
321*2d543d20SAndroid Build Coastguard Worker *dst = NULL;
322*2d543d20SAndroid Build Coastguard Worker while (src != NULL) {
323*2d543d20SAndroid Build Coastguard Worker constraint_expr_t *expr, *expr_l = NULL;
324*2d543d20SAndroid Build Coastguard Worker new_con =
325*2d543d20SAndroid Build Coastguard Worker (constraint_node_t *) malloc(sizeof(constraint_node_t));
326*2d543d20SAndroid Build Coastguard Worker if (!new_con) {
327*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
328*2d543d20SAndroid Build Coastguard Worker }
329*2d543d20SAndroid Build Coastguard Worker memset(new_con, 0, sizeof(constraint_node_t));
330*2d543d20SAndroid Build Coastguard Worker new_con->permissions = src->permissions;
331*2d543d20SAndroid Build Coastguard Worker for (expr = src->expr; expr; expr = expr->next) {
332*2d543d20SAndroid Build Coastguard Worker if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) {
333*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
334*2d543d20SAndroid Build Coastguard Worker }
335*2d543d20SAndroid Build Coastguard Worker if (constraint_expr_init(new_expr) == -1) {
336*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
337*2d543d20SAndroid Build Coastguard Worker }
338*2d543d20SAndroid Build Coastguard Worker new_expr->expr_type = expr->expr_type;
339*2d543d20SAndroid Build Coastguard Worker new_expr->attr = expr->attr;
340*2d543d20SAndroid Build Coastguard Worker new_expr->op = expr->op;
341*2d543d20SAndroid Build Coastguard Worker if (new_expr->expr_type == CEXPR_NAMES) {
342*2d543d20SAndroid Build Coastguard Worker if (new_expr->attr & CEXPR_TYPE) {
343*2d543d20SAndroid Build Coastguard Worker /*
344*2d543d20SAndroid Build Coastguard Worker * Copy over constraint policy source types and/or
345*2d543d20SAndroid Build Coastguard Worker * attributes for sepol_compute_av_reason_buffer(3)
346*2d543d20SAndroid Build Coastguard Worker * so that utilities can analyse constraint errors.
347*2d543d20SAndroid Build Coastguard Worker */
348*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&expr->type_names->types,
349*2d543d20SAndroid Build Coastguard Worker &new_expr->type_names->types,
350*2d543d20SAndroid Build Coastguard Worker state->typemap)) {
351*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Failed to map type_names->types");
352*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
353*2d543d20SAndroid Build Coastguard Worker }
354*2d543d20SAndroid Build Coastguard Worker /* Type sets require expansion and conversion. */
355*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set(state->out,
356*2d543d20SAndroid Build Coastguard Worker state->
357*2d543d20SAndroid Build Coastguard Worker typemap,
358*2d543d20SAndroid Build Coastguard Worker expr->
359*2d543d20SAndroid Build Coastguard Worker type_names,
360*2d543d20SAndroid Build Coastguard Worker &new_expr->
361*2d543d20SAndroid Build Coastguard Worker names, 1)) {
362*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
363*2d543d20SAndroid Build Coastguard Worker }
364*2d543d20SAndroid Build Coastguard Worker } else if (new_expr->attr & CEXPR_ROLE) {
365*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
366*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
367*2d543d20SAndroid Build Coastguard Worker }
368*2d543d20SAndroid Build Coastguard Worker if (ebitmap_expand_roles(state->out, &new_expr->names)) {
369*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
370*2d543d20SAndroid Build Coastguard Worker }
371*2d543d20SAndroid Build Coastguard Worker } else if (new_expr->attr & CEXPR_USER) {
372*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
373*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
374*2d543d20SAndroid Build Coastguard Worker }
375*2d543d20SAndroid Build Coastguard Worker } else {
376*2d543d20SAndroid Build Coastguard Worker /* Other kinds of sets do not. */
377*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&new_expr->names,
378*2d543d20SAndroid Build Coastguard Worker &expr->names)) {
379*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
380*2d543d20SAndroid Build Coastguard Worker }
381*2d543d20SAndroid Build Coastguard Worker }
382*2d543d20SAndroid Build Coastguard Worker }
383*2d543d20SAndroid Build Coastguard Worker if (expr_l) {
384*2d543d20SAndroid Build Coastguard Worker expr_l->next = new_expr;
385*2d543d20SAndroid Build Coastguard Worker } else {
386*2d543d20SAndroid Build Coastguard Worker new_con->expr = new_expr;
387*2d543d20SAndroid Build Coastguard Worker }
388*2d543d20SAndroid Build Coastguard Worker expr_l = new_expr;
389*2d543d20SAndroid Build Coastguard Worker new_expr = NULL;
390*2d543d20SAndroid Build Coastguard Worker }
391*2d543d20SAndroid Build Coastguard Worker if (last_new_con == NULL) {
392*2d543d20SAndroid Build Coastguard Worker *dst = new_con;
393*2d543d20SAndroid Build Coastguard Worker } else {
394*2d543d20SAndroid Build Coastguard Worker last_new_con->next = new_con;
395*2d543d20SAndroid Build Coastguard Worker }
396*2d543d20SAndroid Build Coastguard Worker last_new_con = new_con;
397*2d543d20SAndroid Build Coastguard Worker src = src->next;
398*2d543d20SAndroid Build Coastguard Worker }
399*2d543d20SAndroid Build Coastguard Worker
400*2d543d20SAndroid Build Coastguard Worker return 0;
401*2d543d20SAndroid Build Coastguard Worker out_of_mem:
402*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
403*2d543d20SAndroid Build Coastguard Worker if (new_con)
404*2d543d20SAndroid Build Coastguard Worker free(new_con);
405*2d543d20SAndroid Build Coastguard Worker constraint_expr_destroy(new_expr);
406*2d543d20SAndroid Build Coastguard Worker return -1;
407*2d543d20SAndroid Build Coastguard Worker }
408*2d543d20SAndroid Build Coastguard Worker
class_copy_default_new_object(expand_state_t * state,class_datum_t * olddatum,class_datum_t * newdatum)409*2d543d20SAndroid Build Coastguard Worker static int class_copy_default_new_object(expand_state_t *state,
410*2d543d20SAndroid Build Coastguard Worker class_datum_t *olddatum,
411*2d543d20SAndroid Build Coastguard Worker class_datum_t *newdatum)
412*2d543d20SAndroid Build Coastguard Worker {
413*2d543d20SAndroid Build Coastguard Worker if (olddatum->default_user) {
414*2d543d20SAndroid Build Coastguard Worker if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
415*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Found conflicting default user definitions");
416*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOTSUP;
417*2d543d20SAndroid Build Coastguard Worker }
418*2d543d20SAndroid Build Coastguard Worker newdatum->default_user = olddatum->default_user;
419*2d543d20SAndroid Build Coastguard Worker
420*2d543d20SAndroid Build Coastguard Worker }
421*2d543d20SAndroid Build Coastguard Worker if (olddatum->default_role) {
422*2d543d20SAndroid Build Coastguard Worker if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
423*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Found conflicting default role definitions");
424*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOTSUP;
425*2d543d20SAndroid Build Coastguard Worker }
426*2d543d20SAndroid Build Coastguard Worker newdatum->default_role = olddatum->default_role;
427*2d543d20SAndroid Build Coastguard Worker }
428*2d543d20SAndroid Build Coastguard Worker if (olddatum->default_type) {
429*2d543d20SAndroid Build Coastguard Worker if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
430*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Found conflicting default type definitions");
431*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOTSUP;
432*2d543d20SAndroid Build Coastguard Worker }
433*2d543d20SAndroid Build Coastguard Worker newdatum->default_type = olddatum->default_type;
434*2d543d20SAndroid Build Coastguard Worker }
435*2d543d20SAndroid Build Coastguard Worker if (olddatum->default_range) {
436*2d543d20SAndroid Build Coastguard Worker if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
437*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Found conflicting default range definitions");
438*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOTSUP;
439*2d543d20SAndroid Build Coastguard Worker }
440*2d543d20SAndroid Build Coastguard Worker newdatum->default_range = olddatum->default_range;
441*2d543d20SAndroid Build Coastguard Worker }
442*2d543d20SAndroid Build Coastguard Worker return 0;
443*2d543d20SAndroid Build Coastguard Worker }
444*2d543d20SAndroid Build Coastguard Worker
class_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)445*2d543d20SAndroid Build Coastguard Worker static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
446*2d543d20SAndroid Build Coastguard Worker void *data)
447*2d543d20SAndroid Build Coastguard Worker {
448*2d543d20SAndroid Build Coastguard Worker int ret;
449*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
450*2d543d20SAndroid Build Coastguard Worker class_datum_t *class, *new_class;
451*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
452*2d543d20SAndroid Build Coastguard Worker
453*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
454*2d543d20SAndroid Build Coastguard Worker class = (class_datum_t *) datum;
455*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
456*2d543d20SAndroid Build Coastguard Worker
457*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_CLASSES)) {
458*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
459*2d543d20SAndroid Build Coastguard Worker return 0;
460*2d543d20SAndroid Build Coastguard Worker }
461*2d543d20SAndroid Build Coastguard Worker
462*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
463*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying class %s", id);
464*2d543d20SAndroid Build Coastguard Worker
465*2d543d20SAndroid Build Coastguard Worker new_class = (class_datum_t *) malloc(sizeof(class_datum_t));
466*2d543d20SAndroid Build Coastguard Worker if (!new_class) {
467*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
468*2d543d20SAndroid Build Coastguard Worker return -1;
469*2d543d20SAndroid Build Coastguard Worker }
470*2d543d20SAndroid Build Coastguard Worker memset(new_class, 0, sizeof(class_datum_t));
471*2d543d20SAndroid Build Coastguard Worker if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) {
472*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
473*2d543d20SAndroid Build Coastguard Worker free(new_class);
474*2d543d20SAndroid Build Coastguard Worker return -1;
475*2d543d20SAndroid Build Coastguard Worker }
476*2d543d20SAndroid Build Coastguard Worker
477*2d543d20SAndroid Build Coastguard Worker new_class->s.value = class->s.value;
478*2d543d20SAndroid Build Coastguard Worker state->out->p_classes.nprim++;
479*2d543d20SAndroid Build Coastguard Worker
480*2d543d20SAndroid Build Coastguard Worker ret = class_copy_default_new_object(state, class, new_class);
481*2d543d20SAndroid Build Coastguard Worker if (ret) {
482*2d543d20SAndroid Build Coastguard Worker free(new_class);
483*2d543d20SAndroid Build Coastguard Worker return ret;
484*2d543d20SAndroid Build Coastguard Worker }
485*2d543d20SAndroid Build Coastguard Worker
486*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
487*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
488*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
489*2d543d20SAndroid Build Coastguard Worker free(new_class);
490*2d543d20SAndroid Build Coastguard Worker return -1;
491*2d543d20SAndroid Build Coastguard Worker }
492*2d543d20SAndroid Build Coastguard Worker
493*2d543d20SAndroid Build Coastguard Worker ret =
494*2d543d20SAndroid Build Coastguard Worker hashtab_insert(state->out->p_classes.table, new_id,
495*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_class);
496*2d543d20SAndroid Build Coastguard Worker if (ret) {
497*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
498*2d543d20SAndroid Build Coastguard Worker free(new_class);
499*2d543d20SAndroid Build Coastguard Worker free(new_id);
500*2d543d20SAndroid Build Coastguard Worker return -1;
501*2d543d20SAndroid Build Coastguard Worker }
502*2d543d20SAndroid Build Coastguard Worker
503*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
504*2d543d20SAndroid Build Coastguard Worker (class->permissions.table, perm_copy_callback,
505*2d543d20SAndroid Build Coastguard Worker &new_class->permissions)) {
506*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
507*2d543d20SAndroid Build Coastguard Worker return -1;
508*2d543d20SAndroid Build Coastguard Worker }
509*2d543d20SAndroid Build Coastguard Worker
510*2d543d20SAndroid Build Coastguard Worker if (class->comkey) {
511*2d543d20SAndroid Build Coastguard Worker new_class->comkey = strdup(class->comkey);
512*2d543d20SAndroid Build Coastguard Worker if (!new_class->comkey) {
513*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
514*2d543d20SAndroid Build Coastguard Worker return -1;
515*2d543d20SAndroid Build Coastguard Worker }
516*2d543d20SAndroid Build Coastguard Worker
517*2d543d20SAndroid Build Coastguard Worker new_class->comdatum =
518*2d543d20SAndroid Build Coastguard Worker hashtab_search(state->out->p_commons.table,
519*2d543d20SAndroid Build Coastguard Worker new_class->comkey);
520*2d543d20SAndroid Build Coastguard Worker if (!new_class->comdatum) {
521*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "could not find common datum %s",
522*2d543d20SAndroid Build Coastguard Worker new_class->comkey);
523*2d543d20SAndroid Build Coastguard Worker return -1;
524*2d543d20SAndroid Build Coastguard Worker }
525*2d543d20SAndroid Build Coastguard Worker new_class->permissions.nprim +=
526*2d543d20SAndroid Build Coastguard Worker new_class->comdatum->permissions.nprim;
527*2d543d20SAndroid Build Coastguard Worker }
528*2d543d20SAndroid Build Coastguard Worker
529*2d543d20SAndroid Build Coastguard Worker return 0;
530*2d543d20SAndroid Build Coastguard Worker }
531*2d543d20SAndroid Build Coastguard Worker
constraint_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)532*2d543d20SAndroid Build Coastguard Worker static int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
533*2d543d20SAndroid Build Coastguard Worker void *data)
534*2d543d20SAndroid Build Coastguard Worker {
535*2d543d20SAndroid Build Coastguard Worker char *id;
536*2d543d20SAndroid Build Coastguard Worker class_datum_t *class, *new_class;
537*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
538*2d543d20SAndroid Build Coastguard Worker
539*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
540*2d543d20SAndroid Build Coastguard Worker class = (class_datum_t *) datum;
541*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
542*2d543d20SAndroid Build Coastguard Worker
543*2d543d20SAndroid Build Coastguard Worker new_class = hashtab_search(state->out->p_classes.table, id);
544*2d543d20SAndroid Build Coastguard Worker if (!new_class) {
545*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "class %s vanished", id);
546*2d543d20SAndroid Build Coastguard Worker return -1;
547*2d543d20SAndroid Build Coastguard Worker }
548*2d543d20SAndroid Build Coastguard Worker
549*2d543d20SAndroid Build Coastguard Worker /* constraints */
550*2d543d20SAndroid Build Coastguard Worker if (constraint_node_clone
551*2d543d20SAndroid Build Coastguard Worker (&new_class->constraints, class->constraints, state) == -1
552*2d543d20SAndroid Build Coastguard Worker || constraint_node_clone(&new_class->validatetrans,
553*2d543d20SAndroid Build Coastguard Worker class->validatetrans, state) == -1) {
554*2d543d20SAndroid Build Coastguard Worker return -1;
555*2d543d20SAndroid Build Coastguard Worker }
556*2d543d20SAndroid Build Coastguard Worker return 0;
557*2d543d20SAndroid Build Coastguard Worker }
558*2d543d20SAndroid Build Coastguard Worker
559*2d543d20SAndroid Build Coastguard Worker /*
560*2d543d20SAndroid Build Coastguard Worker * The boundaries have to be copied after the types/roles/users are copied,
561*2d543d20SAndroid Build Coastguard Worker * because it refers hashtab to lookup destinated objects.
562*2d543d20SAndroid Build Coastguard Worker */
type_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)563*2d543d20SAndroid Build Coastguard Worker static int type_bounds_copy_callback(hashtab_key_t key,
564*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t datum, void *data)
565*2d543d20SAndroid Build Coastguard Worker {
566*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
567*2d543d20SAndroid Build Coastguard Worker type_datum_t *type = (type_datum_t *) datum;
568*2d543d20SAndroid Build Coastguard Worker type_datum_t *dest;
569*2d543d20SAndroid Build Coastguard Worker uint32_t bounds_val;
570*2d543d20SAndroid Build Coastguard Worker
571*2d543d20SAndroid Build Coastguard Worker if (!type->bounds)
572*2d543d20SAndroid Build Coastguard Worker return 0;
573*2d543d20SAndroid Build Coastguard Worker
574*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled((char *)key, state->base, SYM_TYPES))
575*2d543d20SAndroid Build Coastguard Worker return 0;
576*2d543d20SAndroid Build Coastguard Worker
577*2d543d20SAndroid Build Coastguard Worker bounds_val = state->typemap[type->bounds - 1];
578*2d543d20SAndroid Build Coastguard Worker
579*2d543d20SAndroid Build Coastguard Worker dest = hashtab_search(state->out->p_types.table, (char *)key);
580*2d543d20SAndroid Build Coastguard Worker if (!dest) {
581*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Type lookup failed for %s", (char *)key);
582*2d543d20SAndroid Build Coastguard Worker return -1;
583*2d543d20SAndroid Build Coastguard Worker }
584*2d543d20SAndroid Build Coastguard Worker if (dest->bounds != 0 && dest->bounds != bounds_val) {
585*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
586*2d543d20SAndroid Build Coastguard Worker return -1;
587*2d543d20SAndroid Build Coastguard Worker }
588*2d543d20SAndroid Build Coastguard Worker dest->bounds = bounds_val;
589*2d543d20SAndroid Build Coastguard Worker
590*2d543d20SAndroid Build Coastguard Worker return 0;
591*2d543d20SAndroid Build Coastguard Worker }
592*2d543d20SAndroid Build Coastguard Worker
role_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)593*2d543d20SAndroid Build Coastguard Worker static int role_bounds_copy_callback(hashtab_key_t key,
594*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t datum, void *data)
595*2d543d20SAndroid Build Coastguard Worker {
596*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
597*2d543d20SAndroid Build Coastguard Worker role_datum_t *role = (role_datum_t *) datum;
598*2d543d20SAndroid Build Coastguard Worker role_datum_t *dest;
599*2d543d20SAndroid Build Coastguard Worker uint32_t bounds_val;
600*2d543d20SAndroid Build Coastguard Worker
601*2d543d20SAndroid Build Coastguard Worker if (!role->bounds)
602*2d543d20SAndroid Build Coastguard Worker return 0;
603*2d543d20SAndroid Build Coastguard Worker
604*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled((char *)key, state->base, SYM_ROLES))
605*2d543d20SAndroid Build Coastguard Worker return 0;
606*2d543d20SAndroid Build Coastguard Worker
607*2d543d20SAndroid Build Coastguard Worker bounds_val = state->rolemap[role->bounds - 1];
608*2d543d20SAndroid Build Coastguard Worker
609*2d543d20SAndroid Build Coastguard Worker dest = hashtab_search(state->out->p_roles.table, (char *)key);
610*2d543d20SAndroid Build Coastguard Worker if (!dest) {
611*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Role lookup failed for %s", (char *)key);
612*2d543d20SAndroid Build Coastguard Worker return -1;
613*2d543d20SAndroid Build Coastguard Worker }
614*2d543d20SAndroid Build Coastguard Worker if (dest->bounds != 0 && dest->bounds != bounds_val) {
615*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
616*2d543d20SAndroid Build Coastguard Worker return -1;
617*2d543d20SAndroid Build Coastguard Worker }
618*2d543d20SAndroid Build Coastguard Worker dest->bounds = bounds_val;
619*2d543d20SAndroid Build Coastguard Worker
620*2d543d20SAndroid Build Coastguard Worker return 0;
621*2d543d20SAndroid Build Coastguard Worker }
622*2d543d20SAndroid Build Coastguard Worker
user_bounds_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)623*2d543d20SAndroid Build Coastguard Worker static int user_bounds_copy_callback(hashtab_key_t key,
624*2d543d20SAndroid Build Coastguard Worker hashtab_datum_t datum, void *data)
625*2d543d20SAndroid Build Coastguard Worker {
626*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
627*2d543d20SAndroid Build Coastguard Worker user_datum_t *user = (user_datum_t *) datum;
628*2d543d20SAndroid Build Coastguard Worker user_datum_t *dest;
629*2d543d20SAndroid Build Coastguard Worker uint32_t bounds_val;
630*2d543d20SAndroid Build Coastguard Worker
631*2d543d20SAndroid Build Coastguard Worker if (!user->bounds)
632*2d543d20SAndroid Build Coastguard Worker return 0;
633*2d543d20SAndroid Build Coastguard Worker
634*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled((char *)key, state->base, SYM_USERS))
635*2d543d20SAndroid Build Coastguard Worker return 0;
636*2d543d20SAndroid Build Coastguard Worker
637*2d543d20SAndroid Build Coastguard Worker bounds_val = state->usermap[user->bounds - 1];
638*2d543d20SAndroid Build Coastguard Worker
639*2d543d20SAndroid Build Coastguard Worker dest = hashtab_search(state->out->p_users.table, (char *)key);
640*2d543d20SAndroid Build Coastguard Worker if (!dest) {
641*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "User lookup failed for %s", (char *)key);
642*2d543d20SAndroid Build Coastguard Worker return -1;
643*2d543d20SAndroid Build Coastguard Worker }
644*2d543d20SAndroid Build Coastguard Worker if (dest->bounds != 0 && dest->bounds != bounds_val) {
645*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Inconsistent boundary for %s", (char *)key);
646*2d543d20SAndroid Build Coastguard Worker return -1;
647*2d543d20SAndroid Build Coastguard Worker }
648*2d543d20SAndroid Build Coastguard Worker dest->bounds = bounds_val;
649*2d543d20SAndroid Build Coastguard Worker
650*2d543d20SAndroid Build Coastguard Worker return 0;
651*2d543d20SAndroid Build Coastguard Worker }
652*2d543d20SAndroid Build Coastguard Worker
653*2d543d20SAndroid Build Coastguard Worker /* The aliases have to be copied after the types and attributes to be certain that
654*2d543d20SAndroid Build Coastguard Worker * the out symbol table will have the type that the alias refers. Otherwise, we
655*2d543d20SAndroid Build Coastguard Worker * won't be able to find the type value for the alias. We can't depend on the
656*2d543d20SAndroid Build Coastguard Worker * declaration ordering because of the hash table.
657*2d543d20SAndroid Build Coastguard Worker */
alias_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)658*2d543d20SAndroid Build Coastguard Worker static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
659*2d543d20SAndroid Build Coastguard Worker void *data)
660*2d543d20SAndroid Build Coastguard Worker {
661*2d543d20SAndroid Build Coastguard Worker int ret;
662*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
663*2d543d20SAndroid Build Coastguard Worker type_datum_t *alias, *new_alias;
664*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
665*2d543d20SAndroid Build Coastguard Worker uint32_t prival;
666*2d543d20SAndroid Build Coastguard Worker
667*2d543d20SAndroid Build Coastguard Worker id = (char *)key;
668*2d543d20SAndroid Build Coastguard Worker alias = (type_datum_t *) datum;
669*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
670*2d543d20SAndroid Build Coastguard Worker
671*2d543d20SAndroid Build Coastguard Worker /* ignore regular types */
672*2d543d20SAndroid Build Coastguard Worker if (alias->flavor == TYPE_TYPE && alias->primary)
673*2d543d20SAndroid Build Coastguard Worker return 0;
674*2d543d20SAndroid Build Coastguard Worker
675*2d543d20SAndroid Build Coastguard Worker /* ignore attributes */
676*2d543d20SAndroid Build Coastguard Worker if (alias->flavor == TYPE_ATTRIB)
677*2d543d20SAndroid Build Coastguard Worker return 0;
678*2d543d20SAndroid Build Coastguard Worker
679*2d543d20SAndroid Build Coastguard Worker if (alias->flavor == TYPE_ALIAS)
680*2d543d20SAndroid Build Coastguard Worker prival = alias->primary;
681*2d543d20SAndroid Build Coastguard Worker else
682*2d543d20SAndroid Build Coastguard Worker prival = alias->s.value;
683*2d543d20SAndroid Build Coastguard Worker
684*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(state->base->p_type_val_to_name[prival - 1],
685*2d543d20SAndroid Build Coastguard Worker state->base, SYM_TYPES)) {
686*2d543d20SAndroid Build Coastguard Worker /* The primary type for this alias is not enabled, the alias
687*2d543d20SAndroid Build Coastguard Worker * shouldn't be either */
688*2d543d20SAndroid Build Coastguard Worker return 0;
689*2d543d20SAndroid Build Coastguard Worker }
690*2d543d20SAndroid Build Coastguard Worker
691*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
692*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying alias %s", id);
693*2d543d20SAndroid Build Coastguard Worker
694*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
695*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
696*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
697*2d543d20SAndroid Build Coastguard Worker return -1;
698*2d543d20SAndroid Build Coastguard Worker }
699*2d543d20SAndroid Build Coastguard Worker
700*2d543d20SAndroid Build Coastguard Worker new_alias = (type_datum_t *) malloc(sizeof(type_datum_t));
701*2d543d20SAndroid Build Coastguard Worker if (!new_alias) {
702*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
703*2d543d20SAndroid Build Coastguard Worker free(new_id);
704*2d543d20SAndroid Build Coastguard Worker return SEPOL_ENOMEM;
705*2d543d20SAndroid Build Coastguard Worker }
706*2d543d20SAndroid Build Coastguard Worker memset(new_alias, 0, sizeof(type_datum_t));
707*2d543d20SAndroid Build Coastguard Worker if (alias->flavor == TYPE_TYPE)
708*2d543d20SAndroid Build Coastguard Worker new_alias->s.value = state->typemap[alias->s.value - 1];
709*2d543d20SAndroid Build Coastguard Worker else if (alias->flavor == TYPE_ALIAS)
710*2d543d20SAndroid Build Coastguard Worker new_alias->s.value = state->typemap[alias->primary - 1];
711*2d543d20SAndroid Build Coastguard Worker else
712*2d543d20SAndroid Build Coastguard Worker assert(0); /* unreachable */
713*2d543d20SAndroid Build Coastguard Worker
714*2d543d20SAndroid Build Coastguard Worker new_alias->flags = alias->flags;
715*2d543d20SAndroid Build Coastguard Worker
716*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(state->out->p_types.table,
717*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
718*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_alias);
719*2d543d20SAndroid Build Coastguard Worker
720*2d543d20SAndroid Build Coastguard Worker if (ret) {
721*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
722*2d543d20SAndroid Build Coastguard Worker free(new_alias);
723*2d543d20SAndroid Build Coastguard Worker free(new_id);
724*2d543d20SAndroid Build Coastguard Worker return -1;
725*2d543d20SAndroid Build Coastguard Worker }
726*2d543d20SAndroid Build Coastguard Worker
727*2d543d20SAndroid Build Coastguard Worker state->typemap[alias->s.value - 1] = new_alias->s.value;
728*2d543d20SAndroid Build Coastguard Worker
729*2d543d20SAndroid Build Coastguard Worker if (new_alias->flags & TYPE_FLAGS_PERMISSIVE)
730*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) {
731*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
732*2d543d20SAndroid Build Coastguard Worker return -1;
733*2d543d20SAndroid Build Coastguard Worker }
734*2d543d20SAndroid Build Coastguard Worker
735*2d543d20SAndroid Build Coastguard Worker return 0;
736*2d543d20SAndroid Build Coastguard Worker }
737*2d543d20SAndroid Build Coastguard Worker
role_remap_dominates(hashtab_key_t key,hashtab_datum_t datum,void * data)738*2d543d20SAndroid Build Coastguard Worker static int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data)
739*2d543d20SAndroid Build Coastguard Worker {
740*2d543d20SAndroid Build Coastguard Worker ebitmap_t mapped_roles;
741*2d543d20SAndroid Build Coastguard Worker role_datum_t *role = (role_datum_t *) datum;
742*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
743*2d543d20SAndroid Build Coastguard Worker
744*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap))
745*2d543d20SAndroid Build Coastguard Worker return -1;
746*2d543d20SAndroid Build Coastguard Worker
747*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&role->dominates);
748*2d543d20SAndroid Build Coastguard Worker
749*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&role->dominates, &mapped_roles))
750*2d543d20SAndroid Build Coastguard Worker return -1;
751*2d543d20SAndroid Build Coastguard Worker
752*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&mapped_roles);
753*2d543d20SAndroid Build Coastguard Worker
754*2d543d20SAndroid Build Coastguard Worker return 0;
755*2d543d20SAndroid Build Coastguard Worker }
756*2d543d20SAndroid Build Coastguard Worker
757*2d543d20SAndroid Build Coastguard Worker /* For the role attribute in the base module, escalate its counterpart's
758*2d543d20SAndroid Build Coastguard Worker * types.types ebitmap in the out module to the counterparts of all the
759*2d543d20SAndroid Build Coastguard Worker * regular role that belongs to the current role attribute. Note, must be
760*2d543d20SAndroid Build Coastguard Worker * invoked after role_copy_callback so that state->rolemap is available.
761*2d543d20SAndroid Build Coastguard Worker */
role_fix_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)762*2d543d20SAndroid Build Coastguard Worker static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
763*2d543d20SAndroid Build Coastguard Worker void *data)
764*2d543d20SAndroid Build Coastguard Worker {
765*2d543d20SAndroid Build Coastguard Worker char *id, *base_reg_role_id;
766*2d543d20SAndroid Build Coastguard Worker role_datum_t *role, *new_role, *regular_role;
767*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
768*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *rnode;
769*2d543d20SAndroid Build Coastguard Worker unsigned int i;
770*2d543d20SAndroid Build Coastguard Worker ebitmap_t mapped_roles;
771*2d543d20SAndroid Build Coastguard Worker
772*2d543d20SAndroid Build Coastguard Worker id = key;
773*2d543d20SAndroid Build Coastguard Worker role = (role_datum_t *)datum;
774*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *)data;
775*2d543d20SAndroid Build Coastguard Worker
776*2d543d20SAndroid Build Coastguard Worker if (strcmp(id, OBJECT_R) == 0) {
777*2d543d20SAndroid Build Coastguard Worker /* object_r is never a role attribute by far */
778*2d543d20SAndroid Build Coastguard Worker return 0;
779*2d543d20SAndroid Build Coastguard Worker }
780*2d543d20SAndroid Build Coastguard Worker
781*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_ROLES)) {
782*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
783*2d543d20SAndroid Build Coastguard Worker return 0;
784*2d543d20SAndroid Build Coastguard Worker }
785*2d543d20SAndroid Build Coastguard Worker
786*2d543d20SAndroid Build Coastguard Worker if (role->flavor != ROLE_ATTRIB)
787*2d543d20SAndroid Build Coastguard Worker return 0;
788*2d543d20SAndroid Build Coastguard Worker
789*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
790*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "fixing role attribute %s", id);
791*2d543d20SAndroid Build Coastguard Worker
792*2d543d20SAndroid Build Coastguard Worker new_role =
793*2d543d20SAndroid Build Coastguard Worker (role_datum_t *)hashtab_search(state->out->p_roles.table, id);
794*2d543d20SAndroid Build Coastguard Worker
795*2d543d20SAndroid Build Coastguard Worker assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB);
796*2d543d20SAndroid Build Coastguard Worker
797*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&mapped_roles);
798*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap))
799*2d543d20SAndroid Build Coastguard Worker return -1;
800*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&new_role->roles, &mapped_roles)) {
801*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
802*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&mapped_roles);
803*2d543d20SAndroid Build Coastguard Worker return -1;
804*2d543d20SAndroid Build Coastguard Worker }
805*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&mapped_roles);
806*2d543d20SAndroid Build Coastguard Worker
807*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&role->roles, rnode, i) {
808*2d543d20SAndroid Build Coastguard Worker /* take advantage of sym_val_to_name[]
809*2d543d20SAndroid Build Coastguard Worker * of the base module */
810*2d543d20SAndroid Build Coastguard Worker base_reg_role_id = state->base->p_role_val_to_name[i];
811*2d543d20SAndroid Build Coastguard Worker regular_role = (role_datum_t *)hashtab_search(
812*2d543d20SAndroid Build Coastguard Worker state->out->p_roles.table,
813*2d543d20SAndroid Build Coastguard Worker base_reg_role_id);
814*2d543d20SAndroid Build Coastguard Worker assert(regular_role != NULL &&
815*2d543d20SAndroid Build Coastguard Worker regular_role->flavor == ROLE_ROLE);
816*2d543d20SAndroid Build Coastguard Worker
817*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(®ular_role->types.types,
818*2d543d20SAndroid Build Coastguard Worker &new_role->types.types)) {
819*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
820*2d543d20SAndroid Build Coastguard Worker return -1;
821*2d543d20SAndroid Build Coastguard Worker }
822*2d543d20SAndroid Build Coastguard Worker }
823*2d543d20SAndroid Build Coastguard Worker
824*2d543d20SAndroid Build Coastguard Worker return 0;
825*2d543d20SAndroid Build Coastguard Worker }
826*2d543d20SAndroid Build Coastguard Worker
role_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)827*2d543d20SAndroid Build Coastguard Worker static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
828*2d543d20SAndroid Build Coastguard Worker void *data)
829*2d543d20SAndroid Build Coastguard Worker {
830*2d543d20SAndroid Build Coastguard Worker int ret;
831*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
832*2d543d20SAndroid Build Coastguard Worker role_datum_t *role;
833*2d543d20SAndroid Build Coastguard Worker role_datum_t *new_role;
834*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
835*2d543d20SAndroid Build Coastguard Worker ebitmap_t tmp_union_types;
836*2d543d20SAndroid Build Coastguard Worker
837*2d543d20SAndroid Build Coastguard Worker id = key;
838*2d543d20SAndroid Build Coastguard Worker role = (role_datum_t *) datum;
839*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
840*2d543d20SAndroid Build Coastguard Worker
841*2d543d20SAndroid Build Coastguard Worker if (strcmp(id, OBJECT_R) == 0) {
842*2d543d20SAndroid Build Coastguard Worker /* object_r is always value 1 */
843*2d543d20SAndroid Build Coastguard Worker state->rolemap[role->s.value - 1] = 1;
844*2d543d20SAndroid Build Coastguard Worker return 0;
845*2d543d20SAndroid Build Coastguard Worker }
846*2d543d20SAndroid Build Coastguard Worker
847*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_ROLES)) {
848*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
849*2d543d20SAndroid Build Coastguard Worker return 0;
850*2d543d20SAndroid Build Coastguard Worker }
851*2d543d20SAndroid Build Coastguard Worker
852*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
853*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying role %s", id);
854*2d543d20SAndroid Build Coastguard Worker
855*2d543d20SAndroid Build Coastguard Worker new_role =
856*2d543d20SAndroid Build Coastguard Worker (role_datum_t *) hashtab_search(state->out->p_roles.table, id);
857*2d543d20SAndroid Build Coastguard Worker if (!new_role) {
858*2d543d20SAndroid Build Coastguard Worker new_role = (role_datum_t *) malloc(sizeof(role_datum_t));
859*2d543d20SAndroid Build Coastguard Worker if (!new_role) {
860*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
861*2d543d20SAndroid Build Coastguard Worker return -1;
862*2d543d20SAndroid Build Coastguard Worker }
863*2d543d20SAndroid Build Coastguard Worker memset(new_role, 0, sizeof(role_datum_t));
864*2d543d20SAndroid Build Coastguard Worker
865*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
866*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
867*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
868*2d543d20SAndroid Build Coastguard Worker free(new_role);
869*2d543d20SAndroid Build Coastguard Worker return -1;
870*2d543d20SAndroid Build Coastguard Worker }
871*2d543d20SAndroid Build Coastguard Worker
872*2d543d20SAndroid Build Coastguard Worker state->out->p_roles.nprim++;
873*2d543d20SAndroid Build Coastguard Worker new_role->flavor = role->flavor;
874*2d543d20SAndroid Build Coastguard Worker new_role->s.value = state->out->p_roles.nprim;
875*2d543d20SAndroid Build Coastguard Worker state->rolemap[role->s.value - 1] = new_role->s.value;
876*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(state->out->p_roles.table,
877*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
878*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_role);
879*2d543d20SAndroid Build Coastguard Worker
880*2d543d20SAndroid Build Coastguard Worker if (ret) {
881*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
882*2d543d20SAndroid Build Coastguard Worker free(new_role);
883*2d543d20SAndroid Build Coastguard Worker free(new_id);
884*2d543d20SAndroid Build Coastguard Worker return -1;
885*2d543d20SAndroid Build Coastguard Worker }
886*2d543d20SAndroid Build Coastguard Worker }
887*2d543d20SAndroid Build Coastguard Worker
888*2d543d20SAndroid Build Coastguard Worker /* The dominates bitmap is going to be wrong for the moment,
889*2d543d20SAndroid Build Coastguard Worker * we'll come back later and remap them, after we are sure all
890*2d543d20SAndroid Build Coastguard Worker * the roles have been added */
891*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&new_role->dominates, &role->dominates)) {
892*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
893*2d543d20SAndroid Build Coastguard Worker return -1;
894*2d543d20SAndroid Build Coastguard Worker }
895*2d543d20SAndroid Build Coastguard Worker
896*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&tmp_union_types);
897*2d543d20SAndroid Build Coastguard Worker
898*2d543d20SAndroid Build Coastguard Worker /* convert types in the role datum in the global symtab */
899*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
900*2d543d20SAndroid Build Coastguard Worker (state->out, state->typemap, &role->types, &tmp_union_types, 1)) {
901*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union_types);
902*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
903*2d543d20SAndroid Build Coastguard Worker return -1;
904*2d543d20SAndroid Build Coastguard Worker }
905*2d543d20SAndroid Build Coastguard Worker
906*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&new_role->types.types, &tmp_union_types)) {
907*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
908*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union_types);
909*2d543d20SAndroid Build Coastguard Worker return -1;
910*2d543d20SAndroid Build Coastguard Worker }
911*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union_types);
912*2d543d20SAndroid Build Coastguard Worker
913*2d543d20SAndroid Build Coastguard Worker return 0;
914*2d543d20SAndroid Build Coastguard Worker }
915*2d543d20SAndroid Build Coastguard Worker
mls_semantic_level_expand(mls_semantic_level_t * sl,mls_level_t * l,policydb_t * p,sepol_handle_t * h)916*2d543d20SAndroid Build Coastguard Worker int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
917*2d543d20SAndroid Build Coastguard Worker policydb_t * p, sepol_handle_t * h)
918*2d543d20SAndroid Build Coastguard Worker {
919*2d543d20SAndroid Build Coastguard Worker mls_semantic_cat_t *cat;
920*2d543d20SAndroid Build Coastguard Worker level_datum_t *levdatum;
921*2d543d20SAndroid Build Coastguard Worker unsigned int i;
922*2d543d20SAndroid Build Coastguard Worker
923*2d543d20SAndroid Build Coastguard Worker mls_level_init(l);
924*2d543d20SAndroid Build Coastguard Worker
925*2d543d20SAndroid Build Coastguard Worker if (!p->mls)
926*2d543d20SAndroid Build Coastguard Worker return 0;
927*2d543d20SAndroid Build Coastguard Worker
928*2d543d20SAndroid Build Coastguard Worker /* Required not declared. */
929*2d543d20SAndroid Build Coastguard Worker if (!sl->sens)
930*2d543d20SAndroid Build Coastguard Worker return 0;
931*2d543d20SAndroid Build Coastguard Worker
932*2d543d20SAndroid Build Coastguard Worker /* Invalid sensitivity */
933*2d543d20SAndroid Build Coastguard Worker if (sl->sens > p->p_levels.nprim || !p->p_sens_val_to_name[sl->sens - 1])
934*2d543d20SAndroid Build Coastguard Worker return -1;
935*2d543d20SAndroid Build Coastguard Worker
936*2d543d20SAndroid Build Coastguard Worker l->sens = sl->sens;
937*2d543d20SAndroid Build Coastguard Worker levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
938*2d543d20SAndroid Build Coastguard Worker p->p_sens_val_to_name[l->sens - 1]);
939*2d543d20SAndroid Build Coastguard Worker if (!levdatum) {
940*2d543d20SAndroid Build Coastguard Worker ERR(h, "%s: Impossible situation found, nothing in p_levels.table.",
941*2d543d20SAndroid Build Coastguard Worker __func__);
942*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
943*2d543d20SAndroid Build Coastguard Worker return -1;
944*2d543d20SAndroid Build Coastguard Worker }
945*2d543d20SAndroid Build Coastguard Worker for (cat = sl->cat; cat; cat = cat->next) {
946*2d543d20SAndroid Build Coastguard Worker if (!cat->low || cat->low > cat->high) {
947*2d543d20SAndroid Build Coastguard Worker ERR(h, "Category range is not valid %s.%s",
948*2d543d20SAndroid Build Coastguard Worker cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid",
949*2d543d20SAndroid Build Coastguard Worker cat->high > 0 ? p->p_cat_val_to_name[cat->high - 1] : "Invalid");
950*2d543d20SAndroid Build Coastguard Worker return -1;
951*2d543d20SAndroid Build Coastguard Worker }
952*2d543d20SAndroid Build Coastguard Worker for (i = cat->low - 1; i < cat->high; i++) {
953*2d543d20SAndroid Build Coastguard Worker if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
954*2d543d20SAndroid Build Coastguard Worker ERR(h, "Category %s can not be associated with "
955*2d543d20SAndroid Build Coastguard Worker "level %s",
956*2d543d20SAndroid Build Coastguard Worker p->p_cat_val_to_name[i],
957*2d543d20SAndroid Build Coastguard Worker p->p_sens_val_to_name[l->sens - 1]);
958*2d543d20SAndroid Build Coastguard Worker return -1;
959*2d543d20SAndroid Build Coastguard Worker }
960*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&l->cat, i, 1)) {
961*2d543d20SAndroid Build Coastguard Worker ERR(h, "Out of memory!");
962*2d543d20SAndroid Build Coastguard Worker return -1;
963*2d543d20SAndroid Build Coastguard Worker }
964*2d543d20SAndroid Build Coastguard Worker }
965*2d543d20SAndroid Build Coastguard Worker }
966*2d543d20SAndroid Build Coastguard Worker
967*2d543d20SAndroid Build Coastguard Worker return 0;
968*2d543d20SAndroid Build Coastguard Worker }
969*2d543d20SAndroid Build Coastguard Worker
mls_semantic_range_expand(mls_semantic_range_t * sr,mls_range_t * r,policydb_t * p,sepol_handle_t * h)970*2d543d20SAndroid Build Coastguard Worker int mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r,
971*2d543d20SAndroid Build Coastguard Worker policydb_t * p, sepol_handle_t * h)
972*2d543d20SAndroid Build Coastguard Worker {
973*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0)
974*2d543d20SAndroid Build Coastguard Worker return -1;
975*2d543d20SAndroid Build Coastguard Worker
976*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) {
977*2d543d20SAndroid Build Coastguard Worker mls_level_destroy(&r->level[0]);
978*2d543d20SAndroid Build Coastguard Worker return -1;
979*2d543d20SAndroid Build Coastguard Worker }
980*2d543d20SAndroid Build Coastguard Worker
981*2d543d20SAndroid Build Coastguard Worker if (!mls_level_dom(&r->level[1], &r->level[0])) {
982*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(r);
983*2d543d20SAndroid Build Coastguard Worker ERR(h, "MLS range high level does not dominate low level");
984*2d543d20SAndroid Build Coastguard Worker return -1;
985*2d543d20SAndroid Build Coastguard Worker }
986*2d543d20SAndroid Build Coastguard Worker
987*2d543d20SAndroid Build Coastguard Worker return 0;
988*2d543d20SAndroid Build Coastguard Worker }
989*2d543d20SAndroid Build Coastguard Worker
user_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)990*2d543d20SAndroid Build Coastguard Worker static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
991*2d543d20SAndroid Build Coastguard Worker void *data)
992*2d543d20SAndroid Build Coastguard Worker {
993*2d543d20SAndroid Build Coastguard Worker int ret;
994*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
995*2d543d20SAndroid Build Coastguard Worker user_datum_t *user;
996*2d543d20SAndroid Build Coastguard Worker user_datum_t *new_user;
997*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
998*2d543d20SAndroid Build Coastguard Worker ebitmap_t tmp_union;
999*2d543d20SAndroid Build Coastguard Worker
1000*2d543d20SAndroid Build Coastguard Worker id = key;
1001*2d543d20SAndroid Build Coastguard Worker user = (user_datum_t *) datum;
1002*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
1003*2d543d20SAndroid Build Coastguard Worker
1004*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_USERS)) {
1005*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
1006*2d543d20SAndroid Build Coastguard Worker return 0;
1007*2d543d20SAndroid Build Coastguard Worker }
1008*2d543d20SAndroid Build Coastguard Worker
1009*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
1010*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying user %s", id);
1011*2d543d20SAndroid Build Coastguard Worker
1012*2d543d20SAndroid Build Coastguard Worker new_user =
1013*2d543d20SAndroid Build Coastguard Worker (user_datum_t *) hashtab_search(state->out->p_users.table, id);
1014*2d543d20SAndroid Build Coastguard Worker if (!new_user) {
1015*2d543d20SAndroid Build Coastguard Worker new_user = (user_datum_t *) malloc(sizeof(user_datum_t));
1016*2d543d20SAndroid Build Coastguard Worker if (!new_user) {
1017*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1018*2d543d20SAndroid Build Coastguard Worker return -1;
1019*2d543d20SAndroid Build Coastguard Worker }
1020*2d543d20SAndroid Build Coastguard Worker memset(new_user, 0, sizeof(user_datum_t));
1021*2d543d20SAndroid Build Coastguard Worker
1022*2d543d20SAndroid Build Coastguard Worker state->out->p_users.nprim++;
1023*2d543d20SAndroid Build Coastguard Worker new_user->s.value = state->out->p_users.nprim;
1024*2d543d20SAndroid Build Coastguard Worker state->usermap[user->s.value - 1] = new_user->s.value;
1025*2d543d20SAndroid Build Coastguard Worker
1026*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
1027*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
1028*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1029*2d543d20SAndroid Build Coastguard Worker free(new_user);
1030*2d543d20SAndroid Build Coastguard Worker return -1;
1031*2d543d20SAndroid Build Coastguard Worker }
1032*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(state->out->p_users.table,
1033*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
1034*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_user);
1035*2d543d20SAndroid Build Coastguard Worker if (ret) {
1036*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
1037*2d543d20SAndroid Build Coastguard Worker user_datum_destroy(new_user);
1038*2d543d20SAndroid Build Coastguard Worker free(new_user);
1039*2d543d20SAndroid Build Coastguard Worker free(new_id);
1040*2d543d20SAndroid Build Coastguard Worker return -1;
1041*2d543d20SAndroid Build Coastguard Worker }
1042*2d543d20SAndroid Build Coastguard Worker
1043*2d543d20SAndroid Build Coastguard Worker /* expand the semantic MLS info */
1044*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_range_expand(&user->range,
1045*2d543d20SAndroid Build Coastguard Worker &new_user->exp_range,
1046*2d543d20SAndroid Build Coastguard Worker state->out, state->handle)) {
1047*2d543d20SAndroid Build Coastguard Worker return -1;
1048*2d543d20SAndroid Build Coastguard Worker }
1049*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_level_expand(&user->dfltlevel,
1050*2d543d20SAndroid Build Coastguard Worker &new_user->exp_dfltlevel,
1051*2d543d20SAndroid Build Coastguard Worker state->out, state->handle)) {
1052*2d543d20SAndroid Build Coastguard Worker return -1;
1053*2d543d20SAndroid Build Coastguard Worker }
1054*2d543d20SAndroid Build Coastguard Worker if (!mls_level_between(&new_user->exp_dfltlevel,
1055*2d543d20SAndroid Build Coastguard Worker &new_user->exp_range.level[0],
1056*2d543d20SAndroid Build Coastguard Worker &new_user->exp_range.level[1])) {
1057*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "default level not within user "
1058*2d543d20SAndroid Build Coastguard Worker "range");
1059*2d543d20SAndroid Build Coastguard Worker return -1;
1060*2d543d20SAndroid Build Coastguard Worker }
1061*2d543d20SAndroid Build Coastguard Worker } else {
1062*2d543d20SAndroid Build Coastguard Worker /* require that the MLS info match */
1063*2d543d20SAndroid Build Coastguard Worker mls_range_t tmp_range;
1064*2d543d20SAndroid Build Coastguard Worker mls_level_t tmp_level;
1065*2d543d20SAndroid Build Coastguard Worker
1066*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_range_expand(&user->range, &tmp_range,
1067*2d543d20SAndroid Build Coastguard Worker state->out, state->handle)) {
1068*2d543d20SAndroid Build Coastguard Worker return -1;
1069*2d543d20SAndroid Build Coastguard Worker }
1070*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
1071*2d543d20SAndroid Build Coastguard Worker state->out, state->handle)) {
1072*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(&tmp_range);
1073*2d543d20SAndroid Build Coastguard Worker return -1;
1074*2d543d20SAndroid Build Coastguard Worker }
1075*2d543d20SAndroid Build Coastguard Worker if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
1076*2d543d20SAndroid Build Coastguard Worker !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
1077*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(&tmp_range);
1078*2d543d20SAndroid Build Coastguard Worker mls_level_destroy(&tmp_level);
1079*2d543d20SAndroid Build Coastguard Worker return -1;
1080*2d543d20SAndroid Build Coastguard Worker }
1081*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(&tmp_range);
1082*2d543d20SAndroid Build Coastguard Worker mls_level_destroy(&tmp_level);
1083*2d543d20SAndroid Build Coastguard Worker }
1084*2d543d20SAndroid Build Coastguard Worker
1085*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&tmp_union);
1086*2d543d20SAndroid Build Coastguard Worker
1087*2d543d20SAndroid Build Coastguard Worker /* get global roles for this user */
1088*2d543d20SAndroid Build Coastguard Worker if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) {
1089*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1090*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union);
1091*2d543d20SAndroid Build Coastguard Worker return -1;
1092*2d543d20SAndroid Build Coastguard Worker }
1093*2d543d20SAndroid Build Coastguard Worker
1094*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&new_user->roles.roles, &tmp_union)) {
1095*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1096*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union);
1097*2d543d20SAndroid Build Coastguard Worker return -1;
1098*2d543d20SAndroid Build Coastguard Worker }
1099*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&tmp_union);
1100*2d543d20SAndroid Build Coastguard Worker
1101*2d543d20SAndroid Build Coastguard Worker return 0;
1102*2d543d20SAndroid Build Coastguard Worker }
1103*2d543d20SAndroid Build Coastguard Worker
bool_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1104*2d543d20SAndroid Build Coastguard Worker static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
1105*2d543d20SAndroid Build Coastguard Worker void *data)
1106*2d543d20SAndroid Build Coastguard Worker {
1107*2d543d20SAndroid Build Coastguard Worker int ret;
1108*2d543d20SAndroid Build Coastguard Worker expand_state_t *state;
1109*2d543d20SAndroid Build Coastguard Worker cond_bool_datum_t *boolean, *new_bool;
1110*2d543d20SAndroid Build Coastguard Worker char *id, *new_id;
1111*2d543d20SAndroid Build Coastguard Worker
1112*2d543d20SAndroid Build Coastguard Worker id = key;
1113*2d543d20SAndroid Build Coastguard Worker boolean = (cond_bool_datum_t *) datum;
1114*2d543d20SAndroid Build Coastguard Worker state = (expand_state_t *) data;
1115*2d543d20SAndroid Build Coastguard Worker
1116*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_BOOLS)) {
1117*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
1118*2d543d20SAndroid Build Coastguard Worker return 0;
1119*2d543d20SAndroid Build Coastguard Worker }
1120*2d543d20SAndroid Build Coastguard Worker
1121*2d543d20SAndroid Build Coastguard Worker if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) {
1122*2d543d20SAndroid Build Coastguard Worker /* Skip tunables */
1123*2d543d20SAndroid Build Coastguard Worker return 0;
1124*2d543d20SAndroid Build Coastguard Worker }
1125*2d543d20SAndroid Build Coastguard Worker
1126*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
1127*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying boolean %s", id);
1128*2d543d20SAndroid Build Coastguard Worker
1129*2d543d20SAndroid Build Coastguard Worker new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
1130*2d543d20SAndroid Build Coastguard Worker if (!new_bool) {
1131*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1132*2d543d20SAndroid Build Coastguard Worker return -1;
1133*2d543d20SAndroid Build Coastguard Worker }
1134*2d543d20SAndroid Build Coastguard Worker
1135*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
1136*2d543d20SAndroid Build Coastguard Worker if (!new_id) {
1137*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1138*2d543d20SAndroid Build Coastguard Worker free(new_bool);
1139*2d543d20SAndroid Build Coastguard Worker return -1;
1140*2d543d20SAndroid Build Coastguard Worker }
1141*2d543d20SAndroid Build Coastguard Worker
1142*2d543d20SAndroid Build Coastguard Worker state->out->p_bools.nprim++;
1143*2d543d20SAndroid Build Coastguard Worker new_bool->s.value = state->out->p_bools.nprim;
1144*2d543d20SAndroid Build Coastguard Worker
1145*2d543d20SAndroid Build Coastguard Worker ret = hashtab_insert(state->out->p_bools.table,
1146*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
1147*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_bool);
1148*2d543d20SAndroid Build Coastguard Worker if (ret) {
1149*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "hashtab overflow");
1150*2d543d20SAndroid Build Coastguard Worker free(new_bool);
1151*2d543d20SAndroid Build Coastguard Worker free(new_id);
1152*2d543d20SAndroid Build Coastguard Worker return -1;
1153*2d543d20SAndroid Build Coastguard Worker }
1154*2d543d20SAndroid Build Coastguard Worker
1155*2d543d20SAndroid Build Coastguard Worker state->boolmap[boolean->s.value - 1] = new_bool->s.value;
1156*2d543d20SAndroid Build Coastguard Worker
1157*2d543d20SAndroid Build Coastguard Worker new_bool->state = boolean->state;
1158*2d543d20SAndroid Build Coastguard Worker new_bool->flags = boolean->flags;
1159*2d543d20SAndroid Build Coastguard Worker
1160*2d543d20SAndroid Build Coastguard Worker return 0;
1161*2d543d20SAndroid Build Coastguard Worker }
1162*2d543d20SAndroid Build Coastguard Worker
sens_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1163*2d543d20SAndroid Build Coastguard Worker static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
1164*2d543d20SAndroid Build Coastguard Worker void *data)
1165*2d543d20SAndroid Build Coastguard Worker {
1166*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
1167*2d543d20SAndroid Build Coastguard Worker level_datum_t *level = (level_datum_t *) datum, *new_level = NULL;
1168*2d543d20SAndroid Build Coastguard Worker char *id = (char *)key, *new_id = NULL;
1169*2d543d20SAndroid Build Coastguard Worker
1170*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_LEVELS)) {
1171*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
1172*2d543d20SAndroid Build Coastguard Worker return 0;
1173*2d543d20SAndroid Build Coastguard Worker }
1174*2d543d20SAndroid Build Coastguard Worker
1175*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
1176*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying sensitivity level %s", id);
1177*2d543d20SAndroid Build Coastguard Worker
1178*2d543d20SAndroid Build Coastguard Worker new_level = (level_datum_t *) malloc(sizeof(level_datum_t));
1179*2d543d20SAndroid Build Coastguard Worker if (!new_level)
1180*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1181*2d543d20SAndroid Build Coastguard Worker level_datum_init(new_level);
1182*2d543d20SAndroid Build Coastguard Worker new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t));
1183*2d543d20SAndroid Build Coastguard Worker if (!new_level->level)
1184*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1185*2d543d20SAndroid Build Coastguard Worker mls_level_init(new_level->level);
1186*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
1187*2d543d20SAndroid Build Coastguard Worker if (!new_id)
1188*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1189*2d543d20SAndroid Build Coastguard Worker
1190*2d543d20SAndroid Build Coastguard Worker if (mls_level_cpy(new_level->level, level->level)) {
1191*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1192*2d543d20SAndroid Build Coastguard Worker }
1193*2d543d20SAndroid Build Coastguard Worker new_level->isalias = level->isalias;
1194*2d543d20SAndroid Build Coastguard Worker state->out->p_levels.nprim++;
1195*2d543d20SAndroid Build Coastguard Worker
1196*2d543d20SAndroid Build Coastguard Worker if (hashtab_insert(state->out->p_levels.table,
1197*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id,
1198*2d543d20SAndroid Build Coastguard Worker (hashtab_datum_t) new_level)) {
1199*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1200*2d543d20SAndroid Build Coastguard Worker }
1201*2d543d20SAndroid Build Coastguard Worker return 0;
1202*2d543d20SAndroid Build Coastguard Worker
1203*2d543d20SAndroid Build Coastguard Worker out_of_mem:
1204*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1205*2d543d20SAndroid Build Coastguard Worker if (new_level != NULL && new_level->level != NULL) {
1206*2d543d20SAndroid Build Coastguard Worker mls_level_destroy(new_level->level);
1207*2d543d20SAndroid Build Coastguard Worker free(new_level->level);
1208*2d543d20SAndroid Build Coastguard Worker }
1209*2d543d20SAndroid Build Coastguard Worker level_datum_destroy(new_level);
1210*2d543d20SAndroid Build Coastguard Worker free(new_level);
1211*2d543d20SAndroid Build Coastguard Worker free(new_id);
1212*2d543d20SAndroid Build Coastguard Worker return -1;
1213*2d543d20SAndroid Build Coastguard Worker }
1214*2d543d20SAndroid Build Coastguard Worker
cats_copy_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)1215*2d543d20SAndroid Build Coastguard Worker static int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
1216*2d543d20SAndroid Build Coastguard Worker void *data)
1217*2d543d20SAndroid Build Coastguard Worker {
1218*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = (expand_state_t *) data;
1219*2d543d20SAndroid Build Coastguard Worker cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL;
1220*2d543d20SAndroid Build Coastguard Worker char *id = (char *)key, *new_id = NULL;
1221*2d543d20SAndroid Build Coastguard Worker
1222*2d543d20SAndroid Build Coastguard Worker if (!is_id_enabled(id, state->base, SYM_CATS)) {
1223*2d543d20SAndroid Build Coastguard Worker /* identifier's scope is not enabled */
1224*2d543d20SAndroid Build Coastguard Worker return 0;
1225*2d543d20SAndroid Build Coastguard Worker }
1226*2d543d20SAndroid Build Coastguard Worker
1227*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
1228*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "copying category attribute %s", id);
1229*2d543d20SAndroid Build Coastguard Worker
1230*2d543d20SAndroid Build Coastguard Worker new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t));
1231*2d543d20SAndroid Build Coastguard Worker if (!new_cat)
1232*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1233*2d543d20SAndroid Build Coastguard Worker cat_datum_init(new_cat);
1234*2d543d20SAndroid Build Coastguard Worker new_id = strdup(id);
1235*2d543d20SAndroid Build Coastguard Worker if (!new_id)
1236*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1237*2d543d20SAndroid Build Coastguard Worker
1238*2d543d20SAndroid Build Coastguard Worker new_cat->s.value = cat->s.value;
1239*2d543d20SAndroid Build Coastguard Worker new_cat->isalias = cat->isalias;
1240*2d543d20SAndroid Build Coastguard Worker state->out->p_cats.nprim++;
1241*2d543d20SAndroid Build Coastguard Worker if (hashtab_insert(state->out->p_cats.table,
1242*2d543d20SAndroid Build Coastguard Worker (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) {
1243*2d543d20SAndroid Build Coastguard Worker goto out_of_mem;
1244*2d543d20SAndroid Build Coastguard Worker }
1245*2d543d20SAndroid Build Coastguard Worker
1246*2d543d20SAndroid Build Coastguard Worker return 0;
1247*2d543d20SAndroid Build Coastguard Worker
1248*2d543d20SAndroid Build Coastguard Worker out_of_mem:
1249*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1250*2d543d20SAndroid Build Coastguard Worker cat_datum_destroy(new_cat);
1251*2d543d20SAndroid Build Coastguard Worker free(new_cat);
1252*2d543d20SAndroid Build Coastguard Worker free(new_id);
1253*2d543d20SAndroid Build Coastguard Worker return -1;
1254*2d543d20SAndroid Build Coastguard Worker }
1255*2d543d20SAndroid Build Coastguard Worker
copy_role_allows(expand_state_t * state,role_allow_rule_t * rules)1256*2d543d20SAndroid Build Coastguard Worker static int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules)
1257*2d543d20SAndroid Build Coastguard Worker {
1258*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
1259*2d543d20SAndroid Build Coastguard Worker role_allow_t *cur_allow, *n, *l;
1260*2d543d20SAndroid Build Coastguard Worker role_allow_rule_t *cur;
1261*2d543d20SAndroid Build Coastguard Worker ebitmap_t roles, new_roles;
1262*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode;
1263*2d543d20SAndroid Build Coastguard Worker
1264*2d543d20SAndroid Build Coastguard Worker /* start at the end of the list */
1265*2d543d20SAndroid Build Coastguard Worker for (l = state->out->role_allow; l && l->next; l = l->next) ;
1266*2d543d20SAndroid Build Coastguard Worker
1267*2d543d20SAndroid Build Coastguard Worker cur = rules;
1268*2d543d20SAndroid Build Coastguard Worker while (cur) {
1269*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&roles);
1270*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&new_roles);
1271*2d543d20SAndroid Build Coastguard Worker
1272*2d543d20SAndroid Build Coastguard Worker if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
1273*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1274*2d543d20SAndroid Build Coastguard Worker return -1;
1275*2d543d20SAndroid Build Coastguard Worker }
1276*2d543d20SAndroid Build Coastguard Worker
1277*2d543d20SAndroid Build Coastguard Worker if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) {
1278*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1279*2d543d20SAndroid Build Coastguard Worker return -1;
1280*2d543d20SAndroid Build Coastguard Worker }
1281*2d543d20SAndroid Build Coastguard Worker
1282*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&roles, snode, i) {
1283*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&new_roles, tnode, j) {
1284*2d543d20SAndroid Build Coastguard Worker /* check for duplicates */
1285*2d543d20SAndroid Build Coastguard Worker cur_allow = state->out->role_allow;
1286*2d543d20SAndroid Build Coastguard Worker while (cur_allow) {
1287*2d543d20SAndroid Build Coastguard Worker if ((cur_allow->role == i + 1) &&
1288*2d543d20SAndroid Build Coastguard Worker (cur_allow->new_role == j + 1))
1289*2d543d20SAndroid Build Coastguard Worker break;
1290*2d543d20SAndroid Build Coastguard Worker cur_allow = cur_allow->next;
1291*2d543d20SAndroid Build Coastguard Worker }
1292*2d543d20SAndroid Build Coastguard Worker if (cur_allow)
1293*2d543d20SAndroid Build Coastguard Worker continue;
1294*2d543d20SAndroid Build Coastguard Worker n = (role_allow_t *)
1295*2d543d20SAndroid Build Coastguard Worker malloc(sizeof(role_allow_t));
1296*2d543d20SAndroid Build Coastguard Worker if (!n) {
1297*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1298*2d543d20SAndroid Build Coastguard Worker return -1;
1299*2d543d20SAndroid Build Coastguard Worker }
1300*2d543d20SAndroid Build Coastguard Worker memset(n, 0, sizeof(role_allow_t));
1301*2d543d20SAndroid Build Coastguard Worker n->role = i + 1;
1302*2d543d20SAndroid Build Coastguard Worker n->new_role = j + 1;
1303*2d543d20SAndroid Build Coastguard Worker if (l) {
1304*2d543d20SAndroid Build Coastguard Worker l->next = n;
1305*2d543d20SAndroid Build Coastguard Worker } else {
1306*2d543d20SAndroid Build Coastguard Worker state->out->role_allow = n;
1307*2d543d20SAndroid Build Coastguard Worker }
1308*2d543d20SAndroid Build Coastguard Worker l = n;
1309*2d543d20SAndroid Build Coastguard Worker }
1310*2d543d20SAndroid Build Coastguard Worker }
1311*2d543d20SAndroid Build Coastguard Worker
1312*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&roles);
1313*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&new_roles);
1314*2d543d20SAndroid Build Coastguard Worker
1315*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
1316*2d543d20SAndroid Build Coastguard Worker }
1317*2d543d20SAndroid Build Coastguard Worker
1318*2d543d20SAndroid Build Coastguard Worker return 0;
1319*2d543d20SAndroid Build Coastguard Worker }
1320*2d543d20SAndroid Build Coastguard Worker
copy_role_trans(expand_state_t * state,role_trans_rule_t * rules)1321*2d543d20SAndroid Build Coastguard Worker static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
1322*2d543d20SAndroid Build Coastguard Worker {
1323*2d543d20SAndroid Build Coastguard Worker unsigned int i, j, k;
1324*2d543d20SAndroid Build Coastguard Worker role_trans_t *n, *l, *cur_trans;
1325*2d543d20SAndroid Build Coastguard Worker role_trans_rule_t *cur;
1326*2d543d20SAndroid Build Coastguard Worker ebitmap_t roles, types;
1327*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *rnode, *tnode, *cnode;
1328*2d543d20SAndroid Build Coastguard Worker
1329*2d543d20SAndroid Build Coastguard Worker /* start at the end of the list */
1330*2d543d20SAndroid Build Coastguard Worker for (l = state->out->role_tr; l && l->next; l = l->next) ;
1331*2d543d20SAndroid Build Coastguard Worker
1332*2d543d20SAndroid Build Coastguard Worker cur = rules;
1333*2d543d20SAndroid Build Coastguard Worker while (cur) {
1334*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&roles);
1335*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&types);
1336*2d543d20SAndroid Build Coastguard Worker
1337*2d543d20SAndroid Build Coastguard Worker if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
1338*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1339*2d543d20SAndroid Build Coastguard Worker return -1;
1340*2d543d20SAndroid Build Coastguard Worker }
1341*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
1342*2d543d20SAndroid Build Coastguard Worker (state->out, state->typemap, &cur->types, &types, 1)) {
1343*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1344*2d543d20SAndroid Build Coastguard Worker return -1;
1345*2d543d20SAndroid Build Coastguard Worker }
1346*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&roles, rnode, i) {
1347*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&types, tnode, j) {
1348*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&cur->classes, cnode, k) {
1349*2d543d20SAndroid Build Coastguard Worker cur_trans = state->out->role_tr;
1350*2d543d20SAndroid Build Coastguard Worker while (cur_trans) {
1351*2d543d20SAndroid Build Coastguard Worker unsigned int mapped_role;
1352*2d543d20SAndroid Build Coastguard Worker
1353*2d543d20SAndroid Build Coastguard Worker mapped_role = state->rolemap[cur->new_role - 1];
1354*2d543d20SAndroid Build Coastguard Worker
1355*2d543d20SAndroid Build Coastguard Worker if ((cur_trans->role ==
1356*2d543d20SAndroid Build Coastguard Worker i + 1) &&
1357*2d543d20SAndroid Build Coastguard Worker (cur_trans->type ==
1358*2d543d20SAndroid Build Coastguard Worker j + 1) &&
1359*2d543d20SAndroid Build Coastguard Worker (cur_trans->tclass ==
1360*2d543d20SAndroid Build Coastguard Worker k + 1)) {
1361*2d543d20SAndroid Build Coastguard Worker if (cur_trans->new_role == mapped_role) {
1362*2d543d20SAndroid Build Coastguard Worker break;
1363*2d543d20SAndroid Build Coastguard Worker } else {
1364*2d543d20SAndroid Build Coastguard Worker ERR(state->handle,
1365*2d543d20SAndroid Build Coastguard Worker "Conflicting role trans rule %s %s : %s { %s vs %s }",
1366*2d543d20SAndroid Build Coastguard Worker state->out->p_role_val_to_name[i],
1367*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[j],
1368*2d543d20SAndroid Build Coastguard Worker state->out->p_class_val_to_name[k],
1369*2d543d20SAndroid Build Coastguard Worker state->out->p_role_val_to_name[mapped_role - 1],
1370*2d543d20SAndroid Build Coastguard Worker state->out->p_role_val_to_name[cur_trans->new_role - 1]);
1371*2d543d20SAndroid Build Coastguard Worker return -1;
1372*2d543d20SAndroid Build Coastguard Worker }
1373*2d543d20SAndroid Build Coastguard Worker }
1374*2d543d20SAndroid Build Coastguard Worker cur_trans = cur_trans->next;
1375*2d543d20SAndroid Build Coastguard Worker }
1376*2d543d20SAndroid Build Coastguard Worker if (cur_trans)
1377*2d543d20SAndroid Build Coastguard Worker continue;
1378*2d543d20SAndroid Build Coastguard Worker
1379*2d543d20SAndroid Build Coastguard Worker n = (role_trans_t *)
1380*2d543d20SAndroid Build Coastguard Worker malloc(sizeof(role_trans_t));
1381*2d543d20SAndroid Build Coastguard Worker if (!n) {
1382*2d543d20SAndroid Build Coastguard Worker ERR(state->handle,
1383*2d543d20SAndroid Build Coastguard Worker "Out of memory!");
1384*2d543d20SAndroid Build Coastguard Worker return -1;
1385*2d543d20SAndroid Build Coastguard Worker }
1386*2d543d20SAndroid Build Coastguard Worker memset(n, 0, sizeof(role_trans_t));
1387*2d543d20SAndroid Build Coastguard Worker n->role = i + 1;
1388*2d543d20SAndroid Build Coastguard Worker n->type = j + 1;
1389*2d543d20SAndroid Build Coastguard Worker n->tclass = k + 1;
1390*2d543d20SAndroid Build Coastguard Worker n->new_role = state->rolemap
1391*2d543d20SAndroid Build Coastguard Worker [cur->new_role - 1];
1392*2d543d20SAndroid Build Coastguard Worker if (l)
1393*2d543d20SAndroid Build Coastguard Worker l->next = n;
1394*2d543d20SAndroid Build Coastguard Worker else
1395*2d543d20SAndroid Build Coastguard Worker state->out->role_tr = n;
1396*2d543d20SAndroid Build Coastguard Worker
1397*2d543d20SAndroid Build Coastguard Worker l = n;
1398*2d543d20SAndroid Build Coastguard Worker }
1399*2d543d20SAndroid Build Coastguard Worker }
1400*2d543d20SAndroid Build Coastguard Worker }
1401*2d543d20SAndroid Build Coastguard Worker
1402*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&roles);
1403*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&types);
1404*2d543d20SAndroid Build Coastguard Worker
1405*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
1406*2d543d20SAndroid Build Coastguard Worker }
1407*2d543d20SAndroid Build Coastguard Worker return 0;
1408*2d543d20SAndroid Build Coastguard Worker }
1409*2d543d20SAndroid Build Coastguard Worker
expand_filename_trans_helper(expand_state_t * state,filename_trans_rule_t * rule,unsigned int s,unsigned int t)1410*2d543d20SAndroid Build Coastguard Worker static int expand_filename_trans_helper(expand_state_t *state,
1411*2d543d20SAndroid Build Coastguard Worker filename_trans_rule_t *rule,
1412*2d543d20SAndroid Build Coastguard Worker unsigned int s, unsigned int t)
1413*2d543d20SAndroid Build Coastguard Worker {
1414*2d543d20SAndroid Build Coastguard Worker uint32_t mapped_otype, present_otype;
1415*2d543d20SAndroid Build Coastguard Worker int rc;
1416*2d543d20SAndroid Build Coastguard Worker
1417*2d543d20SAndroid Build Coastguard Worker mapped_otype = state->typemap[rule->otype - 1];
1418*2d543d20SAndroid Build Coastguard Worker
1419*2d543d20SAndroid Build Coastguard Worker rc = policydb_filetrans_insert(
1420*2d543d20SAndroid Build Coastguard Worker state->out, s + 1, t + 1,
1421*2d543d20SAndroid Build Coastguard Worker rule->tclass, rule->name,
1422*2d543d20SAndroid Build Coastguard Worker NULL, mapped_otype, &present_otype
1423*2d543d20SAndroid Build Coastguard Worker );
1424*2d543d20SAndroid Build Coastguard Worker if (rc == SEPOL_EEXIST) {
1425*2d543d20SAndroid Build Coastguard Worker /* duplicate rule, ignore */
1426*2d543d20SAndroid Build Coastguard Worker if (present_otype == mapped_otype)
1427*2d543d20SAndroid Build Coastguard Worker return 0;
1428*2d543d20SAndroid Build Coastguard Worker
1429*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s",
1430*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[s],
1431*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[t],
1432*2d543d20SAndroid Build Coastguard Worker state->out->p_class_val_to_name[rule->tclass - 1],
1433*2d543d20SAndroid Build Coastguard Worker rule->name,
1434*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[present_otype - 1],
1435*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[mapped_otype - 1]);
1436*2d543d20SAndroid Build Coastguard Worker return -1;
1437*2d543d20SAndroid Build Coastguard Worker } else if (rc < 0) {
1438*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1439*2d543d20SAndroid Build Coastguard Worker return -1;
1440*2d543d20SAndroid Build Coastguard Worker }
1441*2d543d20SAndroid Build Coastguard Worker return 0;
1442*2d543d20SAndroid Build Coastguard Worker }
1443*2d543d20SAndroid Build Coastguard Worker
expand_filename_trans(expand_state_t * state,filename_trans_rule_t * rules)1444*2d543d20SAndroid Build Coastguard Worker static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
1445*2d543d20SAndroid Build Coastguard Worker {
1446*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
1447*2d543d20SAndroid Build Coastguard Worker filename_trans_rule_t *cur_rule;
1448*2d543d20SAndroid Build Coastguard Worker ebitmap_t stypes, ttypes;
1449*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode;
1450*2d543d20SAndroid Build Coastguard Worker int rc;
1451*2d543d20SAndroid Build Coastguard Worker
1452*2d543d20SAndroid Build Coastguard Worker cur_rule = rules;
1453*2d543d20SAndroid Build Coastguard Worker while (cur_rule) {
1454*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&stypes);
1455*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&ttypes);
1456*2d543d20SAndroid Build Coastguard Worker
1457*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set(state->out, state->typemap,
1458*2d543d20SAndroid Build Coastguard Worker &cur_rule->stypes, &stypes, 1)) {
1459*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1460*2d543d20SAndroid Build Coastguard Worker return -1;
1461*2d543d20SAndroid Build Coastguard Worker }
1462*2d543d20SAndroid Build Coastguard Worker
1463*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set(state->out, state->typemap,
1464*2d543d20SAndroid Build Coastguard Worker &cur_rule->ttypes, &ttypes, 1)) {
1465*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1466*2d543d20SAndroid Build Coastguard Worker return -1;
1467*2d543d20SAndroid Build Coastguard Worker }
1468*2d543d20SAndroid Build Coastguard Worker
1469*2d543d20SAndroid Build Coastguard Worker
1470*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&stypes, snode, i) {
1471*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&ttypes, tnode, j) {
1472*2d543d20SAndroid Build Coastguard Worker rc = expand_filename_trans_helper(
1473*2d543d20SAndroid Build Coastguard Worker state, cur_rule, i, j
1474*2d543d20SAndroid Build Coastguard Worker );
1475*2d543d20SAndroid Build Coastguard Worker if (rc)
1476*2d543d20SAndroid Build Coastguard Worker return rc;
1477*2d543d20SAndroid Build Coastguard Worker }
1478*2d543d20SAndroid Build Coastguard Worker if (cur_rule->flags & RULE_SELF) {
1479*2d543d20SAndroid Build Coastguard Worker rc = expand_filename_trans_helper(
1480*2d543d20SAndroid Build Coastguard Worker state, cur_rule, i, i
1481*2d543d20SAndroid Build Coastguard Worker );
1482*2d543d20SAndroid Build Coastguard Worker if (rc)
1483*2d543d20SAndroid Build Coastguard Worker return rc;
1484*2d543d20SAndroid Build Coastguard Worker }
1485*2d543d20SAndroid Build Coastguard Worker }
1486*2d543d20SAndroid Build Coastguard Worker
1487*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
1488*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
1489*2d543d20SAndroid Build Coastguard Worker
1490*2d543d20SAndroid Build Coastguard Worker cur_rule = cur_rule->next;
1491*2d543d20SAndroid Build Coastguard Worker }
1492*2d543d20SAndroid Build Coastguard Worker return 0;
1493*2d543d20SAndroid Build Coastguard Worker }
1494*2d543d20SAndroid Build Coastguard Worker
exp_rangetr_helper(uint32_t stype,uint32_t ttype,uint32_t tclass,mls_semantic_range_t * trange,expand_state_t * state)1495*2d543d20SAndroid Build Coastguard Worker static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
1496*2d543d20SAndroid Build Coastguard Worker mls_semantic_range_t * trange,
1497*2d543d20SAndroid Build Coastguard Worker expand_state_t * state)
1498*2d543d20SAndroid Build Coastguard Worker {
1499*2d543d20SAndroid Build Coastguard Worker range_trans_t *rt = NULL, key;
1500*2d543d20SAndroid Build Coastguard Worker mls_range_t *r, *exp_range = NULL;
1501*2d543d20SAndroid Build Coastguard Worker int rc = -1;
1502*2d543d20SAndroid Build Coastguard Worker
1503*2d543d20SAndroid Build Coastguard Worker exp_range = calloc(1, sizeof(*exp_range));
1504*2d543d20SAndroid Build Coastguard Worker if (!exp_range) {
1505*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1506*2d543d20SAndroid Build Coastguard Worker return -1;
1507*2d543d20SAndroid Build Coastguard Worker }
1508*2d543d20SAndroid Build Coastguard Worker
1509*2d543d20SAndroid Build Coastguard Worker if (mls_semantic_range_expand(trange, exp_range, state->out,
1510*2d543d20SAndroid Build Coastguard Worker state->handle))
1511*2d543d20SAndroid Build Coastguard Worker goto err;
1512*2d543d20SAndroid Build Coastguard Worker
1513*2d543d20SAndroid Build Coastguard Worker /* check for duplicates/conflicts */
1514*2d543d20SAndroid Build Coastguard Worker key.source_type = stype;
1515*2d543d20SAndroid Build Coastguard Worker key.target_type = ttype;
1516*2d543d20SAndroid Build Coastguard Worker key.target_class = tclass;
1517*2d543d20SAndroid Build Coastguard Worker r = hashtab_search(state->out->range_tr, (hashtab_key_t) &key);
1518*2d543d20SAndroid Build Coastguard Worker if (r) {
1519*2d543d20SAndroid Build Coastguard Worker if (mls_range_eq(r, exp_range)) {
1520*2d543d20SAndroid Build Coastguard Worker /* duplicate, ignore */
1521*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(exp_range);
1522*2d543d20SAndroid Build Coastguard Worker free(exp_range);
1523*2d543d20SAndroid Build Coastguard Worker return 0;
1524*2d543d20SAndroid Build Coastguard Worker }
1525*2d543d20SAndroid Build Coastguard Worker
1526*2d543d20SAndroid Build Coastguard Worker /* conflict */
1527*2d543d20SAndroid Build Coastguard Worker ERR(state->handle,
1528*2d543d20SAndroid Build Coastguard Worker "Conflicting range trans rule %s %s : %s",
1529*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[stype - 1],
1530*2d543d20SAndroid Build Coastguard Worker state->out->p_type_val_to_name[ttype - 1],
1531*2d543d20SAndroid Build Coastguard Worker state->out->p_class_val_to_name[tclass - 1]);
1532*2d543d20SAndroid Build Coastguard Worker goto err;
1533*2d543d20SAndroid Build Coastguard Worker }
1534*2d543d20SAndroid Build Coastguard Worker
1535*2d543d20SAndroid Build Coastguard Worker rt = calloc(1, sizeof(*rt));
1536*2d543d20SAndroid Build Coastguard Worker if (!rt) {
1537*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1538*2d543d20SAndroid Build Coastguard Worker goto err;
1539*2d543d20SAndroid Build Coastguard Worker }
1540*2d543d20SAndroid Build Coastguard Worker rt->source_type = stype;
1541*2d543d20SAndroid Build Coastguard Worker rt->target_type = ttype;
1542*2d543d20SAndroid Build Coastguard Worker rt->target_class = tclass;
1543*2d543d20SAndroid Build Coastguard Worker
1544*2d543d20SAndroid Build Coastguard Worker rc = hashtab_insert(state->out->range_tr, (hashtab_key_t) rt,
1545*2d543d20SAndroid Build Coastguard Worker exp_range);
1546*2d543d20SAndroid Build Coastguard Worker if (rc) {
1547*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1548*2d543d20SAndroid Build Coastguard Worker goto err;
1549*2d543d20SAndroid Build Coastguard Worker
1550*2d543d20SAndroid Build Coastguard Worker }
1551*2d543d20SAndroid Build Coastguard Worker
1552*2d543d20SAndroid Build Coastguard Worker return 0;
1553*2d543d20SAndroid Build Coastguard Worker err:
1554*2d543d20SAndroid Build Coastguard Worker free(rt);
1555*2d543d20SAndroid Build Coastguard Worker if (exp_range) {
1556*2d543d20SAndroid Build Coastguard Worker mls_range_destroy(exp_range);
1557*2d543d20SAndroid Build Coastguard Worker free(exp_range);
1558*2d543d20SAndroid Build Coastguard Worker }
1559*2d543d20SAndroid Build Coastguard Worker return -1;
1560*2d543d20SAndroid Build Coastguard Worker }
1561*2d543d20SAndroid Build Coastguard Worker
expand_range_trans(expand_state_t * state,range_trans_rule_t * rules)1562*2d543d20SAndroid Build Coastguard Worker static int expand_range_trans(expand_state_t * state,
1563*2d543d20SAndroid Build Coastguard Worker range_trans_rule_t * rules)
1564*2d543d20SAndroid Build Coastguard Worker {
1565*2d543d20SAndroid Build Coastguard Worker unsigned int i, j, k;
1566*2d543d20SAndroid Build Coastguard Worker range_trans_rule_t *rule;
1567*2d543d20SAndroid Build Coastguard Worker
1568*2d543d20SAndroid Build Coastguard Worker ebitmap_t stypes, ttypes;
1569*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode, *cnode;
1570*2d543d20SAndroid Build Coastguard Worker
1571*2d543d20SAndroid Build Coastguard Worker if (state->verbose)
1572*2d543d20SAndroid Build Coastguard Worker INFO(state->handle, "expanding range transitions");
1573*2d543d20SAndroid Build Coastguard Worker
1574*2d543d20SAndroid Build Coastguard Worker for (rule = rules; rule; rule = rule->next) {
1575*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&stypes);
1576*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&ttypes);
1577*2d543d20SAndroid Build Coastguard Worker
1578*2d543d20SAndroid Build Coastguard Worker /* expand the type sets */
1579*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set(state->out, state->typemap,
1580*2d543d20SAndroid Build Coastguard Worker &rule->stypes, &stypes, 1)) {
1581*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1582*2d543d20SAndroid Build Coastguard Worker return -1;
1583*2d543d20SAndroid Build Coastguard Worker }
1584*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set(state->out, state->typemap,
1585*2d543d20SAndroid Build Coastguard Worker &rule->ttypes, &ttypes, 1)) {
1586*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
1587*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
1588*2d543d20SAndroid Build Coastguard Worker return -1;
1589*2d543d20SAndroid Build Coastguard Worker }
1590*2d543d20SAndroid Build Coastguard Worker
1591*2d543d20SAndroid Build Coastguard Worker /* loop on source type */
1592*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&stypes, snode, i) {
1593*2d543d20SAndroid Build Coastguard Worker /* loop on target type */
1594*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&ttypes, tnode, j) {
1595*2d543d20SAndroid Build Coastguard Worker /* loop on target class */
1596*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&rule->tclasses, cnode, k) {
1597*2d543d20SAndroid Build Coastguard Worker if (exp_rangetr_helper(i + 1,
1598*2d543d20SAndroid Build Coastguard Worker j + 1,
1599*2d543d20SAndroid Build Coastguard Worker k + 1,
1600*2d543d20SAndroid Build Coastguard Worker &rule->trange,
1601*2d543d20SAndroid Build Coastguard Worker state)) {
1602*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
1603*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
1604*2d543d20SAndroid Build Coastguard Worker return -1;
1605*2d543d20SAndroid Build Coastguard Worker }
1606*2d543d20SAndroid Build Coastguard Worker }
1607*2d543d20SAndroid Build Coastguard Worker }
1608*2d543d20SAndroid Build Coastguard Worker }
1609*2d543d20SAndroid Build Coastguard Worker
1610*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
1611*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
1612*2d543d20SAndroid Build Coastguard Worker }
1613*2d543d20SAndroid Build Coastguard Worker
1614*2d543d20SAndroid Build Coastguard Worker return 0;
1615*2d543d20SAndroid Build Coastguard Worker }
1616*2d543d20SAndroid Build Coastguard Worker
1617*2d543d20SAndroid Build Coastguard Worker /* Search for an AV tab node within a hash table with the given key.
1618*2d543d20SAndroid Build Coastguard Worker * If the node does not exist, create it and return it; otherwise
1619*2d543d20SAndroid Build Coastguard Worker * return the pre-existing one.
1620*2d543d20SAndroid Build Coastguard Worker */
find_avtab_node(sepol_handle_t * handle,avtab_t * avtab,avtab_key_t * key,cond_av_list_t ** cond,av_extended_perms_t * xperms)1621*2d543d20SAndroid Build Coastguard Worker static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
1622*2d543d20SAndroid Build Coastguard Worker avtab_t * avtab, avtab_key_t * key,
1623*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** cond,
1624*2d543d20SAndroid Build Coastguard Worker av_extended_perms_t *xperms)
1625*2d543d20SAndroid Build Coastguard Worker {
1626*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
1627*2d543d20SAndroid Build Coastguard Worker avtab_datum_t avdatum;
1628*2d543d20SAndroid Build Coastguard Worker cond_av_list_t *nl;
1629*2d543d20SAndroid Build Coastguard Worker int match = 0;
1630*2d543d20SAndroid Build Coastguard Worker
1631*2d543d20SAndroid Build Coastguard Worker /* AVTAB_XPERMS entries are not necessarily unique */
1632*2d543d20SAndroid Build Coastguard Worker if (key->specified & AVTAB_XPERMS) {
1633*2d543d20SAndroid Build Coastguard Worker if (xperms == NULL) {
1634*2d543d20SAndroid Build Coastguard Worker ERR(handle, "searching xperms NULL");
1635*2d543d20SAndroid Build Coastguard Worker node = NULL;
1636*2d543d20SAndroid Build Coastguard Worker } else {
1637*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(avtab, key);
1638*2d543d20SAndroid Build Coastguard Worker while (node) {
1639*2d543d20SAndroid Build Coastguard Worker if ((node->datum.xperms->specified == xperms->specified) &&
1640*2d543d20SAndroid Build Coastguard Worker (node->datum.xperms->driver == xperms->driver)) {
1641*2d543d20SAndroid Build Coastguard Worker match = 1;
1642*2d543d20SAndroid Build Coastguard Worker break;
1643*2d543d20SAndroid Build Coastguard Worker }
1644*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node_next(node, key->specified);
1645*2d543d20SAndroid Build Coastguard Worker }
1646*2d543d20SAndroid Build Coastguard Worker if (!match)
1647*2d543d20SAndroid Build Coastguard Worker node = NULL;
1648*2d543d20SAndroid Build Coastguard Worker }
1649*2d543d20SAndroid Build Coastguard Worker } else {
1650*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(avtab, key);
1651*2d543d20SAndroid Build Coastguard Worker }
1652*2d543d20SAndroid Build Coastguard Worker
1653*2d543d20SAndroid Build Coastguard Worker /* If this is for conditional policies, keep searching in case
1654*2d543d20SAndroid Build Coastguard Worker the node is part of my conditional avtab. */
1655*2d543d20SAndroid Build Coastguard Worker if (cond) {
1656*2d543d20SAndroid Build Coastguard Worker while (node) {
1657*2d543d20SAndroid Build Coastguard Worker if (node->parse_context == cond)
1658*2d543d20SAndroid Build Coastguard Worker break;
1659*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node_next(node, key->specified);
1660*2d543d20SAndroid Build Coastguard Worker }
1661*2d543d20SAndroid Build Coastguard Worker }
1662*2d543d20SAndroid Build Coastguard Worker
1663*2d543d20SAndroid Build Coastguard Worker if (!node) {
1664*2d543d20SAndroid Build Coastguard Worker memset(&avdatum, 0, sizeof avdatum);
1665*2d543d20SAndroid Build Coastguard Worker /*
1666*2d543d20SAndroid Build Coastguard Worker * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
1667*2d543d20SAndroid Build Coastguard Worker * others. Initialize the data accordingly.
1668*2d543d20SAndroid Build Coastguard Worker */
1669*2d543d20SAndroid Build Coastguard Worker avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0);
1670*2d543d20SAndroid Build Coastguard Worker /* this is used to get the node - insertion is actually unique */
1671*2d543d20SAndroid Build Coastguard Worker node = avtab_insert_nonunique(avtab, key, &avdatum);
1672*2d543d20SAndroid Build Coastguard Worker if (!node) {
1673*2d543d20SAndroid Build Coastguard Worker ERR(handle, "hash table overflow");
1674*2d543d20SAndroid Build Coastguard Worker return NULL;
1675*2d543d20SAndroid Build Coastguard Worker }
1676*2d543d20SAndroid Build Coastguard Worker if (cond) {
1677*2d543d20SAndroid Build Coastguard Worker node->parse_context = cond;
1678*2d543d20SAndroid Build Coastguard Worker nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t));
1679*2d543d20SAndroid Build Coastguard Worker if (!nl) {
1680*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Memory error");
1681*2d543d20SAndroid Build Coastguard Worker return NULL;
1682*2d543d20SAndroid Build Coastguard Worker }
1683*2d543d20SAndroid Build Coastguard Worker memset(nl, 0, sizeof(cond_av_list_t));
1684*2d543d20SAndroid Build Coastguard Worker nl->node = node;
1685*2d543d20SAndroid Build Coastguard Worker nl->next = *cond;
1686*2d543d20SAndroid Build Coastguard Worker *cond = nl;
1687*2d543d20SAndroid Build Coastguard Worker }
1688*2d543d20SAndroid Build Coastguard Worker }
1689*2d543d20SAndroid Build Coastguard Worker
1690*2d543d20SAndroid Build Coastguard Worker return node;
1691*2d543d20SAndroid Build Coastguard Worker }
1692*2d543d20SAndroid Build Coastguard Worker
avrule_to_avtab_spec(uint32_t specification)1693*2d543d20SAndroid Build Coastguard Worker static uint32_t avrule_to_avtab_spec(uint32_t specification)
1694*2d543d20SAndroid Build Coastguard Worker {
1695*2d543d20SAndroid Build Coastguard Worker return (specification == AVRULE_DONTAUDIT) ?
1696*2d543d20SAndroid Build Coastguard Worker AVTAB_AUDITDENY : specification;
1697*2d543d20SAndroid Build Coastguard Worker }
1698*2d543d20SAndroid Build Coastguard Worker
1699*2d543d20SAndroid Build Coastguard Worker #define EXPAND_RULE_SUCCESS 1
1700*2d543d20SAndroid Build Coastguard Worker #define EXPAND_RULE_CONFLICT 0
1701*2d543d20SAndroid Build Coastguard Worker #define EXPAND_RULE_ERROR -1
1702*2d543d20SAndroid Build Coastguard Worker
expand_terule_helper(sepol_handle_t * handle,policydb_t * p,uint32_t * typemap,uint32_t specified,cond_av_list_t ** cond,cond_av_list_t ** other,uint32_t stype,uint32_t ttype,class_perm_node_t * perms,avtab_t * avtab,int enabled)1703*2d543d20SAndroid Build Coastguard Worker static int expand_terule_helper(sepol_handle_t * handle,
1704*2d543d20SAndroid Build Coastguard Worker policydb_t * p, uint32_t * typemap,
1705*2d543d20SAndroid Build Coastguard Worker uint32_t specified, cond_av_list_t ** cond,
1706*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** other, uint32_t stype,
1707*2d543d20SAndroid Build Coastguard Worker uint32_t ttype, class_perm_node_t * perms,
1708*2d543d20SAndroid Build Coastguard Worker avtab_t * avtab, int enabled)
1709*2d543d20SAndroid Build Coastguard Worker {
1710*2d543d20SAndroid Build Coastguard Worker avtab_key_t avkey;
1711*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *avdatump;
1712*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
1713*2d543d20SAndroid Build Coastguard Worker class_perm_node_t *cur;
1714*2d543d20SAndroid Build Coastguard Worker int conflict;
1715*2d543d20SAndroid Build Coastguard Worker uint32_t oldtype = 0;
1716*2d543d20SAndroid Build Coastguard Worker
1717*2d543d20SAndroid Build Coastguard Worker if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) {
1718*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Invalid specification: %"PRIu32, specified);
1719*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1720*2d543d20SAndroid Build Coastguard Worker }
1721*2d543d20SAndroid Build Coastguard Worker
1722*2d543d20SAndroid Build Coastguard Worker avkey.specified = avrule_to_avtab_spec(specified);
1723*2d543d20SAndroid Build Coastguard Worker avkey.source_type = stype + 1;
1724*2d543d20SAndroid Build Coastguard Worker avkey.target_type = ttype + 1;
1725*2d543d20SAndroid Build Coastguard Worker
1726*2d543d20SAndroid Build Coastguard Worker cur = perms;
1727*2d543d20SAndroid Build Coastguard Worker while (cur) {
1728*2d543d20SAndroid Build Coastguard Worker uint32_t remapped_data =
1729*2d543d20SAndroid Build Coastguard Worker typemap ? typemap[cur->data - 1] : cur->data;
1730*2d543d20SAndroid Build Coastguard Worker avkey.target_class = cur->tclass;
1731*2d543d20SAndroid Build Coastguard Worker
1732*2d543d20SAndroid Build Coastguard Worker conflict = 0;
1733*2d543d20SAndroid Build Coastguard Worker /* check to see if the expanded TE already exists --
1734*2d543d20SAndroid Build Coastguard Worker * either in the global scope or in another
1735*2d543d20SAndroid Build Coastguard Worker * conditional AV tab */
1736*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(&p->te_avtab, &avkey);
1737*2d543d20SAndroid Build Coastguard Worker if (node) {
1738*2d543d20SAndroid Build Coastguard Worker conflict = 1;
1739*2d543d20SAndroid Build Coastguard Worker } else {
1740*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(&p->te_cond_avtab, &avkey);
1741*2d543d20SAndroid Build Coastguard Worker if (node && node->parse_context != other) {
1742*2d543d20SAndroid Build Coastguard Worker conflict = 2;
1743*2d543d20SAndroid Build Coastguard Worker }
1744*2d543d20SAndroid Build Coastguard Worker }
1745*2d543d20SAndroid Build Coastguard Worker
1746*2d543d20SAndroid Build Coastguard Worker if (conflict) {
1747*2d543d20SAndroid Build Coastguard Worker avdatump = &node->datum;
1748*2d543d20SAndroid Build Coastguard Worker if (specified & AVRULE_TRANSITION) {
1749*2d543d20SAndroid Build Coastguard Worker oldtype = avdatump->data;
1750*2d543d20SAndroid Build Coastguard Worker } else if (specified & AVRULE_MEMBER) {
1751*2d543d20SAndroid Build Coastguard Worker oldtype = avdatump->data;
1752*2d543d20SAndroid Build Coastguard Worker } else if (specified & AVRULE_CHANGE) {
1753*2d543d20SAndroid Build Coastguard Worker oldtype = avdatump->data;
1754*2d543d20SAndroid Build Coastguard Worker }
1755*2d543d20SAndroid Build Coastguard Worker
1756*2d543d20SAndroid Build Coastguard Worker if (oldtype == remapped_data) {
1757*2d543d20SAndroid Build Coastguard Worker /* if the duplicate is inside the same scope (eg., unconditional
1758*2d543d20SAndroid Build Coastguard Worker * or in same conditional then ignore it */
1759*2d543d20SAndroid Build Coastguard Worker if ((conflict == 1 && cond == NULL)
1760*2d543d20SAndroid Build Coastguard Worker || node->parse_context == cond)
1761*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1762*2d543d20SAndroid Build Coastguard Worker ERR(handle, "duplicate TE rule for %s %s:%s %s",
1763*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[avkey.source_type -
1764*2d543d20SAndroid Build Coastguard Worker 1],
1765*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[avkey.target_type -
1766*2d543d20SAndroid Build Coastguard Worker 1],
1767*2d543d20SAndroid Build Coastguard Worker p->p_class_val_to_name[avkey.target_class -
1768*2d543d20SAndroid Build Coastguard Worker 1],
1769*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[oldtype - 1]);
1770*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_CONFLICT;
1771*2d543d20SAndroid Build Coastguard Worker }
1772*2d543d20SAndroid Build Coastguard Worker ERR(handle,
1773*2d543d20SAndroid Build Coastguard Worker "conflicting TE rule for (%s, %s:%s): old was %s, new is %s",
1774*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[avkey.source_type - 1],
1775*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[avkey.target_type - 1],
1776*2d543d20SAndroid Build Coastguard Worker p->p_class_val_to_name[avkey.target_class - 1],
1777*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[oldtype - 1],
1778*2d543d20SAndroid Build Coastguard Worker p->p_type_val_to_name[remapped_data - 1]);
1779*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_CONFLICT;
1780*2d543d20SAndroid Build Coastguard Worker }
1781*2d543d20SAndroid Build Coastguard Worker
1782*2d543d20SAndroid Build Coastguard Worker node = find_avtab_node(handle, avtab, &avkey, cond, NULL);
1783*2d543d20SAndroid Build Coastguard Worker if (!node)
1784*2d543d20SAndroid Build Coastguard Worker return -1;
1785*2d543d20SAndroid Build Coastguard Worker if (enabled) {
1786*2d543d20SAndroid Build Coastguard Worker node->key.specified |= AVTAB_ENABLED;
1787*2d543d20SAndroid Build Coastguard Worker } else {
1788*2d543d20SAndroid Build Coastguard Worker node->key.specified &= ~AVTAB_ENABLED;
1789*2d543d20SAndroid Build Coastguard Worker }
1790*2d543d20SAndroid Build Coastguard Worker
1791*2d543d20SAndroid Build Coastguard Worker avdatump = &node->datum;
1792*2d543d20SAndroid Build Coastguard Worker avdatump->data = remapped_data;
1793*2d543d20SAndroid Build Coastguard Worker
1794*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
1795*2d543d20SAndroid Build Coastguard Worker }
1796*2d543d20SAndroid Build Coastguard Worker
1797*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1798*2d543d20SAndroid Build Coastguard Worker }
1799*2d543d20SAndroid Build Coastguard Worker
1800*2d543d20SAndroid Build Coastguard Worker /* 0 for success -1 indicates failure */
allocate_xperms(sepol_handle_t * handle,avtab_datum_t * avdatump,av_extended_perms_t * extended_perms)1801*2d543d20SAndroid Build Coastguard Worker static int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump,
1802*2d543d20SAndroid Build Coastguard Worker av_extended_perms_t * extended_perms)
1803*2d543d20SAndroid Build Coastguard Worker {
1804*2d543d20SAndroid Build Coastguard Worker unsigned int i;
1805*2d543d20SAndroid Build Coastguard Worker
1806*2d543d20SAndroid Build Coastguard Worker avtab_extended_perms_t *xperms = avdatump->xperms;
1807*2d543d20SAndroid Build Coastguard Worker if (!xperms) {
1808*2d543d20SAndroid Build Coastguard Worker xperms = (avtab_extended_perms_t *)
1809*2d543d20SAndroid Build Coastguard Worker calloc(1, sizeof(avtab_extended_perms_t));
1810*2d543d20SAndroid Build Coastguard Worker if (!xperms) {
1811*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
1812*2d543d20SAndroid Build Coastguard Worker return -1;
1813*2d543d20SAndroid Build Coastguard Worker }
1814*2d543d20SAndroid Build Coastguard Worker avdatump->xperms = xperms;
1815*2d543d20SAndroid Build Coastguard Worker }
1816*2d543d20SAndroid Build Coastguard Worker
1817*2d543d20SAndroid Build Coastguard Worker switch (extended_perms->specified) {
1818*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_IOCTLFUNCTION:
1819*2d543d20SAndroid Build Coastguard Worker xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION;
1820*2d543d20SAndroid Build Coastguard Worker break;
1821*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_IOCTLDRIVER:
1822*2d543d20SAndroid Build Coastguard Worker xperms->specified = AVTAB_XPERMS_IOCTLDRIVER;
1823*2d543d20SAndroid Build Coastguard Worker break;
1824*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_NLMSG:
1825*2d543d20SAndroid Build Coastguard Worker xperms->specified = AVTAB_XPERMS_NLMSG;
1826*2d543d20SAndroid Build Coastguard Worker break;
1827*2d543d20SAndroid Build Coastguard Worker default:
1828*2d543d20SAndroid Build Coastguard Worker return -1;
1829*2d543d20SAndroid Build Coastguard Worker }
1830*2d543d20SAndroid Build Coastguard Worker
1831*2d543d20SAndroid Build Coastguard Worker xperms->driver = extended_perms->driver;
1832*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
1833*2d543d20SAndroid Build Coastguard Worker xperms->perms[i] |= extended_perms->perms[i];
1834*2d543d20SAndroid Build Coastguard Worker
1835*2d543d20SAndroid Build Coastguard Worker return 0;
1836*2d543d20SAndroid Build Coastguard Worker }
1837*2d543d20SAndroid Build Coastguard Worker
expand_avrule_helper(sepol_handle_t * handle,uint32_t specified,cond_av_list_t ** cond,uint32_t stype,uint32_t ttype,class_perm_node_t * perms,avtab_t * avtab,int enabled,av_extended_perms_t * extended_perms)1838*2d543d20SAndroid Build Coastguard Worker static int expand_avrule_helper(sepol_handle_t * handle,
1839*2d543d20SAndroid Build Coastguard Worker uint32_t specified,
1840*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** cond,
1841*2d543d20SAndroid Build Coastguard Worker uint32_t stype, uint32_t ttype,
1842*2d543d20SAndroid Build Coastguard Worker class_perm_node_t * perms, avtab_t * avtab,
1843*2d543d20SAndroid Build Coastguard Worker int enabled, av_extended_perms_t *extended_perms)
1844*2d543d20SAndroid Build Coastguard Worker {
1845*2d543d20SAndroid Build Coastguard Worker avtab_key_t avkey;
1846*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *avdatump;
1847*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
1848*2d543d20SAndroid Build Coastguard Worker class_perm_node_t *cur;
1849*2d543d20SAndroid Build Coastguard Worker
1850*2d543d20SAndroid Build Coastguard Worker /* bail early if dontaudit's are disabled and it's a dontaudit rule */
1851*2d543d20SAndroid Build Coastguard Worker if ((specified & (AVRULE_DONTAUDIT|AVRULE_XPERMS_DONTAUDIT))
1852*2d543d20SAndroid Build Coastguard Worker && handle && handle->disable_dontaudit)
1853*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1854*2d543d20SAndroid Build Coastguard Worker
1855*2d543d20SAndroid Build Coastguard Worker avkey.source_type = stype + 1;
1856*2d543d20SAndroid Build Coastguard Worker avkey.target_type = ttype + 1;
1857*2d543d20SAndroid Build Coastguard Worker avkey.specified = avrule_to_avtab_spec(specified);
1858*2d543d20SAndroid Build Coastguard Worker
1859*2d543d20SAndroid Build Coastguard Worker cur = perms;
1860*2d543d20SAndroid Build Coastguard Worker while (cur) {
1861*2d543d20SAndroid Build Coastguard Worker avkey.target_class = cur->tclass;
1862*2d543d20SAndroid Build Coastguard Worker
1863*2d543d20SAndroid Build Coastguard Worker node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms);
1864*2d543d20SAndroid Build Coastguard Worker if (!node)
1865*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1866*2d543d20SAndroid Build Coastguard Worker if (enabled) {
1867*2d543d20SAndroid Build Coastguard Worker node->key.specified |= AVTAB_ENABLED;
1868*2d543d20SAndroid Build Coastguard Worker } else {
1869*2d543d20SAndroid Build Coastguard Worker node->key.specified &= ~AVTAB_ENABLED;
1870*2d543d20SAndroid Build Coastguard Worker }
1871*2d543d20SAndroid Build Coastguard Worker
1872*2d543d20SAndroid Build Coastguard Worker avdatump = &node->datum;
1873*2d543d20SAndroid Build Coastguard Worker switch (specified) {
1874*2d543d20SAndroid Build Coastguard Worker case AVRULE_ALLOWED:
1875*2d543d20SAndroid Build Coastguard Worker case AVRULE_AUDITALLOW:
1876*2d543d20SAndroid Build Coastguard Worker case AVRULE_NEVERALLOW:
1877*2d543d20SAndroid Build Coastguard Worker avdatump->data |= cur->data;
1878*2d543d20SAndroid Build Coastguard Worker break;
1879*2d543d20SAndroid Build Coastguard Worker case AVRULE_DONTAUDIT:
1880*2d543d20SAndroid Build Coastguard Worker avdatump->data &= ~cur->data;
1881*2d543d20SAndroid Build Coastguard Worker break;
1882*2d543d20SAndroid Build Coastguard Worker case AVRULE_AUDITDENY:
1883*2d543d20SAndroid Build Coastguard Worker /* Since a '0' in an auditdeny mask represents
1884*2d543d20SAndroid Build Coastguard Worker * a permission we do NOT want to audit
1885*2d543d20SAndroid Build Coastguard Worker * (dontaudit), we use the '&' operand to
1886*2d543d20SAndroid Build Coastguard Worker * ensure that all '0's in the mask are
1887*2d543d20SAndroid Build Coastguard Worker * retained (much unlike the allow and
1888*2d543d20SAndroid Build Coastguard Worker * auditallow cases).
1889*2d543d20SAndroid Build Coastguard Worker */
1890*2d543d20SAndroid Build Coastguard Worker avdatump->data &= cur->data;
1891*2d543d20SAndroid Build Coastguard Worker break;
1892*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_ALLOWED:
1893*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_AUDITALLOW:
1894*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_DONTAUDIT:
1895*2d543d20SAndroid Build Coastguard Worker case AVRULE_XPERMS_NEVERALLOW:
1896*2d543d20SAndroid Build Coastguard Worker if (allocate_xperms(handle, avdatump, extended_perms))
1897*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1898*2d543d20SAndroid Build Coastguard Worker break;
1899*2d543d20SAndroid Build Coastguard Worker default:
1900*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Unknown specification: %"PRIu32, specified);
1901*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1902*2d543d20SAndroid Build Coastguard Worker }
1903*2d543d20SAndroid Build Coastguard Worker
1904*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
1905*2d543d20SAndroid Build Coastguard Worker }
1906*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1907*2d543d20SAndroid Build Coastguard Worker }
1908*2d543d20SAndroid Build Coastguard Worker
expand_rule_helper(sepol_handle_t * handle,policydb_t * p,uint32_t * typemap,avrule_t * source_rule,avtab_t * dest_avtab,cond_av_list_t ** cond,cond_av_list_t ** other,int enabled,ebitmap_t * stypes,ebitmap_t * ttypes)1909*2d543d20SAndroid Build Coastguard Worker static int expand_rule_helper(sepol_handle_t * handle,
1910*2d543d20SAndroid Build Coastguard Worker policydb_t * p, uint32_t * typemap,
1911*2d543d20SAndroid Build Coastguard Worker avrule_t * source_rule, avtab_t * dest_avtab,
1912*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** cond, cond_av_list_t ** other,
1913*2d543d20SAndroid Build Coastguard Worker int enabled,
1914*2d543d20SAndroid Build Coastguard Worker ebitmap_t * stypes, ebitmap_t * ttypes)
1915*2d543d20SAndroid Build Coastguard Worker {
1916*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
1917*2d543d20SAndroid Build Coastguard Worker int retval;
1918*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode;
1919*2d543d20SAndroid Build Coastguard Worker
1920*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(stypes, snode, i) {
1921*2d543d20SAndroid Build Coastguard Worker if (source_rule->flags & RULE_SELF) {
1922*2d543d20SAndroid Build Coastguard Worker if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
1923*2d543d20SAndroid Build Coastguard Worker retval = expand_avrule_helper(handle, source_rule->specified,
1924*2d543d20SAndroid Build Coastguard Worker cond, i, i, source_rule->perms,
1925*2d543d20SAndroid Build Coastguard Worker dest_avtab, enabled, source_rule->xperms);
1926*2d543d20SAndroid Build Coastguard Worker if (retval != EXPAND_RULE_SUCCESS)
1927*2d543d20SAndroid Build Coastguard Worker return retval;
1928*2d543d20SAndroid Build Coastguard Worker } else {
1929*2d543d20SAndroid Build Coastguard Worker retval = expand_terule_helper(handle, p, typemap,
1930*2d543d20SAndroid Build Coastguard Worker source_rule->specified, cond,
1931*2d543d20SAndroid Build Coastguard Worker other, i, i, source_rule->perms,
1932*2d543d20SAndroid Build Coastguard Worker dest_avtab, enabled);
1933*2d543d20SAndroid Build Coastguard Worker if (retval != EXPAND_RULE_SUCCESS)
1934*2d543d20SAndroid Build Coastguard Worker return retval;
1935*2d543d20SAndroid Build Coastguard Worker }
1936*2d543d20SAndroid Build Coastguard Worker }
1937*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(ttypes, tnode, j) {
1938*2d543d20SAndroid Build Coastguard Worker if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
1939*2d543d20SAndroid Build Coastguard Worker retval = expand_avrule_helper(handle, source_rule->specified,
1940*2d543d20SAndroid Build Coastguard Worker cond, i, j, source_rule->perms,
1941*2d543d20SAndroid Build Coastguard Worker dest_avtab, enabled, source_rule->xperms);
1942*2d543d20SAndroid Build Coastguard Worker if (retval != EXPAND_RULE_SUCCESS)
1943*2d543d20SAndroid Build Coastguard Worker return retval;
1944*2d543d20SAndroid Build Coastguard Worker } else {
1945*2d543d20SAndroid Build Coastguard Worker retval = expand_terule_helper(handle, p, typemap,
1946*2d543d20SAndroid Build Coastguard Worker source_rule->specified, cond,
1947*2d543d20SAndroid Build Coastguard Worker other, i, j, source_rule->perms,
1948*2d543d20SAndroid Build Coastguard Worker dest_avtab, enabled);
1949*2d543d20SAndroid Build Coastguard Worker if (retval != EXPAND_RULE_SUCCESS)
1950*2d543d20SAndroid Build Coastguard Worker return retval;
1951*2d543d20SAndroid Build Coastguard Worker }
1952*2d543d20SAndroid Build Coastguard Worker }
1953*2d543d20SAndroid Build Coastguard Worker }
1954*2d543d20SAndroid Build Coastguard Worker
1955*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1956*2d543d20SAndroid Build Coastguard Worker }
1957*2d543d20SAndroid Build Coastguard Worker
1958*2d543d20SAndroid Build Coastguard Worker /*
1959*2d543d20SAndroid Build Coastguard Worker * Expand a rule into a given avtab - checking for conflicting type
1960*2d543d20SAndroid Build Coastguard Worker * rules in the destination policy. Return EXPAND_RULE_SUCCESS on
1961*2d543d20SAndroid Build Coastguard Worker * success, EXPAND_RULE_CONFLICT if the rule conflicts with something
1962*2d543d20SAndroid Build Coastguard Worker * (and hence was not added), or EXPAND_RULE_ERROR on error.
1963*2d543d20SAndroid Build Coastguard Worker */
convert_and_expand_rule(sepol_handle_t * handle,policydb_t * dest_pol,uint32_t * typemap,avrule_t * source_rule,avtab_t * dest_avtab,cond_av_list_t ** cond,cond_av_list_t ** other,int enabled,int do_neverallow)1964*2d543d20SAndroid Build Coastguard Worker static int convert_and_expand_rule(sepol_handle_t * handle,
1965*2d543d20SAndroid Build Coastguard Worker policydb_t * dest_pol, uint32_t * typemap,
1966*2d543d20SAndroid Build Coastguard Worker avrule_t * source_rule, avtab_t * dest_avtab,
1967*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** cond,
1968*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** other, int enabled,
1969*2d543d20SAndroid Build Coastguard Worker int do_neverallow)
1970*2d543d20SAndroid Build Coastguard Worker {
1971*2d543d20SAndroid Build Coastguard Worker int retval;
1972*2d543d20SAndroid Build Coastguard Worker ebitmap_t stypes, ttypes;
1973*2d543d20SAndroid Build Coastguard Worker unsigned char alwaysexpand;
1974*2d543d20SAndroid Build Coastguard Worker
1975*2d543d20SAndroid Build Coastguard Worker if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW)
1976*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1977*2d543d20SAndroid Build Coastguard Worker if (!do_neverallow && source_rule->specified & AVRULE_XPERMS_NEVERALLOW)
1978*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_SUCCESS;
1979*2d543d20SAndroid Build Coastguard Worker
1980*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&stypes);
1981*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&ttypes);
1982*2d543d20SAndroid Build Coastguard Worker
1983*2d543d20SAndroid Build Coastguard Worker /* Force expansion for type rules and for self rules. */
1984*2d543d20SAndroid Build Coastguard Worker alwaysexpand = ((source_rule->specified & AVRULE_TYPE) ||
1985*2d543d20SAndroid Build Coastguard Worker (source_rule->flags & RULE_SELF));
1986*2d543d20SAndroid Build Coastguard Worker
1987*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
1988*2d543d20SAndroid Build Coastguard Worker (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand))
1989*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1990*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
1991*2d543d20SAndroid Build Coastguard Worker (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand))
1992*2d543d20SAndroid Build Coastguard Worker return EXPAND_RULE_ERROR;
1993*2d543d20SAndroid Build Coastguard Worker
1994*2d543d20SAndroid Build Coastguard Worker retval = expand_rule_helper(handle, dest_pol, typemap,
1995*2d543d20SAndroid Build Coastguard Worker source_rule, dest_avtab,
1996*2d543d20SAndroid Build Coastguard Worker cond, other, enabled, &stypes, &ttypes);
1997*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
1998*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
1999*2d543d20SAndroid Build Coastguard Worker return retval;
2000*2d543d20SAndroid Build Coastguard Worker }
2001*2d543d20SAndroid Build Coastguard Worker
cond_avrule_list_copy(policydb_t * dest_pol,avrule_t * source_rules,avtab_t * dest_avtab,cond_av_list_t ** list,cond_av_list_t ** other,uint32_t * typemap,int enabled,expand_state_t * state)2002*2d543d20SAndroid Build Coastguard Worker static int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules,
2003*2d543d20SAndroid Build Coastguard Worker avtab_t * dest_avtab, cond_av_list_t ** list,
2004*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** other, uint32_t * typemap,
2005*2d543d20SAndroid Build Coastguard Worker int enabled, expand_state_t * state)
2006*2d543d20SAndroid Build Coastguard Worker {
2007*2d543d20SAndroid Build Coastguard Worker avrule_t *cur;
2008*2d543d20SAndroid Build Coastguard Worker
2009*2d543d20SAndroid Build Coastguard Worker cur = source_rules;
2010*2d543d20SAndroid Build Coastguard Worker while (cur) {
2011*2d543d20SAndroid Build Coastguard Worker if (convert_and_expand_rule(state->handle, dest_pol,
2012*2d543d20SAndroid Build Coastguard Worker typemap, cur, dest_avtab,
2013*2d543d20SAndroid Build Coastguard Worker list, other, enabled,
2014*2d543d20SAndroid Build Coastguard Worker 0) != EXPAND_RULE_SUCCESS) {
2015*2d543d20SAndroid Build Coastguard Worker return -1;
2016*2d543d20SAndroid Build Coastguard Worker }
2017*2d543d20SAndroid Build Coastguard Worker
2018*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
2019*2d543d20SAndroid Build Coastguard Worker }
2020*2d543d20SAndroid Build Coastguard Worker
2021*2d543d20SAndroid Build Coastguard Worker return 0;
2022*2d543d20SAndroid Build Coastguard Worker }
2023*2d543d20SAndroid Build Coastguard Worker
cond_node_map_bools(expand_state_t * state,cond_node_t * cn)2024*2d543d20SAndroid Build Coastguard Worker static int cond_node_map_bools(expand_state_t * state, cond_node_t * cn)
2025*2d543d20SAndroid Build Coastguard Worker {
2026*2d543d20SAndroid Build Coastguard Worker cond_expr_t *cur;
2027*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2028*2d543d20SAndroid Build Coastguard Worker
2029*2d543d20SAndroid Build Coastguard Worker cur = cn->expr;
2030*2d543d20SAndroid Build Coastguard Worker while (cur) {
2031*2d543d20SAndroid Build Coastguard Worker if (cur->boolean)
2032*2d543d20SAndroid Build Coastguard Worker cur->boolean = state->boolmap[cur->boolean - 1];
2033*2d543d20SAndroid Build Coastguard Worker cur = cur->next;
2034*2d543d20SAndroid Build Coastguard Worker }
2035*2d543d20SAndroid Build Coastguard Worker
2036*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++)
2037*2d543d20SAndroid Build Coastguard Worker cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1];
2038*2d543d20SAndroid Build Coastguard Worker
2039*2d543d20SAndroid Build Coastguard Worker if (cond_normalize_expr(state->out, cn)) {
2040*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Error while normalizing conditional");
2041*2d543d20SAndroid Build Coastguard Worker return -1;
2042*2d543d20SAndroid Build Coastguard Worker }
2043*2d543d20SAndroid Build Coastguard Worker
2044*2d543d20SAndroid Build Coastguard Worker return 0;
2045*2d543d20SAndroid Build Coastguard Worker }
2046*2d543d20SAndroid Build Coastguard Worker
2047*2d543d20SAndroid Build Coastguard Worker /* copy the nodes in *reverse* order -- the result is that the last
2048*2d543d20SAndroid Build Coastguard Worker * given conditional appears first in the policy, so as to match the
2049*2d543d20SAndroid Build Coastguard Worker * behavior of the upstream compiler */
cond_node_copy(expand_state_t * state,cond_node_t * cn)2050*2d543d20SAndroid Build Coastguard Worker static int cond_node_copy(expand_state_t * state, cond_node_t * cn)
2051*2d543d20SAndroid Build Coastguard Worker {
2052*2d543d20SAndroid Build Coastguard Worker cond_node_t *new_cond, *tmp;
2053*2d543d20SAndroid Build Coastguard Worker
2054*2d543d20SAndroid Build Coastguard Worker if (cn == NULL) {
2055*2d543d20SAndroid Build Coastguard Worker return 0;
2056*2d543d20SAndroid Build Coastguard Worker }
2057*2d543d20SAndroid Build Coastguard Worker if (cond_node_copy(state, cn->next)) {
2058*2d543d20SAndroid Build Coastguard Worker return -1;
2059*2d543d20SAndroid Build Coastguard Worker }
2060*2d543d20SAndroid Build Coastguard Worker
2061*2d543d20SAndroid Build Coastguard Worker /* If current cond_node_t is of tunable, its effective branch
2062*2d543d20SAndroid Build Coastguard Worker * has been appended to its home decl->avrules list during link
2063*2d543d20SAndroid Build Coastguard Worker * and now we should just skip it. */
2064*2d543d20SAndroid Build Coastguard Worker if (cn->flags & COND_NODE_FLAGS_TUNABLE)
2065*2d543d20SAndroid Build Coastguard Worker return 0;
2066*2d543d20SAndroid Build Coastguard Worker
2067*2d543d20SAndroid Build Coastguard Worker if (cond_normalize_expr(state->base, cn)) {
2068*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Error while normalizing conditional");
2069*2d543d20SAndroid Build Coastguard Worker return -1;
2070*2d543d20SAndroid Build Coastguard Worker }
2071*2d543d20SAndroid Build Coastguard Worker
2072*2d543d20SAndroid Build Coastguard Worker /* create a new temporary conditional node with the booleans
2073*2d543d20SAndroid Build Coastguard Worker * mapped */
2074*2d543d20SAndroid Build Coastguard Worker tmp = cond_node_create(state->base, cn);
2075*2d543d20SAndroid Build Coastguard Worker if (!tmp) {
2076*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory");
2077*2d543d20SAndroid Build Coastguard Worker return -1;
2078*2d543d20SAndroid Build Coastguard Worker }
2079*2d543d20SAndroid Build Coastguard Worker
2080*2d543d20SAndroid Build Coastguard Worker if (cond_node_map_bools(state, tmp)) {
2081*2d543d20SAndroid Build Coastguard Worker cond_node_destroy(tmp);
2082*2d543d20SAndroid Build Coastguard Worker free(tmp);
2083*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Error mapping booleans");
2084*2d543d20SAndroid Build Coastguard Worker return -1;
2085*2d543d20SAndroid Build Coastguard Worker }
2086*2d543d20SAndroid Build Coastguard Worker
2087*2d543d20SAndroid Build Coastguard Worker new_cond = cond_node_search(state->out, state->out->cond_list, tmp);
2088*2d543d20SAndroid Build Coastguard Worker if (!new_cond) {
2089*2d543d20SAndroid Build Coastguard Worker cond_node_destroy(tmp);
2090*2d543d20SAndroid Build Coastguard Worker free(tmp);
2091*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2092*2d543d20SAndroid Build Coastguard Worker return -1;
2093*2d543d20SAndroid Build Coastguard Worker }
2094*2d543d20SAndroid Build Coastguard Worker cond_node_destroy(tmp);
2095*2d543d20SAndroid Build Coastguard Worker free(tmp);
2096*2d543d20SAndroid Build Coastguard Worker
2097*2d543d20SAndroid Build Coastguard Worker if (cond_avrule_list_copy
2098*2d543d20SAndroid Build Coastguard Worker (state->out, cn->avtrue_list, &state->out->te_cond_avtab,
2099*2d543d20SAndroid Build Coastguard Worker &new_cond->true_list, &new_cond->false_list, state->typemap,
2100*2d543d20SAndroid Build Coastguard Worker new_cond->cur_state, state))
2101*2d543d20SAndroid Build Coastguard Worker return -1;
2102*2d543d20SAndroid Build Coastguard Worker if (cond_avrule_list_copy
2103*2d543d20SAndroid Build Coastguard Worker (state->out, cn->avfalse_list, &state->out->te_cond_avtab,
2104*2d543d20SAndroid Build Coastguard Worker &new_cond->false_list, &new_cond->true_list, state->typemap,
2105*2d543d20SAndroid Build Coastguard Worker !new_cond->cur_state, state))
2106*2d543d20SAndroid Build Coastguard Worker return -1;
2107*2d543d20SAndroid Build Coastguard Worker
2108*2d543d20SAndroid Build Coastguard Worker return 0;
2109*2d543d20SAndroid Build Coastguard Worker }
2110*2d543d20SAndroid Build Coastguard Worker
context_copy(context_struct_t * dst,context_struct_t * src,expand_state_t * state)2111*2d543d20SAndroid Build Coastguard Worker static int context_copy(context_struct_t * dst, context_struct_t * src,
2112*2d543d20SAndroid Build Coastguard Worker expand_state_t * state)
2113*2d543d20SAndroid Build Coastguard Worker {
2114*2d543d20SAndroid Build Coastguard Worker dst->user = state->usermap[src->user - 1];
2115*2d543d20SAndroid Build Coastguard Worker dst->role = state->rolemap[src->role - 1];
2116*2d543d20SAndroid Build Coastguard Worker dst->type = state->typemap[src->type - 1];
2117*2d543d20SAndroid Build Coastguard Worker return mls_context_cpy(dst, src);
2118*2d543d20SAndroid Build Coastguard Worker }
2119*2d543d20SAndroid Build Coastguard Worker
ocontext_copy_xen(expand_state_t * state)2120*2d543d20SAndroid Build Coastguard Worker static int ocontext_copy_xen(expand_state_t *state)
2121*2d543d20SAndroid Build Coastguard Worker {
2122*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2123*2d543d20SAndroid Build Coastguard Worker ocontext_t *c, *n, *l;
2124*2d543d20SAndroid Build Coastguard Worker
2125*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < OCON_NUM; i++) {
2126*2d543d20SAndroid Build Coastguard Worker l = NULL;
2127*2d543d20SAndroid Build Coastguard Worker for (c = state->base->ocontexts[i]; c; c = c->next) {
2128*2d543d20SAndroid Build Coastguard Worker if (i == OCON_XEN_ISID && !c->context[0].user) {
2129*2d543d20SAndroid Build Coastguard Worker INFO(state->handle,
2130*2d543d20SAndroid Build Coastguard Worker "No context assigned to SID %s, omitting from policy",
2131*2d543d20SAndroid Build Coastguard Worker c->u.name);
2132*2d543d20SAndroid Build Coastguard Worker continue;
2133*2d543d20SAndroid Build Coastguard Worker }
2134*2d543d20SAndroid Build Coastguard Worker n = malloc(sizeof(ocontext_t));
2135*2d543d20SAndroid Build Coastguard Worker if (!n) {
2136*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2137*2d543d20SAndroid Build Coastguard Worker return -1;
2138*2d543d20SAndroid Build Coastguard Worker }
2139*2d543d20SAndroid Build Coastguard Worker memset(n, 0, sizeof(ocontext_t));
2140*2d543d20SAndroid Build Coastguard Worker if (l)
2141*2d543d20SAndroid Build Coastguard Worker l->next = n;
2142*2d543d20SAndroid Build Coastguard Worker else
2143*2d543d20SAndroid Build Coastguard Worker state->out->ocontexts[i] = n;
2144*2d543d20SAndroid Build Coastguard Worker l = n;
2145*2d543d20SAndroid Build Coastguard Worker switch (i) {
2146*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_ISID:
2147*2d543d20SAndroid Build Coastguard Worker n->sid[0] = c->sid[0];
2148*2d543d20SAndroid Build Coastguard Worker break;
2149*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_PIRQ:
2150*2d543d20SAndroid Build Coastguard Worker n->u.pirq = c->u.pirq;
2151*2d543d20SAndroid Build Coastguard Worker break;
2152*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_IOPORT:
2153*2d543d20SAndroid Build Coastguard Worker n->u.ioport.low_ioport = c->u.ioport.low_ioport;
2154*2d543d20SAndroid Build Coastguard Worker n->u.ioport.high_ioport =
2155*2d543d20SAndroid Build Coastguard Worker c->u.ioport.high_ioport;
2156*2d543d20SAndroid Build Coastguard Worker break;
2157*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_IOMEM:
2158*2d543d20SAndroid Build Coastguard Worker n->u.iomem.low_iomem = c->u.iomem.low_iomem;
2159*2d543d20SAndroid Build Coastguard Worker n->u.iomem.high_iomem = c->u.iomem.high_iomem;
2160*2d543d20SAndroid Build Coastguard Worker break;
2161*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_PCIDEVICE:
2162*2d543d20SAndroid Build Coastguard Worker n->u.device = c->u.device;
2163*2d543d20SAndroid Build Coastguard Worker break;
2164*2d543d20SAndroid Build Coastguard Worker case OCON_XEN_DEVICETREE:
2165*2d543d20SAndroid Build Coastguard Worker n->u.name = strdup(c->u.name);
2166*2d543d20SAndroid Build Coastguard Worker if (!n->u.name) {
2167*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2168*2d543d20SAndroid Build Coastguard Worker return -1;
2169*2d543d20SAndroid Build Coastguard Worker }
2170*2d543d20SAndroid Build Coastguard Worker break;
2171*2d543d20SAndroid Build Coastguard Worker default:
2172*2d543d20SAndroid Build Coastguard Worker /* shouldn't get here */
2173*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Unknown ocontext");
2174*2d543d20SAndroid Build Coastguard Worker return -1;
2175*2d543d20SAndroid Build Coastguard Worker }
2176*2d543d20SAndroid Build Coastguard Worker if (context_copy(&n->context[0], &c->context[0],
2177*2d543d20SAndroid Build Coastguard Worker state)) {
2178*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2179*2d543d20SAndroid Build Coastguard Worker return -1;
2180*2d543d20SAndroid Build Coastguard Worker }
2181*2d543d20SAndroid Build Coastguard Worker }
2182*2d543d20SAndroid Build Coastguard Worker }
2183*2d543d20SAndroid Build Coastguard Worker return 0;
2184*2d543d20SAndroid Build Coastguard Worker }
2185*2d543d20SAndroid Build Coastguard Worker
ocontext_copy_selinux(expand_state_t * state)2186*2d543d20SAndroid Build Coastguard Worker static int ocontext_copy_selinux(expand_state_t *state)
2187*2d543d20SAndroid Build Coastguard Worker {
2188*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
2189*2d543d20SAndroid Build Coastguard Worker ocontext_t *c, *n, *l;
2190*2d543d20SAndroid Build Coastguard Worker
2191*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < OCON_NUM; i++) {
2192*2d543d20SAndroid Build Coastguard Worker l = NULL;
2193*2d543d20SAndroid Build Coastguard Worker for (c = state->base->ocontexts[i]; c; c = c->next) {
2194*2d543d20SAndroid Build Coastguard Worker if (i == OCON_ISID && !c->context[0].user) {
2195*2d543d20SAndroid Build Coastguard Worker INFO(state->handle,
2196*2d543d20SAndroid Build Coastguard Worker "No context assigned to SID %s, omitting from policy",
2197*2d543d20SAndroid Build Coastguard Worker c->u.name);
2198*2d543d20SAndroid Build Coastguard Worker continue;
2199*2d543d20SAndroid Build Coastguard Worker }
2200*2d543d20SAndroid Build Coastguard Worker n = malloc(sizeof(ocontext_t));
2201*2d543d20SAndroid Build Coastguard Worker if (!n) {
2202*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2203*2d543d20SAndroid Build Coastguard Worker return -1;
2204*2d543d20SAndroid Build Coastguard Worker }
2205*2d543d20SAndroid Build Coastguard Worker memset(n, 0, sizeof(ocontext_t));
2206*2d543d20SAndroid Build Coastguard Worker if (l)
2207*2d543d20SAndroid Build Coastguard Worker l->next = n;
2208*2d543d20SAndroid Build Coastguard Worker else
2209*2d543d20SAndroid Build Coastguard Worker state->out->ocontexts[i] = n;
2210*2d543d20SAndroid Build Coastguard Worker l = n;
2211*2d543d20SAndroid Build Coastguard Worker switch (i) {
2212*2d543d20SAndroid Build Coastguard Worker case OCON_ISID:
2213*2d543d20SAndroid Build Coastguard Worker n->sid[0] = c->sid[0];
2214*2d543d20SAndroid Build Coastguard Worker break;
2215*2d543d20SAndroid Build Coastguard Worker case OCON_FS: /* FALLTHROUGH */
2216*2d543d20SAndroid Build Coastguard Worker case OCON_NETIF:
2217*2d543d20SAndroid Build Coastguard Worker n->u.name = strdup(c->u.name);
2218*2d543d20SAndroid Build Coastguard Worker if (!n->u.name) {
2219*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2220*2d543d20SAndroid Build Coastguard Worker return -1;
2221*2d543d20SAndroid Build Coastguard Worker }
2222*2d543d20SAndroid Build Coastguard Worker if (context_copy
2223*2d543d20SAndroid Build Coastguard Worker (&n->context[1], &c->context[1], state)) {
2224*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2225*2d543d20SAndroid Build Coastguard Worker return -1;
2226*2d543d20SAndroid Build Coastguard Worker }
2227*2d543d20SAndroid Build Coastguard Worker break;
2228*2d543d20SAndroid Build Coastguard Worker case OCON_IBPKEY:
2229*2d543d20SAndroid Build Coastguard Worker n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix;
2230*2d543d20SAndroid Build Coastguard Worker
2231*2d543d20SAndroid Build Coastguard Worker n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
2232*2d543d20SAndroid Build Coastguard Worker n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
2233*2d543d20SAndroid Build Coastguard Worker break;
2234*2d543d20SAndroid Build Coastguard Worker case OCON_IBENDPORT:
2235*2d543d20SAndroid Build Coastguard Worker n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name);
2236*2d543d20SAndroid Build Coastguard Worker if (!n->u.ibendport.dev_name) {
2237*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2238*2d543d20SAndroid Build Coastguard Worker return -1;
2239*2d543d20SAndroid Build Coastguard Worker }
2240*2d543d20SAndroid Build Coastguard Worker n->u.ibendport.port = c->u.ibendport.port;
2241*2d543d20SAndroid Build Coastguard Worker break;
2242*2d543d20SAndroid Build Coastguard Worker case OCON_PORT:
2243*2d543d20SAndroid Build Coastguard Worker n->u.port.protocol = c->u.port.protocol;
2244*2d543d20SAndroid Build Coastguard Worker n->u.port.low_port = c->u.port.low_port;
2245*2d543d20SAndroid Build Coastguard Worker n->u.port.high_port = c->u.port.high_port;
2246*2d543d20SAndroid Build Coastguard Worker break;
2247*2d543d20SAndroid Build Coastguard Worker case OCON_NODE:
2248*2d543d20SAndroid Build Coastguard Worker n->u.node.addr = c->u.node.addr;
2249*2d543d20SAndroid Build Coastguard Worker n->u.node.mask = c->u.node.mask;
2250*2d543d20SAndroid Build Coastguard Worker break;
2251*2d543d20SAndroid Build Coastguard Worker case OCON_FSUSE:
2252*2d543d20SAndroid Build Coastguard Worker n->v.behavior = c->v.behavior;
2253*2d543d20SAndroid Build Coastguard Worker n->u.name = strdup(c->u.name);
2254*2d543d20SAndroid Build Coastguard Worker if (!n->u.name) {
2255*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2256*2d543d20SAndroid Build Coastguard Worker return -1;
2257*2d543d20SAndroid Build Coastguard Worker }
2258*2d543d20SAndroid Build Coastguard Worker break;
2259*2d543d20SAndroid Build Coastguard Worker case OCON_NODE6:
2260*2d543d20SAndroid Build Coastguard Worker for (j = 0; j < 4; j++)
2261*2d543d20SAndroid Build Coastguard Worker n->u.node6.addr[j] = c->u.node6.addr[j];
2262*2d543d20SAndroid Build Coastguard Worker for (j = 0; j < 4; j++)
2263*2d543d20SAndroid Build Coastguard Worker n->u.node6.mask[j] = c->u.node6.mask[j];
2264*2d543d20SAndroid Build Coastguard Worker break;
2265*2d543d20SAndroid Build Coastguard Worker default:
2266*2d543d20SAndroid Build Coastguard Worker /* shouldn't get here */
2267*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Unknown ocontext");
2268*2d543d20SAndroid Build Coastguard Worker return -1;
2269*2d543d20SAndroid Build Coastguard Worker }
2270*2d543d20SAndroid Build Coastguard Worker if (context_copy(&n->context[0], &c->context[0], state)) {
2271*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2272*2d543d20SAndroid Build Coastguard Worker return -1;
2273*2d543d20SAndroid Build Coastguard Worker }
2274*2d543d20SAndroid Build Coastguard Worker }
2275*2d543d20SAndroid Build Coastguard Worker }
2276*2d543d20SAndroid Build Coastguard Worker return 0;
2277*2d543d20SAndroid Build Coastguard Worker }
2278*2d543d20SAndroid Build Coastguard Worker
ocontext_copy(expand_state_t * state,uint32_t target)2279*2d543d20SAndroid Build Coastguard Worker static int ocontext_copy(expand_state_t *state, uint32_t target)
2280*2d543d20SAndroid Build Coastguard Worker {
2281*2d543d20SAndroid Build Coastguard Worker int rc = -1;
2282*2d543d20SAndroid Build Coastguard Worker switch (target) {
2283*2d543d20SAndroid Build Coastguard Worker case SEPOL_TARGET_SELINUX:
2284*2d543d20SAndroid Build Coastguard Worker rc = ocontext_copy_selinux(state);
2285*2d543d20SAndroid Build Coastguard Worker break;
2286*2d543d20SAndroid Build Coastguard Worker case SEPOL_TARGET_XEN:
2287*2d543d20SAndroid Build Coastguard Worker rc = ocontext_copy_xen(state);
2288*2d543d20SAndroid Build Coastguard Worker break;
2289*2d543d20SAndroid Build Coastguard Worker default:
2290*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Unknown target");
2291*2d543d20SAndroid Build Coastguard Worker return -1;
2292*2d543d20SAndroid Build Coastguard Worker }
2293*2d543d20SAndroid Build Coastguard Worker return rc;
2294*2d543d20SAndroid Build Coastguard Worker }
2295*2d543d20SAndroid Build Coastguard Worker
genfs_copy(expand_state_t * state)2296*2d543d20SAndroid Build Coastguard Worker static int genfs_copy(expand_state_t * state)
2297*2d543d20SAndroid Build Coastguard Worker {
2298*2d543d20SAndroid Build Coastguard Worker ocontext_t *c, *newc, *l;
2299*2d543d20SAndroid Build Coastguard Worker genfs_t *genfs, *newgenfs, *end;
2300*2d543d20SAndroid Build Coastguard Worker
2301*2d543d20SAndroid Build Coastguard Worker end = NULL;
2302*2d543d20SAndroid Build Coastguard Worker for (genfs = state->base->genfs; genfs; genfs = genfs->next) {
2303*2d543d20SAndroid Build Coastguard Worker newgenfs = malloc(sizeof(genfs_t));
2304*2d543d20SAndroid Build Coastguard Worker if (!newgenfs) {
2305*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2306*2d543d20SAndroid Build Coastguard Worker return -1;
2307*2d543d20SAndroid Build Coastguard Worker }
2308*2d543d20SAndroid Build Coastguard Worker memset(newgenfs, 0, sizeof(genfs_t));
2309*2d543d20SAndroid Build Coastguard Worker newgenfs->fstype = strdup(genfs->fstype);
2310*2d543d20SAndroid Build Coastguard Worker if (!newgenfs->fstype) {
2311*2d543d20SAndroid Build Coastguard Worker free(newgenfs);
2312*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2313*2d543d20SAndroid Build Coastguard Worker return -1;
2314*2d543d20SAndroid Build Coastguard Worker }
2315*2d543d20SAndroid Build Coastguard Worker if (!end)
2316*2d543d20SAndroid Build Coastguard Worker state->out->genfs = newgenfs;
2317*2d543d20SAndroid Build Coastguard Worker else
2318*2d543d20SAndroid Build Coastguard Worker end->next = newgenfs;
2319*2d543d20SAndroid Build Coastguard Worker end = newgenfs;
2320*2d543d20SAndroid Build Coastguard Worker
2321*2d543d20SAndroid Build Coastguard Worker l = NULL;
2322*2d543d20SAndroid Build Coastguard Worker for (c = genfs->head; c; c = c->next) {
2323*2d543d20SAndroid Build Coastguard Worker newc = malloc(sizeof(ocontext_t));
2324*2d543d20SAndroid Build Coastguard Worker if (!newc) {
2325*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2326*2d543d20SAndroid Build Coastguard Worker return -1;
2327*2d543d20SAndroid Build Coastguard Worker }
2328*2d543d20SAndroid Build Coastguard Worker memset(newc, 0, sizeof(ocontext_t));
2329*2d543d20SAndroid Build Coastguard Worker newc->u.name = strdup(c->u.name);
2330*2d543d20SAndroid Build Coastguard Worker if (!newc->u.name) {
2331*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2332*2d543d20SAndroid Build Coastguard Worker free(newc);
2333*2d543d20SAndroid Build Coastguard Worker return -1;
2334*2d543d20SAndroid Build Coastguard Worker }
2335*2d543d20SAndroid Build Coastguard Worker newc->v.sclass = c->v.sclass;
2336*2d543d20SAndroid Build Coastguard Worker context_copy(&newc->context[0], &c->context[0], state);
2337*2d543d20SAndroid Build Coastguard Worker if (l)
2338*2d543d20SAndroid Build Coastguard Worker l->next = newc;
2339*2d543d20SAndroid Build Coastguard Worker else
2340*2d543d20SAndroid Build Coastguard Worker newgenfs->head = newc;
2341*2d543d20SAndroid Build Coastguard Worker l = newc;
2342*2d543d20SAndroid Build Coastguard Worker }
2343*2d543d20SAndroid Build Coastguard Worker }
2344*2d543d20SAndroid Build Coastguard Worker return 0;
2345*2d543d20SAndroid Build Coastguard Worker }
2346*2d543d20SAndroid Build Coastguard Worker
type_attr_map(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2347*2d543d20SAndroid Build Coastguard Worker static int type_attr_map(hashtab_key_t key
2348*2d543d20SAndroid Build Coastguard Worker __attribute__ ((unused)), hashtab_datum_t datum,
2349*2d543d20SAndroid Build Coastguard Worker void *ptr)
2350*2d543d20SAndroid Build Coastguard Worker {
2351*2d543d20SAndroid Build Coastguard Worker type_datum_t *type;
2352*2d543d20SAndroid Build Coastguard Worker expand_state_t *state = ptr;
2353*2d543d20SAndroid Build Coastguard Worker policydb_t *p = state->out;
2354*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2355*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *tnode;
2356*2d543d20SAndroid Build Coastguard Worker uint32_t value;
2357*2d543d20SAndroid Build Coastguard Worker
2358*2d543d20SAndroid Build Coastguard Worker type = (type_datum_t *) datum;
2359*2d543d20SAndroid Build Coastguard Worker value = type->s.value;
2360*2d543d20SAndroid Build Coastguard Worker
2361*2d543d20SAndroid Build Coastguard Worker if (type->flavor == TYPE_ATTRIB) {
2362*2d543d20SAndroid Build Coastguard Worker if (!(type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE)) {
2363*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) {
2364*2d543d20SAndroid Build Coastguard Worker goto oom;
2365*2d543d20SAndroid Build Coastguard Worker }
2366*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&type->types, tnode, i) {
2367*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) {
2368*2d543d20SAndroid Build Coastguard Worker goto oom;
2369*2d543d20SAndroid Build Coastguard Worker }
2370*2d543d20SAndroid Build Coastguard Worker }
2371*2d543d20SAndroid Build Coastguard Worker } else {
2372*2d543d20SAndroid Build Coastguard Worker /* Attribute is being expanded, so remove */
2373*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&p->type_attr_map[value - 1], value - 1, 0)) {
2374*2d543d20SAndroid Build Coastguard Worker goto oom;
2375*2d543d20SAndroid Build Coastguard Worker }
2376*2d543d20SAndroid Build Coastguard Worker }
2377*2d543d20SAndroid Build Coastguard Worker } else {
2378*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) {
2379*2d543d20SAndroid Build Coastguard Worker goto oom;
2380*2d543d20SAndroid Build Coastguard Worker }
2381*2d543d20SAndroid Build Coastguard Worker }
2382*2d543d20SAndroid Build Coastguard Worker
2383*2d543d20SAndroid Build Coastguard Worker return 0;
2384*2d543d20SAndroid Build Coastguard Worker
2385*2d543d20SAndroid Build Coastguard Worker oom:
2386*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of memory!");
2387*2d543d20SAndroid Build Coastguard Worker return -1;
2388*2d543d20SAndroid Build Coastguard Worker }
2389*2d543d20SAndroid Build Coastguard Worker
2390*2d543d20SAndroid Build Coastguard Worker /* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy.
2391*2d543d20SAndroid Build Coastguard Worker * this should not be called until after all the blocks have been processed and the attributes in target policy
2392*2d543d20SAndroid Build Coastguard Worker * are complete. */
expand_convert_type_set(policydb_t * p,uint32_t * typemap,type_set_t * set,ebitmap_t * types,unsigned char alwaysexpand)2393*2d543d20SAndroid Build Coastguard Worker int expand_convert_type_set(policydb_t * p, uint32_t * typemap,
2394*2d543d20SAndroid Build Coastguard Worker type_set_t * set, ebitmap_t * types,
2395*2d543d20SAndroid Build Coastguard Worker unsigned char alwaysexpand)
2396*2d543d20SAndroid Build Coastguard Worker {
2397*2d543d20SAndroid Build Coastguard Worker type_set_t tmpset;
2398*2d543d20SAndroid Build Coastguard Worker
2399*2d543d20SAndroid Build Coastguard Worker type_set_init(&tmpset);
2400*2d543d20SAndroid Build Coastguard Worker
2401*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&set->types, &tmpset.types, typemap))
2402*2d543d20SAndroid Build Coastguard Worker return -1;
2403*2d543d20SAndroid Build Coastguard Worker
2404*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&set->negset, &tmpset.negset, typemap))
2405*2d543d20SAndroid Build Coastguard Worker return -1;
2406*2d543d20SAndroid Build Coastguard Worker
2407*2d543d20SAndroid Build Coastguard Worker tmpset.flags = set->flags;
2408*2d543d20SAndroid Build Coastguard Worker
2409*2d543d20SAndroid Build Coastguard Worker if (type_set_expand(&tmpset, types, p, alwaysexpand))
2410*2d543d20SAndroid Build Coastguard Worker return -1;
2411*2d543d20SAndroid Build Coastguard Worker
2412*2d543d20SAndroid Build Coastguard Worker type_set_destroy(&tmpset);
2413*2d543d20SAndroid Build Coastguard Worker
2414*2d543d20SAndroid Build Coastguard Worker return 0;
2415*2d543d20SAndroid Build Coastguard Worker }
2416*2d543d20SAndroid Build Coastguard Worker
2417*2d543d20SAndroid Build Coastguard Worker /* Expand a rule into a given avtab - checking for conflicting type
2418*2d543d20SAndroid Build Coastguard Worker * rules. Return 1 on success, 0 if the rule conflicts with something
2419*2d543d20SAndroid Build Coastguard Worker * (and hence was not added), or -1 on error. */
expand_rule(sepol_handle_t * handle,policydb_t * source_pol,avrule_t * source_rule,avtab_t * dest_avtab,cond_av_list_t ** cond,cond_av_list_t ** other,int enabled)2420*2d543d20SAndroid Build Coastguard Worker int expand_rule(sepol_handle_t * handle,
2421*2d543d20SAndroid Build Coastguard Worker policydb_t * source_pol,
2422*2d543d20SAndroid Build Coastguard Worker avrule_t * source_rule, avtab_t * dest_avtab,
2423*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** cond, cond_av_list_t ** other, int enabled)
2424*2d543d20SAndroid Build Coastguard Worker {
2425*2d543d20SAndroid Build Coastguard Worker int retval;
2426*2d543d20SAndroid Build Coastguard Worker ebitmap_t stypes, ttypes;
2427*2d543d20SAndroid Build Coastguard Worker
2428*2d543d20SAndroid Build Coastguard Worker if ((source_rule->specified & AVRULE_NEVERALLOW)
2429*2d543d20SAndroid Build Coastguard Worker || (source_rule->specified & AVRULE_XPERMS_NEVERALLOW))
2430*2d543d20SAndroid Build Coastguard Worker return 1;
2431*2d543d20SAndroid Build Coastguard Worker
2432*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&stypes);
2433*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&ttypes);
2434*2d543d20SAndroid Build Coastguard Worker
2435*2d543d20SAndroid Build Coastguard Worker if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1))
2436*2d543d20SAndroid Build Coastguard Worker return -1;
2437*2d543d20SAndroid Build Coastguard Worker if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1))
2438*2d543d20SAndroid Build Coastguard Worker return -1;
2439*2d543d20SAndroid Build Coastguard Worker retval = expand_rule_helper(handle, source_pol, NULL,
2440*2d543d20SAndroid Build Coastguard Worker source_rule, dest_avtab,
2441*2d543d20SAndroid Build Coastguard Worker cond, other, enabled, &stypes, &ttypes);
2442*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
2443*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
2444*2d543d20SAndroid Build Coastguard Worker return retval;
2445*2d543d20SAndroid Build Coastguard Worker }
2446*2d543d20SAndroid Build Coastguard Worker
2447*2d543d20SAndroid Build Coastguard Worker /* Expand a role set into an ebitmap containing the roles.
2448*2d543d20SAndroid Build Coastguard Worker * This handles the attribute and flags.
2449*2d543d20SAndroid Build Coastguard Worker * Attribute expansion depends on if the rolemap is available.
2450*2d543d20SAndroid Build Coastguard Worker * During module compile the rolemap is not available, the
2451*2d543d20SAndroid Build Coastguard Worker * possible duplicates of a regular role and the role attribute
2452*2d543d20SAndroid Build Coastguard Worker * the regular role belongs to could be properly handled by
2453*2d543d20SAndroid Build Coastguard Worker * copy_role_trans and copy_role_allow.
2454*2d543d20SAndroid Build Coastguard Worker */
role_set_expand(role_set_t * x,ebitmap_t * r,policydb_t * out,policydb_t * base,uint32_t * rolemap)2455*2d543d20SAndroid Build Coastguard Worker int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap)
2456*2d543d20SAndroid Build Coastguard Worker {
2457*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2458*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *rnode;
2459*2d543d20SAndroid Build Coastguard Worker ebitmap_t mapped_roles, roles;
2460*2d543d20SAndroid Build Coastguard Worker policydb_t *p = out;
2461*2d543d20SAndroid Build Coastguard Worker role_datum_t *role;
2462*2d543d20SAndroid Build Coastguard Worker
2463*2d543d20SAndroid Build Coastguard Worker ebitmap_init(r);
2464*2d543d20SAndroid Build Coastguard Worker
2465*2d543d20SAndroid Build Coastguard Worker if (x->flags & ROLE_STAR) {
2466*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < p->p_roles.nprim; i++)
2467*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(r, i, 1))
2468*2d543d20SAndroid Build Coastguard Worker return -1;
2469*2d543d20SAndroid Build Coastguard Worker return 0;
2470*2d543d20SAndroid Build Coastguard Worker }
2471*2d543d20SAndroid Build Coastguard Worker
2472*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&mapped_roles);
2473*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&roles);
2474*2d543d20SAndroid Build Coastguard Worker
2475*2d543d20SAndroid Build Coastguard Worker if (rolemap) {
2476*2d543d20SAndroid Build Coastguard Worker assert(base != NULL);
2477*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&x->roles, rnode, i) {
2478*2d543d20SAndroid Build Coastguard Worker /* take advantage of p_role_val_to_struct[]
2479*2d543d20SAndroid Build Coastguard Worker * of the base module */
2480*2d543d20SAndroid Build Coastguard Worker role = base->role_val_to_struct[i];
2481*2d543d20SAndroid Build Coastguard Worker assert(role != NULL);
2482*2d543d20SAndroid Build Coastguard Worker if (role->flavor == ROLE_ATTRIB) {
2483*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&roles,
2484*2d543d20SAndroid Build Coastguard Worker &role->roles))
2485*2d543d20SAndroid Build Coastguard Worker goto bad;
2486*2d543d20SAndroid Build Coastguard Worker } else {
2487*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&roles, i, 1))
2488*2d543d20SAndroid Build Coastguard Worker goto bad;
2489*2d543d20SAndroid Build Coastguard Worker }
2490*2d543d20SAndroid Build Coastguard Worker }
2491*2d543d20SAndroid Build Coastguard Worker if (map_ebitmap(&roles, &mapped_roles, rolemap))
2492*2d543d20SAndroid Build Coastguard Worker goto bad;
2493*2d543d20SAndroid Build Coastguard Worker } else {
2494*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&mapped_roles, &x->roles))
2495*2d543d20SAndroid Build Coastguard Worker goto bad;
2496*2d543d20SAndroid Build Coastguard Worker }
2497*2d543d20SAndroid Build Coastguard Worker
2498*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&mapped_roles, rnode, i) {
2499*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(r, i, 1))
2500*2d543d20SAndroid Build Coastguard Worker goto bad;
2501*2d543d20SAndroid Build Coastguard Worker }
2502*2d543d20SAndroid Build Coastguard Worker
2503*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&mapped_roles);
2504*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&roles);
2505*2d543d20SAndroid Build Coastguard Worker
2506*2d543d20SAndroid Build Coastguard Worker /* if role is to be complimented, invert the entire bitmap here */
2507*2d543d20SAndroid Build Coastguard Worker if (x->flags & ROLE_COMP) {
2508*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < p->p_roles.nprim; i++) {
2509*2d543d20SAndroid Build Coastguard Worker if (ebitmap_get_bit(r, i)) {
2510*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(r, i, 0))
2511*2d543d20SAndroid Build Coastguard Worker return -1;
2512*2d543d20SAndroid Build Coastguard Worker } else {
2513*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(r, i, 1))
2514*2d543d20SAndroid Build Coastguard Worker return -1;
2515*2d543d20SAndroid Build Coastguard Worker }
2516*2d543d20SAndroid Build Coastguard Worker }
2517*2d543d20SAndroid Build Coastguard Worker }
2518*2d543d20SAndroid Build Coastguard Worker return 0;
2519*2d543d20SAndroid Build Coastguard Worker
2520*2d543d20SAndroid Build Coastguard Worker bad:
2521*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&mapped_roles);
2522*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&roles);
2523*2d543d20SAndroid Build Coastguard Worker return -1;
2524*2d543d20SAndroid Build Coastguard Worker }
2525*2d543d20SAndroid Build Coastguard Worker
2526*2d543d20SAndroid Build Coastguard Worker /* Expand a type set into an ebitmap containing the types. This
2527*2d543d20SAndroid Build Coastguard Worker * handles the negset, attributes, and flags.
2528*2d543d20SAndroid Build Coastguard Worker * Attribute expansion depends on several factors:
2529*2d543d20SAndroid Build Coastguard Worker * - if alwaysexpand is 1, then they will be expanded,
2530*2d543d20SAndroid Build Coastguard Worker * - if the type set has a negset or flags, then they will be expanded,
2531*2d543d20SAndroid Build Coastguard Worker * - otherwise, they will not be expanded.
2532*2d543d20SAndroid Build Coastguard Worker */
type_set_expand(type_set_t * set,ebitmap_t * t,policydb_t * p,unsigned char alwaysexpand)2533*2d543d20SAndroid Build Coastguard Worker int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p,
2534*2d543d20SAndroid Build Coastguard Worker unsigned char alwaysexpand)
2535*2d543d20SAndroid Build Coastguard Worker {
2536*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2537*2d543d20SAndroid Build Coastguard Worker ebitmap_t types, neg_types;
2538*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *tnode;
2539*2d543d20SAndroid Build Coastguard Worker unsigned char expand = alwaysexpand || !ebitmap_is_empty(&set->negset) || set->flags;
2540*2d543d20SAndroid Build Coastguard Worker type_datum_t *type;
2541*2d543d20SAndroid Build Coastguard Worker int rc =-1;
2542*2d543d20SAndroid Build Coastguard Worker
2543*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&types);
2544*2d543d20SAndroid Build Coastguard Worker ebitmap_init(t);
2545*2d543d20SAndroid Build Coastguard Worker
2546*2d543d20SAndroid Build Coastguard Worker /* First go through the types and OR all the attributes to types */
2547*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&set->types, tnode, i) {
2548*2d543d20SAndroid Build Coastguard Worker /*
2549*2d543d20SAndroid Build Coastguard Worker * invalid policies might have more types set in the ebitmap than
2550*2d543d20SAndroid Build Coastguard Worker * what's available in the type_val_to_struct mapping
2551*2d543d20SAndroid Build Coastguard Worker */
2552*2d543d20SAndroid Build Coastguard Worker if (i >= p->p_types.nprim)
2553*2d543d20SAndroid Build Coastguard Worker goto err_types;
2554*2d543d20SAndroid Build Coastguard Worker
2555*2d543d20SAndroid Build Coastguard Worker type = p->type_val_to_struct[i];
2556*2d543d20SAndroid Build Coastguard Worker
2557*2d543d20SAndroid Build Coastguard Worker if (!type) {
2558*2d543d20SAndroid Build Coastguard Worker goto err_types;
2559*2d543d20SAndroid Build Coastguard Worker }
2560*2d543d20SAndroid Build Coastguard Worker
2561*2d543d20SAndroid Build Coastguard Worker if (type->flavor == TYPE_ATTRIB &&
2562*2d543d20SAndroid Build Coastguard Worker (expand || (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE))) {
2563*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union(&types, &type->types)) {
2564*2d543d20SAndroid Build Coastguard Worker goto err_types;
2565*2d543d20SAndroid Build Coastguard Worker }
2566*2d543d20SAndroid Build Coastguard Worker } else {
2567*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&types, i, 1)) {
2568*2d543d20SAndroid Build Coastguard Worker goto err_types;
2569*2d543d20SAndroid Build Coastguard Worker }
2570*2d543d20SAndroid Build Coastguard Worker }
2571*2d543d20SAndroid Build Coastguard Worker }
2572*2d543d20SAndroid Build Coastguard Worker
2573*2d543d20SAndroid Build Coastguard Worker /* Now do the same thing for negset */
2574*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&neg_types);
2575*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&set->negset, tnode, i) {
2576*2d543d20SAndroid Build Coastguard Worker if (p->type_val_to_struct[i] &&
2577*2d543d20SAndroid Build Coastguard Worker p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
2578*2d543d20SAndroid Build Coastguard Worker if (ebitmap_union
2579*2d543d20SAndroid Build Coastguard Worker (&neg_types,
2580*2d543d20SAndroid Build Coastguard Worker &p->type_val_to_struct[i]->types)) {
2581*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2582*2d543d20SAndroid Build Coastguard Worker }
2583*2d543d20SAndroid Build Coastguard Worker } else {
2584*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&neg_types, i, 1)) {
2585*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2586*2d543d20SAndroid Build Coastguard Worker }
2587*2d543d20SAndroid Build Coastguard Worker }
2588*2d543d20SAndroid Build Coastguard Worker }
2589*2d543d20SAndroid Build Coastguard Worker
2590*2d543d20SAndroid Build Coastguard Worker if (set->flags & TYPE_STAR) {
2591*2d543d20SAndroid Build Coastguard Worker /* set all types not in neg_types */
2592*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < p->p_types.nprim; i++) {
2593*2d543d20SAndroid Build Coastguard Worker if (ebitmap_get_bit(&neg_types, i))
2594*2d543d20SAndroid Build Coastguard Worker continue;
2595*2d543d20SAndroid Build Coastguard Worker if (p->type_val_to_struct[i] &&
2596*2d543d20SAndroid Build Coastguard Worker p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
2597*2d543d20SAndroid Build Coastguard Worker continue;
2598*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(t, i, 1))
2599*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2600*2d543d20SAndroid Build Coastguard Worker }
2601*2d543d20SAndroid Build Coastguard Worker goto out;
2602*2d543d20SAndroid Build Coastguard Worker }
2603*2d543d20SAndroid Build Coastguard Worker
2604*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(&types, tnode, i) {
2605*2d543d20SAndroid Build Coastguard Worker if (!ebitmap_get_bit(&neg_types, i))
2606*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(t, i, 1))
2607*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2608*2d543d20SAndroid Build Coastguard Worker }
2609*2d543d20SAndroid Build Coastguard Worker
2610*2d543d20SAndroid Build Coastguard Worker if (set->flags & TYPE_COMP) {
2611*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < p->p_types.nprim; i++) {
2612*2d543d20SAndroid Build Coastguard Worker if (p->type_val_to_struct[i] &&
2613*2d543d20SAndroid Build Coastguard Worker p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) {
2614*2d543d20SAndroid Build Coastguard Worker assert(!ebitmap_get_bit(t, i));
2615*2d543d20SAndroid Build Coastguard Worker continue;
2616*2d543d20SAndroid Build Coastguard Worker }
2617*2d543d20SAndroid Build Coastguard Worker if (ebitmap_get_bit(t, i)) {
2618*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(t, i, 0))
2619*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2620*2d543d20SAndroid Build Coastguard Worker } else {
2621*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(t, i, 1))
2622*2d543d20SAndroid Build Coastguard Worker goto err_neg;
2623*2d543d20SAndroid Build Coastguard Worker }
2624*2d543d20SAndroid Build Coastguard Worker }
2625*2d543d20SAndroid Build Coastguard Worker }
2626*2d543d20SAndroid Build Coastguard Worker
2627*2d543d20SAndroid Build Coastguard Worker out:
2628*2d543d20SAndroid Build Coastguard Worker rc = 0;
2629*2d543d20SAndroid Build Coastguard Worker
2630*2d543d20SAndroid Build Coastguard Worker err_neg:
2631*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&neg_types);
2632*2d543d20SAndroid Build Coastguard Worker err_types:
2633*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&types);
2634*2d543d20SAndroid Build Coastguard Worker
2635*2d543d20SAndroid Build Coastguard Worker return rc;
2636*2d543d20SAndroid Build Coastguard Worker }
2637*2d543d20SAndroid Build Coastguard Worker
copy_neverallow(policydb_t * dest_pol,uint32_t * typemap,avrule_t * source_rule)2638*2d543d20SAndroid Build Coastguard Worker static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
2639*2d543d20SAndroid Build Coastguard Worker avrule_t * source_rule)
2640*2d543d20SAndroid Build Coastguard Worker {
2641*2d543d20SAndroid Build Coastguard Worker ebitmap_t stypes, ttypes;
2642*2d543d20SAndroid Build Coastguard Worker avrule_t *avrule;
2643*2d543d20SAndroid Build Coastguard Worker class_perm_node_t *cur_perm, *new_perm, *tail_perm;
2644*2d543d20SAndroid Build Coastguard Worker av_extended_perms_t *xperms = NULL;
2645*2d543d20SAndroid Build Coastguard Worker
2646*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&stypes);
2647*2d543d20SAndroid Build Coastguard Worker ebitmap_init(&ttypes);
2648*2d543d20SAndroid Build Coastguard Worker
2649*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
2650*2d543d20SAndroid Build Coastguard Worker (dest_pol, typemap, &source_rule->stypes, &stypes, 1))
2651*2d543d20SAndroid Build Coastguard Worker return -1;
2652*2d543d20SAndroid Build Coastguard Worker if (expand_convert_type_set
2653*2d543d20SAndroid Build Coastguard Worker (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1))
2654*2d543d20SAndroid Build Coastguard Worker return -1;
2655*2d543d20SAndroid Build Coastguard Worker
2656*2d543d20SAndroid Build Coastguard Worker avrule = (avrule_t *) malloc(sizeof(avrule_t));
2657*2d543d20SAndroid Build Coastguard Worker if (!avrule)
2658*2d543d20SAndroid Build Coastguard Worker return -1;
2659*2d543d20SAndroid Build Coastguard Worker
2660*2d543d20SAndroid Build Coastguard Worker avrule_init(avrule);
2661*2d543d20SAndroid Build Coastguard Worker avrule->specified = source_rule->specified;
2662*2d543d20SAndroid Build Coastguard Worker avrule->line = source_rule->line;
2663*2d543d20SAndroid Build Coastguard Worker avrule->flags = source_rule->flags;
2664*2d543d20SAndroid Build Coastguard Worker avrule->source_line = source_rule->source_line;
2665*2d543d20SAndroid Build Coastguard Worker if (source_rule->source_filename) {
2666*2d543d20SAndroid Build Coastguard Worker avrule->source_filename = strdup(source_rule->source_filename);
2667*2d543d20SAndroid Build Coastguard Worker if (!avrule->source_filename)
2668*2d543d20SAndroid Build Coastguard Worker goto err;
2669*2d543d20SAndroid Build Coastguard Worker }
2670*2d543d20SAndroid Build Coastguard Worker
2671*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&avrule->stypes.types, &stypes))
2672*2d543d20SAndroid Build Coastguard Worker goto err;
2673*2d543d20SAndroid Build Coastguard Worker
2674*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&avrule->ttypes.types, &ttypes))
2675*2d543d20SAndroid Build Coastguard Worker goto err;
2676*2d543d20SAndroid Build Coastguard Worker
2677*2d543d20SAndroid Build Coastguard Worker cur_perm = source_rule->perms;
2678*2d543d20SAndroid Build Coastguard Worker tail_perm = NULL;
2679*2d543d20SAndroid Build Coastguard Worker while (cur_perm) {
2680*2d543d20SAndroid Build Coastguard Worker new_perm =
2681*2d543d20SAndroid Build Coastguard Worker (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2682*2d543d20SAndroid Build Coastguard Worker if (!new_perm)
2683*2d543d20SAndroid Build Coastguard Worker goto err;
2684*2d543d20SAndroid Build Coastguard Worker class_perm_node_init(new_perm);
2685*2d543d20SAndroid Build Coastguard Worker new_perm->tclass = cur_perm->tclass;
2686*2d543d20SAndroid Build Coastguard Worker assert(new_perm->tclass);
2687*2d543d20SAndroid Build Coastguard Worker
2688*2d543d20SAndroid Build Coastguard Worker /* once we have modules with permissions we'll need to map the permissions (and classes) */
2689*2d543d20SAndroid Build Coastguard Worker new_perm->data = cur_perm->data;
2690*2d543d20SAndroid Build Coastguard Worker
2691*2d543d20SAndroid Build Coastguard Worker if (!avrule->perms)
2692*2d543d20SAndroid Build Coastguard Worker avrule->perms = new_perm;
2693*2d543d20SAndroid Build Coastguard Worker
2694*2d543d20SAndroid Build Coastguard Worker if (tail_perm)
2695*2d543d20SAndroid Build Coastguard Worker tail_perm->next = new_perm;
2696*2d543d20SAndroid Build Coastguard Worker tail_perm = new_perm;
2697*2d543d20SAndroid Build Coastguard Worker cur_perm = cur_perm->next;
2698*2d543d20SAndroid Build Coastguard Worker }
2699*2d543d20SAndroid Build Coastguard Worker
2700*2d543d20SAndroid Build Coastguard Worker /* copy over extended permissions */
2701*2d543d20SAndroid Build Coastguard Worker if (source_rule->xperms) {
2702*2d543d20SAndroid Build Coastguard Worker xperms = calloc(1, sizeof(av_extended_perms_t));
2703*2d543d20SAndroid Build Coastguard Worker if (!xperms)
2704*2d543d20SAndroid Build Coastguard Worker goto err;
2705*2d543d20SAndroid Build Coastguard Worker memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t));
2706*2d543d20SAndroid Build Coastguard Worker avrule->xperms = xperms;
2707*2d543d20SAndroid Build Coastguard Worker }
2708*2d543d20SAndroid Build Coastguard Worker
2709*2d543d20SAndroid Build Coastguard Worker /* just prepend the avrule to the first branch; it'll never be
2710*2d543d20SAndroid Build Coastguard Worker written to disk */
2711*2d543d20SAndroid Build Coastguard Worker if (!dest_pol->global->branch_list->avrules)
2712*2d543d20SAndroid Build Coastguard Worker dest_pol->global->branch_list->avrules = avrule;
2713*2d543d20SAndroid Build Coastguard Worker else {
2714*2d543d20SAndroid Build Coastguard Worker avrule->next = dest_pol->global->branch_list->avrules;
2715*2d543d20SAndroid Build Coastguard Worker dest_pol->global->branch_list->avrules = avrule;
2716*2d543d20SAndroid Build Coastguard Worker }
2717*2d543d20SAndroid Build Coastguard Worker
2718*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
2719*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
2720*2d543d20SAndroid Build Coastguard Worker
2721*2d543d20SAndroid Build Coastguard Worker return 0;
2722*2d543d20SAndroid Build Coastguard Worker
2723*2d543d20SAndroid Build Coastguard Worker err:
2724*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&stypes);
2725*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&ttypes);
2726*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&avrule->stypes.types);
2727*2d543d20SAndroid Build Coastguard Worker ebitmap_destroy(&avrule->ttypes.types);
2728*2d543d20SAndroid Build Coastguard Worker cur_perm = avrule->perms;
2729*2d543d20SAndroid Build Coastguard Worker while (cur_perm) {
2730*2d543d20SAndroid Build Coastguard Worker tail_perm = cur_perm->next;
2731*2d543d20SAndroid Build Coastguard Worker free(cur_perm);
2732*2d543d20SAndroid Build Coastguard Worker cur_perm = tail_perm;
2733*2d543d20SAndroid Build Coastguard Worker }
2734*2d543d20SAndroid Build Coastguard Worker free(xperms);
2735*2d543d20SAndroid Build Coastguard Worker free(avrule);
2736*2d543d20SAndroid Build Coastguard Worker return -1;
2737*2d543d20SAndroid Build Coastguard Worker }
2738*2d543d20SAndroid Build Coastguard Worker
2739*2d543d20SAndroid Build Coastguard Worker /*
2740*2d543d20SAndroid Build Coastguard Worker * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow
2741*2d543d20SAndroid Build Coastguard Worker * rules are copied or expanded as per the settings in the state object; all
2742*2d543d20SAndroid Build Coastguard Worker * other AV rules are expanded. If neverallow rules are expanded, they are not
2743*2d543d20SAndroid Build Coastguard Worker * copied, otherwise they are copied for later use by the assertion checker.
2744*2d543d20SAndroid Build Coastguard Worker */
copy_and_expand_avrule_block(expand_state_t * state)2745*2d543d20SAndroid Build Coastguard Worker static int copy_and_expand_avrule_block(expand_state_t * state)
2746*2d543d20SAndroid Build Coastguard Worker {
2747*2d543d20SAndroid Build Coastguard Worker avrule_block_t *curblock = state->base->global;
2748*2d543d20SAndroid Build Coastguard Worker avrule_block_t *prevblock;
2749*2d543d20SAndroid Build Coastguard Worker int retval = -1;
2750*2d543d20SAndroid Build Coastguard Worker
2751*2d543d20SAndroid Build Coastguard Worker if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) {
2752*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of Memory!");
2753*2d543d20SAndroid Build Coastguard Worker return -1;
2754*2d543d20SAndroid Build Coastguard Worker }
2755*2d543d20SAndroid Build Coastguard Worker
2756*2d543d20SAndroid Build Coastguard Worker if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) {
2757*2d543d20SAndroid Build Coastguard Worker ERR(state->handle, "Out of Memory!");
2758*2d543d20SAndroid Build Coastguard Worker return -1;
2759*2d543d20SAndroid Build Coastguard Worker }
2760*2d543d20SAndroid Build Coastguard Worker
2761*2d543d20SAndroid Build Coastguard Worker while (curblock) {
2762*2d543d20SAndroid Build Coastguard Worker avrule_decl_t *decl = curblock->enabled;
2763*2d543d20SAndroid Build Coastguard Worker avrule_t *cur_avrule;
2764*2d543d20SAndroid Build Coastguard Worker
2765*2d543d20SAndroid Build Coastguard Worker if (decl == NULL) {
2766*2d543d20SAndroid Build Coastguard Worker /* nothing was enabled within this block */
2767*2d543d20SAndroid Build Coastguard Worker goto cont;
2768*2d543d20SAndroid Build Coastguard Worker }
2769*2d543d20SAndroid Build Coastguard Worker
2770*2d543d20SAndroid Build Coastguard Worker /* copy role allows and role trans */
2771*2d543d20SAndroid Build Coastguard Worker if (copy_role_allows(state, decl->role_allow_rules) != 0 ||
2772*2d543d20SAndroid Build Coastguard Worker copy_role_trans(state, decl->role_tr_rules) != 0) {
2773*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2774*2d543d20SAndroid Build Coastguard Worker }
2775*2d543d20SAndroid Build Coastguard Worker
2776*2d543d20SAndroid Build Coastguard Worker if (expand_filename_trans(state, decl->filename_trans_rules))
2777*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2778*2d543d20SAndroid Build Coastguard Worker
2779*2d543d20SAndroid Build Coastguard Worker /* expand the range transition rules */
2780*2d543d20SAndroid Build Coastguard Worker if (expand_range_trans(state, decl->range_tr_rules))
2781*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2782*2d543d20SAndroid Build Coastguard Worker
2783*2d543d20SAndroid Build Coastguard Worker /* copy rules */
2784*2d543d20SAndroid Build Coastguard Worker cur_avrule = decl->avrules;
2785*2d543d20SAndroid Build Coastguard Worker while (cur_avrule != NULL) {
2786*2d543d20SAndroid Build Coastguard Worker if (!(state->expand_neverallow)
2787*2d543d20SAndroid Build Coastguard Worker && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) {
2788*2d543d20SAndroid Build Coastguard Worker /* copy this over directly so that assertions are checked later */
2789*2d543d20SAndroid Build Coastguard Worker if (copy_neverallow
2790*2d543d20SAndroid Build Coastguard Worker (state->out, state->typemap, cur_avrule))
2791*2d543d20SAndroid Build Coastguard Worker ERR(state->handle,
2792*2d543d20SAndroid Build Coastguard Worker "Error while copying neverallow.");
2793*2d543d20SAndroid Build Coastguard Worker } else {
2794*2d543d20SAndroid Build Coastguard Worker if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))
2795*2d543d20SAndroid Build Coastguard Worker state->out->unsupported_format = 1;
2796*2d543d20SAndroid Build Coastguard Worker if (convert_and_expand_rule
2797*2d543d20SAndroid Build Coastguard Worker (state->handle, state->out, state->typemap,
2798*2d543d20SAndroid Build Coastguard Worker cur_avrule, &state->out->te_avtab, NULL,
2799*2d543d20SAndroid Build Coastguard Worker NULL, 0,
2800*2d543d20SAndroid Build Coastguard Worker state->expand_neverallow) !=
2801*2d543d20SAndroid Build Coastguard Worker EXPAND_RULE_SUCCESS) {
2802*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2803*2d543d20SAndroid Build Coastguard Worker }
2804*2d543d20SAndroid Build Coastguard Worker }
2805*2d543d20SAndroid Build Coastguard Worker cur_avrule = cur_avrule->next;
2806*2d543d20SAndroid Build Coastguard Worker }
2807*2d543d20SAndroid Build Coastguard Worker
2808*2d543d20SAndroid Build Coastguard Worker /* copy conditional rules */
2809*2d543d20SAndroid Build Coastguard Worker if (cond_node_copy(state, decl->cond_list))
2810*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2811*2d543d20SAndroid Build Coastguard Worker
2812*2d543d20SAndroid Build Coastguard Worker cont:
2813*2d543d20SAndroid Build Coastguard Worker prevblock = curblock;
2814*2d543d20SAndroid Build Coastguard Worker curblock = curblock->next;
2815*2d543d20SAndroid Build Coastguard Worker
2816*2d543d20SAndroid Build Coastguard Worker if (state->handle && state->handle->expand_consume_base) {
2817*2d543d20SAndroid Build Coastguard Worker /* set base top avrule block in case there
2818*2d543d20SAndroid Build Coastguard Worker * is an error condition and the policy needs
2819*2d543d20SAndroid Build Coastguard Worker * to be destroyed */
2820*2d543d20SAndroid Build Coastguard Worker state->base->global = curblock;
2821*2d543d20SAndroid Build Coastguard Worker avrule_block_destroy(prevblock);
2822*2d543d20SAndroid Build Coastguard Worker }
2823*2d543d20SAndroid Build Coastguard Worker }
2824*2d543d20SAndroid Build Coastguard Worker
2825*2d543d20SAndroid Build Coastguard Worker retval = 0;
2826*2d543d20SAndroid Build Coastguard Worker
2827*2d543d20SAndroid Build Coastguard Worker cleanup:
2828*2d543d20SAndroid Build Coastguard Worker return retval;
2829*2d543d20SAndroid Build Coastguard Worker }
2830*2d543d20SAndroid Build Coastguard Worker
2831*2d543d20SAndroid Build Coastguard Worker /*
2832*2d543d20SAndroid Build Coastguard Worker * This function allows external users of the library (such as setools) to
2833*2d543d20SAndroid Build Coastguard Worker * expand only the avrules and optionally perform expansion of neverallow rules
2834*2d543d20SAndroid Build Coastguard Worker * or expand into the same policy for analysis purposes.
2835*2d543d20SAndroid Build Coastguard Worker */
expand_module_avrules(sepol_handle_t * handle,policydb_t * base,policydb_t * out,uint32_t * typemap,uint32_t * boolmap,uint32_t * rolemap,uint32_t * usermap,int verbose,int expand_neverallow)2836*2d543d20SAndroid Build Coastguard Worker int expand_module_avrules(sepol_handle_t * handle, policydb_t * base,
2837*2d543d20SAndroid Build Coastguard Worker policydb_t * out, uint32_t * typemap,
2838*2d543d20SAndroid Build Coastguard Worker uint32_t * boolmap, uint32_t * rolemap,
2839*2d543d20SAndroid Build Coastguard Worker uint32_t * usermap, int verbose,
2840*2d543d20SAndroid Build Coastguard Worker int expand_neverallow)
2841*2d543d20SAndroid Build Coastguard Worker {
2842*2d543d20SAndroid Build Coastguard Worker expand_state_t state;
2843*2d543d20SAndroid Build Coastguard Worker
2844*2d543d20SAndroid Build Coastguard Worker expand_state_init(&state);
2845*2d543d20SAndroid Build Coastguard Worker
2846*2d543d20SAndroid Build Coastguard Worker state.base = base;
2847*2d543d20SAndroid Build Coastguard Worker state.out = out;
2848*2d543d20SAndroid Build Coastguard Worker state.typemap = typemap;
2849*2d543d20SAndroid Build Coastguard Worker state.boolmap = boolmap;
2850*2d543d20SAndroid Build Coastguard Worker state.rolemap = rolemap;
2851*2d543d20SAndroid Build Coastguard Worker state.usermap = usermap;
2852*2d543d20SAndroid Build Coastguard Worker state.handle = handle;
2853*2d543d20SAndroid Build Coastguard Worker state.verbose = verbose;
2854*2d543d20SAndroid Build Coastguard Worker state.expand_neverallow = expand_neverallow;
2855*2d543d20SAndroid Build Coastguard Worker
2856*2d543d20SAndroid Build Coastguard Worker return copy_and_expand_avrule_block(&state);
2857*2d543d20SAndroid Build Coastguard Worker }
2858*2d543d20SAndroid Build Coastguard Worker
discard_tunables(sepol_handle_t * sh,policydb_t * pol)2859*2d543d20SAndroid Build Coastguard Worker static void discard_tunables(sepol_handle_t *sh, policydb_t *pol)
2860*2d543d20SAndroid Build Coastguard Worker {
2861*2d543d20SAndroid Build Coastguard Worker avrule_block_t *block;
2862*2d543d20SAndroid Build Coastguard Worker avrule_decl_t *decl;
2863*2d543d20SAndroid Build Coastguard Worker cond_node_t *cur_node;
2864*2d543d20SAndroid Build Coastguard Worker cond_expr_t *cur_expr;
2865*2d543d20SAndroid Build Coastguard Worker int cur_state, preserve_tunables = 0;
2866*2d543d20SAndroid Build Coastguard Worker avrule_t *tail, *to_be_appended;
2867*2d543d20SAndroid Build Coastguard Worker
2868*2d543d20SAndroid Build Coastguard Worker if (sh && sh->preserve_tunables)
2869*2d543d20SAndroid Build Coastguard Worker preserve_tunables = 1;
2870*2d543d20SAndroid Build Coastguard Worker
2871*2d543d20SAndroid Build Coastguard Worker /* Iterate through all cond_node of all enabled decls, if a cond_node
2872*2d543d20SAndroid Build Coastguard Worker * is about tunable, calculate its state value and concatenate one of
2873*2d543d20SAndroid Build Coastguard Worker * its avrule list to the current decl->avrules list. On the other
2874*2d543d20SAndroid Build Coastguard Worker * hand, the disabled unused branch of a tunable would be discarded.
2875*2d543d20SAndroid Build Coastguard Worker *
2876*2d543d20SAndroid Build Coastguard Worker * Note, such tunable cond_node would be skipped over in expansion,
2877*2d543d20SAndroid Build Coastguard Worker * so we won't have to worry about removing it from decl->cond_list
2878*2d543d20SAndroid Build Coastguard Worker * here :-)
2879*2d543d20SAndroid Build Coastguard Worker *
2880*2d543d20SAndroid Build Coastguard Worker * If tunables are requested to be preserved then they would be
2881*2d543d20SAndroid Build Coastguard Worker * "transformed" as booleans by having their TUNABLE flag cleared.
2882*2d543d20SAndroid Build Coastguard Worker */
2883*2d543d20SAndroid Build Coastguard Worker for (block = pol->global; block != NULL; block = block->next) {
2884*2d543d20SAndroid Build Coastguard Worker decl = block->enabled;
2885*2d543d20SAndroid Build Coastguard Worker if (decl == NULL || decl->enabled == 0)
2886*2d543d20SAndroid Build Coastguard Worker continue;
2887*2d543d20SAndroid Build Coastguard Worker
2888*2d543d20SAndroid Build Coastguard Worker tail = decl->avrules;
2889*2d543d20SAndroid Build Coastguard Worker while (tail && tail->next)
2890*2d543d20SAndroid Build Coastguard Worker tail = tail->next;
2891*2d543d20SAndroid Build Coastguard Worker
2892*2d543d20SAndroid Build Coastguard Worker for (cur_node = decl->cond_list; cur_node != NULL;
2893*2d543d20SAndroid Build Coastguard Worker cur_node = cur_node->next) {
2894*2d543d20SAndroid Build Coastguard Worker int booleans, tunables, i;
2895*2d543d20SAndroid Build Coastguard Worker cond_bool_datum_t *booldatum;
2896*2d543d20SAndroid Build Coastguard Worker cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH];
2897*2d543d20SAndroid Build Coastguard Worker
2898*2d543d20SAndroid Build Coastguard Worker booleans = tunables = 0;
2899*2d543d20SAndroid Build Coastguard Worker memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH);
2900*2d543d20SAndroid Build Coastguard Worker
2901*2d543d20SAndroid Build Coastguard Worker for (cur_expr = cur_node->expr; cur_expr != NULL;
2902*2d543d20SAndroid Build Coastguard Worker cur_expr = cur_expr->next) {
2903*2d543d20SAndroid Build Coastguard Worker if (cur_expr->expr_type != COND_BOOL)
2904*2d543d20SAndroid Build Coastguard Worker continue;
2905*2d543d20SAndroid Build Coastguard Worker booldatum = pol->bool_val_to_struct[cur_expr->boolean - 1];
2906*2d543d20SAndroid Build Coastguard Worker if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE)
2907*2d543d20SAndroid Build Coastguard Worker tmp[tunables++] = booldatum;
2908*2d543d20SAndroid Build Coastguard Worker else
2909*2d543d20SAndroid Build Coastguard Worker booleans++;
2910*2d543d20SAndroid Build Coastguard Worker }
2911*2d543d20SAndroid Build Coastguard Worker
2912*2d543d20SAndroid Build Coastguard Worker /* bool_copy_callback() at link phase has ensured
2913*2d543d20SAndroid Build Coastguard Worker * that no mixture of tunables and booleans in one
2914*2d543d20SAndroid Build Coastguard Worker * expression. However, this would be broken by the
2915*2d543d20SAndroid Build Coastguard Worker * request to preserve tunables */
2916*2d543d20SAndroid Build Coastguard Worker if (!preserve_tunables)
2917*2d543d20SAndroid Build Coastguard Worker assert(!(booleans && tunables));
2918*2d543d20SAndroid Build Coastguard Worker
2919*2d543d20SAndroid Build Coastguard Worker if (booleans || preserve_tunables) {
2920*2d543d20SAndroid Build Coastguard Worker cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE;
2921*2d543d20SAndroid Build Coastguard Worker if (tunables) {
2922*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < tunables; i++)
2923*2d543d20SAndroid Build Coastguard Worker tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE;
2924*2d543d20SAndroid Build Coastguard Worker }
2925*2d543d20SAndroid Build Coastguard Worker } else {
2926*2d543d20SAndroid Build Coastguard Worker cur_node->flags |= COND_NODE_FLAGS_TUNABLE;
2927*2d543d20SAndroid Build Coastguard Worker cur_state = cond_evaluate_expr(pol, cur_node->expr);
2928*2d543d20SAndroid Build Coastguard Worker if (cur_state == -1) {
2929*2d543d20SAndroid Build Coastguard Worker printf("Expression result was "
2930*2d543d20SAndroid Build Coastguard Worker "undefined, skipping all"
2931*2d543d20SAndroid Build Coastguard Worker "rules\n");
2932*2d543d20SAndroid Build Coastguard Worker continue;
2933*2d543d20SAndroid Build Coastguard Worker }
2934*2d543d20SAndroid Build Coastguard Worker
2935*2d543d20SAndroid Build Coastguard Worker to_be_appended = (cur_state == 1) ?
2936*2d543d20SAndroid Build Coastguard Worker cur_node->avtrue_list : cur_node->avfalse_list;
2937*2d543d20SAndroid Build Coastguard Worker
2938*2d543d20SAndroid Build Coastguard Worker if (tail)
2939*2d543d20SAndroid Build Coastguard Worker tail->next = to_be_appended;
2940*2d543d20SAndroid Build Coastguard Worker else
2941*2d543d20SAndroid Build Coastguard Worker tail = decl->avrules = to_be_appended;
2942*2d543d20SAndroid Build Coastguard Worker
2943*2d543d20SAndroid Build Coastguard Worker /* Now that the effective branch has been
2944*2d543d20SAndroid Build Coastguard Worker * appended, neutralize its original pointer */
2945*2d543d20SAndroid Build Coastguard Worker if (cur_state == 1)
2946*2d543d20SAndroid Build Coastguard Worker cur_node->avtrue_list = NULL;
2947*2d543d20SAndroid Build Coastguard Worker else
2948*2d543d20SAndroid Build Coastguard Worker cur_node->avfalse_list = NULL;
2949*2d543d20SAndroid Build Coastguard Worker
2950*2d543d20SAndroid Build Coastguard Worker /* Update the tail of decl->avrules for
2951*2d543d20SAndroid Build Coastguard Worker * further concatenation */
2952*2d543d20SAndroid Build Coastguard Worker while (tail && tail->next)
2953*2d543d20SAndroid Build Coastguard Worker tail = tail->next;
2954*2d543d20SAndroid Build Coastguard Worker }
2955*2d543d20SAndroid Build Coastguard Worker }
2956*2d543d20SAndroid Build Coastguard Worker }
2957*2d543d20SAndroid Build Coastguard Worker }
2958*2d543d20SAndroid Build Coastguard Worker
2959*2d543d20SAndroid Build Coastguard Worker /* Linking should always be done before calling expand, even if
2960*2d543d20SAndroid Build Coastguard Worker * there is only a base since all optionals are dealt with at link time
2961*2d543d20SAndroid Build Coastguard Worker * the base passed in should be indexed and avrule blocks should be
2962*2d543d20SAndroid Build Coastguard Worker * enabled.
2963*2d543d20SAndroid Build Coastguard Worker */
expand_module(sepol_handle_t * handle,policydb_t * base,policydb_t * out,int verbose,int check)2964*2d543d20SAndroid Build Coastguard Worker int expand_module(sepol_handle_t * handle,
2965*2d543d20SAndroid Build Coastguard Worker policydb_t * base, policydb_t * out, int verbose, int check)
2966*2d543d20SAndroid Build Coastguard Worker {
2967*2d543d20SAndroid Build Coastguard Worker int retval = -1;
2968*2d543d20SAndroid Build Coastguard Worker unsigned int i;
2969*2d543d20SAndroid Build Coastguard Worker expand_state_t state;
2970*2d543d20SAndroid Build Coastguard Worker avrule_block_t *curblock;
2971*2d543d20SAndroid Build Coastguard Worker
2972*2d543d20SAndroid Build Coastguard Worker /* Append tunable's avtrue_list or avfalse_list to the avrules list
2973*2d543d20SAndroid Build Coastguard Worker * of its home decl depending on its state value, so that the effect
2974*2d543d20SAndroid Build Coastguard Worker * rules of a tunable would be added to te_avtab permanently. Whereas
2975*2d543d20SAndroid Build Coastguard Worker * the disabled unused branch would be discarded.
2976*2d543d20SAndroid Build Coastguard Worker *
2977*2d543d20SAndroid Build Coastguard Worker * Originally this function is called at the very end of link phase,
2978*2d543d20SAndroid Build Coastguard Worker * however, we need to keep the linked policy intact for analysis
2979*2d543d20SAndroid Build Coastguard Worker * purpose. */
2980*2d543d20SAndroid Build Coastguard Worker discard_tunables(handle, base);
2981*2d543d20SAndroid Build Coastguard Worker
2982*2d543d20SAndroid Build Coastguard Worker expand_state_init(&state);
2983*2d543d20SAndroid Build Coastguard Worker
2984*2d543d20SAndroid Build Coastguard Worker state.verbose = verbose;
2985*2d543d20SAndroid Build Coastguard Worker state.typemap = NULL;
2986*2d543d20SAndroid Build Coastguard Worker state.base = base;
2987*2d543d20SAndroid Build Coastguard Worker state.out = out;
2988*2d543d20SAndroid Build Coastguard Worker state.handle = handle;
2989*2d543d20SAndroid Build Coastguard Worker
2990*2d543d20SAndroid Build Coastguard Worker if (base->policy_type != POLICY_BASE) {
2991*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Target of expand was not a base policy.");
2992*2d543d20SAndroid Build Coastguard Worker return -1;
2993*2d543d20SAndroid Build Coastguard Worker }
2994*2d543d20SAndroid Build Coastguard Worker
2995*2d543d20SAndroid Build Coastguard Worker state.out->policy_type = POLICY_KERN;
2996*2d543d20SAndroid Build Coastguard Worker state.out->policyvers = POLICYDB_VERSION_MAX;
2997*2d543d20SAndroid Build Coastguard Worker if (state.base->name) {
2998*2d543d20SAndroid Build Coastguard Worker state.out->name = strdup(state.base->name);
2999*2d543d20SAndroid Build Coastguard Worker if (!state.out->name) {
3000*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3001*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3002*2d543d20SAndroid Build Coastguard Worker }
3003*2d543d20SAndroid Build Coastguard Worker }
3004*2d543d20SAndroid Build Coastguard Worker
3005*2d543d20SAndroid Build Coastguard Worker /* Copy mls state from base to out */
3006*2d543d20SAndroid Build Coastguard Worker out->mls = base->mls;
3007*2d543d20SAndroid Build Coastguard Worker out->handle_unknown = base->handle_unknown;
3008*2d543d20SAndroid Build Coastguard Worker
3009*2d543d20SAndroid Build Coastguard Worker /* Copy target from base to out */
3010*2d543d20SAndroid Build Coastguard Worker out->target_platform = base->target_platform;
3011*2d543d20SAndroid Build Coastguard Worker
3012*2d543d20SAndroid Build Coastguard Worker /* Copy policy capabilities */
3013*2d543d20SAndroid Build Coastguard Worker if (ebitmap_cpy(&out->policycaps, &base->policycaps)) {
3014*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3015*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3016*2d543d20SAndroid Build Coastguard Worker }
3017*2d543d20SAndroid Build Coastguard Worker
3018*2d543d20SAndroid Build Coastguard Worker if ((state.typemap =
3019*2d543d20SAndroid Build Coastguard Worker (uint32_t *) calloc(state.base->p_types.nprim,
3020*2d543d20SAndroid Build Coastguard Worker sizeof(uint32_t))) == NULL) {
3021*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3022*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3023*2d543d20SAndroid Build Coastguard Worker }
3024*2d543d20SAndroid Build Coastguard Worker
3025*2d543d20SAndroid Build Coastguard Worker state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t));
3026*2d543d20SAndroid Build Coastguard Worker if (!state.boolmap) {
3027*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3028*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3029*2d543d20SAndroid Build Coastguard Worker }
3030*2d543d20SAndroid Build Coastguard Worker
3031*2d543d20SAndroid Build Coastguard Worker state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t));
3032*2d543d20SAndroid Build Coastguard Worker if (!state.rolemap) {
3033*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3034*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3035*2d543d20SAndroid Build Coastguard Worker }
3036*2d543d20SAndroid Build Coastguard Worker
3037*2d543d20SAndroid Build Coastguard Worker state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t));
3038*2d543d20SAndroid Build Coastguard Worker if (!state.usermap) {
3039*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3040*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3041*2d543d20SAndroid Build Coastguard Worker }
3042*2d543d20SAndroid Build Coastguard Worker
3043*2d543d20SAndroid Build Coastguard Worker /* order is important - types must be first */
3044*2d543d20SAndroid Build Coastguard Worker
3045*2d543d20SAndroid Build Coastguard Worker /* copy types */
3046*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) {
3047*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3048*2d543d20SAndroid Build Coastguard Worker }
3049*2d543d20SAndroid Build Coastguard Worker
3050*2d543d20SAndroid Build Coastguard Worker /* convert attribute type sets */
3051*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3052*2d543d20SAndroid Build Coastguard Worker (state.base->p_types.table, attr_convert_callback, &state)) {
3053*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3054*2d543d20SAndroid Build Coastguard Worker }
3055*2d543d20SAndroid Build Coastguard Worker
3056*2d543d20SAndroid Build Coastguard Worker /* copy commons */
3057*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3058*2d543d20SAndroid Build Coastguard Worker (state.base->p_commons.table, common_copy_callback, &state)) {
3059*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3060*2d543d20SAndroid Build Coastguard Worker }
3061*2d543d20SAndroid Build Coastguard Worker
3062*2d543d20SAndroid Build Coastguard Worker /* copy classes, note, this does not copy constraints, constraints can't be
3063*2d543d20SAndroid Build Coastguard Worker * copied until after all the blocks have been processed and attributes are complete */
3064*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3065*2d543d20SAndroid Build Coastguard Worker (state.base->p_classes.table, class_copy_callback, &state)) {
3066*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3067*2d543d20SAndroid Build Coastguard Worker }
3068*2d543d20SAndroid Build Coastguard Worker
3069*2d543d20SAndroid Build Coastguard Worker /* copy type bounds */
3070*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_types.table,
3071*2d543d20SAndroid Build Coastguard Worker type_bounds_copy_callback, &state))
3072*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3073*2d543d20SAndroid Build Coastguard Worker
3074*2d543d20SAndroid Build Coastguard Worker /* copy aliases */
3075*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state))
3076*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3077*2d543d20SAndroid Build Coastguard Worker
3078*2d543d20SAndroid Build Coastguard Worker /* index here so that type indexes are available for role_copy_callback */
3079*2d543d20SAndroid Build Coastguard Worker if (policydb_index_others(handle, out, verbose)) {
3080*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Error while indexing out symbols");
3081*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3082*2d543d20SAndroid Build Coastguard Worker }
3083*2d543d20SAndroid Build Coastguard Worker
3084*2d543d20SAndroid Build Coastguard Worker /* copy roles */
3085*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
3086*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3087*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_roles.table,
3088*2d543d20SAndroid Build Coastguard Worker role_bounds_copy_callback, &state))
3089*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3090*2d543d20SAndroid Build Coastguard Worker
3091*2d543d20SAndroid Build Coastguard Worker /* copy MLS's sensitivity level and categories - this needs to be done
3092*2d543d20SAndroid Build Coastguard Worker * before expanding users (they need to be indexed too) */
3093*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
3094*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3095*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
3096*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3097*2d543d20SAndroid Build Coastguard Worker if (policydb_index_others(handle, out, verbose)) {
3098*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Error while indexing out symbols");
3099*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3100*2d543d20SAndroid Build Coastguard Worker }
3101*2d543d20SAndroid Build Coastguard Worker
3102*2d543d20SAndroid Build Coastguard Worker /* copy users */
3103*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
3104*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3105*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_users.table,
3106*2d543d20SAndroid Build Coastguard Worker user_bounds_copy_callback, &state))
3107*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3108*2d543d20SAndroid Build Coastguard Worker
3109*2d543d20SAndroid Build Coastguard Worker /* copy bools */
3110*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
3111*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3112*2d543d20SAndroid Build Coastguard Worker
3113*2d543d20SAndroid Build Coastguard Worker if (policydb_index_classes(out)) {
3114*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Error while indexing out classes");
3115*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3116*2d543d20SAndroid Build Coastguard Worker }
3117*2d543d20SAndroid Build Coastguard Worker if (policydb_index_others(handle, out, verbose)) {
3118*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Error while indexing out symbols");
3119*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3120*2d543d20SAndroid Build Coastguard Worker }
3121*2d543d20SAndroid Build Coastguard Worker
3122*2d543d20SAndroid Build Coastguard Worker /* loop through all decls and union attributes, roles, users */
3123*2d543d20SAndroid Build Coastguard Worker for (curblock = state.base->global; curblock != NULL;
3124*2d543d20SAndroid Build Coastguard Worker curblock = curblock->next) {
3125*2d543d20SAndroid Build Coastguard Worker avrule_decl_t *decl = curblock->enabled;
3126*2d543d20SAndroid Build Coastguard Worker
3127*2d543d20SAndroid Build Coastguard Worker if (decl == NULL) {
3128*2d543d20SAndroid Build Coastguard Worker /* nothing was enabled within this block */
3129*2d543d20SAndroid Build Coastguard Worker continue;
3130*2d543d20SAndroid Build Coastguard Worker }
3131*2d543d20SAndroid Build Coastguard Worker
3132*2d543d20SAndroid Build Coastguard Worker /* convert attribute type sets */
3133*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3134*2d543d20SAndroid Build Coastguard Worker (decl->p_types.table, attr_convert_callback, &state)) {
3135*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3136*2d543d20SAndroid Build Coastguard Worker }
3137*2d543d20SAndroid Build Coastguard Worker
3138*2d543d20SAndroid Build Coastguard Worker /* copy roles */
3139*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3140*2d543d20SAndroid Build Coastguard Worker (decl->p_roles.table, role_copy_callback, &state))
3141*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3142*2d543d20SAndroid Build Coastguard Worker
3143*2d543d20SAndroid Build Coastguard Worker /* copy users */
3144*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3145*2d543d20SAndroid Build Coastguard Worker (decl->p_users.table, user_copy_callback, &state))
3146*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3147*2d543d20SAndroid Build Coastguard Worker
3148*2d543d20SAndroid Build Coastguard Worker }
3149*2d543d20SAndroid Build Coastguard Worker
3150*2d543d20SAndroid Build Coastguard Worker /* remap role dominates bitmaps */
3151*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) {
3152*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3153*2d543d20SAndroid Build Coastguard Worker }
3154*2d543d20SAndroid Build Coastguard Worker
3155*2d543d20SAndroid Build Coastguard Worker /* escalate the type_set_t in a role attribute to all regular roles
3156*2d543d20SAndroid Build Coastguard Worker * that belongs to it. */
3157*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
3158*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3159*2d543d20SAndroid Build Coastguard Worker
3160*2d543d20SAndroid Build Coastguard Worker if (copy_and_expand_avrule_block(&state) < 0) {
3161*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Error during expand");
3162*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3163*2d543d20SAndroid Build Coastguard Worker }
3164*2d543d20SAndroid Build Coastguard Worker
3165*2d543d20SAndroid Build Coastguard Worker /* copy constraints */
3166*2d543d20SAndroid Build Coastguard Worker if (hashtab_map
3167*2d543d20SAndroid Build Coastguard Worker (state.base->p_classes.table, constraint_copy_callback, &state)) {
3168*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3169*2d543d20SAndroid Build Coastguard Worker }
3170*2d543d20SAndroid Build Coastguard Worker
3171*2d543d20SAndroid Build Coastguard Worker cond_optimize_lists(state.out->cond_list);
3172*2d543d20SAndroid Build Coastguard Worker if (evaluate_conds(state.out))
3173*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3174*2d543d20SAndroid Build Coastguard Worker
3175*2d543d20SAndroid Build Coastguard Worker /* copy ocontexts */
3176*2d543d20SAndroid Build Coastguard Worker if (ocontext_copy(&state, out->target_platform))
3177*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3178*2d543d20SAndroid Build Coastguard Worker
3179*2d543d20SAndroid Build Coastguard Worker /* copy genfs */
3180*2d543d20SAndroid Build Coastguard Worker if (genfs_copy(&state))
3181*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3182*2d543d20SAndroid Build Coastguard Worker
3183*2d543d20SAndroid Build Coastguard Worker /* Build the type<->attribute maps and remove attributes. */
3184*2d543d20SAndroid Build Coastguard Worker state.out->attr_type_map = calloc(state.out->p_types.nprim,
3185*2d543d20SAndroid Build Coastguard Worker sizeof(ebitmap_t));
3186*2d543d20SAndroid Build Coastguard Worker state.out->type_attr_map = calloc(state.out->p_types.nprim,
3187*2d543d20SAndroid Build Coastguard Worker sizeof(ebitmap_t));
3188*2d543d20SAndroid Build Coastguard Worker if (!state.out->attr_type_map || !state.out->type_attr_map) {
3189*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3190*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3191*2d543d20SAndroid Build Coastguard Worker }
3192*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < state.out->p_types.nprim; i++) {
3193*2d543d20SAndroid Build Coastguard Worker /* add the type itself as the degenerate case */
3194*2d543d20SAndroid Build Coastguard Worker if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) {
3195*2d543d20SAndroid Build Coastguard Worker ERR(handle, "Out of memory!");
3196*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3197*2d543d20SAndroid Build Coastguard Worker }
3198*2d543d20SAndroid Build Coastguard Worker }
3199*2d543d20SAndroid Build Coastguard Worker if (hashtab_map(state.out->p_types.table, type_attr_map, &state))
3200*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3201*2d543d20SAndroid Build Coastguard Worker if (check) {
3202*2d543d20SAndroid Build Coastguard Worker if (hierarchy_check_constraints(handle, state.out))
3203*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3204*2d543d20SAndroid Build Coastguard Worker
3205*2d543d20SAndroid Build Coastguard Worker if (check_assertions
3206*2d543d20SAndroid Build Coastguard Worker (handle, state.out,
3207*2d543d20SAndroid Build Coastguard Worker state.out->global->branch_list->avrules))
3208*2d543d20SAndroid Build Coastguard Worker goto cleanup;
3209*2d543d20SAndroid Build Coastguard Worker }
3210*2d543d20SAndroid Build Coastguard Worker
3211*2d543d20SAndroid Build Coastguard Worker retval = 0;
3212*2d543d20SAndroid Build Coastguard Worker
3213*2d543d20SAndroid Build Coastguard Worker cleanup:
3214*2d543d20SAndroid Build Coastguard Worker free(state.typemap);
3215*2d543d20SAndroid Build Coastguard Worker free(state.boolmap);
3216*2d543d20SAndroid Build Coastguard Worker free(state.rolemap);
3217*2d543d20SAndroid Build Coastguard Worker free(state.usermap);
3218*2d543d20SAndroid Build Coastguard Worker return retval;
3219*2d543d20SAndroid Build Coastguard Worker }
3220*2d543d20SAndroid Build Coastguard Worker
expand_avtab_insert(avtab_t * a,avtab_key_t * k,avtab_datum_t * d)3221*2d543d20SAndroid Build Coastguard Worker static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
3222*2d543d20SAndroid Build Coastguard Worker {
3223*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
3224*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *avd;
3225*2d543d20SAndroid Build Coastguard Worker avtab_extended_perms_t *xperms;
3226*2d543d20SAndroid Build Coastguard Worker unsigned int i;
3227*2d543d20SAndroid Build Coastguard Worker unsigned int match = 0;
3228*2d543d20SAndroid Build Coastguard Worker
3229*2d543d20SAndroid Build Coastguard Worker if (k->specified & AVTAB_XPERMS) {
3230*2d543d20SAndroid Build Coastguard Worker /*
3231*2d543d20SAndroid Build Coastguard Worker * AVTAB_XPERMS entries are not necessarily unique.
3232*2d543d20SAndroid Build Coastguard Worker * find node with matching xperms
3233*2d543d20SAndroid Build Coastguard Worker */
3234*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(a, k);
3235*2d543d20SAndroid Build Coastguard Worker while (node) {
3236*2d543d20SAndroid Build Coastguard Worker if ((node->datum.xperms->specified == d->xperms->specified) &&
3237*2d543d20SAndroid Build Coastguard Worker (node->datum.xperms->driver == d->xperms->driver)) {
3238*2d543d20SAndroid Build Coastguard Worker match = 1;
3239*2d543d20SAndroid Build Coastguard Worker break;
3240*2d543d20SAndroid Build Coastguard Worker }
3241*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node_next(node, k->specified);
3242*2d543d20SAndroid Build Coastguard Worker }
3243*2d543d20SAndroid Build Coastguard Worker if (!match)
3244*2d543d20SAndroid Build Coastguard Worker node = NULL;
3245*2d543d20SAndroid Build Coastguard Worker } else {
3246*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(a, k);
3247*2d543d20SAndroid Build Coastguard Worker }
3248*2d543d20SAndroid Build Coastguard Worker
3249*2d543d20SAndroid Build Coastguard Worker if (!node || ((k->specified & AVTAB_ENABLED) !=
3250*2d543d20SAndroid Build Coastguard Worker (node->key.specified & AVTAB_ENABLED))) {
3251*2d543d20SAndroid Build Coastguard Worker node = avtab_insert_nonunique(a, k, d);
3252*2d543d20SAndroid Build Coastguard Worker if (!node) {
3253*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Out of memory!");
3254*2d543d20SAndroid Build Coastguard Worker return -1;
3255*2d543d20SAndroid Build Coastguard Worker }
3256*2d543d20SAndroid Build Coastguard Worker return 0;
3257*2d543d20SAndroid Build Coastguard Worker }
3258*2d543d20SAndroid Build Coastguard Worker
3259*2d543d20SAndroid Build Coastguard Worker avd = &node->datum;
3260*2d543d20SAndroid Build Coastguard Worker xperms = node->datum.xperms;
3261*2d543d20SAndroid Build Coastguard Worker switch (k->specified & ~AVTAB_ENABLED) {
3262*2d543d20SAndroid Build Coastguard Worker case AVTAB_ALLOWED:
3263*2d543d20SAndroid Build Coastguard Worker case AVTAB_AUDITALLOW:
3264*2d543d20SAndroid Build Coastguard Worker avd->data |= d->data;
3265*2d543d20SAndroid Build Coastguard Worker break;
3266*2d543d20SAndroid Build Coastguard Worker case AVTAB_AUDITDENY:
3267*2d543d20SAndroid Build Coastguard Worker avd->data &= d->data;
3268*2d543d20SAndroid Build Coastguard Worker break;
3269*2d543d20SAndroid Build Coastguard Worker case AVTAB_XPERMS_ALLOWED:
3270*2d543d20SAndroid Build Coastguard Worker case AVTAB_XPERMS_AUDITALLOW:
3271*2d543d20SAndroid Build Coastguard Worker case AVTAB_XPERMS_DONTAUDIT:
3272*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
3273*2d543d20SAndroid Build Coastguard Worker xperms->perms[i] |= d->xperms->perms[i];
3274*2d543d20SAndroid Build Coastguard Worker break;
3275*2d543d20SAndroid Build Coastguard Worker default:
3276*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Type conflict!");
3277*2d543d20SAndroid Build Coastguard Worker return -1;
3278*2d543d20SAndroid Build Coastguard Worker }
3279*2d543d20SAndroid Build Coastguard Worker
3280*2d543d20SAndroid Build Coastguard Worker return 0;
3281*2d543d20SAndroid Build Coastguard Worker }
3282*2d543d20SAndroid Build Coastguard Worker
3283*2d543d20SAndroid Build Coastguard Worker struct expand_avtab_data {
3284*2d543d20SAndroid Build Coastguard Worker avtab_t *expa;
3285*2d543d20SAndroid Build Coastguard Worker policydb_t *p;
3286*2d543d20SAndroid Build Coastguard Worker
3287*2d543d20SAndroid Build Coastguard Worker };
3288*2d543d20SAndroid Build Coastguard Worker
expand_avtab_node(avtab_key_t * k,avtab_datum_t * d,void * args)3289*2d543d20SAndroid Build Coastguard Worker static int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args)
3290*2d543d20SAndroid Build Coastguard Worker {
3291*2d543d20SAndroid Build Coastguard Worker struct expand_avtab_data *ptr = args;
3292*2d543d20SAndroid Build Coastguard Worker avtab_t *expa = ptr->expa;
3293*2d543d20SAndroid Build Coastguard Worker policydb_t *p = ptr->p;
3294*2d543d20SAndroid Build Coastguard Worker type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
3295*2d543d20SAndroid Build Coastguard Worker type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
3296*2d543d20SAndroid Build Coastguard Worker ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
3297*2d543d20SAndroid Build Coastguard Worker ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
3298*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode;
3299*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
3300*2d543d20SAndroid Build Coastguard Worker avtab_key_t newkey;
3301*2d543d20SAndroid Build Coastguard Worker int rc;
3302*2d543d20SAndroid Build Coastguard Worker
3303*2d543d20SAndroid Build Coastguard Worker newkey.target_class = k->target_class;
3304*2d543d20SAndroid Build Coastguard Worker newkey.specified = k->specified;
3305*2d543d20SAndroid Build Coastguard Worker
3306*2d543d20SAndroid Build Coastguard Worker if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
3307*2d543d20SAndroid Build Coastguard Worker /* Both are individual types, no expansion required. */
3308*2d543d20SAndroid Build Coastguard Worker return expand_avtab_insert(expa, k, d);
3309*2d543d20SAndroid Build Coastguard Worker }
3310*2d543d20SAndroid Build Coastguard Worker
3311*2d543d20SAndroid Build Coastguard Worker if (stype && stype->flavor != TYPE_ATTRIB) {
3312*2d543d20SAndroid Build Coastguard Worker /* Source is an individual type, target is an attribute. */
3313*2d543d20SAndroid Build Coastguard Worker newkey.source_type = k->source_type;
3314*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(tattr, tnode, j) {
3315*2d543d20SAndroid Build Coastguard Worker newkey.target_type = j + 1;
3316*2d543d20SAndroid Build Coastguard Worker rc = expand_avtab_insert(expa, &newkey, d);
3317*2d543d20SAndroid Build Coastguard Worker if (rc)
3318*2d543d20SAndroid Build Coastguard Worker return -1;
3319*2d543d20SAndroid Build Coastguard Worker }
3320*2d543d20SAndroid Build Coastguard Worker return 0;
3321*2d543d20SAndroid Build Coastguard Worker }
3322*2d543d20SAndroid Build Coastguard Worker
3323*2d543d20SAndroid Build Coastguard Worker if (ttype && ttype->flavor != TYPE_ATTRIB) {
3324*2d543d20SAndroid Build Coastguard Worker /* Target is an individual type, source is an attribute. */
3325*2d543d20SAndroid Build Coastguard Worker newkey.target_type = k->target_type;
3326*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(sattr, snode, i) {
3327*2d543d20SAndroid Build Coastguard Worker newkey.source_type = i + 1;
3328*2d543d20SAndroid Build Coastguard Worker rc = expand_avtab_insert(expa, &newkey, d);
3329*2d543d20SAndroid Build Coastguard Worker if (rc)
3330*2d543d20SAndroid Build Coastguard Worker return -1;
3331*2d543d20SAndroid Build Coastguard Worker }
3332*2d543d20SAndroid Build Coastguard Worker return 0;
3333*2d543d20SAndroid Build Coastguard Worker }
3334*2d543d20SAndroid Build Coastguard Worker
3335*2d543d20SAndroid Build Coastguard Worker /* Both source and target type are attributes. */
3336*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(sattr, snode, i) {
3337*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(tattr, tnode, j) {
3338*2d543d20SAndroid Build Coastguard Worker newkey.source_type = i + 1;
3339*2d543d20SAndroid Build Coastguard Worker newkey.target_type = j + 1;
3340*2d543d20SAndroid Build Coastguard Worker rc = expand_avtab_insert(expa, &newkey, d);
3341*2d543d20SAndroid Build Coastguard Worker if (rc)
3342*2d543d20SAndroid Build Coastguard Worker return -1;
3343*2d543d20SAndroid Build Coastguard Worker }
3344*2d543d20SAndroid Build Coastguard Worker }
3345*2d543d20SAndroid Build Coastguard Worker
3346*2d543d20SAndroid Build Coastguard Worker return 0;
3347*2d543d20SAndroid Build Coastguard Worker }
3348*2d543d20SAndroid Build Coastguard Worker
expand_avtab(policydb_t * p,avtab_t * a,avtab_t * expa)3349*2d543d20SAndroid Build Coastguard Worker int expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa)
3350*2d543d20SAndroid Build Coastguard Worker {
3351*2d543d20SAndroid Build Coastguard Worker struct expand_avtab_data data;
3352*2d543d20SAndroid Build Coastguard Worker
3353*2d543d20SAndroid Build Coastguard Worker if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
3354*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Out of memory!");
3355*2d543d20SAndroid Build Coastguard Worker return -1;
3356*2d543d20SAndroid Build Coastguard Worker }
3357*2d543d20SAndroid Build Coastguard Worker
3358*2d543d20SAndroid Build Coastguard Worker data.expa = expa;
3359*2d543d20SAndroid Build Coastguard Worker data.p = p;
3360*2d543d20SAndroid Build Coastguard Worker return avtab_map(a, expand_avtab_node, &data);
3361*2d543d20SAndroid Build Coastguard Worker }
3362*2d543d20SAndroid Build Coastguard Worker
expand_cond_insert(cond_av_list_t ** l,avtab_t * expa,avtab_key_t * k,avtab_datum_t * d)3363*2d543d20SAndroid Build Coastguard Worker static int expand_cond_insert(cond_av_list_t ** l,
3364*2d543d20SAndroid Build Coastguard Worker avtab_t * expa,
3365*2d543d20SAndroid Build Coastguard Worker avtab_key_t * k, avtab_datum_t * d)
3366*2d543d20SAndroid Build Coastguard Worker {
3367*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
3368*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *avd;
3369*2d543d20SAndroid Build Coastguard Worker cond_av_list_t *nl;
3370*2d543d20SAndroid Build Coastguard Worker
3371*2d543d20SAndroid Build Coastguard Worker node = avtab_search_node(expa, k);
3372*2d543d20SAndroid Build Coastguard Worker if (!node ||
3373*2d543d20SAndroid Build Coastguard Worker (k->specified & AVTAB_ENABLED) !=
3374*2d543d20SAndroid Build Coastguard Worker (node->key.specified & AVTAB_ENABLED)) {
3375*2d543d20SAndroid Build Coastguard Worker node = avtab_insert_nonunique(expa, k, d);
3376*2d543d20SAndroid Build Coastguard Worker if (!node) {
3377*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Out of memory!");
3378*2d543d20SAndroid Build Coastguard Worker return -1;
3379*2d543d20SAndroid Build Coastguard Worker }
3380*2d543d20SAndroid Build Coastguard Worker node->parse_context = (void *)1;
3381*2d543d20SAndroid Build Coastguard Worker nl = (cond_av_list_t *) malloc(sizeof(*nl));
3382*2d543d20SAndroid Build Coastguard Worker if (!nl) {
3383*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Out of memory!");
3384*2d543d20SAndroid Build Coastguard Worker return -1;
3385*2d543d20SAndroid Build Coastguard Worker }
3386*2d543d20SAndroid Build Coastguard Worker memset(nl, 0, sizeof(*nl));
3387*2d543d20SAndroid Build Coastguard Worker nl->node = node;
3388*2d543d20SAndroid Build Coastguard Worker nl->next = *l;
3389*2d543d20SAndroid Build Coastguard Worker *l = nl;
3390*2d543d20SAndroid Build Coastguard Worker return 0;
3391*2d543d20SAndroid Build Coastguard Worker }
3392*2d543d20SAndroid Build Coastguard Worker
3393*2d543d20SAndroid Build Coastguard Worker avd = &node->datum;
3394*2d543d20SAndroid Build Coastguard Worker switch (k->specified & ~AVTAB_ENABLED) {
3395*2d543d20SAndroid Build Coastguard Worker case AVTAB_ALLOWED:
3396*2d543d20SAndroid Build Coastguard Worker case AVTAB_AUDITALLOW:
3397*2d543d20SAndroid Build Coastguard Worker avd->data |= d->data;
3398*2d543d20SAndroid Build Coastguard Worker break;
3399*2d543d20SAndroid Build Coastguard Worker case AVTAB_AUDITDENY:
3400*2d543d20SAndroid Build Coastguard Worker avd->data &= d->data;
3401*2d543d20SAndroid Build Coastguard Worker break;
3402*2d543d20SAndroid Build Coastguard Worker default:
3403*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Type conflict!");
3404*2d543d20SAndroid Build Coastguard Worker return -1;
3405*2d543d20SAndroid Build Coastguard Worker }
3406*2d543d20SAndroid Build Coastguard Worker
3407*2d543d20SAndroid Build Coastguard Worker return 0;
3408*2d543d20SAndroid Build Coastguard Worker }
3409*2d543d20SAndroid Build Coastguard Worker
expand_cond_av_node(policydb_t * p,avtab_ptr_t node,cond_av_list_t ** newl,avtab_t * expa)3410*2d543d20SAndroid Build Coastguard Worker static int expand_cond_av_node(policydb_t * p,
3411*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node,
3412*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** newl, avtab_t * expa)
3413*2d543d20SAndroid Build Coastguard Worker {
3414*2d543d20SAndroid Build Coastguard Worker avtab_key_t *k = &node->key;
3415*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *d = &node->datum;
3416*2d543d20SAndroid Build Coastguard Worker type_datum_t *stype = p->type_val_to_struct[k->source_type - 1];
3417*2d543d20SAndroid Build Coastguard Worker type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1];
3418*2d543d20SAndroid Build Coastguard Worker ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1];
3419*2d543d20SAndroid Build Coastguard Worker ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1];
3420*2d543d20SAndroid Build Coastguard Worker ebitmap_node_t *snode, *tnode;
3421*2d543d20SAndroid Build Coastguard Worker unsigned int i, j;
3422*2d543d20SAndroid Build Coastguard Worker avtab_key_t newkey;
3423*2d543d20SAndroid Build Coastguard Worker int rc;
3424*2d543d20SAndroid Build Coastguard Worker
3425*2d543d20SAndroid Build Coastguard Worker newkey.target_class = k->target_class;
3426*2d543d20SAndroid Build Coastguard Worker newkey.specified = k->specified;
3427*2d543d20SAndroid Build Coastguard Worker
3428*2d543d20SAndroid Build Coastguard Worker if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
3429*2d543d20SAndroid Build Coastguard Worker /* Both are individual types, no expansion required. */
3430*2d543d20SAndroid Build Coastguard Worker return expand_cond_insert(newl, expa, k, d);
3431*2d543d20SAndroid Build Coastguard Worker }
3432*2d543d20SAndroid Build Coastguard Worker
3433*2d543d20SAndroid Build Coastguard Worker if (stype && stype->flavor != TYPE_ATTRIB) {
3434*2d543d20SAndroid Build Coastguard Worker /* Source is an individual type, target is an attribute. */
3435*2d543d20SAndroid Build Coastguard Worker newkey.source_type = k->source_type;
3436*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(tattr, tnode, j) {
3437*2d543d20SAndroid Build Coastguard Worker newkey.target_type = j + 1;
3438*2d543d20SAndroid Build Coastguard Worker rc = expand_cond_insert(newl, expa, &newkey, d);
3439*2d543d20SAndroid Build Coastguard Worker if (rc)
3440*2d543d20SAndroid Build Coastguard Worker return -1;
3441*2d543d20SAndroid Build Coastguard Worker }
3442*2d543d20SAndroid Build Coastguard Worker return 0;
3443*2d543d20SAndroid Build Coastguard Worker }
3444*2d543d20SAndroid Build Coastguard Worker
3445*2d543d20SAndroid Build Coastguard Worker if (ttype && ttype->flavor != TYPE_ATTRIB) {
3446*2d543d20SAndroid Build Coastguard Worker /* Target is an individual type, source is an attribute. */
3447*2d543d20SAndroid Build Coastguard Worker newkey.target_type = k->target_type;
3448*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(sattr, snode, i) {
3449*2d543d20SAndroid Build Coastguard Worker newkey.source_type = i + 1;
3450*2d543d20SAndroid Build Coastguard Worker rc = expand_cond_insert(newl, expa, &newkey, d);
3451*2d543d20SAndroid Build Coastguard Worker if (rc)
3452*2d543d20SAndroid Build Coastguard Worker return -1;
3453*2d543d20SAndroid Build Coastguard Worker }
3454*2d543d20SAndroid Build Coastguard Worker return 0;
3455*2d543d20SAndroid Build Coastguard Worker }
3456*2d543d20SAndroid Build Coastguard Worker
3457*2d543d20SAndroid Build Coastguard Worker /* Both source and target type are attributes. */
3458*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(sattr, snode, i) {
3459*2d543d20SAndroid Build Coastguard Worker ebitmap_for_each_positive_bit(tattr, tnode, j) {
3460*2d543d20SAndroid Build Coastguard Worker newkey.source_type = i + 1;
3461*2d543d20SAndroid Build Coastguard Worker newkey.target_type = j + 1;
3462*2d543d20SAndroid Build Coastguard Worker rc = expand_cond_insert(newl, expa, &newkey, d);
3463*2d543d20SAndroid Build Coastguard Worker if (rc)
3464*2d543d20SAndroid Build Coastguard Worker return -1;
3465*2d543d20SAndroid Build Coastguard Worker }
3466*2d543d20SAndroid Build Coastguard Worker }
3467*2d543d20SAndroid Build Coastguard Worker
3468*2d543d20SAndroid Build Coastguard Worker return 0;
3469*2d543d20SAndroid Build Coastguard Worker }
3470*2d543d20SAndroid Build Coastguard Worker
expand_cond_av_list(policydb_t * p,cond_av_list_t * l,cond_av_list_t ** newl,avtab_t * expa)3471*2d543d20SAndroid Build Coastguard Worker int expand_cond_av_list(policydb_t * p, cond_av_list_t * l,
3472*2d543d20SAndroid Build Coastguard Worker cond_av_list_t ** newl, avtab_t * expa)
3473*2d543d20SAndroid Build Coastguard Worker {
3474*2d543d20SAndroid Build Coastguard Worker cond_av_list_t *cur;
3475*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t node;
3476*2d543d20SAndroid Build Coastguard Worker int rc;
3477*2d543d20SAndroid Build Coastguard Worker
3478*2d543d20SAndroid Build Coastguard Worker if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
3479*2d543d20SAndroid Build Coastguard Worker ERR(NULL, "Out of memory!");
3480*2d543d20SAndroid Build Coastguard Worker return -1;
3481*2d543d20SAndroid Build Coastguard Worker }
3482*2d543d20SAndroid Build Coastguard Worker
3483*2d543d20SAndroid Build Coastguard Worker *newl = NULL;
3484*2d543d20SAndroid Build Coastguard Worker for (cur = l; cur; cur = cur->next) {
3485*2d543d20SAndroid Build Coastguard Worker node = cur->node;
3486*2d543d20SAndroid Build Coastguard Worker rc = expand_cond_av_node(p, node, newl, expa);
3487*2d543d20SAndroid Build Coastguard Worker if (rc)
3488*2d543d20SAndroid Build Coastguard Worker return rc;
3489*2d543d20SAndroid Build Coastguard Worker }
3490*2d543d20SAndroid Build Coastguard Worker
3491*2d543d20SAndroid Build Coastguard Worker return 0;
3492*2d543d20SAndroid Build Coastguard Worker }
3493