16cd6a6acSopenharmony_ci/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com> 26cd6a6acSopenharmony_ci * Jason Tang <jtang@tresys.com> 36cd6a6acSopenharmony_ci * Joshua Brindle <jbrindle@tresys.com> 46cd6a6acSopenharmony_ci * 56cd6a6acSopenharmony_ci * Copyright (C) 2004-2005 Tresys Technology, LLC 66cd6a6acSopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. 76cd6a6acSopenharmony_ci * Copyright (C) 2017 Mellanox Technologies, Inc. 86cd6a6acSopenharmony_ci * 96cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 106cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 116cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 126cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 136cd6a6acSopenharmony_ci * 146cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 156cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 166cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 176cd6a6acSopenharmony_ci * Lesser General Public License for more details. 186cd6a6acSopenharmony_ci * 196cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 206cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 216cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 226cd6a6acSopenharmony_ci */ 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci#include "context.h" 256cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 266cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h> 276cd6a6acSopenharmony_ci#include <sepol/policydb/hashtab.h> 286cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h> 296cd6a6acSopenharmony_ci#include <sepol/policydb/hierarchy.h> 306cd6a6acSopenharmony_ci#include <sepol/policydb/avrule_block.h> 316cd6a6acSopenharmony_ci 326cd6a6acSopenharmony_ci#include <stdlib.h> 336cd6a6acSopenharmony_ci#include <stdarg.h> 346cd6a6acSopenharmony_ci#include <stdio.h> 356cd6a6acSopenharmony_ci#include <string.h> 366cd6a6acSopenharmony_ci#include <assert.h> 376cd6a6acSopenharmony_ci#include <inttypes.h> 386cd6a6acSopenharmony_ci 396cd6a6acSopenharmony_ci#include "debug.h" 406cd6a6acSopenharmony_ci#include "private.h" 416cd6a6acSopenharmony_ci 426cd6a6acSopenharmony_citypedef struct expand_state { 436cd6a6acSopenharmony_ci int verbose; 446cd6a6acSopenharmony_ci uint32_t *typemap; 456cd6a6acSopenharmony_ci uint32_t *boolmap; 466cd6a6acSopenharmony_ci uint32_t *rolemap; 476cd6a6acSopenharmony_ci uint32_t *usermap; 486cd6a6acSopenharmony_ci policydb_t *base; 496cd6a6acSopenharmony_ci policydb_t *out; 506cd6a6acSopenharmony_ci sepol_handle_t *handle; 516cd6a6acSopenharmony_ci int expand_neverallow; 526cd6a6acSopenharmony_ci} expand_state_t; 536cd6a6acSopenharmony_ci 546cd6a6acSopenharmony_cistatic void expand_state_init(expand_state_t * state) 556cd6a6acSopenharmony_ci{ 566cd6a6acSopenharmony_ci memset(state, 0, sizeof(expand_state_t)); 576cd6a6acSopenharmony_ci} 586cd6a6acSopenharmony_ci 596cd6a6acSopenharmony_cistatic int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map) 606cd6a6acSopenharmony_ci{ 616cd6a6acSopenharmony_ci unsigned int i; 626cd6a6acSopenharmony_ci ebitmap_node_t *tnode; 636cd6a6acSopenharmony_ci ebitmap_init(dst); 646cd6a6acSopenharmony_ci 656cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(src, tnode, i) { 666cd6a6acSopenharmony_ci if (!map[i]) 676cd6a6acSopenharmony_ci continue; 686cd6a6acSopenharmony_ci if (ebitmap_set_bit(dst, map[i] - 1, 1)) 696cd6a6acSopenharmony_ci return -1; 706cd6a6acSopenharmony_ci } 716cd6a6acSopenharmony_ci return 0; 726cd6a6acSopenharmony_ci} 736cd6a6acSopenharmony_ci 746cd6a6acSopenharmony_cistatic int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles) 756cd6a6acSopenharmony_ci{ 766cd6a6acSopenharmony_ci ebitmap_node_t *node; 776cd6a6acSopenharmony_ci unsigned int bit; 786cd6a6acSopenharmony_ci role_datum_t *role; 796cd6a6acSopenharmony_ci ebitmap_t tmp; 806cd6a6acSopenharmony_ci 816cd6a6acSopenharmony_ci ebitmap_init(&tmp); 826cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(roles, node, bit) { 836cd6a6acSopenharmony_ci role = p->role_val_to_struct[bit]; 846cd6a6acSopenharmony_ci assert(role); 856cd6a6acSopenharmony_ci if (role->flavor != ROLE_ATTRIB) { 866cd6a6acSopenharmony_ci if (ebitmap_set_bit(&tmp, bit, 1)) { 876cd6a6acSopenharmony_ci ebitmap_destroy(&tmp); 886cd6a6acSopenharmony_ci return -1; 896cd6a6acSopenharmony_ci } 906cd6a6acSopenharmony_ci } else { 916cd6a6acSopenharmony_ci if (ebitmap_union(&tmp, &role->roles)) { 926cd6a6acSopenharmony_ci ebitmap_destroy(&tmp); 936cd6a6acSopenharmony_ci return -1; 946cd6a6acSopenharmony_ci } 956cd6a6acSopenharmony_ci } 966cd6a6acSopenharmony_ci } 976cd6a6acSopenharmony_ci ebitmap_destroy(roles); 986cd6a6acSopenharmony_ci if (ebitmap_cpy(roles, &tmp)) { 996cd6a6acSopenharmony_ci ebitmap_destroy(&tmp); 1006cd6a6acSopenharmony_ci return -1; 1016cd6a6acSopenharmony_ci } 1026cd6a6acSopenharmony_ci ebitmap_destroy(&tmp); 1036cd6a6acSopenharmony_ci return 0; 1046cd6a6acSopenharmony_ci} 1056cd6a6acSopenharmony_ci 1066cd6a6acSopenharmony_cistatic int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 1076cd6a6acSopenharmony_ci void *data) 1086cd6a6acSopenharmony_ci{ 1096cd6a6acSopenharmony_ci int ret; 1106cd6a6acSopenharmony_ci char *id, *new_id; 1116cd6a6acSopenharmony_ci type_datum_t *type, *new_type; 1126cd6a6acSopenharmony_ci expand_state_t *state; 1136cd6a6acSopenharmony_ci 1146cd6a6acSopenharmony_ci id = (char *)key; 1156cd6a6acSopenharmony_ci type = (type_datum_t *) datum; 1166cd6a6acSopenharmony_ci state = (expand_state_t *) data; 1176cd6a6acSopenharmony_ci 1186cd6a6acSopenharmony_ci if ((type->flavor == TYPE_TYPE && !type->primary) 1196cd6a6acSopenharmony_ci || type->flavor == TYPE_ALIAS) { 1206cd6a6acSopenharmony_ci /* aliases are handled later */ 1216cd6a6acSopenharmony_ci return 0; 1226cd6a6acSopenharmony_ci } 1236cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_TYPES)) { 1246cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 1256cd6a6acSopenharmony_ci return 0; 1266cd6a6acSopenharmony_ci } 1276cd6a6acSopenharmony_ci 1286cd6a6acSopenharmony_ci if (state->verbose) 1296cd6a6acSopenharmony_ci INFO(state->handle, "copying type or attribute %s", id); 1306cd6a6acSopenharmony_ci 1316cd6a6acSopenharmony_ci new_id = strdup(id); 1326cd6a6acSopenharmony_ci if (new_id == NULL) { 1336cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 1346cd6a6acSopenharmony_ci return -1; 1356cd6a6acSopenharmony_ci } 1366cd6a6acSopenharmony_ci 1376cd6a6acSopenharmony_ci new_type = (type_datum_t *) malloc(sizeof(type_datum_t)); 1386cd6a6acSopenharmony_ci if (!new_type) { 1396cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 1406cd6a6acSopenharmony_ci free(new_id); 1416cd6a6acSopenharmony_ci return SEPOL_ENOMEM; 1426cd6a6acSopenharmony_ci } 1436cd6a6acSopenharmony_ci memset(new_type, 0, sizeof(type_datum_t)); 1446cd6a6acSopenharmony_ci 1456cd6a6acSopenharmony_ci new_type->flavor = type->flavor; 1466cd6a6acSopenharmony_ci new_type->flags = type->flags; 1476cd6a6acSopenharmony_ci new_type->s.value = ++state->out->p_types.nprim; 1486cd6a6acSopenharmony_ci if (new_type->s.value > UINT16_MAX) { 1496cd6a6acSopenharmony_ci free(new_id); 1506cd6a6acSopenharmony_ci free(new_type); 1516cd6a6acSopenharmony_ci ERR(state->handle, "type space overflow"); 1526cd6a6acSopenharmony_ci return -1; 1536cd6a6acSopenharmony_ci } 1546cd6a6acSopenharmony_ci new_type->primary = 1; 1556cd6a6acSopenharmony_ci state->typemap[type->s.value - 1] = new_type->s.value; 1566cd6a6acSopenharmony_ci 1576cd6a6acSopenharmony_ci ret = hashtab_insert(state->out->p_types.table, 1586cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 1596cd6a6acSopenharmony_ci (hashtab_datum_t) new_type); 1606cd6a6acSopenharmony_ci if (ret) { 1616cd6a6acSopenharmony_ci free(new_id); 1626cd6a6acSopenharmony_ci free(new_type); 1636cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 1646cd6a6acSopenharmony_ci return -1; 1656cd6a6acSopenharmony_ci } 1666cd6a6acSopenharmony_ci 1676cd6a6acSopenharmony_ci if (new_type->flags & TYPE_FLAGS_PERMISSIVE) 1686cd6a6acSopenharmony_ci if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) { 1696cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 1706cd6a6acSopenharmony_ci return -1; 1716cd6a6acSopenharmony_ci } 1726cd6a6acSopenharmony_ci 1736cd6a6acSopenharmony_ci return 0; 1746cd6a6acSopenharmony_ci} 1756cd6a6acSopenharmony_ci 1766cd6a6acSopenharmony_cistatic int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum, 1776cd6a6acSopenharmony_ci void *data) 1786cd6a6acSopenharmony_ci{ 1796cd6a6acSopenharmony_ci char *id; 1806cd6a6acSopenharmony_ci type_datum_t *type, *new_type; 1816cd6a6acSopenharmony_ci expand_state_t *state; 1826cd6a6acSopenharmony_ci ebitmap_t tmp_union; 1836cd6a6acSopenharmony_ci 1846cd6a6acSopenharmony_ci id = (char *)key; 1856cd6a6acSopenharmony_ci type = (type_datum_t *) datum; 1866cd6a6acSopenharmony_ci state = (expand_state_t *) data; 1876cd6a6acSopenharmony_ci 1886cd6a6acSopenharmony_ci if (type->flavor != TYPE_ATTRIB) 1896cd6a6acSopenharmony_ci return 0; 1906cd6a6acSopenharmony_ci 1916cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_TYPES)) { 1926cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 1936cd6a6acSopenharmony_ci return 0; 1946cd6a6acSopenharmony_ci } 1956cd6a6acSopenharmony_ci 1966cd6a6acSopenharmony_ci if (state->verbose) 1976cd6a6acSopenharmony_ci INFO(state->handle, "converting attribute %s", id); 1986cd6a6acSopenharmony_ci 1996cd6a6acSopenharmony_ci new_type = hashtab_search(state->out->p_types.table, id); 2006cd6a6acSopenharmony_ci if (!new_type) { 2016cd6a6acSopenharmony_ci ERR(state->handle, "attribute %s vanished!", id); 2026cd6a6acSopenharmony_ci return -1; 2036cd6a6acSopenharmony_ci } 2046cd6a6acSopenharmony_ci if (map_ebitmap(&type->types, &tmp_union, state->typemap)) { 2056cd6a6acSopenharmony_ci ERR(state->handle, "out of memory"); 2066cd6a6acSopenharmony_ci return -1; 2076cd6a6acSopenharmony_ci } 2086cd6a6acSopenharmony_ci 2096cd6a6acSopenharmony_ci /* then union tmp_union onto &new_type->types */ 2106cd6a6acSopenharmony_ci if (ebitmap_union(&new_type->types, &tmp_union)) { 2116cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 2126cd6a6acSopenharmony_ci return -1; 2136cd6a6acSopenharmony_ci } 2146cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union); 2156cd6a6acSopenharmony_ci 2166cd6a6acSopenharmony_ci return 0; 2176cd6a6acSopenharmony_ci} 2186cd6a6acSopenharmony_ci 2196cd6a6acSopenharmony_cistatic int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 2206cd6a6acSopenharmony_ci void *data) 2216cd6a6acSopenharmony_ci{ 2226cd6a6acSopenharmony_ci int ret; 2236cd6a6acSopenharmony_ci char *id, *new_id; 2246cd6a6acSopenharmony_ci symtab_t *s; 2256cd6a6acSopenharmony_ci perm_datum_t *perm, *new_perm; 2266cd6a6acSopenharmony_ci 2276cd6a6acSopenharmony_ci id = key; 2286cd6a6acSopenharmony_ci perm = (perm_datum_t *) datum; 2296cd6a6acSopenharmony_ci s = (symtab_t *) data; 2306cd6a6acSopenharmony_ci 2316cd6a6acSopenharmony_ci new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t)); 2326cd6a6acSopenharmony_ci if (!new_perm) { 2336cd6a6acSopenharmony_ci return -1; 2346cd6a6acSopenharmony_ci } 2356cd6a6acSopenharmony_ci memset(new_perm, 0, sizeof(perm_datum_t)); 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_ci new_id = strdup(id); 2386cd6a6acSopenharmony_ci if (!new_id) { 2396cd6a6acSopenharmony_ci free(new_perm); 2406cd6a6acSopenharmony_ci return -1; 2416cd6a6acSopenharmony_ci } 2426cd6a6acSopenharmony_ci 2436cd6a6acSopenharmony_ci new_perm->s.value = perm->s.value; 2446cd6a6acSopenharmony_ci s->nprim++; 2456cd6a6acSopenharmony_ci 2466cd6a6acSopenharmony_ci ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm); 2476cd6a6acSopenharmony_ci if (ret) { 2486cd6a6acSopenharmony_ci free(new_id); 2496cd6a6acSopenharmony_ci free(new_perm); 2506cd6a6acSopenharmony_ci return -1; 2516cd6a6acSopenharmony_ci } 2526cd6a6acSopenharmony_ci 2536cd6a6acSopenharmony_ci return 0; 2546cd6a6acSopenharmony_ci} 2556cd6a6acSopenharmony_ci 2566cd6a6acSopenharmony_cistatic int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 2576cd6a6acSopenharmony_ci void *data) 2586cd6a6acSopenharmony_ci{ 2596cd6a6acSopenharmony_ci int ret; 2606cd6a6acSopenharmony_ci char *id, *new_id; 2616cd6a6acSopenharmony_ci common_datum_t *common, *new_common; 2626cd6a6acSopenharmony_ci expand_state_t *state; 2636cd6a6acSopenharmony_ci 2646cd6a6acSopenharmony_ci id = (char *)key; 2656cd6a6acSopenharmony_ci common = (common_datum_t *) datum; 2666cd6a6acSopenharmony_ci state = (expand_state_t *) data; 2676cd6a6acSopenharmony_ci 2686cd6a6acSopenharmony_ci if (state->verbose) 2696cd6a6acSopenharmony_ci INFO(state->handle, "copying common %s", id); 2706cd6a6acSopenharmony_ci 2716cd6a6acSopenharmony_ci new_common = (common_datum_t *) malloc(sizeof(common_datum_t)); 2726cd6a6acSopenharmony_ci if (!new_common) { 2736cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 2746cd6a6acSopenharmony_ci return -1; 2756cd6a6acSopenharmony_ci } 2766cd6a6acSopenharmony_ci memset(new_common, 0, sizeof(common_datum_t)); 2776cd6a6acSopenharmony_ci if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) { 2786cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 2796cd6a6acSopenharmony_ci free(new_common); 2806cd6a6acSopenharmony_ci return -1; 2816cd6a6acSopenharmony_ci } 2826cd6a6acSopenharmony_ci 2836cd6a6acSopenharmony_ci new_id = strdup(id); 2846cd6a6acSopenharmony_ci if (!new_id) { 2856cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 2866cd6a6acSopenharmony_ci /* free memory created by symtab_init first, then free new_common */ 2876cd6a6acSopenharmony_ci symtab_destroy(&new_common->permissions); 2886cd6a6acSopenharmony_ci free(new_common); 2896cd6a6acSopenharmony_ci return -1; 2906cd6a6acSopenharmony_ci } 2916cd6a6acSopenharmony_ci 2926cd6a6acSopenharmony_ci new_common->s.value = common->s.value; 2936cd6a6acSopenharmony_ci state->out->p_commons.nprim++; 2946cd6a6acSopenharmony_ci 2956cd6a6acSopenharmony_ci ret = 2966cd6a6acSopenharmony_ci hashtab_insert(state->out->p_commons.table, new_id, 2976cd6a6acSopenharmony_ci (hashtab_datum_t) new_common); 2986cd6a6acSopenharmony_ci if (ret) { 2996cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 3006cd6a6acSopenharmony_ci free(new_common); 3016cd6a6acSopenharmony_ci free(new_id); 3026cd6a6acSopenharmony_ci return -1; 3036cd6a6acSopenharmony_ci } 3046cd6a6acSopenharmony_ci 3056cd6a6acSopenharmony_ci if (hashtab_map 3066cd6a6acSopenharmony_ci (common->permissions.table, perm_copy_callback, 3076cd6a6acSopenharmony_ci &new_common->permissions)) { 3086cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 3096cd6a6acSopenharmony_ci return -1; 3106cd6a6acSopenharmony_ci } 3116cd6a6acSopenharmony_ci 3126cd6a6acSopenharmony_ci return 0; 3136cd6a6acSopenharmony_ci} 3146cd6a6acSopenharmony_ci 3156cd6a6acSopenharmony_cistatic int constraint_node_clone(constraint_node_t ** dst, 3166cd6a6acSopenharmony_ci constraint_node_t * src, 3176cd6a6acSopenharmony_ci expand_state_t * state) 3186cd6a6acSopenharmony_ci{ 3196cd6a6acSopenharmony_ci constraint_node_t *new_con = NULL, *last_new_con = NULL; 3206cd6a6acSopenharmony_ci constraint_expr_t *new_expr = NULL; 3216cd6a6acSopenharmony_ci *dst = NULL; 3226cd6a6acSopenharmony_ci while (src != NULL) { 3236cd6a6acSopenharmony_ci constraint_expr_t *expr, *expr_l = NULL; 3246cd6a6acSopenharmony_ci new_con = 3256cd6a6acSopenharmony_ci (constraint_node_t *) malloc(sizeof(constraint_node_t)); 3266cd6a6acSopenharmony_ci if (!new_con) { 3276cd6a6acSopenharmony_ci goto out_of_mem; 3286cd6a6acSopenharmony_ci } 3296cd6a6acSopenharmony_ci memset(new_con, 0, sizeof(constraint_node_t)); 3306cd6a6acSopenharmony_ci new_con->permissions = src->permissions; 3316cd6a6acSopenharmony_ci for (expr = src->expr; expr; expr = expr->next) { 3326cd6a6acSopenharmony_ci if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) { 3336cd6a6acSopenharmony_ci goto out_of_mem; 3346cd6a6acSopenharmony_ci } 3356cd6a6acSopenharmony_ci if (constraint_expr_init(new_expr) == -1) { 3366cd6a6acSopenharmony_ci goto out_of_mem; 3376cd6a6acSopenharmony_ci } 3386cd6a6acSopenharmony_ci new_expr->expr_type = expr->expr_type; 3396cd6a6acSopenharmony_ci new_expr->attr = expr->attr; 3406cd6a6acSopenharmony_ci new_expr->op = expr->op; 3416cd6a6acSopenharmony_ci if (new_expr->expr_type == CEXPR_NAMES) { 3426cd6a6acSopenharmony_ci if (new_expr->attr & CEXPR_TYPE) { 3436cd6a6acSopenharmony_ci /* 3446cd6a6acSopenharmony_ci * Copy over constraint policy source types and/or 3456cd6a6acSopenharmony_ci * attributes for sepol_compute_av_reason_buffer(3) 3466cd6a6acSopenharmony_ci * so that utilities can analyse constraint errors. 3476cd6a6acSopenharmony_ci */ 3486cd6a6acSopenharmony_ci if (map_ebitmap(&expr->type_names->types, 3496cd6a6acSopenharmony_ci &new_expr->type_names->types, 3506cd6a6acSopenharmony_ci state->typemap)) { 3516cd6a6acSopenharmony_ci ERR(NULL, "Failed to map type_names->types"); 3526cd6a6acSopenharmony_ci goto out_of_mem; 3536cd6a6acSopenharmony_ci } 3546cd6a6acSopenharmony_ci /* Type sets require expansion and conversion. */ 3556cd6a6acSopenharmony_ci if (expand_convert_type_set(state->out, 3566cd6a6acSopenharmony_ci state-> 3576cd6a6acSopenharmony_ci typemap, 3586cd6a6acSopenharmony_ci expr-> 3596cd6a6acSopenharmony_ci type_names, 3606cd6a6acSopenharmony_ci &new_expr-> 3616cd6a6acSopenharmony_ci names, 1)) { 3626cd6a6acSopenharmony_ci goto out_of_mem; 3636cd6a6acSopenharmony_ci } 3646cd6a6acSopenharmony_ci } else if (new_expr->attr & CEXPR_ROLE) { 3656cd6a6acSopenharmony_ci if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) { 3666cd6a6acSopenharmony_ci goto out_of_mem; 3676cd6a6acSopenharmony_ci } 3686cd6a6acSopenharmony_ci if (ebitmap_expand_roles(state->out, &new_expr->names)) { 3696cd6a6acSopenharmony_ci goto out_of_mem; 3706cd6a6acSopenharmony_ci } 3716cd6a6acSopenharmony_ci } else if (new_expr->attr & CEXPR_USER) { 3726cd6a6acSopenharmony_ci if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) { 3736cd6a6acSopenharmony_ci goto out_of_mem; 3746cd6a6acSopenharmony_ci } 3756cd6a6acSopenharmony_ci } else { 3766cd6a6acSopenharmony_ci /* Other kinds of sets do not. */ 3776cd6a6acSopenharmony_ci if (ebitmap_cpy(&new_expr->names, 3786cd6a6acSopenharmony_ci &expr->names)) { 3796cd6a6acSopenharmony_ci goto out_of_mem; 3806cd6a6acSopenharmony_ci } 3816cd6a6acSopenharmony_ci } 3826cd6a6acSopenharmony_ci } 3836cd6a6acSopenharmony_ci if (expr_l) { 3846cd6a6acSopenharmony_ci expr_l->next = new_expr; 3856cd6a6acSopenharmony_ci } else { 3866cd6a6acSopenharmony_ci new_con->expr = new_expr; 3876cd6a6acSopenharmony_ci } 3886cd6a6acSopenharmony_ci expr_l = new_expr; 3896cd6a6acSopenharmony_ci new_expr = NULL; 3906cd6a6acSopenharmony_ci } 3916cd6a6acSopenharmony_ci if (last_new_con == NULL) { 3926cd6a6acSopenharmony_ci *dst = new_con; 3936cd6a6acSopenharmony_ci } else { 3946cd6a6acSopenharmony_ci last_new_con->next = new_con; 3956cd6a6acSopenharmony_ci } 3966cd6a6acSopenharmony_ci last_new_con = new_con; 3976cd6a6acSopenharmony_ci src = src->next; 3986cd6a6acSopenharmony_ci } 3996cd6a6acSopenharmony_ci 4006cd6a6acSopenharmony_ci return 0; 4016cd6a6acSopenharmony_ci out_of_mem: 4026cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 4036cd6a6acSopenharmony_ci if (new_con) 4046cd6a6acSopenharmony_ci free(new_con); 4056cd6a6acSopenharmony_ci constraint_expr_destroy(new_expr); 4066cd6a6acSopenharmony_ci return -1; 4076cd6a6acSopenharmony_ci} 4086cd6a6acSopenharmony_ci 4096cd6a6acSopenharmony_cistatic int class_copy_default_new_object(expand_state_t *state, 4106cd6a6acSopenharmony_ci class_datum_t *olddatum, 4116cd6a6acSopenharmony_ci class_datum_t *newdatum) 4126cd6a6acSopenharmony_ci{ 4136cd6a6acSopenharmony_ci if (olddatum->default_user) { 4146cd6a6acSopenharmony_ci if (newdatum->default_user && olddatum->default_user != newdatum->default_user) { 4156cd6a6acSopenharmony_ci ERR(state->handle, "Found conflicting default user definitions"); 4166cd6a6acSopenharmony_ci return SEPOL_ENOTSUP; 4176cd6a6acSopenharmony_ci } 4186cd6a6acSopenharmony_ci newdatum->default_user = olddatum->default_user; 4196cd6a6acSopenharmony_ci 4206cd6a6acSopenharmony_ci } 4216cd6a6acSopenharmony_ci if (olddatum->default_role) { 4226cd6a6acSopenharmony_ci if (newdatum->default_role && olddatum->default_role != newdatum->default_role) { 4236cd6a6acSopenharmony_ci ERR(state->handle, "Found conflicting default role definitions"); 4246cd6a6acSopenharmony_ci return SEPOL_ENOTSUP; 4256cd6a6acSopenharmony_ci } 4266cd6a6acSopenharmony_ci newdatum->default_role = olddatum->default_role; 4276cd6a6acSopenharmony_ci } 4286cd6a6acSopenharmony_ci if (olddatum->default_type) { 4296cd6a6acSopenharmony_ci if (newdatum->default_type && olddatum->default_type != newdatum->default_type) { 4306cd6a6acSopenharmony_ci ERR(state->handle, "Found conflicting default type definitions"); 4316cd6a6acSopenharmony_ci return SEPOL_ENOTSUP; 4326cd6a6acSopenharmony_ci } 4336cd6a6acSopenharmony_ci newdatum->default_type = olddatum->default_type; 4346cd6a6acSopenharmony_ci } 4356cd6a6acSopenharmony_ci if (olddatum->default_range) { 4366cd6a6acSopenharmony_ci if (newdatum->default_range && olddatum->default_range != newdatum->default_range) { 4376cd6a6acSopenharmony_ci ERR(state->handle, "Found conflicting default range definitions"); 4386cd6a6acSopenharmony_ci return SEPOL_ENOTSUP; 4396cd6a6acSopenharmony_ci } 4406cd6a6acSopenharmony_ci newdatum->default_range = olddatum->default_range; 4416cd6a6acSopenharmony_ci } 4426cd6a6acSopenharmony_ci return 0; 4436cd6a6acSopenharmony_ci} 4446cd6a6acSopenharmony_ci 4456cd6a6acSopenharmony_cistatic int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 4466cd6a6acSopenharmony_ci void *data) 4476cd6a6acSopenharmony_ci{ 4486cd6a6acSopenharmony_ci int ret; 4496cd6a6acSopenharmony_ci char *id, *new_id; 4506cd6a6acSopenharmony_ci class_datum_t *class, *new_class; 4516cd6a6acSopenharmony_ci expand_state_t *state; 4526cd6a6acSopenharmony_ci 4536cd6a6acSopenharmony_ci id = (char *)key; 4546cd6a6acSopenharmony_ci class = (class_datum_t *) datum; 4556cd6a6acSopenharmony_ci state = (expand_state_t *) data; 4566cd6a6acSopenharmony_ci 4576cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_CLASSES)) { 4586cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 4596cd6a6acSopenharmony_ci return 0; 4606cd6a6acSopenharmony_ci } 4616cd6a6acSopenharmony_ci 4626cd6a6acSopenharmony_ci if (state->verbose) 4636cd6a6acSopenharmony_ci INFO(state->handle, "copying class %s", id); 4646cd6a6acSopenharmony_ci 4656cd6a6acSopenharmony_ci new_class = (class_datum_t *) malloc(sizeof(class_datum_t)); 4666cd6a6acSopenharmony_ci if (!new_class) { 4676cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 4686cd6a6acSopenharmony_ci return -1; 4696cd6a6acSopenharmony_ci } 4706cd6a6acSopenharmony_ci memset(new_class, 0, sizeof(class_datum_t)); 4716cd6a6acSopenharmony_ci if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) { 4726cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 4736cd6a6acSopenharmony_ci free(new_class); 4746cd6a6acSopenharmony_ci return -1; 4756cd6a6acSopenharmony_ci } 4766cd6a6acSopenharmony_ci 4776cd6a6acSopenharmony_ci new_class->s.value = class->s.value; 4786cd6a6acSopenharmony_ci state->out->p_classes.nprim++; 4796cd6a6acSopenharmony_ci 4806cd6a6acSopenharmony_ci ret = class_copy_default_new_object(state, class, new_class); 4816cd6a6acSopenharmony_ci if (ret) { 4826cd6a6acSopenharmony_ci free(new_class); 4836cd6a6acSopenharmony_ci return ret; 4846cd6a6acSopenharmony_ci } 4856cd6a6acSopenharmony_ci 4866cd6a6acSopenharmony_ci new_id = strdup(id); 4876cd6a6acSopenharmony_ci if (!new_id) { 4886cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 4896cd6a6acSopenharmony_ci free(new_class); 4906cd6a6acSopenharmony_ci return -1; 4916cd6a6acSopenharmony_ci } 4926cd6a6acSopenharmony_ci 4936cd6a6acSopenharmony_ci ret = 4946cd6a6acSopenharmony_ci hashtab_insert(state->out->p_classes.table, new_id, 4956cd6a6acSopenharmony_ci (hashtab_datum_t) new_class); 4966cd6a6acSopenharmony_ci if (ret) { 4976cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 4986cd6a6acSopenharmony_ci free(new_class); 4996cd6a6acSopenharmony_ci free(new_id); 5006cd6a6acSopenharmony_ci return -1; 5016cd6a6acSopenharmony_ci } 5026cd6a6acSopenharmony_ci 5036cd6a6acSopenharmony_ci if (hashtab_map 5046cd6a6acSopenharmony_ci (class->permissions.table, perm_copy_callback, 5056cd6a6acSopenharmony_ci &new_class->permissions)) { 5066cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 5076cd6a6acSopenharmony_ci return -1; 5086cd6a6acSopenharmony_ci } 5096cd6a6acSopenharmony_ci 5106cd6a6acSopenharmony_ci if (class->comkey) { 5116cd6a6acSopenharmony_ci new_class->comkey = strdup(class->comkey); 5126cd6a6acSopenharmony_ci if (!new_class->comkey) { 5136cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 5146cd6a6acSopenharmony_ci return -1; 5156cd6a6acSopenharmony_ci } 5166cd6a6acSopenharmony_ci 5176cd6a6acSopenharmony_ci new_class->comdatum = 5186cd6a6acSopenharmony_ci hashtab_search(state->out->p_commons.table, 5196cd6a6acSopenharmony_ci new_class->comkey); 5206cd6a6acSopenharmony_ci if (!new_class->comdatum) { 5216cd6a6acSopenharmony_ci ERR(state->handle, "could not find common datum %s", 5226cd6a6acSopenharmony_ci new_class->comkey); 5236cd6a6acSopenharmony_ci return -1; 5246cd6a6acSopenharmony_ci } 5256cd6a6acSopenharmony_ci new_class->permissions.nprim += 5266cd6a6acSopenharmony_ci new_class->comdatum->permissions.nprim; 5276cd6a6acSopenharmony_ci } 5286cd6a6acSopenharmony_ci 5296cd6a6acSopenharmony_ci return 0; 5306cd6a6acSopenharmony_ci} 5316cd6a6acSopenharmony_ci 5326cd6a6acSopenharmony_cistatic int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 5336cd6a6acSopenharmony_ci void *data) 5346cd6a6acSopenharmony_ci{ 5356cd6a6acSopenharmony_ci char *id; 5366cd6a6acSopenharmony_ci class_datum_t *class, *new_class; 5376cd6a6acSopenharmony_ci expand_state_t *state; 5386cd6a6acSopenharmony_ci 5396cd6a6acSopenharmony_ci id = (char *)key; 5406cd6a6acSopenharmony_ci class = (class_datum_t *) datum; 5416cd6a6acSopenharmony_ci state = (expand_state_t *) data; 5426cd6a6acSopenharmony_ci 5436cd6a6acSopenharmony_ci new_class = hashtab_search(state->out->p_classes.table, id); 5446cd6a6acSopenharmony_ci if (!new_class) { 5456cd6a6acSopenharmony_ci ERR(state->handle, "class %s vanished", id); 5466cd6a6acSopenharmony_ci return -1; 5476cd6a6acSopenharmony_ci } 5486cd6a6acSopenharmony_ci 5496cd6a6acSopenharmony_ci /* constraints */ 5506cd6a6acSopenharmony_ci if (constraint_node_clone 5516cd6a6acSopenharmony_ci (&new_class->constraints, class->constraints, state) == -1 5526cd6a6acSopenharmony_ci || constraint_node_clone(&new_class->validatetrans, 5536cd6a6acSopenharmony_ci class->validatetrans, state) == -1) { 5546cd6a6acSopenharmony_ci return -1; 5556cd6a6acSopenharmony_ci } 5566cd6a6acSopenharmony_ci return 0; 5576cd6a6acSopenharmony_ci} 5586cd6a6acSopenharmony_ci 5596cd6a6acSopenharmony_ci/* 5606cd6a6acSopenharmony_ci * The boundaries have to be copied after the types/roles/users are copied, 5616cd6a6acSopenharmony_ci * because it refers hashtab to lookup destinated objects. 5626cd6a6acSopenharmony_ci */ 5636cd6a6acSopenharmony_cistatic int type_bounds_copy_callback(hashtab_key_t key, 5646cd6a6acSopenharmony_ci hashtab_datum_t datum, void *data) 5656cd6a6acSopenharmony_ci{ 5666cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 5676cd6a6acSopenharmony_ci type_datum_t *type = (type_datum_t *) datum; 5686cd6a6acSopenharmony_ci type_datum_t *dest; 5696cd6a6acSopenharmony_ci uint32_t bounds_val; 5706cd6a6acSopenharmony_ci 5716cd6a6acSopenharmony_ci if (!type->bounds) 5726cd6a6acSopenharmony_ci return 0; 5736cd6a6acSopenharmony_ci 5746cd6a6acSopenharmony_ci if (!is_id_enabled((char *)key, state->base, SYM_TYPES)) 5756cd6a6acSopenharmony_ci return 0; 5766cd6a6acSopenharmony_ci 5776cd6a6acSopenharmony_ci bounds_val = state->typemap[type->bounds - 1]; 5786cd6a6acSopenharmony_ci 5796cd6a6acSopenharmony_ci dest = hashtab_search(state->out->p_types.table, (char *)key); 5806cd6a6acSopenharmony_ci if (!dest) { 5816cd6a6acSopenharmony_ci ERR(state->handle, "Type lookup failed for %s", (char *)key); 5826cd6a6acSopenharmony_ci return -1; 5836cd6a6acSopenharmony_ci } 5846cd6a6acSopenharmony_ci if (dest->bounds != 0 && dest->bounds != bounds_val) { 5856cd6a6acSopenharmony_ci ERR(state->handle, "Inconsistent boundary for %s", (char *)key); 5866cd6a6acSopenharmony_ci return -1; 5876cd6a6acSopenharmony_ci } 5886cd6a6acSopenharmony_ci dest->bounds = bounds_val; 5896cd6a6acSopenharmony_ci 5906cd6a6acSopenharmony_ci return 0; 5916cd6a6acSopenharmony_ci} 5926cd6a6acSopenharmony_ci 5936cd6a6acSopenharmony_cistatic int role_bounds_copy_callback(hashtab_key_t key, 5946cd6a6acSopenharmony_ci hashtab_datum_t datum, void *data) 5956cd6a6acSopenharmony_ci{ 5966cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 5976cd6a6acSopenharmony_ci role_datum_t *role = (role_datum_t *) datum; 5986cd6a6acSopenharmony_ci role_datum_t *dest; 5996cd6a6acSopenharmony_ci uint32_t bounds_val; 6006cd6a6acSopenharmony_ci 6016cd6a6acSopenharmony_ci if (!role->bounds) 6026cd6a6acSopenharmony_ci return 0; 6036cd6a6acSopenharmony_ci 6046cd6a6acSopenharmony_ci if (!is_id_enabled((char *)key, state->base, SYM_ROLES)) 6056cd6a6acSopenharmony_ci return 0; 6066cd6a6acSopenharmony_ci 6076cd6a6acSopenharmony_ci bounds_val = state->rolemap[role->bounds - 1]; 6086cd6a6acSopenharmony_ci 6096cd6a6acSopenharmony_ci dest = hashtab_search(state->out->p_roles.table, (char *)key); 6106cd6a6acSopenharmony_ci if (!dest) { 6116cd6a6acSopenharmony_ci ERR(state->handle, "Role lookup failed for %s", (char *)key); 6126cd6a6acSopenharmony_ci return -1; 6136cd6a6acSopenharmony_ci } 6146cd6a6acSopenharmony_ci if (dest->bounds != 0 && dest->bounds != bounds_val) { 6156cd6a6acSopenharmony_ci ERR(state->handle, "Inconsistent boundary for %s", (char *)key); 6166cd6a6acSopenharmony_ci return -1; 6176cd6a6acSopenharmony_ci } 6186cd6a6acSopenharmony_ci dest->bounds = bounds_val; 6196cd6a6acSopenharmony_ci 6206cd6a6acSopenharmony_ci return 0; 6216cd6a6acSopenharmony_ci} 6226cd6a6acSopenharmony_ci 6236cd6a6acSopenharmony_cistatic int user_bounds_copy_callback(hashtab_key_t key, 6246cd6a6acSopenharmony_ci hashtab_datum_t datum, void *data) 6256cd6a6acSopenharmony_ci{ 6266cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 6276cd6a6acSopenharmony_ci user_datum_t *user = (user_datum_t *) datum; 6286cd6a6acSopenharmony_ci user_datum_t *dest; 6296cd6a6acSopenharmony_ci uint32_t bounds_val; 6306cd6a6acSopenharmony_ci 6316cd6a6acSopenharmony_ci if (!user->bounds) 6326cd6a6acSopenharmony_ci return 0; 6336cd6a6acSopenharmony_ci 6346cd6a6acSopenharmony_ci if (!is_id_enabled((char *)key, state->base, SYM_USERS)) 6356cd6a6acSopenharmony_ci return 0; 6366cd6a6acSopenharmony_ci 6376cd6a6acSopenharmony_ci bounds_val = state->usermap[user->bounds - 1]; 6386cd6a6acSopenharmony_ci 6396cd6a6acSopenharmony_ci dest = hashtab_search(state->out->p_users.table, (char *)key); 6406cd6a6acSopenharmony_ci if (!dest) { 6416cd6a6acSopenharmony_ci ERR(state->handle, "User lookup failed for %s", (char *)key); 6426cd6a6acSopenharmony_ci return -1; 6436cd6a6acSopenharmony_ci } 6446cd6a6acSopenharmony_ci if (dest->bounds != 0 && dest->bounds != bounds_val) { 6456cd6a6acSopenharmony_ci ERR(state->handle, "Inconsistent boundary for %s", (char *)key); 6466cd6a6acSopenharmony_ci return -1; 6476cd6a6acSopenharmony_ci } 6486cd6a6acSopenharmony_ci dest->bounds = bounds_val; 6496cd6a6acSopenharmony_ci 6506cd6a6acSopenharmony_ci return 0; 6516cd6a6acSopenharmony_ci} 6526cd6a6acSopenharmony_ci 6536cd6a6acSopenharmony_ci/* The aliases have to be copied after the types and attributes to be certain that 6546cd6a6acSopenharmony_ci * the out symbol table will have the type that the alias refers. Otherwise, we 6556cd6a6acSopenharmony_ci * won't be able to find the type value for the alias. We can't depend on the 6566cd6a6acSopenharmony_ci * declaration ordering because of the hash table. 6576cd6a6acSopenharmony_ci */ 6586cd6a6acSopenharmony_cistatic int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 6596cd6a6acSopenharmony_ci void *data) 6606cd6a6acSopenharmony_ci{ 6616cd6a6acSopenharmony_ci int ret; 6626cd6a6acSopenharmony_ci char *id, *new_id; 6636cd6a6acSopenharmony_ci type_datum_t *alias, *new_alias; 6646cd6a6acSopenharmony_ci expand_state_t *state; 6656cd6a6acSopenharmony_ci uint32_t prival; 6666cd6a6acSopenharmony_ci 6676cd6a6acSopenharmony_ci id = (char *)key; 6686cd6a6acSopenharmony_ci alias = (type_datum_t *) datum; 6696cd6a6acSopenharmony_ci state = (expand_state_t *) data; 6706cd6a6acSopenharmony_ci 6716cd6a6acSopenharmony_ci /* ignore regular types */ 6726cd6a6acSopenharmony_ci if (alias->flavor == TYPE_TYPE && alias->primary) 6736cd6a6acSopenharmony_ci return 0; 6746cd6a6acSopenharmony_ci 6756cd6a6acSopenharmony_ci /* ignore attributes */ 6766cd6a6acSopenharmony_ci if (alias->flavor == TYPE_ATTRIB) 6776cd6a6acSopenharmony_ci return 0; 6786cd6a6acSopenharmony_ci 6796cd6a6acSopenharmony_ci if (alias->flavor == TYPE_ALIAS) 6806cd6a6acSopenharmony_ci prival = alias->primary; 6816cd6a6acSopenharmony_ci else 6826cd6a6acSopenharmony_ci prival = alias->s.value; 6836cd6a6acSopenharmony_ci 6846cd6a6acSopenharmony_ci if (!is_id_enabled(state->base->p_type_val_to_name[prival - 1], 6856cd6a6acSopenharmony_ci state->base, SYM_TYPES)) { 6866cd6a6acSopenharmony_ci /* The primary type for this alias is not enabled, the alias 6876cd6a6acSopenharmony_ci * shouldn't be either */ 6886cd6a6acSopenharmony_ci return 0; 6896cd6a6acSopenharmony_ci } 6906cd6a6acSopenharmony_ci 6916cd6a6acSopenharmony_ci if (state->verbose) 6926cd6a6acSopenharmony_ci INFO(state->handle, "copying alias %s", id); 6936cd6a6acSopenharmony_ci 6946cd6a6acSopenharmony_ci new_id = strdup(id); 6956cd6a6acSopenharmony_ci if (!new_id) { 6966cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 6976cd6a6acSopenharmony_ci return -1; 6986cd6a6acSopenharmony_ci } 6996cd6a6acSopenharmony_ci 7006cd6a6acSopenharmony_ci new_alias = (type_datum_t *) malloc(sizeof(type_datum_t)); 7016cd6a6acSopenharmony_ci if (!new_alias) { 7026cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 7036cd6a6acSopenharmony_ci free(new_id); 7046cd6a6acSopenharmony_ci return SEPOL_ENOMEM; 7056cd6a6acSopenharmony_ci } 7066cd6a6acSopenharmony_ci memset(new_alias, 0, sizeof(type_datum_t)); 7076cd6a6acSopenharmony_ci if (alias->flavor == TYPE_TYPE) 7086cd6a6acSopenharmony_ci new_alias->s.value = state->typemap[alias->s.value - 1]; 7096cd6a6acSopenharmony_ci else if (alias->flavor == TYPE_ALIAS) 7106cd6a6acSopenharmony_ci new_alias->s.value = state->typemap[alias->primary - 1]; 7116cd6a6acSopenharmony_ci else 7126cd6a6acSopenharmony_ci assert(0); /* unreachable */ 7136cd6a6acSopenharmony_ci 7146cd6a6acSopenharmony_ci new_alias->flags = alias->flags; 7156cd6a6acSopenharmony_ci 7166cd6a6acSopenharmony_ci ret = hashtab_insert(state->out->p_types.table, 7176cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 7186cd6a6acSopenharmony_ci (hashtab_datum_t) new_alias); 7196cd6a6acSopenharmony_ci 7206cd6a6acSopenharmony_ci if (ret) { 7216cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 7226cd6a6acSopenharmony_ci free(new_alias); 7236cd6a6acSopenharmony_ci free(new_id); 7246cd6a6acSopenharmony_ci return -1; 7256cd6a6acSopenharmony_ci } 7266cd6a6acSopenharmony_ci 7276cd6a6acSopenharmony_ci state->typemap[alias->s.value - 1] = new_alias->s.value; 7286cd6a6acSopenharmony_ci 7296cd6a6acSopenharmony_ci if (new_alias->flags & TYPE_FLAGS_PERMISSIVE) 7306cd6a6acSopenharmony_ci if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) { 7316cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 7326cd6a6acSopenharmony_ci return -1; 7336cd6a6acSopenharmony_ci } 7346cd6a6acSopenharmony_ci 7356cd6a6acSopenharmony_ci return 0; 7366cd6a6acSopenharmony_ci} 7376cd6a6acSopenharmony_ci 7386cd6a6acSopenharmony_cistatic int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data) 7396cd6a6acSopenharmony_ci{ 7406cd6a6acSopenharmony_ci ebitmap_t mapped_roles; 7416cd6a6acSopenharmony_ci role_datum_t *role = (role_datum_t *) datum; 7426cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 7436cd6a6acSopenharmony_ci 7446cd6a6acSopenharmony_ci if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap)) 7456cd6a6acSopenharmony_ci return -1; 7466cd6a6acSopenharmony_ci 7476cd6a6acSopenharmony_ci ebitmap_destroy(&role->dominates); 7486cd6a6acSopenharmony_ci 7496cd6a6acSopenharmony_ci if (ebitmap_cpy(&role->dominates, &mapped_roles)) 7506cd6a6acSopenharmony_ci return -1; 7516cd6a6acSopenharmony_ci 7526cd6a6acSopenharmony_ci ebitmap_destroy(&mapped_roles); 7536cd6a6acSopenharmony_ci 7546cd6a6acSopenharmony_ci return 0; 7556cd6a6acSopenharmony_ci} 7566cd6a6acSopenharmony_ci 7576cd6a6acSopenharmony_ci/* For the role attribute in the base module, escalate its counterpart's 7586cd6a6acSopenharmony_ci * types.types ebitmap in the out module to the counterparts of all the 7596cd6a6acSopenharmony_ci * regular role that belongs to the current role attribute. Note, must be 7606cd6a6acSopenharmony_ci * invoked after role_copy_callback so that state->rolemap is available. 7616cd6a6acSopenharmony_ci */ 7626cd6a6acSopenharmony_cistatic int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, 7636cd6a6acSopenharmony_ci void *data) 7646cd6a6acSopenharmony_ci{ 7656cd6a6acSopenharmony_ci char *id, *base_reg_role_id; 7666cd6a6acSopenharmony_ci role_datum_t *role, *new_role, *regular_role; 7676cd6a6acSopenharmony_ci expand_state_t *state; 7686cd6a6acSopenharmony_ci ebitmap_node_t *rnode; 7696cd6a6acSopenharmony_ci unsigned int i; 7706cd6a6acSopenharmony_ci ebitmap_t mapped_roles; 7716cd6a6acSopenharmony_ci 7726cd6a6acSopenharmony_ci id = key; 7736cd6a6acSopenharmony_ci role = (role_datum_t *)datum; 7746cd6a6acSopenharmony_ci state = (expand_state_t *)data; 7756cd6a6acSopenharmony_ci 7766cd6a6acSopenharmony_ci if (strcmp(id, OBJECT_R) == 0) { 7776cd6a6acSopenharmony_ci /* object_r is never a role attribute by far */ 7786cd6a6acSopenharmony_ci return 0; 7796cd6a6acSopenharmony_ci } 7806cd6a6acSopenharmony_ci 7816cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_ROLES)) { 7826cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 7836cd6a6acSopenharmony_ci return 0; 7846cd6a6acSopenharmony_ci } 7856cd6a6acSopenharmony_ci 7866cd6a6acSopenharmony_ci if (role->flavor != ROLE_ATTRIB) 7876cd6a6acSopenharmony_ci return 0; 7886cd6a6acSopenharmony_ci 7896cd6a6acSopenharmony_ci if (state->verbose) 7906cd6a6acSopenharmony_ci INFO(state->handle, "fixing role attribute %s", id); 7916cd6a6acSopenharmony_ci 7926cd6a6acSopenharmony_ci new_role = 7936cd6a6acSopenharmony_ci (role_datum_t *)hashtab_search(state->out->p_roles.table, id); 7946cd6a6acSopenharmony_ci 7956cd6a6acSopenharmony_ci assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB); 7966cd6a6acSopenharmony_ci 7976cd6a6acSopenharmony_ci ebitmap_init(&mapped_roles); 7986cd6a6acSopenharmony_ci if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap)) 7996cd6a6acSopenharmony_ci return -1; 8006cd6a6acSopenharmony_ci if (ebitmap_union(&new_role->roles, &mapped_roles)) { 8016cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 8026cd6a6acSopenharmony_ci ebitmap_destroy(&mapped_roles); 8036cd6a6acSopenharmony_ci return -1; 8046cd6a6acSopenharmony_ci } 8056cd6a6acSopenharmony_ci ebitmap_destroy(&mapped_roles); 8066cd6a6acSopenharmony_ci 8076cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&role->roles, rnode, i) { 8086cd6a6acSopenharmony_ci /* take advantage of sym_val_to_name[] 8096cd6a6acSopenharmony_ci * of the base module */ 8106cd6a6acSopenharmony_ci base_reg_role_id = state->base->p_role_val_to_name[i]; 8116cd6a6acSopenharmony_ci regular_role = (role_datum_t *)hashtab_search( 8126cd6a6acSopenharmony_ci state->out->p_roles.table, 8136cd6a6acSopenharmony_ci base_reg_role_id); 8146cd6a6acSopenharmony_ci assert(regular_role != NULL && 8156cd6a6acSopenharmony_ci regular_role->flavor == ROLE_ROLE); 8166cd6a6acSopenharmony_ci 8176cd6a6acSopenharmony_ci if (ebitmap_union(®ular_role->types.types, 8186cd6a6acSopenharmony_ci &new_role->types.types)) { 8196cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 8206cd6a6acSopenharmony_ci return -1; 8216cd6a6acSopenharmony_ci } 8226cd6a6acSopenharmony_ci } 8236cd6a6acSopenharmony_ci 8246cd6a6acSopenharmony_ci return 0; 8256cd6a6acSopenharmony_ci} 8266cd6a6acSopenharmony_ci 8276cd6a6acSopenharmony_cistatic int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 8286cd6a6acSopenharmony_ci void *data) 8296cd6a6acSopenharmony_ci{ 8306cd6a6acSopenharmony_ci int ret; 8316cd6a6acSopenharmony_ci char *id, *new_id; 8326cd6a6acSopenharmony_ci role_datum_t *role; 8336cd6a6acSopenharmony_ci role_datum_t *new_role; 8346cd6a6acSopenharmony_ci expand_state_t *state; 8356cd6a6acSopenharmony_ci ebitmap_t tmp_union_types; 8366cd6a6acSopenharmony_ci 8376cd6a6acSopenharmony_ci id = key; 8386cd6a6acSopenharmony_ci role = (role_datum_t *) datum; 8396cd6a6acSopenharmony_ci state = (expand_state_t *) data; 8406cd6a6acSopenharmony_ci 8416cd6a6acSopenharmony_ci if (strcmp(id, OBJECT_R) == 0) { 8426cd6a6acSopenharmony_ci /* object_r is always value 1 */ 8436cd6a6acSopenharmony_ci state->rolemap[role->s.value - 1] = 1; 8446cd6a6acSopenharmony_ci return 0; 8456cd6a6acSopenharmony_ci } 8466cd6a6acSopenharmony_ci 8476cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_ROLES)) { 8486cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 8496cd6a6acSopenharmony_ci return 0; 8506cd6a6acSopenharmony_ci } 8516cd6a6acSopenharmony_ci 8526cd6a6acSopenharmony_ci if (state->verbose) 8536cd6a6acSopenharmony_ci INFO(state->handle, "copying role %s", id); 8546cd6a6acSopenharmony_ci 8556cd6a6acSopenharmony_ci new_role = 8566cd6a6acSopenharmony_ci (role_datum_t *) hashtab_search(state->out->p_roles.table, id); 8576cd6a6acSopenharmony_ci if (!new_role) { 8586cd6a6acSopenharmony_ci new_role = (role_datum_t *) malloc(sizeof(role_datum_t)); 8596cd6a6acSopenharmony_ci if (!new_role) { 8606cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 8616cd6a6acSopenharmony_ci return -1; 8626cd6a6acSopenharmony_ci } 8636cd6a6acSopenharmony_ci memset(new_role, 0, sizeof(role_datum_t)); 8646cd6a6acSopenharmony_ci 8656cd6a6acSopenharmony_ci new_id = strdup(id); 8666cd6a6acSopenharmony_ci if (!new_id) { 8676cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 8686cd6a6acSopenharmony_ci free(new_role); 8696cd6a6acSopenharmony_ci return -1; 8706cd6a6acSopenharmony_ci } 8716cd6a6acSopenharmony_ci 8726cd6a6acSopenharmony_ci state->out->p_roles.nprim++; 8736cd6a6acSopenharmony_ci new_role->flavor = role->flavor; 8746cd6a6acSopenharmony_ci new_role->s.value = state->out->p_roles.nprim; 8756cd6a6acSopenharmony_ci state->rolemap[role->s.value - 1] = new_role->s.value; 8766cd6a6acSopenharmony_ci ret = hashtab_insert(state->out->p_roles.table, 8776cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 8786cd6a6acSopenharmony_ci (hashtab_datum_t) new_role); 8796cd6a6acSopenharmony_ci 8806cd6a6acSopenharmony_ci if (ret) { 8816cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 8826cd6a6acSopenharmony_ci free(new_role); 8836cd6a6acSopenharmony_ci free(new_id); 8846cd6a6acSopenharmony_ci return -1; 8856cd6a6acSopenharmony_ci } 8866cd6a6acSopenharmony_ci } 8876cd6a6acSopenharmony_ci 8886cd6a6acSopenharmony_ci /* The dominates bitmap is going to be wrong for the moment, 8896cd6a6acSopenharmony_ci * we'll come back later and remap them, after we are sure all 8906cd6a6acSopenharmony_ci * the roles have been added */ 8916cd6a6acSopenharmony_ci if (ebitmap_union(&new_role->dominates, &role->dominates)) { 8926cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 8936cd6a6acSopenharmony_ci return -1; 8946cd6a6acSopenharmony_ci } 8956cd6a6acSopenharmony_ci 8966cd6a6acSopenharmony_ci ebitmap_init(&tmp_union_types); 8976cd6a6acSopenharmony_ci 8986cd6a6acSopenharmony_ci /* convert types in the role datum in the global symtab */ 8996cd6a6acSopenharmony_ci if (expand_convert_type_set 9006cd6a6acSopenharmony_ci (state->out, state->typemap, &role->types, &tmp_union_types, 1)) { 9016cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union_types); 9026cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 9036cd6a6acSopenharmony_ci return -1; 9046cd6a6acSopenharmony_ci } 9056cd6a6acSopenharmony_ci 9066cd6a6acSopenharmony_ci if (ebitmap_union(&new_role->types.types, &tmp_union_types)) { 9076cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 9086cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union_types); 9096cd6a6acSopenharmony_ci return -1; 9106cd6a6acSopenharmony_ci } 9116cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union_types); 9126cd6a6acSopenharmony_ci 9136cd6a6acSopenharmony_ci return 0; 9146cd6a6acSopenharmony_ci} 9156cd6a6acSopenharmony_ci 9166cd6a6acSopenharmony_ciint mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, 9176cd6a6acSopenharmony_ci policydb_t * p, sepol_handle_t * h) 9186cd6a6acSopenharmony_ci{ 9196cd6a6acSopenharmony_ci mls_semantic_cat_t *cat; 9206cd6a6acSopenharmony_ci level_datum_t *levdatum; 9216cd6a6acSopenharmony_ci unsigned int i; 9226cd6a6acSopenharmony_ci 9236cd6a6acSopenharmony_ci mls_level_init(l); 9246cd6a6acSopenharmony_ci 9256cd6a6acSopenharmony_ci if (!p->mls) 9266cd6a6acSopenharmony_ci return 0; 9276cd6a6acSopenharmony_ci 9286cd6a6acSopenharmony_ci /* Required not declared. */ 9296cd6a6acSopenharmony_ci if (!sl->sens) 9306cd6a6acSopenharmony_ci return 0; 9316cd6a6acSopenharmony_ci 9326cd6a6acSopenharmony_ci /* Invalid sensitivity */ 9336cd6a6acSopenharmony_ci if (sl->sens > p->p_levels.nprim || !p->p_sens_val_to_name[sl->sens - 1]) 9346cd6a6acSopenharmony_ci return -1; 9356cd6a6acSopenharmony_ci 9366cd6a6acSopenharmony_ci l->sens = sl->sens; 9376cd6a6acSopenharmony_ci levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, 9386cd6a6acSopenharmony_ci p->p_sens_val_to_name[l->sens - 1]); 9396cd6a6acSopenharmony_ci if (!levdatum) { 9406cd6a6acSopenharmony_ci ERR(h, "%s: Impossible situation found, nothing in p_levels.table.", 9416cd6a6acSopenharmony_ci __func__); 9426cd6a6acSopenharmony_ci errno = ENOENT; 9436cd6a6acSopenharmony_ci return -1; 9446cd6a6acSopenharmony_ci } 9456cd6a6acSopenharmony_ci for (cat = sl->cat; cat; cat = cat->next) { 9466cd6a6acSopenharmony_ci if (cat->low > cat->high) { 9476cd6a6acSopenharmony_ci ERR(h, "Category range is not valid %s.%s", 9486cd6a6acSopenharmony_ci p->p_cat_val_to_name[cat->low - 1], 9496cd6a6acSopenharmony_ci p->p_cat_val_to_name[cat->high - 1]); 9506cd6a6acSopenharmony_ci return -1; 9516cd6a6acSopenharmony_ci } 9526cd6a6acSopenharmony_ci for (i = cat->low - 1; i < cat->high; i++) { 9536cd6a6acSopenharmony_ci if (!ebitmap_get_bit(&levdatum->level->cat, i)) { 9546cd6a6acSopenharmony_ci ERR(h, "Category %s can not be associated with " 9556cd6a6acSopenharmony_ci "level %s", 9566cd6a6acSopenharmony_ci p->p_cat_val_to_name[i], 9576cd6a6acSopenharmony_ci p->p_sens_val_to_name[l->sens - 1]); 9586cd6a6acSopenharmony_ci return -1; 9596cd6a6acSopenharmony_ci } 9606cd6a6acSopenharmony_ci if (ebitmap_set_bit(&l->cat, i, 1)) { 9616cd6a6acSopenharmony_ci ERR(h, "Out of memory!"); 9626cd6a6acSopenharmony_ci return -1; 9636cd6a6acSopenharmony_ci } 9646cd6a6acSopenharmony_ci } 9656cd6a6acSopenharmony_ci } 9666cd6a6acSopenharmony_ci 9676cd6a6acSopenharmony_ci return 0; 9686cd6a6acSopenharmony_ci} 9696cd6a6acSopenharmony_ci 9706cd6a6acSopenharmony_ciint mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r, 9716cd6a6acSopenharmony_ci policydb_t * p, sepol_handle_t * h) 9726cd6a6acSopenharmony_ci{ 9736cd6a6acSopenharmony_ci if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0) 9746cd6a6acSopenharmony_ci return -1; 9756cd6a6acSopenharmony_ci 9766cd6a6acSopenharmony_ci if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) { 9776cd6a6acSopenharmony_ci mls_level_destroy(&r->level[0]); 9786cd6a6acSopenharmony_ci return -1; 9796cd6a6acSopenharmony_ci } 9806cd6a6acSopenharmony_ci 9816cd6a6acSopenharmony_ci if (!mls_level_dom(&r->level[1], &r->level[0])) { 9826cd6a6acSopenharmony_ci mls_range_destroy(r); 9836cd6a6acSopenharmony_ci ERR(h, "MLS range high level does not dominate low level"); 9846cd6a6acSopenharmony_ci return -1; 9856cd6a6acSopenharmony_ci } 9866cd6a6acSopenharmony_ci 9876cd6a6acSopenharmony_ci return 0; 9886cd6a6acSopenharmony_ci} 9896cd6a6acSopenharmony_ci 9906cd6a6acSopenharmony_cistatic int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 9916cd6a6acSopenharmony_ci void *data) 9926cd6a6acSopenharmony_ci{ 9936cd6a6acSopenharmony_ci int ret; 9946cd6a6acSopenharmony_ci expand_state_t *state; 9956cd6a6acSopenharmony_ci user_datum_t *user; 9966cd6a6acSopenharmony_ci user_datum_t *new_user; 9976cd6a6acSopenharmony_ci char *id, *new_id; 9986cd6a6acSopenharmony_ci ebitmap_t tmp_union; 9996cd6a6acSopenharmony_ci 10006cd6a6acSopenharmony_ci id = key; 10016cd6a6acSopenharmony_ci user = (user_datum_t *) datum; 10026cd6a6acSopenharmony_ci state = (expand_state_t *) data; 10036cd6a6acSopenharmony_ci 10046cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_USERS)) { 10056cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 10066cd6a6acSopenharmony_ci return 0; 10076cd6a6acSopenharmony_ci } 10086cd6a6acSopenharmony_ci 10096cd6a6acSopenharmony_ci if (state->verbose) 10106cd6a6acSopenharmony_ci INFO(state->handle, "copying user %s", id); 10116cd6a6acSopenharmony_ci 10126cd6a6acSopenharmony_ci new_user = 10136cd6a6acSopenharmony_ci (user_datum_t *) hashtab_search(state->out->p_users.table, id); 10146cd6a6acSopenharmony_ci if (!new_user) { 10156cd6a6acSopenharmony_ci new_user = (user_datum_t *) malloc(sizeof(user_datum_t)); 10166cd6a6acSopenharmony_ci if (!new_user) { 10176cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 10186cd6a6acSopenharmony_ci return -1; 10196cd6a6acSopenharmony_ci } 10206cd6a6acSopenharmony_ci memset(new_user, 0, sizeof(user_datum_t)); 10216cd6a6acSopenharmony_ci 10226cd6a6acSopenharmony_ci state->out->p_users.nprim++; 10236cd6a6acSopenharmony_ci new_user->s.value = state->out->p_users.nprim; 10246cd6a6acSopenharmony_ci state->usermap[user->s.value - 1] = new_user->s.value; 10256cd6a6acSopenharmony_ci 10266cd6a6acSopenharmony_ci new_id = strdup(id); 10276cd6a6acSopenharmony_ci if (!new_id) { 10286cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 10296cd6a6acSopenharmony_ci free(new_user); 10306cd6a6acSopenharmony_ci return -1; 10316cd6a6acSopenharmony_ci } 10326cd6a6acSopenharmony_ci ret = hashtab_insert(state->out->p_users.table, 10336cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 10346cd6a6acSopenharmony_ci (hashtab_datum_t) new_user); 10356cd6a6acSopenharmony_ci if (ret) { 10366cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 10376cd6a6acSopenharmony_ci user_datum_destroy(new_user); 10386cd6a6acSopenharmony_ci free(new_user); 10396cd6a6acSopenharmony_ci free(new_id); 10406cd6a6acSopenharmony_ci return -1; 10416cd6a6acSopenharmony_ci } 10426cd6a6acSopenharmony_ci 10436cd6a6acSopenharmony_ci /* expand the semantic MLS info */ 10446cd6a6acSopenharmony_ci if (mls_semantic_range_expand(&user->range, 10456cd6a6acSopenharmony_ci &new_user->exp_range, 10466cd6a6acSopenharmony_ci state->out, state->handle)) { 10476cd6a6acSopenharmony_ci return -1; 10486cd6a6acSopenharmony_ci } 10496cd6a6acSopenharmony_ci if (mls_semantic_level_expand(&user->dfltlevel, 10506cd6a6acSopenharmony_ci &new_user->exp_dfltlevel, 10516cd6a6acSopenharmony_ci state->out, state->handle)) { 10526cd6a6acSopenharmony_ci return -1; 10536cd6a6acSopenharmony_ci } 10546cd6a6acSopenharmony_ci if (!mls_level_between(&new_user->exp_dfltlevel, 10556cd6a6acSopenharmony_ci &new_user->exp_range.level[0], 10566cd6a6acSopenharmony_ci &new_user->exp_range.level[1])) { 10576cd6a6acSopenharmony_ci ERR(state->handle, "default level not within user " 10586cd6a6acSopenharmony_ci "range"); 10596cd6a6acSopenharmony_ci return -1; 10606cd6a6acSopenharmony_ci } 10616cd6a6acSopenharmony_ci } else { 10626cd6a6acSopenharmony_ci /* require that the MLS info match */ 10636cd6a6acSopenharmony_ci mls_range_t tmp_range; 10646cd6a6acSopenharmony_ci mls_level_t tmp_level; 10656cd6a6acSopenharmony_ci 10666cd6a6acSopenharmony_ci if (mls_semantic_range_expand(&user->range, &tmp_range, 10676cd6a6acSopenharmony_ci state->out, state->handle)) { 10686cd6a6acSopenharmony_ci return -1; 10696cd6a6acSopenharmony_ci } 10706cd6a6acSopenharmony_ci if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level, 10716cd6a6acSopenharmony_ci state->out, state->handle)) { 10726cd6a6acSopenharmony_ci mls_range_destroy(&tmp_range); 10736cd6a6acSopenharmony_ci return -1; 10746cd6a6acSopenharmony_ci } 10756cd6a6acSopenharmony_ci if (!mls_range_eq(&new_user->exp_range, &tmp_range) || 10766cd6a6acSopenharmony_ci !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) { 10776cd6a6acSopenharmony_ci mls_range_destroy(&tmp_range); 10786cd6a6acSopenharmony_ci mls_level_destroy(&tmp_level); 10796cd6a6acSopenharmony_ci return -1; 10806cd6a6acSopenharmony_ci } 10816cd6a6acSopenharmony_ci mls_range_destroy(&tmp_range); 10826cd6a6acSopenharmony_ci mls_level_destroy(&tmp_level); 10836cd6a6acSopenharmony_ci } 10846cd6a6acSopenharmony_ci 10856cd6a6acSopenharmony_ci ebitmap_init(&tmp_union); 10866cd6a6acSopenharmony_ci 10876cd6a6acSopenharmony_ci /* get global roles for this user */ 10886cd6a6acSopenharmony_ci if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) { 10896cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 10906cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union); 10916cd6a6acSopenharmony_ci return -1; 10926cd6a6acSopenharmony_ci } 10936cd6a6acSopenharmony_ci 10946cd6a6acSopenharmony_ci if (ebitmap_union(&new_user->roles.roles, &tmp_union)) { 10956cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 10966cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union); 10976cd6a6acSopenharmony_ci return -1; 10986cd6a6acSopenharmony_ci } 10996cd6a6acSopenharmony_ci ebitmap_destroy(&tmp_union); 11006cd6a6acSopenharmony_ci 11016cd6a6acSopenharmony_ci return 0; 11026cd6a6acSopenharmony_ci} 11036cd6a6acSopenharmony_ci 11046cd6a6acSopenharmony_cistatic int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 11056cd6a6acSopenharmony_ci void *data) 11066cd6a6acSopenharmony_ci{ 11076cd6a6acSopenharmony_ci int ret; 11086cd6a6acSopenharmony_ci expand_state_t *state; 11096cd6a6acSopenharmony_ci cond_bool_datum_t *bool, *new_bool; 11106cd6a6acSopenharmony_ci char *id, *new_id; 11116cd6a6acSopenharmony_ci 11126cd6a6acSopenharmony_ci id = key; 11136cd6a6acSopenharmony_ci bool = (cond_bool_datum_t *) datum; 11146cd6a6acSopenharmony_ci state = (expand_state_t *) data; 11156cd6a6acSopenharmony_ci 11166cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_BOOLS)) { 11176cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 11186cd6a6acSopenharmony_ci return 0; 11196cd6a6acSopenharmony_ci } 11206cd6a6acSopenharmony_ci 11216cd6a6acSopenharmony_ci if (bool->flags & COND_BOOL_FLAGS_TUNABLE) { 11226cd6a6acSopenharmony_ci /* Skip tunables */ 11236cd6a6acSopenharmony_ci return 0; 11246cd6a6acSopenharmony_ci } 11256cd6a6acSopenharmony_ci 11266cd6a6acSopenharmony_ci if (state->verbose) 11276cd6a6acSopenharmony_ci INFO(state->handle, "copying boolean %s", id); 11286cd6a6acSopenharmony_ci 11296cd6a6acSopenharmony_ci new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t)); 11306cd6a6acSopenharmony_ci if (!new_bool) { 11316cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 11326cd6a6acSopenharmony_ci return -1; 11336cd6a6acSopenharmony_ci } 11346cd6a6acSopenharmony_ci 11356cd6a6acSopenharmony_ci new_id = strdup(id); 11366cd6a6acSopenharmony_ci if (!new_id) { 11376cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 11386cd6a6acSopenharmony_ci free(new_bool); 11396cd6a6acSopenharmony_ci return -1; 11406cd6a6acSopenharmony_ci } 11416cd6a6acSopenharmony_ci 11426cd6a6acSopenharmony_ci state->out->p_bools.nprim++; 11436cd6a6acSopenharmony_ci new_bool->s.value = state->out->p_bools.nprim; 11446cd6a6acSopenharmony_ci 11456cd6a6acSopenharmony_ci ret = hashtab_insert(state->out->p_bools.table, 11466cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 11476cd6a6acSopenharmony_ci (hashtab_datum_t) new_bool); 11486cd6a6acSopenharmony_ci if (ret) { 11496cd6a6acSopenharmony_ci ERR(state->handle, "hashtab overflow"); 11506cd6a6acSopenharmony_ci free(new_bool); 11516cd6a6acSopenharmony_ci free(new_id); 11526cd6a6acSopenharmony_ci return -1; 11536cd6a6acSopenharmony_ci } 11546cd6a6acSopenharmony_ci 11556cd6a6acSopenharmony_ci state->boolmap[bool->s.value - 1] = new_bool->s.value; 11566cd6a6acSopenharmony_ci 11576cd6a6acSopenharmony_ci new_bool->state = bool->state; 11586cd6a6acSopenharmony_ci new_bool->flags = bool->flags; 11596cd6a6acSopenharmony_ci 11606cd6a6acSopenharmony_ci return 0; 11616cd6a6acSopenharmony_ci} 11626cd6a6acSopenharmony_ci 11636cd6a6acSopenharmony_cistatic int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 11646cd6a6acSopenharmony_ci void *data) 11656cd6a6acSopenharmony_ci{ 11666cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 11676cd6a6acSopenharmony_ci level_datum_t *level = (level_datum_t *) datum, *new_level = NULL; 11686cd6a6acSopenharmony_ci char *id = (char *)key, *new_id = NULL; 11696cd6a6acSopenharmony_ci 11706cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_LEVELS)) { 11716cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 11726cd6a6acSopenharmony_ci return 0; 11736cd6a6acSopenharmony_ci } 11746cd6a6acSopenharmony_ci 11756cd6a6acSopenharmony_ci if (state->verbose) 11766cd6a6acSopenharmony_ci INFO(state->handle, "copying sensitivity level %s", id); 11776cd6a6acSopenharmony_ci 11786cd6a6acSopenharmony_ci new_level = (level_datum_t *) malloc(sizeof(level_datum_t)); 11796cd6a6acSopenharmony_ci if (!new_level) 11806cd6a6acSopenharmony_ci goto out_of_mem; 11816cd6a6acSopenharmony_ci level_datum_init(new_level); 11826cd6a6acSopenharmony_ci new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t)); 11836cd6a6acSopenharmony_ci if (!new_level->level) 11846cd6a6acSopenharmony_ci goto out_of_mem; 11856cd6a6acSopenharmony_ci mls_level_init(new_level->level); 11866cd6a6acSopenharmony_ci new_id = strdup(id); 11876cd6a6acSopenharmony_ci if (!new_id) 11886cd6a6acSopenharmony_ci goto out_of_mem; 11896cd6a6acSopenharmony_ci 11906cd6a6acSopenharmony_ci if (mls_level_cpy(new_level->level, level->level)) { 11916cd6a6acSopenharmony_ci goto out_of_mem; 11926cd6a6acSopenharmony_ci } 11936cd6a6acSopenharmony_ci new_level->isalias = level->isalias; 11946cd6a6acSopenharmony_ci state->out->p_levels.nprim++; 11956cd6a6acSopenharmony_ci 11966cd6a6acSopenharmony_ci if (hashtab_insert(state->out->p_levels.table, 11976cd6a6acSopenharmony_ci (hashtab_key_t) new_id, 11986cd6a6acSopenharmony_ci (hashtab_datum_t) new_level)) { 11996cd6a6acSopenharmony_ci goto out_of_mem; 12006cd6a6acSopenharmony_ci } 12016cd6a6acSopenharmony_ci return 0; 12026cd6a6acSopenharmony_ci 12036cd6a6acSopenharmony_ci out_of_mem: 12046cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 12056cd6a6acSopenharmony_ci if (new_level != NULL && new_level->level != NULL) { 12066cd6a6acSopenharmony_ci mls_level_destroy(new_level->level); 12076cd6a6acSopenharmony_ci free(new_level->level); 12086cd6a6acSopenharmony_ci } 12096cd6a6acSopenharmony_ci level_datum_destroy(new_level); 12106cd6a6acSopenharmony_ci free(new_level); 12116cd6a6acSopenharmony_ci free(new_id); 12126cd6a6acSopenharmony_ci return -1; 12136cd6a6acSopenharmony_ci} 12146cd6a6acSopenharmony_ci 12156cd6a6acSopenharmony_cistatic int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum, 12166cd6a6acSopenharmony_ci void *data) 12176cd6a6acSopenharmony_ci{ 12186cd6a6acSopenharmony_ci expand_state_t *state = (expand_state_t *) data; 12196cd6a6acSopenharmony_ci cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL; 12206cd6a6acSopenharmony_ci char *id = (char *)key, *new_id = NULL; 12216cd6a6acSopenharmony_ci 12226cd6a6acSopenharmony_ci if (!is_id_enabled(id, state->base, SYM_CATS)) { 12236cd6a6acSopenharmony_ci /* identifier's scope is not enabled */ 12246cd6a6acSopenharmony_ci return 0; 12256cd6a6acSopenharmony_ci } 12266cd6a6acSopenharmony_ci 12276cd6a6acSopenharmony_ci if (state->verbose) 12286cd6a6acSopenharmony_ci INFO(state->handle, "copying category attribute %s", id); 12296cd6a6acSopenharmony_ci 12306cd6a6acSopenharmony_ci new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t)); 12316cd6a6acSopenharmony_ci if (!new_cat) 12326cd6a6acSopenharmony_ci goto out_of_mem; 12336cd6a6acSopenharmony_ci cat_datum_init(new_cat); 12346cd6a6acSopenharmony_ci new_id = strdup(id); 12356cd6a6acSopenharmony_ci if (!new_id) 12366cd6a6acSopenharmony_ci goto out_of_mem; 12376cd6a6acSopenharmony_ci 12386cd6a6acSopenharmony_ci new_cat->s.value = cat->s.value; 12396cd6a6acSopenharmony_ci new_cat->isalias = cat->isalias; 12406cd6a6acSopenharmony_ci state->out->p_cats.nprim++; 12416cd6a6acSopenharmony_ci if (hashtab_insert(state->out->p_cats.table, 12426cd6a6acSopenharmony_ci (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) { 12436cd6a6acSopenharmony_ci goto out_of_mem; 12446cd6a6acSopenharmony_ci } 12456cd6a6acSopenharmony_ci 12466cd6a6acSopenharmony_ci return 0; 12476cd6a6acSopenharmony_ci 12486cd6a6acSopenharmony_ci out_of_mem: 12496cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 12506cd6a6acSopenharmony_ci cat_datum_destroy(new_cat); 12516cd6a6acSopenharmony_ci free(new_cat); 12526cd6a6acSopenharmony_ci free(new_id); 12536cd6a6acSopenharmony_ci return -1; 12546cd6a6acSopenharmony_ci} 12556cd6a6acSopenharmony_ci 12566cd6a6acSopenharmony_cistatic int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules) 12576cd6a6acSopenharmony_ci{ 12586cd6a6acSopenharmony_ci unsigned int i, j; 12596cd6a6acSopenharmony_ci role_allow_t *cur_allow, *n, *l; 12606cd6a6acSopenharmony_ci role_allow_rule_t *cur; 12616cd6a6acSopenharmony_ci ebitmap_t roles, new_roles; 12626cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 12636cd6a6acSopenharmony_ci 12646cd6a6acSopenharmony_ci /* start at the end of the list */ 12656cd6a6acSopenharmony_ci for (l = state->out->role_allow; l && l->next; l = l->next) ; 12666cd6a6acSopenharmony_ci 12676cd6a6acSopenharmony_ci cur = rules; 12686cd6a6acSopenharmony_ci while (cur) { 12696cd6a6acSopenharmony_ci ebitmap_init(&roles); 12706cd6a6acSopenharmony_ci ebitmap_init(&new_roles); 12716cd6a6acSopenharmony_ci 12726cd6a6acSopenharmony_ci if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { 12736cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 12746cd6a6acSopenharmony_ci return -1; 12756cd6a6acSopenharmony_ci } 12766cd6a6acSopenharmony_ci 12776cd6a6acSopenharmony_ci if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) { 12786cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 12796cd6a6acSopenharmony_ci return -1; 12806cd6a6acSopenharmony_ci } 12816cd6a6acSopenharmony_ci 12826cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&roles, snode, i) { 12836cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&new_roles, tnode, j) { 12846cd6a6acSopenharmony_ci /* check for duplicates */ 12856cd6a6acSopenharmony_ci cur_allow = state->out->role_allow; 12866cd6a6acSopenharmony_ci while (cur_allow) { 12876cd6a6acSopenharmony_ci if ((cur_allow->role == i + 1) && 12886cd6a6acSopenharmony_ci (cur_allow->new_role == j + 1)) 12896cd6a6acSopenharmony_ci break; 12906cd6a6acSopenharmony_ci cur_allow = cur_allow->next; 12916cd6a6acSopenharmony_ci } 12926cd6a6acSopenharmony_ci if (cur_allow) 12936cd6a6acSopenharmony_ci continue; 12946cd6a6acSopenharmony_ci n = (role_allow_t *) 12956cd6a6acSopenharmony_ci malloc(sizeof(role_allow_t)); 12966cd6a6acSopenharmony_ci if (!n) { 12976cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 12986cd6a6acSopenharmony_ci return -1; 12996cd6a6acSopenharmony_ci } 13006cd6a6acSopenharmony_ci memset(n, 0, sizeof(role_allow_t)); 13016cd6a6acSopenharmony_ci n->role = i + 1; 13026cd6a6acSopenharmony_ci n->new_role = j + 1; 13036cd6a6acSopenharmony_ci if (l) { 13046cd6a6acSopenharmony_ci l->next = n; 13056cd6a6acSopenharmony_ci } else { 13066cd6a6acSopenharmony_ci state->out->role_allow = n; 13076cd6a6acSopenharmony_ci } 13086cd6a6acSopenharmony_ci l = n; 13096cd6a6acSopenharmony_ci } 13106cd6a6acSopenharmony_ci } 13116cd6a6acSopenharmony_ci 13126cd6a6acSopenharmony_ci ebitmap_destroy(&roles); 13136cd6a6acSopenharmony_ci ebitmap_destroy(&new_roles); 13146cd6a6acSopenharmony_ci 13156cd6a6acSopenharmony_ci cur = cur->next; 13166cd6a6acSopenharmony_ci } 13176cd6a6acSopenharmony_ci 13186cd6a6acSopenharmony_ci return 0; 13196cd6a6acSopenharmony_ci} 13206cd6a6acSopenharmony_ci 13216cd6a6acSopenharmony_cistatic int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules) 13226cd6a6acSopenharmony_ci{ 13236cd6a6acSopenharmony_ci unsigned int i, j, k; 13246cd6a6acSopenharmony_ci role_trans_t *n, *l, *cur_trans; 13256cd6a6acSopenharmony_ci role_trans_rule_t *cur; 13266cd6a6acSopenharmony_ci ebitmap_t roles, types; 13276cd6a6acSopenharmony_ci ebitmap_node_t *rnode, *tnode, *cnode; 13286cd6a6acSopenharmony_ci 13296cd6a6acSopenharmony_ci /* start at the end of the list */ 13306cd6a6acSopenharmony_ci for (l = state->out->role_tr; l && l->next; l = l->next) ; 13316cd6a6acSopenharmony_ci 13326cd6a6acSopenharmony_ci cur = rules; 13336cd6a6acSopenharmony_ci while (cur) { 13346cd6a6acSopenharmony_ci ebitmap_init(&roles); 13356cd6a6acSopenharmony_ci ebitmap_init(&types); 13366cd6a6acSopenharmony_ci 13376cd6a6acSopenharmony_ci if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { 13386cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 13396cd6a6acSopenharmony_ci return -1; 13406cd6a6acSopenharmony_ci } 13416cd6a6acSopenharmony_ci if (expand_convert_type_set 13426cd6a6acSopenharmony_ci (state->out, state->typemap, &cur->types, &types, 1)) { 13436cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 13446cd6a6acSopenharmony_ci return -1; 13456cd6a6acSopenharmony_ci } 13466cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&roles, rnode, i) { 13476cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&types, tnode, j) { 13486cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&cur->classes, cnode, k) { 13496cd6a6acSopenharmony_ci cur_trans = state->out->role_tr; 13506cd6a6acSopenharmony_ci while (cur_trans) { 13516cd6a6acSopenharmony_ci unsigned int mapped_role; 13526cd6a6acSopenharmony_ci 13536cd6a6acSopenharmony_ci mapped_role = state->rolemap[cur->new_role - 1]; 13546cd6a6acSopenharmony_ci 13556cd6a6acSopenharmony_ci if ((cur_trans->role == 13566cd6a6acSopenharmony_ci i + 1) && 13576cd6a6acSopenharmony_ci (cur_trans->type == 13586cd6a6acSopenharmony_ci j + 1) && 13596cd6a6acSopenharmony_ci (cur_trans->tclass == 13606cd6a6acSopenharmony_ci k + 1)) { 13616cd6a6acSopenharmony_ci if (cur_trans->new_role == mapped_role) { 13626cd6a6acSopenharmony_ci break; 13636cd6a6acSopenharmony_ci } else { 13646cd6a6acSopenharmony_ci ERR(state->handle, 13656cd6a6acSopenharmony_ci "Conflicting role trans rule %s %s : %s { %s vs %s }", 13666cd6a6acSopenharmony_ci state->out->p_role_val_to_name[i], 13676cd6a6acSopenharmony_ci state->out->p_type_val_to_name[j], 13686cd6a6acSopenharmony_ci state->out->p_class_val_to_name[k], 13696cd6a6acSopenharmony_ci state->out->p_role_val_to_name[mapped_role - 1], 13706cd6a6acSopenharmony_ci state->out->p_role_val_to_name[cur_trans->new_role - 1]); 13716cd6a6acSopenharmony_ci return -1; 13726cd6a6acSopenharmony_ci } 13736cd6a6acSopenharmony_ci } 13746cd6a6acSopenharmony_ci cur_trans = cur_trans->next; 13756cd6a6acSopenharmony_ci } 13766cd6a6acSopenharmony_ci if (cur_trans) 13776cd6a6acSopenharmony_ci continue; 13786cd6a6acSopenharmony_ci 13796cd6a6acSopenharmony_ci n = (role_trans_t *) 13806cd6a6acSopenharmony_ci malloc(sizeof(role_trans_t)); 13816cd6a6acSopenharmony_ci if (!n) { 13826cd6a6acSopenharmony_ci ERR(state->handle, 13836cd6a6acSopenharmony_ci "Out of memory!"); 13846cd6a6acSopenharmony_ci return -1; 13856cd6a6acSopenharmony_ci } 13866cd6a6acSopenharmony_ci memset(n, 0, sizeof(role_trans_t)); 13876cd6a6acSopenharmony_ci n->role = i + 1; 13886cd6a6acSopenharmony_ci n->type = j + 1; 13896cd6a6acSopenharmony_ci n->tclass = k + 1; 13906cd6a6acSopenharmony_ci n->new_role = state->rolemap 13916cd6a6acSopenharmony_ci [cur->new_role - 1]; 13926cd6a6acSopenharmony_ci if (l) 13936cd6a6acSopenharmony_ci l->next = n; 13946cd6a6acSopenharmony_ci else 13956cd6a6acSopenharmony_ci state->out->role_tr = n; 13966cd6a6acSopenharmony_ci 13976cd6a6acSopenharmony_ci l = n; 13986cd6a6acSopenharmony_ci } 13996cd6a6acSopenharmony_ci } 14006cd6a6acSopenharmony_ci } 14016cd6a6acSopenharmony_ci 14026cd6a6acSopenharmony_ci ebitmap_destroy(&roles); 14036cd6a6acSopenharmony_ci ebitmap_destroy(&types); 14046cd6a6acSopenharmony_ci 14056cd6a6acSopenharmony_ci cur = cur->next; 14066cd6a6acSopenharmony_ci } 14076cd6a6acSopenharmony_ci return 0; 14086cd6a6acSopenharmony_ci} 14096cd6a6acSopenharmony_ci 14106cd6a6acSopenharmony_cistatic int expand_filename_trans_helper(expand_state_t *state, 14116cd6a6acSopenharmony_ci filename_trans_rule_t *rule, 14126cd6a6acSopenharmony_ci unsigned int s, unsigned int t) 14136cd6a6acSopenharmony_ci{ 14146cd6a6acSopenharmony_ci uint32_t mapped_otype, present_otype; 14156cd6a6acSopenharmony_ci int rc; 14166cd6a6acSopenharmony_ci 14176cd6a6acSopenharmony_ci mapped_otype = state->typemap[rule->otype - 1]; 14186cd6a6acSopenharmony_ci 14196cd6a6acSopenharmony_ci rc = policydb_filetrans_insert( 14206cd6a6acSopenharmony_ci state->out, s + 1, t + 1, 14216cd6a6acSopenharmony_ci rule->tclass, rule->name, 14226cd6a6acSopenharmony_ci NULL, mapped_otype, &present_otype 14236cd6a6acSopenharmony_ci ); 14246cd6a6acSopenharmony_ci if (rc == SEPOL_EEXIST) { 14256cd6a6acSopenharmony_ci /* duplicate rule, ignore */ 14266cd6a6acSopenharmony_ci if (present_otype == mapped_otype) 14276cd6a6acSopenharmony_ci return 0; 14286cd6a6acSopenharmony_ci 14296cd6a6acSopenharmony_ci ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s", 14306cd6a6acSopenharmony_ci state->out->p_type_val_to_name[s], 14316cd6a6acSopenharmony_ci state->out->p_type_val_to_name[t], 14326cd6a6acSopenharmony_ci state->out->p_class_val_to_name[rule->tclass - 1], 14336cd6a6acSopenharmony_ci rule->name, 14346cd6a6acSopenharmony_ci state->out->p_type_val_to_name[present_otype - 1], 14356cd6a6acSopenharmony_ci state->out->p_type_val_to_name[mapped_otype - 1]); 14366cd6a6acSopenharmony_ci return -1; 14376cd6a6acSopenharmony_ci } else if (rc < 0) { 14386cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 14396cd6a6acSopenharmony_ci return -1; 14406cd6a6acSopenharmony_ci } 14416cd6a6acSopenharmony_ci return 0; 14426cd6a6acSopenharmony_ci} 14436cd6a6acSopenharmony_ci 14446cd6a6acSopenharmony_cistatic int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules) 14456cd6a6acSopenharmony_ci{ 14466cd6a6acSopenharmony_ci unsigned int i, j; 14476cd6a6acSopenharmony_ci filename_trans_rule_t *cur_rule; 14486cd6a6acSopenharmony_ci ebitmap_t stypes, ttypes; 14496cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 14506cd6a6acSopenharmony_ci int rc; 14516cd6a6acSopenharmony_ci 14526cd6a6acSopenharmony_ci cur_rule = rules; 14536cd6a6acSopenharmony_ci while (cur_rule) { 14546cd6a6acSopenharmony_ci ebitmap_init(&stypes); 14556cd6a6acSopenharmony_ci ebitmap_init(&ttypes); 14566cd6a6acSopenharmony_ci 14576cd6a6acSopenharmony_ci if (expand_convert_type_set(state->out, state->typemap, 14586cd6a6acSopenharmony_ci &cur_rule->stypes, &stypes, 1)) { 14596cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 14606cd6a6acSopenharmony_ci return -1; 14616cd6a6acSopenharmony_ci } 14626cd6a6acSopenharmony_ci 14636cd6a6acSopenharmony_ci if (expand_convert_type_set(state->out, state->typemap, 14646cd6a6acSopenharmony_ci &cur_rule->ttypes, &ttypes, 1)) { 14656cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 14666cd6a6acSopenharmony_ci return -1; 14676cd6a6acSopenharmony_ci } 14686cd6a6acSopenharmony_ci 14696cd6a6acSopenharmony_ci 14706cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&stypes, snode, i) { 14716cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&ttypes, tnode, j) { 14726cd6a6acSopenharmony_ci rc = expand_filename_trans_helper( 14736cd6a6acSopenharmony_ci state, cur_rule, i, j 14746cd6a6acSopenharmony_ci ); 14756cd6a6acSopenharmony_ci if (rc) 14766cd6a6acSopenharmony_ci return rc; 14776cd6a6acSopenharmony_ci } 14786cd6a6acSopenharmony_ci if (cur_rule->flags & RULE_SELF) { 14796cd6a6acSopenharmony_ci rc = expand_filename_trans_helper( 14806cd6a6acSopenharmony_ci state, cur_rule, i, i 14816cd6a6acSopenharmony_ci ); 14826cd6a6acSopenharmony_ci if (rc) 14836cd6a6acSopenharmony_ci return rc; 14846cd6a6acSopenharmony_ci } 14856cd6a6acSopenharmony_ci } 14866cd6a6acSopenharmony_ci 14876cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 14886cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 14896cd6a6acSopenharmony_ci 14906cd6a6acSopenharmony_ci cur_rule = cur_rule->next; 14916cd6a6acSopenharmony_ci } 14926cd6a6acSopenharmony_ci return 0; 14936cd6a6acSopenharmony_ci} 14946cd6a6acSopenharmony_ci 14956cd6a6acSopenharmony_cistatic int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass, 14966cd6a6acSopenharmony_ci mls_semantic_range_t * trange, 14976cd6a6acSopenharmony_ci expand_state_t * state) 14986cd6a6acSopenharmony_ci{ 14996cd6a6acSopenharmony_ci range_trans_t *rt = NULL, key; 15006cd6a6acSopenharmony_ci mls_range_t *r, *exp_range = NULL; 15016cd6a6acSopenharmony_ci int rc = -1; 15026cd6a6acSopenharmony_ci 15036cd6a6acSopenharmony_ci exp_range = calloc(1, sizeof(*exp_range)); 15046cd6a6acSopenharmony_ci if (!exp_range) { 15056cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 15066cd6a6acSopenharmony_ci return -1; 15076cd6a6acSopenharmony_ci } 15086cd6a6acSopenharmony_ci 15096cd6a6acSopenharmony_ci if (mls_semantic_range_expand(trange, exp_range, state->out, 15106cd6a6acSopenharmony_ci state->handle)) 15116cd6a6acSopenharmony_ci goto err; 15126cd6a6acSopenharmony_ci 15136cd6a6acSopenharmony_ci /* check for duplicates/conflicts */ 15146cd6a6acSopenharmony_ci key.source_type = stype; 15156cd6a6acSopenharmony_ci key.target_type = ttype; 15166cd6a6acSopenharmony_ci key.target_class = tclass; 15176cd6a6acSopenharmony_ci r = hashtab_search(state->out->range_tr, (hashtab_key_t) &key); 15186cd6a6acSopenharmony_ci if (r) { 15196cd6a6acSopenharmony_ci if (mls_range_eq(r, exp_range)) { 15206cd6a6acSopenharmony_ci /* duplicate, ignore */ 15216cd6a6acSopenharmony_ci mls_range_destroy(exp_range); 15226cd6a6acSopenharmony_ci free(exp_range); 15236cd6a6acSopenharmony_ci return 0; 15246cd6a6acSopenharmony_ci } 15256cd6a6acSopenharmony_ci 15266cd6a6acSopenharmony_ci /* conflict */ 15276cd6a6acSopenharmony_ci ERR(state->handle, 15286cd6a6acSopenharmony_ci "Conflicting range trans rule %s %s : %s", 15296cd6a6acSopenharmony_ci state->out->p_type_val_to_name[stype - 1], 15306cd6a6acSopenharmony_ci state->out->p_type_val_to_name[ttype - 1], 15316cd6a6acSopenharmony_ci state->out->p_class_val_to_name[tclass - 1]); 15326cd6a6acSopenharmony_ci goto err; 15336cd6a6acSopenharmony_ci } 15346cd6a6acSopenharmony_ci 15356cd6a6acSopenharmony_ci rt = calloc(1, sizeof(*rt)); 15366cd6a6acSopenharmony_ci if (!rt) { 15376cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 15386cd6a6acSopenharmony_ci goto err; 15396cd6a6acSopenharmony_ci } 15406cd6a6acSopenharmony_ci rt->source_type = stype; 15416cd6a6acSopenharmony_ci rt->target_type = ttype; 15426cd6a6acSopenharmony_ci rt->target_class = tclass; 15436cd6a6acSopenharmony_ci 15446cd6a6acSopenharmony_ci rc = hashtab_insert(state->out->range_tr, (hashtab_key_t) rt, 15456cd6a6acSopenharmony_ci exp_range); 15466cd6a6acSopenharmony_ci if (rc) { 15476cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 15486cd6a6acSopenharmony_ci goto err; 15496cd6a6acSopenharmony_ci 15506cd6a6acSopenharmony_ci } 15516cd6a6acSopenharmony_ci 15526cd6a6acSopenharmony_ci return 0; 15536cd6a6acSopenharmony_cierr: 15546cd6a6acSopenharmony_ci free(rt); 15556cd6a6acSopenharmony_ci if (exp_range) { 15566cd6a6acSopenharmony_ci mls_range_destroy(exp_range); 15576cd6a6acSopenharmony_ci free(exp_range); 15586cd6a6acSopenharmony_ci } 15596cd6a6acSopenharmony_ci return -1; 15606cd6a6acSopenharmony_ci} 15616cd6a6acSopenharmony_ci 15626cd6a6acSopenharmony_cistatic int expand_range_trans(expand_state_t * state, 15636cd6a6acSopenharmony_ci range_trans_rule_t * rules) 15646cd6a6acSopenharmony_ci{ 15656cd6a6acSopenharmony_ci unsigned int i, j, k; 15666cd6a6acSopenharmony_ci range_trans_rule_t *rule; 15676cd6a6acSopenharmony_ci 15686cd6a6acSopenharmony_ci ebitmap_t stypes, ttypes; 15696cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode, *cnode; 15706cd6a6acSopenharmony_ci 15716cd6a6acSopenharmony_ci if (state->verbose) 15726cd6a6acSopenharmony_ci INFO(state->handle, "expanding range transitions"); 15736cd6a6acSopenharmony_ci 15746cd6a6acSopenharmony_ci for (rule = rules; rule; rule = rule->next) { 15756cd6a6acSopenharmony_ci ebitmap_init(&stypes); 15766cd6a6acSopenharmony_ci ebitmap_init(&ttypes); 15776cd6a6acSopenharmony_ci 15786cd6a6acSopenharmony_ci /* expand the type sets */ 15796cd6a6acSopenharmony_ci if (expand_convert_type_set(state->out, state->typemap, 15806cd6a6acSopenharmony_ci &rule->stypes, &stypes, 1)) { 15816cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 15826cd6a6acSopenharmony_ci return -1; 15836cd6a6acSopenharmony_ci } 15846cd6a6acSopenharmony_ci if (expand_convert_type_set(state->out, state->typemap, 15856cd6a6acSopenharmony_ci &rule->ttypes, &ttypes, 1)) { 15866cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 15876cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 15886cd6a6acSopenharmony_ci return -1; 15896cd6a6acSopenharmony_ci } 15906cd6a6acSopenharmony_ci 15916cd6a6acSopenharmony_ci /* loop on source type */ 15926cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&stypes, snode, i) { 15936cd6a6acSopenharmony_ci /* loop on target type */ 15946cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&ttypes, tnode, j) { 15956cd6a6acSopenharmony_ci /* loop on target class */ 15966cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&rule->tclasses, cnode, k) { 15976cd6a6acSopenharmony_ci if (exp_rangetr_helper(i + 1, 15986cd6a6acSopenharmony_ci j + 1, 15996cd6a6acSopenharmony_ci k + 1, 16006cd6a6acSopenharmony_ci &rule->trange, 16016cd6a6acSopenharmony_ci state)) { 16026cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 16036cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 16046cd6a6acSopenharmony_ci return -1; 16056cd6a6acSopenharmony_ci } 16066cd6a6acSopenharmony_ci } 16076cd6a6acSopenharmony_ci } 16086cd6a6acSopenharmony_ci } 16096cd6a6acSopenharmony_ci 16106cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 16116cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 16126cd6a6acSopenharmony_ci } 16136cd6a6acSopenharmony_ci 16146cd6a6acSopenharmony_ci return 0; 16156cd6a6acSopenharmony_ci} 16166cd6a6acSopenharmony_ci 16176cd6a6acSopenharmony_ci/* Search for an AV tab node within a hash table with the given key. 16186cd6a6acSopenharmony_ci * If the node does not exist, create it and return it; otherwise 16196cd6a6acSopenharmony_ci * return the pre-existing one. 16206cd6a6acSopenharmony_ci*/ 16216cd6a6acSopenharmony_cistatic avtab_ptr_t find_avtab_node(sepol_handle_t * handle, 16226cd6a6acSopenharmony_ci avtab_t * avtab, avtab_key_t * key, 16236cd6a6acSopenharmony_ci cond_av_list_t ** cond, 16246cd6a6acSopenharmony_ci av_extended_perms_t *xperms) 16256cd6a6acSopenharmony_ci{ 16266cd6a6acSopenharmony_ci avtab_ptr_t node; 16276cd6a6acSopenharmony_ci avtab_datum_t avdatum; 16286cd6a6acSopenharmony_ci cond_av_list_t *nl; 16296cd6a6acSopenharmony_ci int match = 0; 16306cd6a6acSopenharmony_ci 16316cd6a6acSopenharmony_ci /* AVTAB_XPERMS entries are not necessarily unique */ 16326cd6a6acSopenharmony_ci if (key->specified & AVTAB_XPERMS) { 16336cd6a6acSopenharmony_ci if (xperms == NULL) { 16346cd6a6acSopenharmony_ci ERR(handle, "searching xperms NULL"); 16356cd6a6acSopenharmony_ci node = NULL; 16366cd6a6acSopenharmony_ci } else { 16376cd6a6acSopenharmony_ci node = avtab_search_node(avtab, key); 16386cd6a6acSopenharmony_ci while (node) { 16396cd6a6acSopenharmony_ci if ((node->datum.xperms->specified == xperms->specified) && 16406cd6a6acSopenharmony_ci (node->datum.xperms->driver == xperms->driver)) { 16416cd6a6acSopenharmony_ci match = 1; 16426cd6a6acSopenharmony_ci break; 16436cd6a6acSopenharmony_ci } 16446cd6a6acSopenharmony_ci node = avtab_search_node_next(node, key->specified); 16456cd6a6acSopenharmony_ci } 16466cd6a6acSopenharmony_ci if (!match) 16476cd6a6acSopenharmony_ci node = NULL; 16486cd6a6acSopenharmony_ci } 16496cd6a6acSopenharmony_ci } else { 16506cd6a6acSopenharmony_ci node = avtab_search_node(avtab, key); 16516cd6a6acSopenharmony_ci } 16526cd6a6acSopenharmony_ci 16536cd6a6acSopenharmony_ci /* If this is for conditional policies, keep searching in case 16546cd6a6acSopenharmony_ci the node is part of my conditional avtab. */ 16556cd6a6acSopenharmony_ci if (cond) { 16566cd6a6acSopenharmony_ci while (node) { 16576cd6a6acSopenharmony_ci if (node->parse_context == cond) 16586cd6a6acSopenharmony_ci break; 16596cd6a6acSopenharmony_ci node = avtab_search_node_next(node, key->specified); 16606cd6a6acSopenharmony_ci } 16616cd6a6acSopenharmony_ci } 16626cd6a6acSopenharmony_ci 16636cd6a6acSopenharmony_ci if (!node) { 16646cd6a6acSopenharmony_ci memset(&avdatum, 0, sizeof avdatum); 16656cd6a6acSopenharmony_ci /* 16666cd6a6acSopenharmony_ci * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for 16676cd6a6acSopenharmony_ci * others. Initialize the data accordingly. 16686cd6a6acSopenharmony_ci */ 16696cd6a6acSopenharmony_ci avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0); 16706cd6a6acSopenharmony_ci /* this is used to get the node - insertion is actually unique */ 16716cd6a6acSopenharmony_ci node = avtab_insert_nonunique(avtab, key, &avdatum); 16726cd6a6acSopenharmony_ci if (!node) { 16736cd6a6acSopenharmony_ci ERR(handle, "hash table overflow"); 16746cd6a6acSopenharmony_ci return NULL; 16756cd6a6acSopenharmony_ci } 16766cd6a6acSopenharmony_ci if (cond) { 16776cd6a6acSopenharmony_ci node->parse_context = cond; 16786cd6a6acSopenharmony_ci nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t)); 16796cd6a6acSopenharmony_ci if (!nl) { 16806cd6a6acSopenharmony_ci ERR(handle, "Memory error"); 16816cd6a6acSopenharmony_ci return NULL; 16826cd6a6acSopenharmony_ci } 16836cd6a6acSopenharmony_ci memset(nl, 0, sizeof(cond_av_list_t)); 16846cd6a6acSopenharmony_ci nl->node = node; 16856cd6a6acSopenharmony_ci nl->next = *cond; 16866cd6a6acSopenharmony_ci *cond = nl; 16876cd6a6acSopenharmony_ci } 16886cd6a6acSopenharmony_ci } 16896cd6a6acSopenharmony_ci 16906cd6a6acSopenharmony_ci return node; 16916cd6a6acSopenharmony_ci} 16926cd6a6acSopenharmony_ci 16936cd6a6acSopenharmony_cistatic uint32_t avrule_to_avtab_spec(uint32_t specification) 16946cd6a6acSopenharmony_ci{ 16956cd6a6acSopenharmony_ci return (specification == AVRULE_DONTAUDIT) ? 16966cd6a6acSopenharmony_ci AVTAB_AUDITDENY : specification; 16976cd6a6acSopenharmony_ci} 16986cd6a6acSopenharmony_ci 16996cd6a6acSopenharmony_ci#define EXPAND_RULE_SUCCESS 1 17006cd6a6acSopenharmony_ci#define EXPAND_RULE_CONFLICT 0 17016cd6a6acSopenharmony_ci#define EXPAND_RULE_ERROR -1 17026cd6a6acSopenharmony_ci 17036cd6a6acSopenharmony_cistatic int expand_terule_helper(sepol_handle_t * handle, 17046cd6a6acSopenharmony_ci policydb_t * p, uint32_t * typemap, 17056cd6a6acSopenharmony_ci uint32_t specified, cond_av_list_t ** cond, 17066cd6a6acSopenharmony_ci cond_av_list_t ** other, uint32_t stype, 17076cd6a6acSopenharmony_ci uint32_t ttype, class_perm_node_t * perms, 17086cd6a6acSopenharmony_ci avtab_t * avtab, int enabled) 17096cd6a6acSopenharmony_ci{ 17106cd6a6acSopenharmony_ci avtab_key_t avkey; 17116cd6a6acSopenharmony_ci avtab_datum_t *avdatump; 17126cd6a6acSopenharmony_ci avtab_ptr_t node; 17136cd6a6acSopenharmony_ci class_perm_node_t *cur; 17146cd6a6acSopenharmony_ci int conflict; 17156cd6a6acSopenharmony_ci uint32_t oldtype = 0; 17166cd6a6acSopenharmony_ci 17176cd6a6acSopenharmony_ci if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) { 17186cd6a6acSopenharmony_ci ERR(handle, "Invalid specification: %"PRIu32, specified); 17196cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 17206cd6a6acSopenharmony_ci } 17216cd6a6acSopenharmony_ci 17226cd6a6acSopenharmony_ci avkey.specified = avrule_to_avtab_spec(specified); 17236cd6a6acSopenharmony_ci avkey.source_type = stype + 1; 17246cd6a6acSopenharmony_ci avkey.target_type = ttype + 1; 17256cd6a6acSopenharmony_ci 17266cd6a6acSopenharmony_ci cur = perms; 17276cd6a6acSopenharmony_ci while (cur) { 17286cd6a6acSopenharmony_ci uint32_t remapped_data = 17296cd6a6acSopenharmony_ci typemap ? typemap[cur->data - 1] : cur->data; 17306cd6a6acSopenharmony_ci avkey.target_class = cur->tclass; 17316cd6a6acSopenharmony_ci 17326cd6a6acSopenharmony_ci conflict = 0; 17336cd6a6acSopenharmony_ci /* check to see if the expanded TE already exists -- 17346cd6a6acSopenharmony_ci * either in the global scope or in another 17356cd6a6acSopenharmony_ci * conditional AV tab */ 17366cd6a6acSopenharmony_ci node = avtab_search_node(&p->te_avtab, &avkey); 17376cd6a6acSopenharmony_ci if (node) { 17386cd6a6acSopenharmony_ci conflict = 1; 17396cd6a6acSopenharmony_ci } else { 17406cd6a6acSopenharmony_ci node = avtab_search_node(&p->te_cond_avtab, &avkey); 17416cd6a6acSopenharmony_ci if (node && node->parse_context != other) { 17426cd6a6acSopenharmony_ci conflict = 2; 17436cd6a6acSopenharmony_ci } 17446cd6a6acSopenharmony_ci } 17456cd6a6acSopenharmony_ci 17466cd6a6acSopenharmony_ci if (conflict) { 17476cd6a6acSopenharmony_ci avdatump = &node->datum; 17486cd6a6acSopenharmony_ci if (specified & AVRULE_TRANSITION) { 17496cd6a6acSopenharmony_ci oldtype = avdatump->data; 17506cd6a6acSopenharmony_ci } else if (specified & AVRULE_MEMBER) { 17516cd6a6acSopenharmony_ci oldtype = avdatump->data; 17526cd6a6acSopenharmony_ci } else if (specified & AVRULE_CHANGE) { 17536cd6a6acSopenharmony_ci oldtype = avdatump->data; 17546cd6a6acSopenharmony_ci } 17556cd6a6acSopenharmony_ci 17566cd6a6acSopenharmony_ci if (oldtype == remapped_data) { 17576cd6a6acSopenharmony_ci /* if the duplicate is inside the same scope (eg., unconditional 17586cd6a6acSopenharmony_ci * or in same conditional then ignore it */ 17596cd6a6acSopenharmony_ci if ((conflict == 1 && cond == NULL) 17606cd6a6acSopenharmony_ci || node->parse_context == cond) 17616cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 17626cd6a6acSopenharmony_ci ERR(handle, "duplicate TE rule for %s %s:%s %s", 17636cd6a6acSopenharmony_ci p->p_type_val_to_name[avkey.source_type - 17646cd6a6acSopenharmony_ci 1], 17656cd6a6acSopenharmony_ci p->p_type_val_to_name[avkey.target_type - 17666cd6a6acSopenharmony_ci 1], 17676cd6a6acSopenharmony_ci p->p_class_val_to_name[avkey.target_class - 17686cd6a6acSopenharmony_ci 1], 17696cd6a6acSopenharmony_ci p->p_type_val_to_name[oldtype - 1]); 17706cd6a6acSopenharmony_ci return EXPAND_RULE_CONFLICT; 17716cd6a6acSopenharmony_ci } 17726cd6a6acSopenharmony_ci ERR(handle, 17736cd6a6acSopenharmony_ci "conflicting TE rule for (%s, %s:%s): old was %s, new is %s", 17746cd6a6acSopenharmony_ci p->p_type_val_to_name[avkey.source_type - 1], 17756cd6a6acSopenharmony_ci p->p_type_val_to_name[avkey.target_type - 1], 17766cd6a6acSopenharmony_ci p->p_class_val_to_name[avkey.target_class - 1], 17776cd6a6acSopenharmony_ci p->p_type_val_to_name[oldtype - 1], 17786cd6a6acSopenharmony_ci p->p_type_val_to_name[remapped_data - 1]); 17796cd6a6acSopenharmony_ci return EXPAND_RULE_CONFLICT; 17806cd6a6acSopenharmony_ci } 17816cd6a6acSopenharmony_ci 17826cd6a6acSopenharmony_ci node = find_avtab_node(handle, avtab, &avkey, cond, NULL); 17836cd6a6acSopenharmony_ci if (!node) 17846cd6a6acSopenharmony_ci return -1; 17856cd6a6acSopenharmony_ci if (enabled) { 17866cd6a6acSopenharmony_ci node->key.specified |= AVTAB_ENABLED; 17876cd6a6acSopenharmony_ci } else { 17886cd6a6acSopenharmony_ci node->key.specified &= ~AVTAB_ENABLED; 17896cd6a6acSopenharmony_ci } 17906cd6a6acSopenharmony_ci 17916cd6a6acSopenharmony_ci avdatump = &node->datum; 17926cd6a6acSopenharmony_ci avdatump->data = remapped_data; 17936cd6a6acSopenharmony_ci 17946cd6a6acSopenharmony_ci cur = cur->next; 17956cd6a6acSopenharmony_ci } 17966cd6a6acSopenharmony_ci 17976cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 17986cd6a6acSopenharmony_ci} 17996cd6a6acSopenharmony_ci 18006cd6a6acSopenharmony_ci/* 0 for success -1 indicates failure */ 18016cd6a6acSopenharmony_cistatic int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump, 18026cd6a6acSopenharmony_ci av_extended_perms_t * extended_perms) 18036cd6a6acSopenharmony_ci{ 18046cd6a6acSopenharmony_ci unsigned int i; 18056cd6a6acSopenharmony_ci 18066cd6a6acSopenharmony_ci avtab_extended_perms_t *xperms = avdatump->xperms; 18076cd6a6acSopenharmony_ci if (!xperms) { 18086cd6a6acSopenharmony_ci xperms = (avtab_extended_perms_t *) 18096cd6a6acSopenharmony_ci calloc(1, sizeof(avtab_extended_perms_t)); 18106cd6a6acSopenharmony_ci if (!xperms) { 18116cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 18126cd6a6acSopenharmony_ci return -1; 18136cd6a6acSopenharmony_ci } 18146cd6a6acSopenharmony_ci avdatump->xperms = xperms; 18156cd6a6acSopenharmony_ci } 18166cd6a6acSopenharmony_ci 18176cd6a6acSopenharmony_ci switch (extended_perms->specified) { 18186cd6a6acSopenharmony_ci case AVRULE_XPERMS_IOCTLFUNCTION: 18196cd6a6acSopenharmony_ci xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION; 18206cd6a6acSopenharmony_ci break; 18216cd6a6acSopenharmony_ci case AVRULE_XPERMS_IOCTLDRIVER: 18226cd6a6acSopenharmony_ci xperms->specified = AVTAB_XPERMS_IOCTLDRIVER; 18236cd6a6acSopenharmony_ci break; 18246cd6a6acSopenharmony_ci default: 18256cd6a6acSopenharmony_ci return -1; 18266cd6a6acSopenharmony_ci } 18276cd6a6acSopenharmony_ci 18286cd6a6acSopenharmony_ci xperms->driver = extended_perms->driver; 18296cd6a6acSopenharmony_ci for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) 18306cd6a6acSopenharmony_ci xperms->perms[i] |= extended_perms->perms[i]; 18316cd6a6acSopenharmony_ci 18326cd6a6acSopenharmony_ci return 0; 18336cd6a6acSopenharmony_ci} 18346cd6a6acSopenharmony_ci 18356cd6a6acSopenharmony_cistatic int expand_avrule_helper(sepol_handle_t * handle, 18366cd6a6acSopenharmony_ci uint32_t specified, 18376cd6a6acSopenharmony_ci cond_av_list_t ** cond, 18386cd6a6acSopenharmony_ci uint32_t stype, uint32_t ttype, 18396cd6a6acSopenharmony_ci class_perm_node_t * perms, avtab_t * avtab, 18406cd6a6acSopenharmony_ci int enabled, av_extended_perms_t *extended_perms) 18416cd6a6acSopenharmony_ci{ 18426cd6a6acSopenharmony_ci avtab_key_t avkey; 18436cd6a6acSopenharmony_ci avtab_datum_t *avdatump; 18446cd6a6acSopenharmony_ci avtab_ptr_t node; 18456cd6a6acSopenharmony_ci class_perm_node_t *cur; 18466cd6a6acSopenharmony_ci 18476cd6a6acSopenharmony_ci /* bail early if dontaudit's are disabled and it's a dontaudit rule */ 18486cd6a6acSopenharmony_ci if ((specified & (AVRULE_DONTAUDIT|AVRULE_XPERMS_DONTAUDIT)) 18496cd6a6acSopenharmony_ci && handle && handle->disable_dontaudit) 18506cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 18516cd6a6acSopenharmony_ci 18526cd6a6acSopenharmony_ci avkey.source_type = stype + 1; 18536cd6a6acSopenharmony_ci avkey.target_type = ttype + 1; 18546cd6a6acSopenharmony_ci avkey.specified = avrule_to_avtab_spec(specified); 18556cd6a6acSopenharmony_ci 18566cd6a6acSopenharmony_ci cur = perms; 18576cd6a6acSopenharmony_ci while (cur) { 18586cd6a6acSopenharmony_ci avkey.target_class = cur->tclass; 18596cd6a6acSopenharmony_ci 18606cd6a6acSopenharmony_ci node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms); 18616cd6a6acSopenharmony_ci if (!node) 18626cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 18636cd6a6acSopenharmony_ci if (enabled) { 18646cd6a6acSopenharmony_ci node->key.specified |= AVTAB_ENABLED; 18656cd6a6acSopenharmony_ci } else { 18666cd6a6acSopenharmony_ci node->key.specified &= ~AVTAB_ENABLED; 18676cd6a6acSopenharmony_ci } 18686cd6a6acSopenharmony_ci 18696cd6a6acSopenharmony_ci avdatump = &node->datum; 18706cd6a6acSopenharmony_ci switch (specified) { 18716cd6a6acSopenharmony_ci case AVRULE_ALLOWED: 18726cd6a6acSopenharmony_ci case AVRULE_AUDITALLOW: 18736cd6a6acSopenharmony_ci case AVRULE_NEVERALLOW: 18746cd6a6acSopenharmony_ci avdatump->data |= cur->data; 18756cd6a6acSopenharmony_ci break; 18766cd6a6acSopenharmony_ci case AVRULE_DONTAUDIT: 18776cd6a6acSopenharmony_ci avdatump->data &= ~cur->data; 18786cd6a6acSopenharmony_ci break; 18796cd6a6acSopenharmony_ci case AVRULE_AUDITDENY: 18806cd6a6acSopenharmony_ci /* Since a '0' in an auditdeny mask represents 18816cd6a6acSopenharmony_ci * a permission we do NOT want to audit 18826cd6a6acSopenharmony_ci * (dontaudit), we use the '&' operand to 18836cd6a6acSopenharmony_ci * ensure that all '0's in the mask are 18846cd6a6acSopenharmony_ci * retained (much unlike the allow and 18856cd6a6acSopenharmony_ci * auditallow cases). 18866cd6a6acSopenharmony_ci */ 18876cd6a6acSopenharmony_ci avdatump->data &= cur->data; 18886cd6a6acSopenharmony_ci break; 18896cd6a6acSopenharmony_ci case AVRULE_XPERMS_ALLOWED: 18906cd6a6acSopenharmony_ci case AVRULE_XPERMS_AUDITALLOW: 18916cd6a6acSopenharmony_ci case AVRULE_XPERMS_DONTAUDIT: 18926cd6a6acSopenharmony_ci case AVRULE_XPERMS_NEVERALLOW: 18936cd6a6acSopenharmony_ci if (allocate_xperms(handle, avdatump, extended_perms)) 18946cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 18956cd6a6acSopenharmony_ci break; 18966cd6a6acSopenharmony_ci default: 18976cd6a6acSopenharmony_ci ERR(handle, "Unknown specification: %"PRIu32, specified); 18986cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 18996cd6a6acSopenharmony_ci } 19006cd6a6acSopenharmony_ci 19016cd6a6acSopenharmony_ci cur = cur->next; 19026cd6a6acSopenharmony_ci } 19036cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 19046cd6a6acSopenharmony_ci} 19056cd6a6acSopenharmony_ci 19066cd6a6acSopenharmony_cistatic int expand_rule_helper(sepol_handle_t * handle, 19076cd6a6acSopenharmony_ci policydb_t * p, uint32_t * typemap, 19086cd6a6acSopenharmony_ci avrule_t * source_rule, avtab_t * dest_avtab, 19096cd6a6acSopenharmony_ci cond_av_list_t ** cond, cond_av_list_t ** other, 19106cd6a6acSopenharmony_ci int enabled, 19116cd6a6acSopenharmony_ci ebitmap_t * stypes, ebitmap_t * ttypes) 19126cd6a6acSopenharmony_ci{ 19136cd6a6acSopenharmony_ci unsigned int i, j; 19146cd6a6acSopenharmony_ci int retval; 19156cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 19166cd6a6acSopenharmony_ci 19176cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(stypes, snode, i) { 19186cd6a6acSopenharmony_ci if (source_rule->flags & RULE_SELF) { 19196cd6a6acSopenharmony_ci if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { 19206cd6a6acSopenharmony_ci retval = expand_avrule_helper(handle, source_rule->specified, 19216cd6a6acSopenharmony_ci cond, i, i, source_rule->perms, 19226cd6a6acSopenharmony_ci dest_avtab, enabled, source_rule->xperms); 19236cd6a6acSopenharmony_ci if (retval != EXPAND_RULE_SUCCESS) 19246cd6a6acSopenharmony_ci return retval; 19256cd6a6acSopenharmony_ci } else { 19266cd6a6acSopenharmony_ci retval = expand_terule_helper(handle, p, typemap, 19276cd6a6acSopenharmony_ci source_rule->specified, cond, 19286cd6a6acSopenharmony_ci other, i, i, source_rule->perms, 19296cd6a6acSopenharmony_ci dest_avtab, enabled); 19306cd6a6acSopenharmony_ci if (retval != EXPAND_RULE_SUCCESS) 19316cd6a6acSopenharmony_ci return retval; 19326cd6a6acSopenharmony_ci } 19336cd6a6acSopenharmony_ci } 19346cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(ttypes, tnode, j) { 19356cd6a6acSopenharmony_ci if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { 19366cd6a6acSopenharmony_ci retval = expand_avrule_helper(handle, source_rule->specified, 19376cd6a6acSopenharmony_ci cond, i, j, source_rule->perms, 19386cd6a6acSopenharmony_ci dest_avtab, enabled, source_rule->xperms); 19396cd6a6acSopenharmony_ci if (retval != EXPAND_RULE_SUCCESS) 19406cd6a6acSopenharmony_ci return retval; 19416cd6a6acSopenharmony_ci } else { 19426cd6a6acSopenharmony_ci retval = expand_terule_helper(handle, p, typemap, 19436cd6a6acSopenharmony_ci source_rule->specified, cond, 19446cd6a6acSopenharmony_ci other, i, j, source_rule->perms, 19456cd6a6acSopenharmony_ci dest_avtab, enabled); 19466cd6a6acSopenharmony_ci if (retval != EXPAND_RULE_SUCCESS) 19476cd6a6acSopenharmony_ci return retval; 19486cd6a6acSopenharmony_ci } 19496cd6a6acSopenharmony_ci } 19506cd6a6acSopenharmony_ci } 19516cd6a6acSopenharmony_ci 19526cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 19536cd6a6acSopenharmony_ci} 19546cd6a6acSopenharmony_ci 19556cd6a6acSopenharmony_ci/* 19566cd6a6acSopenharmony_ci * Expand a rule into a given avtab - checking for conflicting type 19576cd6a6acSopenharmony_ci * rules in the destination policy. Return EXPAND_RULE_SUCCESS on 19586cd6a6acSopenharmony_ci * success, EXPAND_RULE_CONFLICT if the rule conflicts with something 19596cd6a6acSopenharmony_ci * (and hence was not added), or EXPAND_RULE_ERROR on error. 19606cd6a6acSopenharmony_ci */ 19616cd6a6acSopenharmony_cistatic int convert_and_expand_rule(sepol_handle_t * handle, 19626cd6a6acSopenharmony_ci policydb_t * dest_pol, uint32_t * typemap, 19636cd6a6acSopenharmony_ci avrule_t * source_rule, avtab_t * dest_avtab, 19646cd6a6acSopenharmony_ci cond_av_list_t ** cond, 19656cd6a6acSopenharmony_ci cond_av_list_t ** other, int enabled, 19666cd6a6acSopenharmony_ci int do_neverallow) 19676cd6a6acSopenharmony_ci{ 19686cd6a6acSopenharmony_ci int retval; 19696cd6a6acSopenharmony_ci ebitmap_t stypes, ttypes; 19706cd6a6acSopenharmony_ci unsigned char alwaysexpand; 19716cd6a6acSopenharmony_ci 19726cd6a6acSopenharmony_ci if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW) 19736cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 19746cd6a6acSopenharmony_ci if (!do_neverallow && source_rule->specified & AVRULE_XPERMS_NEVERALLOW) 19756cd6a6acSopenharmony_ci return EXPAND_RULE_SUCCESS; 19766cd6a6acSopenharmony_ci 19776cd6a6acSopenharmony_ci ebitmap_init(&stypes); 19786cd6a6acSopenharmony_ci ebitmap_init(&ttypes); 19796cd6a6acSopenharmony_ci 19806cd6a6acSopenharmony_ci /* Force expansion for type rules and for self rules. */ 19816cd6a6acSopenharmony_ci alwaysexpand = ((source_rule->specified & AVRULE_TYPE) || 19826cd6a6acSopenharmony_ci (source_rule->flags & RULE_SELF)); 19836cd6a6acSopenharmony_ci 19846cd6a6acSopenharmony_ci if (expand_convert_type_set 19856cd6a6acSopenharmony_ci (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand)) 19866cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 19876cd6a6acSopenharmony_ci if (expand_convert_type_set 19886cd6a6acSopenharmony_ci (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand)) 19896cd6a6acSopenharmony_ci return EXPAND_RULE_ERROR; 19906cd6a6acSopenharmony_ci 19916cd6a6acSopenharmony_ci retval = expand_rule_helper(handle, dest_pol, typemap, 19926cd6a6acSopenharmony_ci source_rule, dest_avtab, 19936cd6a6acSopenharmony_ci cond, other, enabled, &stypes, &ttypes); 19946cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 19956cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 19966cd6a6acSopenharmony_ci return retval; 19976cd6a6acSopenharmony_ci} 19986cd6a6acSopenharmony_ci 19996cd6a6acSopenharmony_cistatic int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules, 20006cd6a6acSopenharmony_ci avtab_t * dest_avtab, cond_av_list_t ** list, 20016cd6a6acSopenharmony_ci cond_av_list_t ** other, uint32_t * typemap, 20026cd6a6acSopenharmony_ci int enabled, expand_state_t * state) 20036cd6a6acSopenharmony_ci{ 20046cd6a6acSopenharmony_ci avrule_t *cur; 20056cd6a6acSopenharmony_ci 20066cd6a6acSopenharmony_ci cur = source_rules; 20076cd6a6acSopenharmony_ci while (cur) { 20086cd6a6acSopenharmony_ci if (convert_and_expand_rule(state->handle, dest_pol, 20096cd6a6acSopenharmony_ci typemap, cur, dest_avtab, 20106cd6a6acSopenharmony_ci list, other, enabled, 20116cd6a6acSopenharmony_ci 0) != EXPAND_RULE_SUCCESS) { 20126cd6a6acSopenharmony_ci return -1; 20136cd6a6acSopenharmony_ci } 20146cd6a6acSopenharmony_ci 20156cd6a6acSopenharmony_ci cur = cur->next; 20166cd6a6acSopenharmony_ci } 20176cd6a6acSopenharmony_ci 20186cd6a6acSopenharmony_ci return 0; 20196cd6a6acSopenharmony_ci} 20206cd6a6acSopenharmony_ci 20216cd6a6acSopenharmony_cistatic int cond_node_map_bools(expand_state_t * state, cond_node_t * cn) 20226cd6a6acSopenharmony_ci{ 20236cd6a6acSopenharmony_ci cond_expr_t *cur; 20246cd6a6acSopenharmony_ci unsigned int i; 20256cd6a6acSopenharmony_ci 20266cd6a6acSopenharmony_ci cur = cn->expr; 20276cd6a6acSopenharmony_ci while (cur) { 20286cd6a6acSopenharmony_ci if (cur->bool) 20296cd6a6acSopenharmony_ci cur->bool = state->boolmap[cur->bool - 1]; 20306cd6a6acSopenharmony_ci cur = cur->next; 20316cd6a6acSopenharmony_ci } 20326cd6a6acSopenharmony_ci 20336cd6a6acSopenharmony_ci for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++) 20346cd6a6acSopenharmony_ci cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1]; 20356cd6a6acSopenharmony_ci 20366cd6a6acSopenharmony_ci if (cond_normalize_expr(state->out, cn)) { 20376cd6a6acSopenharmony_ci ERR(state->handle, "Error while normalizing conditional"); 20386cd6a6acSopenharmony_ci return -1; 20396cd6a6acSopenharmony_ci } 20406cd6a6acSopenharmony_ci 20416cd6a6acSopenharmony_ci return 0; 20426cd6a6acSopenharmony_ci} 20436cd6a6acSopenharmony_ci 20446cd6a6acSopenharmony_ci/* copy the nodes in *reverse* order -- the result is that the last 20456cd6a6acSopenharmony_ci * given conditional appears first in the policy, so as to match the 20466cd6a6acSopenharmony_ci * behavior of the upstream compiler */ 20476cd6a6acSopenharmony_cistatic int cond_node_copy(expand_state_t * state, cond_node_t * cn) 20486cd6a6acSopenharmony_ci{ 20496cd6a6acSopenharmony_ci cond_node_t *new_cond, *tmp; 20506cd6a6acSopenharmony_ci 20516cd6a6acSopenharmony_ci if (cn == NULL) { 20526cd6a6acSopenharmony_ci return 0; 20536cd6a6acSopenharmony_ci } 20546cd6a6acSopenharmony_ci if (cond_node_copy(state, cn->next)) { 20556cd6a6acSopenharmony_ci return -1; 20566cd6a6acSopenharmony_ci } 20576cd6a6acSopenharmony_ci 20586cd6a6acSopenharmony_ci /* If current cond_node_t is of tunable, its effective branch 20596cd6a6acSopenharmony_ci * has been appended to its home decl->avrules list during link 20606cd6a6acSopenharmony_ci * and now we should just skip it. */ 20616cd6a6acSopenharmony_ci if (cn->flags & COND_NODE_FLAGS_TUNABLE) 20626cd6a6acSopenharmony_ci return 0; 20636cd6a6acSopenharmony_ci 20646cd6a6acSopenharmony_ci if (cond_normalize_expr(state->base, cn)) { 20656cd6a6acSopenharmony_ci ERR(state->handle, "Error while normalizing conditional"); 20666cd6a6acSopenharmony_ci return -1; 20676cd6a6acSopenharmony_ci } 20686cd6a6acSopenharmony_ci 20696cd6a6acSopenharmony_ci /* create a new temporary conditional node with the booleans 20706cd6a6acSopenharmony_ci * mapped */ 20716cd6a6acSopenharmony_ci tmp = cond_node_create(state->base, cn); 20726cd6a6acSopenharmony_ci if (!tmp) { 20736cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory"); 20746cd6a6acSopenharmony_ci return -1; 20756cd6a6acSopenharmony_ci } 20766cd6a6acSopenharmony_ci 20776cd6a6acSopenharmony_ci if (cond_node_map_bools(state, tmp)) { 20786cd6a6acSopenharmony_ci cond_node_destroy(tmp); 20796cd6a6acSopenharmony_ci free(tmp); 20806cd6a6acSopenharmony_ci ERR(state->handle, "Error mapping booleans"); 20816cd6a6acSopenharmony_ci return -1; 20826cd6a6acSopenharmony_ci } 20836cd6a6acSopenharmony_ci 20846cd6a6acSopenharmony_ci new_cond = cond_node_search(state->out, state->out->cond_list, tmp); 20856cd6a6acSopenharmony_ci if (!new_cond) { 20866cd6a6acSopenharmony_ci cond_node_destroy(tmp); 20876cd6a6acSopenharmony_ci free(tmp); 20886cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 20896cd6a6acSopenharmony_ci return -1; 20906cd6a6acSopenharmony_ci } 20916cd6a6acSopenharmony_ci cond_node_destroy(tmp); 20926cd6a6acSopenharmony_ci free(tmp); 20936cd6a6acSopenharmony_ci 20946cd6a6acSopenharmony_ci if (cond_avrule_list_copy 20956cd6a6acSopenharmony_ci (state->out, cn->avtrue_list, &state->out->te_cond_avtab, 20966cd6a6acSopenharmony_ci &new_cond->true_list, &new_cond->false_list, state->typemap, 20976cd6a6acSopenharmony_ci new_cond->cur_state, state)) 20986cd6a6acSopenharmony_ci return -1; 20996cd6a6acSopenharmony_ci if (cond_avrule_list_copy 21006cd6a6acSopenharmony_ci (state->out, cn->avfalse_list, &state->out->te_cond_avtab, 21016cd6a6acSopenharmony_ci &new_cond->false_list, &new_cond->true_list, state->typemap, 21026cd6a6acSopenharmony_ci !new_cond->cur_state, state)) 21036cd6a6acSopenharmony_ci return -1; 21046cd6a6acSopenharmony_ci 21056cd6a6acSopenharmony_ci return 0; 21066cd6a6acSopenharmony_ci} 21076cd6a6acSopenharmony_ci 21086cd6a6acSopenharmony_cistatic int context_copy(context_struct_t * dst, context_struct_t * src, 21096cd6a6acSopenharmony_ci expand_state_t * state) 21106cd6a6acSopenharmony_ci{ 21116cd6a6acSopenharmony_ci dst->user = state->usermap[src->user - 1]; 21126cd6a6acSopenharmony_ci dst->role = state->rolemap[src->role - 1]; 21136cd6a6acSopenharmony_ci dst->type = state->typemap[src->type - 1]; 21146cd6a6acSopenharmony_ci return mls_context_cpy(dst, src); 21156cd6a6acSopenharmony_ci} 21166cd6a6acSopenharmony_ci 21176cd6a6acSopenharmony_cistatic int ocontext_copy_xen(expand_state_t *state) 21186cd6a6acSopenharmony_ci{ 21196cd6a6acSopenharmony_ci unsigned int i; 21206cd6a6acSopenharmony_ci ocontext_t *c, *n, *l; 21216cd6a6acSopenharmony_ci 21226cd6a6acSopenharmony_ci for (i = 0; i < OCON_NUM; i++) { 21236cd6a6acSopenharmony_ci l = NULL; 21246cd6a6acSopenharmony_ci for (c = state->base->ocontexts[i]; c; c = c->next) { 21256cd6a6acSopenharmony_ci if (i == OCON_XEN_ISID && !c->context[0].user) { 21266cd6a6acSopenharmony_ci INFO(state->handle, 21276cd6a6acSopenharmony_ci "No context assigned to SID %s, omitting from policy", 21286cd6a6acSopenharmony_ci c->u.name); 21296cd6a6acSopenharmony_ci continue; 21306cd6a6acSopenharmony_ci } 21316cd6a6acSopenharmony_ci n = malloc(sizeof(ocontext_t)); 21326cd6a6acSopenharmony_ci if (!n) { 21336cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 21346cd6a6acSopenharmony_ci return -1; 21356cd6a6acSopenharmony_ci } 21366cd6a6acSopenharmony_ci memset(n, 0, sizeof(ocontext_t)); 21376cd6a6acSopenharmony_ci if (l) 21386cd6a6acSopenharmony_ci l->next = n; 21396cd6a6acSopenharmony_ci else 21406cd6a6acSopenharmony_ci state->out->ocontexts[i] = n; 21416cd6a6acSopenharmony_ci l = n; 21426cd6a6acSopenharmony_ci switch (i) { 21436cd6a6acSopenharmony_ci case OCON_XEN_ISID: 21446cd6a6acSopenharmony_ci n->sid[0] = c->sid[0]; 21456cd6a6acSopenharmony_ci break; 21466cd6a6acSopenharmony_ci case OCON_XEN_PIRQ: 21476cd6a6acSopenharmony_ci n->u.pirq = c->u.pirq; 21486cd6a6acSopenharmony_ci break; 21496cd6a6acSopenharmony_ci case OCON_XEN_IOPORT: 21506cd6a6acSopenharmony_ci n->u.ioport.low_ioport = c->u.ioport.low_ioport; 21516cd6a6acSopenharmony_ci n->u.ioport.high_ioport = 21526cd6a6acSopenharmony_ci c->u.ioport.high_ioport; 21536cd6a6acSopenharmony_ci break; 21546cd6a6acSopenharmony_ci case OCON_XEN_IOMEM: 21556cd6a6acSopenharmony_ci n->u.iomem.low_iomem = c->u.iomem.low_iomem; 21566cd6a6acSopenharmony_ci n->u.iomem.high_iomem = c->u.iomem.high_iomem; 21576cd6a6acSopenharmony_ci break; 21586cd6a6acSopenharmony_ci case OCON_XEN_PCIDEVICE: 21596cd6a6acSopenharmony_ci n->u.device = c->u.device; 21606cd6a6acSopenharmony_ci break; 21616cd6a6acSopenharmony_ci case OCON_XEN_DEVICETREE: 21626cd6a6acSopenharmony_ci n->u.name = strdup(c->u.name); 21636cd6a6acSopenharmony_ci if (!n->u.name) { 21646cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 21656cd6a6acSopenharmony_ci return -1; 21666cd6a6acSopenharmony_ci } 21676cd6a6acSopenharmony_ci break; 21686cd6a6acSopenharmony_ci default: 21696cd6a6acSopenharmony_ci /* shouldn't get here */ 21706cd6a6acSopenharmony_ci ERR(state->handle, "Unknown ocontext"); 21716cd6a6acSopenharmony_ci return -1; 21726cd6a6acSopenharmony_ci } 21736cd6a6acSopenharmony_ci if (context_copy(&n->context[0], &c->context[0], 21746cd6a6acSopenharmony_ci state)) { 21756cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 21766cd6a6acSopenharmony_ci return -1; 21776cd6a6acSopenharmony_ci } 21786cd6a6acSopenharmony_ci } 21796cd6a6acSopenharmony_ci } 21806cd6a6acSopenharmony_ci return 0; 21816cd6a6acSopenharmony_ci} 21826cd6a6acSopenharmony_ci 21836cd6a6acSopenharmony_cistatic int ocontext_copy_selinux(expand_state_t *state) 21846cd6a6acSopenharmony_ci{ 21856cd6a6acSopenharmony_ci unsigned int i, j; 21866cd6a6acSopenharmony_ci ocontext_t *c, *n, *l; 21876cd6a6acSopenharmony_ci 21886cd6a6acSopenharmony_ci for (i = 0; i < OCON_NUM; i++) { 21896cd6a6acSopenharmony_ci l = NULL; 21906cd6a6acSopenharmony_ci for (c = state->base->ocontexts[i]; c; c = c->next) { 21916cd6a6acSopenharmony_ci if (i == OCON_ISID && !c->context[0].user) { 21926cd6a6acSopenharmony_ci INFO(state->handle, 21936cd6a6acSopenharmony_ci "No context assigned to SID %s, omitting from policy", 21946cd6a6acSopenharmony_ci c->u.name); 21956cd6a6acSopenharmony_ci continue; 21966cd6a6acSopenharmony_ci } 21976cd6a6acSopenharmony_ci n = malloc(sizeof(ocontext_t)); 21986cd6a6acSopenharmony_ci if (!n) { 21996cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22006cd6a6acSopenharmony_ci return -1; 22016cd6a6acSopenharmony_ci } 22026cd6a6acSopenharmony_ci memset(n, 0, sizeof(ocontext_t)); 22036cd6a6acSopenharmony_ci if (l) 22046cd6a6acSopenharmony_ci l->next = n; 22056cd6a6acSopenharmony_ci else 22066cd6a6acSopenharmony_ci state->out->ocontexts[i] = n; 22076cd6a6acSopenharmony_ci l = n; 22086cd6a6acSopenharmony_ci switch (i) { 22096cd6a6acSopenharmony_ci case OCON_ISID: 22106cd6a6acSopenharmony_ci n->sid[0] = c->sid[0]; 22116cd6a6acSopenharmony_ci break; 22126cd6a6acSopenharmony_ci case OCON_FS: /* FALLTHROUGH */ 22136cd6a6acSopenharmony_ci case OCON_NETIF: 22146cd6a6acSopenharmony_ci n->u.name = strdup(c->u.name); 22156cd6a6acSopenharmony_ci if (!n->u.name) { 22166cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22176cd6a6acSopenharmony_ci return -1; 22186cd6a6acSopenharmony_ci } 22196cd6a6acSopenharmony_ci if (context_copy 22206cd6a6acSopenharmony_ci (&n->context[1], &c->context[1], state)) { 22216cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22226cd6a6acSopenharmony_ci return -1; 22236cd6a6acSopenharmony_ci } 22246cd6a6acSopenharmony_ci break; 22256cd6a6acSopenharmony_ci case OCON_IBPKEY: 22266cd6a6acSopenharmony_ci n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix; 22276cd6a6acSopenharmony_ci 22286cd6a6acSopenharmony_ci n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey; 22296cd6a6acSopenharmony_ci n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey; 22306cd6a6acSopenharmony_ci break; 22316cd6a6acSopenharmony_ci case OCON_IBENDPORT: 22326cd6a6acSopenharmony_ci n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name); 22336cd6a6acSopenharmony_ci if (!n->u.ibendport.dev_name) { 22346cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22356cd6a6acSopenharmony_ci return -1; 22366cd6a6acSopenharmony_ci } 22376cd6a6acSopenharmony_ci n->u.ibendport.port = c->u.ibendport.port; 22386cd6a6acSopenharmony_ci break; 22396cd6a6acSopenharmony_ci case OCON_PORT: 22406cd6a6acSopenharmony_ci n->u.port.protocol = c->u.port.protocol; 22416cd6a6acSopenharmony_ci n->u.port.low_port = c->u.port.low_port; 22426cd6a6acSopenharmony_ci n->u.port.high_port = c->u.port.high_port; 22436cd6a6acSopenharmony_ci break; 22446cd6a6acSopenharmony_ci case OCON_NODE: 22456cd6a6acSopenharmony_ci n->u.node.addr = c->u.node.addr; 22466cd6a6acSopenharmony_ci n->u.node.mask = c->u.node.mask; 22476cd6a6acSopenharmony_ci break; 22486cd6a6acSopenharmony_ci case OCON_FSUSE: 22496cd6a6acSopenharmony_ci n->v.behavior = c->v.behavior; 22506cd6a6acSopenharmony_ci n->u.name = strdup(c->u.name); 22516cd6a6acSopenharmony_ci if (!n->u.name) { 22526cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22536cd6a6acSopenharmony_ci return -1; 22546cd6a6acSopenharmony_ci } 22556cd6a6acSopenharmony_ci break; 22566cd6a6acSopenharmony_ci case OCON_NODE6: 22576cd6a6acSopenharmony_ci for (j = 0; j < 4; j++) 22586cd6a6acSopenharmony_ci n->u.node6.addr[j] = c->u.node6.addr[j]; 22596cd6a6acSopenharmony_ci for (j = 0; j < 4; j++) 22606cd6a6acSopenharmony_ci n->u.node6.mask[j] = c->u.node6.mask[j]; 22616cd6a6acSopenharmony_ci break; 22626cd6a6acSopenharmony_ci default: 22636cd6a6acSopenharmony_ci /* shouldn't get here */ 22646cd6a6acSopenharmony_ci ERR(state->handle, "Unknown ocontext"); 22656cd6a6acSopenharmony_ci return -1; 22666cd6a6acSopenharmony_ci } 22676cd6a6acSopenharmony_ci if (context_copy(&n->context[0], &c->context[0], state)) { 22686cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 22696cd6a6acSopenharmony_ci return -1; 22706cd6a6acSopenharmony_ci } 22716cd6a6acSopenharmony_ci } 22726cd6a6acSopenharmony_ci } 22736cd6a6acSopenharmony_ci return 0; 22746cd6a6acSopenharmony_ci} 22756cd6a6acSopenharmony_ci 22766cd6a6acSopenharmony_cistatic int ocontext_copy(expand_state_t *state, uint32_t target) 22776cd6a6acSopenharmony_ci{ 22786cd6a6acSopenharmony_ci int rc = -1; 22796cd6a6acSopenharmony_ci switch (target) { 22806cd6a6acSopenharmony_ci case SEPOL_TARGET_SELINUX: 22816cd6a6acSopenharmony_ci rc = ocontext_copy_selinux(state); 22826cd6a6acSopenharmony_ci break; 22836cd6a6acSopenharmony_ci case SEPOL_TARGET_XEN: 22846cd6a6acSopenharmony_ci rc = ocontext_copy_xen(state); 22856cd6a6acSopenharmony_ci break; 22866cd6a6acSopenharmony_ci default: 22876cd6a6acSopenharmony_ci ERR(state->handle, "Unknown target"); 22886cd6a6acSopenharmony_ci return -1; 22896cd6a6acSopenharmony_ci } 22906cd6a6acSopenharmony_ci return rc; 22916cd6a6acSopenharmony_ci} 22926cd6a6acSopenharmony_ci 22936cd6a6acSopenharmony_cistatic int genfs_copy(expand_state_t * state) 22946cd6a6acSopenharmony_ci{ 22956cd6a6acSopenharmony_ci ocontext_t *c, *newc, *l; 22966cd6a6acSopenharmony_ci genfs_t *genfs, *newgenfs, *end; 22976cd6a6acSopenharmony_ci 22986cd6a6acSopenharmony_ci end = NULL; 22996cd6a6acSopenharmony_ci for (genfs = state->base->genfs; genfs; genfs = genfs->next) { 23006cd6a6acSopenharmony_ci newgenfs = malloc(sizeof(genfs_t)); 23016cd6a6acSopenharmony_ci if (!newgenfs) { 23026cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 23036cd6a6acSopenharmony_ci return -1; 23046cd6a6acSopenharmony_ci } 23056cd6a6acSopenharmony_ci memset(newgenfs, 0, sizeof(genfs_t)); 23066cd6a6acSopenharmony_ci newgenfs->fstype = strdup(genfs->fstype); 23076cd6a6acSopenharmony_ci if (!newgenfs->fstype) { 23086cd6a6acSopenharmony_ci free(newgenfs); 23096cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 23106cd6a6acSopenharmony_ci return -1; 23116cd6a6acSopenharmony_ci } 23126cd6a6acSopenharmony_ci if (!end) 23136cd6a6acSopenharmony_ci state->out->genfs = newgenfs; 23146cd6a6acSopenharmony_ci else 23156cd6a6acSopenharmony_ci end->next = newgenfs; 23166cd6a6acSopenharmony_ci end = newgenfs; 23176cd6a6acSopenharmony_ci 23186cd6a6acSopenharmony_ci l = NULL; 23196cd6a6acSopenharmony_ci for (c = genfs->head; c; c = c->next) { 23206cd6a6acSopenharmony_ci newc = malloc(sizeof(ocontext_t)); 23216cd6a6acSopenharmony_ci if (!newc) { 23226cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 23236cd6a6acSopenharmony_ci return -1; 23246cd6a6acSopenharmony_ci } 23256cd6a6acSopenharmony_ci memset(newc, 0, sizeof(ocontext_t)); 23266cd6a6acSopenharmony_ci newc->u.name = strdup(c->u.name); 23276cd6a6acSopenharmony_ci if (!newc->u.name) { 23286cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 23296cd6a6acSopenharmony_ci free(newc); 23306cd6a6acSopenharmony_ci return -1; 23316cd6a6acSopenharmony_ci } 23326cd6a6acSopenharmony_ci newc->v.sclass = c->v.sclass; 23336cd6a6acSopenharmony_ci context_copy(&newc->context[0], &c->context[0], state); 23346cd6a6acSopenharmony_ci if (l) 23356cd6a6acSopenharmony_ci l->next = newc; 23366cd6a6acSopenharmony_ci else 23376cd6a6acSopenharmony_ci newgenfs->head = newc; 23386cd6a6acSopenharmony_ci l = newc; 23396cd6a6acSopenharmony_ci } 23406cd6a6acSopenharmony_ci } 23416cd6a6acSopenharmony_ci return 0; 23426cd6a6acSopenharmony_ci} 23436cd6a6acSopenharmony_ci 23446cd6a6acSopenharmony_cistatic int type_attr_map(hashtab_key_t key 23456cd6a6acSopenharmony_ci __attribute__ ((unused)), hashtab_datum_t datum, 23466cd6a6acSopenharmony_ci void *ptr) 23476cd6a6acSopenharmony_ci{ 23486cd6a6acSopenharmony_ci type_datum_t *type; 23496cd6a6acSopenharmony_ci expand_state_t *state = ptr; 23506cd6a6acSopenharmony_ci policydb_t *p = state->out; 23516cd6a6acSopenharmony_ci unsigned int i; 23526cd6a6acSopenharmony_ci ebitmap_node_t *tnode; 23536cd6a6acSopenharmony_ci int value; 23546cd6a6acSopenharmony_ci 23556cd6a6acSopenharmony_ci type = (type_datum_t *) datum; 23566cd6a6acSopenharmony_ci value = type->s.value; 23576cd6a6acSopenharmony_ci 23586cd6a6acSopenharmony_ci if (type->flavor == TYPE_ATTRIB) { 23596cd6a6acSopenharmony_ci if (!(type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE)) { 23606cd6a6acSopenharmony_ci if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) { 23616cd6a6acSopenharmony_ci goto oom; 23626cd6a6acSopenharmony_ci } 23636cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&type->types, tnode, i) { 23646cd6a6acSopenharmony_ci if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) { 23656cd6a6acSopenharmony_ci goto oom; 23666cd6a6acSopenharmony_ci } 23676cd6a6acSopenharmony_ci } 23686cd6a6acSopenharmony_ci } else { 23696cd6a6acSopenharmony_ci /* Attribute is being expanded, so remove */ 23706cd6a6acSopenharmony_ci if (ebitmap_set_bit(&p->type_attr_map[value - 1], value - 1, 0)) { 23716cd6a6acSopenharmony_ci goto oom; 23726cd6a6acSopenharmony_ci } 23736cd6a6acSopenharmony_ci } 23746cd6a6acSopenharmony_ci } else { 23756cd6a6acSopenharmony_ci if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) { 23766cd6a6acSopenharmony_ci goto oom; 23776cd6a6acSopenharmony_ci } 23786cd6a6acSopenharmony_ci } 23796cd6a6acSopenharmony_ci 23806cd6a6acSopenharmony_ci return 0; 23816cd6a6acSopenharmony_ci 23826cd6a6acSopenharmony_cioom: 23836cd6a6acSopenharmony_ci ERR(state->handle, "Out of memory!"); 23846cd6a6acSopenharmony_ci return -1; 23856cd6a6acSopenharmony_ci} 23866cd6a6acSopenharmony_ci 23876cd6a6acSopenharmony_ci/* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy. 23886cd6a6acSopenharmony_ci * this should not be called until after all the blocks have been processed and the attributes in target policy 23896cd6a6acSopenharmony_ci * are complete. */ 23906cd6a6acSopenharmony_ciint expand_convert_type_set(policydb_t * p, uint32_t * typemap, 23916cd6a6acSopenharmony_ci type_set_t * set, ebitmap_t * types, 23926cd6a6acSopenharmony_ci unsigned char alwaysexpand) 23936cd6a6acSopenharmony_ci{ 23946cd6a6acSopenharmony_ci type_set_t tmpset; 23956cd6a6acSopenharmony_ci 23966cd6a6acSopenharmony_ci type_set_init(&tmpset); 23976cd6a6acSopenharmony_ci 23986cd6a6acSopenharmony_ci if (map_ebitmap(&set->types, &tmpset.types, typemap)) 23996cd6a6acSopenharmony_ci return -1; 24006cd6a6acSopenharmony_ci 24016cd6a6acSopenharmony_ci if (map_ebitmap(&set->negset, &tmpset.negset, typemap)) 24026cd6a6acSopenharmony_ci return -1; 24036cd6a6acSopenharmony_ci 24046cd6a6acSopenharmony_ci tmpset.flags = set->flags; 24056cd6a6acSopenharmony_ci 24066cd6a6acSopenharmony_ci if (type_set_expand(&tmpset, types, p, alwaysexpand)) 24076cd6a6acSopenharmony_ci return -1; 24086cd6a6acSopenharmony_ci 24096cd6a6acSopenharmony_ci type_set_destroy(&tmpset); 24106cd6a6acSopenharmony_ci 24116cd6a6acSopenharmony_ci return 0; 24126cd6a6acSopenharmony_ci} 24136cd6a6acSopenharmony_ci 24146cd6a6acSopenharmony_ci/* Expand a rule into a given avtab - checking for conflicting type 24156cd6a6acSopenharmony_ci * rules. Return 1 on success, 0 if the rule conflicts with something 24166cd6a6acSopenharmony_ci * (and hence was not added), or -1 on error. */ 24176cd6a6acSopenharmony_ciint expand_rule(sepol_handle_t * handle, 24186cd6a6acSopenharmony_ci policydb_t * source_pol, 24196cd6a6acSopenharmony_ci avrule_t * source_rule, avtab_t * dest_avtab, 24206cd6a6acSopenharmony_ci cond_av_list_t ** cond, cond_av_list_t ** other, int enabled) 24216cd6a6acSopenharmony_ci{ 24226cd6a6acSopenharmony_ci int retval; 24236cd6a6acSopenharmony_ci ebitmap_t stypes, ttypes; 24246cd6a6acSopenharmony_ci 24256cd6a6acSopenharmony_ci if ((source_rule->specified & AVRULE_NEVERALLOW) 24266cd6a6acSopenharmony_ci || (source_rule->specified & AVRULE_XPERMS_NEVERALLOW)) 24276cd6a6acSopenharmony_ci return 1; 24286cd6a6acSopenharmony_ci 24296cd6a6acSopenharmony_ci ebitmap_init(&stypes); 24306cd6a6acSopenharmony_ci ebitmap_init(&ttypes); 24316cd6a6acSopenharmony_ci 24326cd6a6acSopenharmony_ci if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1)) 24336cd6a6acSopenharmony_ci return -1; 24346cd6a6acSopenharmony_ci if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1)) 24356cd6a6acSopenharmony_ci return -1; 24366cd6a6acSopenharmony_ci retval = expand_rule_helper(handle, source_pol, NULL, 24376cd6a6acSopenharmony_ci source_rule, dest_avtab, 24386cd6a6acSopenharmony_ci cond, other, enabled, &stypes, &ttypes); 24396cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 24406cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 24416cd6a6acSopenharmony_ci return retval; 24426cd6a6acSopenharmony_ci} 24436cd6a6acSopenharmony_ci 24446cd6a6acSopenharmony_ci/* Expand a role set into an ebitmap containing the roles. 24456cd6a6acSopenharmony_ci * This handles the attribute and flags. 24466cd6a6acSopenharmony_ci * Attribute expansion depends on if the rolemap is available. 24476cd6a6acSopenharmony_ci * During module compile the rolemap is not available, the 24486cd6a6acSopenharmony_ci * possible duplicates of a regular role and the role attribute 24496cd6a6acSopenharmony_ci * the regular role belongs to could be properly handled by 24506cd6a6acSopenharmony_ci * copy_role_trans and copy_role_allow. 24516cd6a6acSopenharmony_ci */ 24526cd6a6acSopenharmony_ciint role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap) 24536cd6a6acSopenharmony_ci{ 24546cd6a6acSopenharmony_ci unsigned int i; 24556cd6a6acSopenharmony_ci ebitmap_node_t *rnode; 24566cd6a6acSopenharmony_ci ebitmap_t mapped_roles, roles; 24576cd6a6acSopenharmony_ci policydb_t *p = out; 24586cd6a6acSopenharmony_ci role_datum_t *role; 24596cd6a6acSopenharmony_ci 24606cd6a6acSopenharmony_ci ebitmap_init(r); 24616cd6a6acSopenharmony_ci 24626cd6a6acSopenharmony_ci if (x->flags & ROLE_STAR) { 24636cd6a6acSopenharmony_ci for (i = 0; i < p->p_roles.nprim; i++) 24646cd6a6acSopenharmony_ci if (ebitmap_set_bit(r, i, 1)) 24656cd6a6acSopenharmony_ci return -1; 24666cd6a6acSopenharmony_ci return 0; 24676cd6a6acSopenharmony_ci } 24686cd6a6acSopenharmony_ci 24696cd6a6acSopenharmony_ci ebitmap_init(&mapped_roles); 24706cd6a6acSopenharmony_ci ebitmap_init(&roles); 24716cd6a6acSopenharmony_ci 24726cd6a6acSopenharmony_ci if (rolemap) { 24736cd6a6acSopenharmony_ci assert(base != NULL); 24746cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&x->roles, rnode, i) { 24756cd6a6acSopenharmony_ci /* take advantage of p_role_val_to_struct[] 24766cd6a6acSopenharmony_ci * of the base module */ 24776cd6a6acSopenharmony_ci role = base->role_val_to_struct[i]; 24786cd6a6acSopenharmony_ci assert(role != NULL); 24796cd6a6acSopenharmony_ci if (role->flavor == ROLE_ATTRIB) { 24806cd6a6acSopenharmony_ci if (ebitmap_union(&roles, 24816cd6a6acSopenharmony_ci &role->roles)) 24826cd6a6acSopenharmony_ci goto bad; 24836cd6a6acSopenharmony_ci } else { 24846cd6a6acSopenharmony_ci if (ebitmap_set_bit(&roles, i, 1)) 24856cd6a6acSopenharmony_ci goto bad; 24866cd6a6acSopenharmony_ci } 24876cd6a6acSopenharmony_ci } 24886cd6a6acSopenharmony_ci if (map_ebitmap(&roles, &mapped_roles, rolemap)) 24896cd6a6acSopenharmony_ci goto bad; 24906cd6a6acSopenharmony_ci } else { 24916cd6a6acSopenharmony_ci if (ebitmap_cpy(&mapped_roles, &x->roles)) 24926cd6a6acSopenharmony_ci goto bad; 24936cd6a6acSopenharmony_ci } 24946cd6a6acSopenharmony_ci 24956cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&mapped_roles, rnode, i) { 24966cd6a6acSopenharmony_ci if (ebitmap_set_bit(r, i, 1)) 24976cd6a6acSopenharmony_ci goto bad; 24986cd6a6acSopenharmony_ci } 24996cd6a6acSopenharmony_ci 25006cd6a6acSopenharmony_ci ebitmap_destroy(&mapped_roles); 25016cd6a6acSopenharmony_ci ebitmap_destroy(&roles); 25026cd6a6acSopenharmony_ci 25036cd6a6acSopenharmony_ci /* if role is to be complimented, invert the entire bitmap here */ 25046cd6a6acSopenharmony_ci if (x->flags & ROLE_COMP) { 25056cd6a6acSopenharmony_ci for (i = 0; i < p->p_roles.nprim; i++) { 25066cd6a6acSopenharmony_ci if (ebitmap_get_bit(r, i)) { 25076cd6a6acSopenharmony_ci if (ebitmap_set_bit(r, i, 0)) 25086cd6a6acSopenharmony_ci return -1; 25096cd6a6acSopenharmony_ci } else { 25106cd6a6acSopenharmony_ci if (ebitmap_set_bit(r, i, 1)) 25116cd6a6acSopenharmony_ci return -1; 25126cd6a6acSopenharmony_ci } 25136cd6a6acSopenharmony_ci } 25146cd6a6acSopenharmony_ci } 25156cd6a6acSopenharmony_ci return 0; 25166cd6a6acSopenharmony_ci 25176cd6a6acSopenharmony_cibad: 25186cd6a6acSopenharmony_ci ebitmap_destroy(&mapped_roles); 25196cd6a6acSopenharmony_ci ebitmap_destroy(&roles); 25206cd6a6acSopenharmony_ci return -1; 25216cd6a6acSopenharmony_ci} 25226cd6a6acSopenharmony_ci 25236cd6a6acSopenharmony_ci/* Expand a type set into an ebitmap containing the types. This 25246cd6a6acSopenharmony_ci * handles the negset, attributes, and flags. 25256cd6a6acSopenharmony_ci * Attribute expansion depends on several factors: 25266cd6a6acSopenharmony_ci * - if alwaysexpand is 1, then they will be expanded, 25276cd6a6acSopenharmony_ci * - if the type set has a negset or flags, then they will be expanded, 25286cd6a6acSopenharmony_ci * - otherwise, they will not be expanded. 25296cd6a6acSopenharmony_ci */ 25306cd6a6acSopenharmony_ciint type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, 25316cd6a6acSopenharmony_ci unsigned char alwaysexpand) 25326cd6a6acSopenharmony_ci{ 25336cd6a6acSopenharmony_ci unsigned int i; 25346cd6a6acSopenharmony_ci ebitmap_t types, neg_types; 25356cd6a6acSopenharmony_ci ebitmap_node_t *tnode; 25366cd6a6acSopenharmony_ci unsigned char expand = alwaysexpand || !ebitmap_is_empty(&set->negset) || set->flags; 25376cd6a6acSopenharmony_ci type_datum_t *type; 25386cd6a6acSopenharmony_ci int rc =-1; 25396cd6a6acSopenharmony_ci 25406cd6a6acSopenharmony_ci ebitmap_init(&types); 25416cd6a6acSopenharmony_ci ebitmap_init(t); 25426cd6a6acSopenharmony_ci 25436cd6a6acSopenharmony_ci /* First go through the types and OR all the attributes to types */ 25446cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&set->types, tnode, i) { 25456cd6a6acSopenharmony_ci /* 25466cd6a6acSopenharmony_ci * invalid policies might have more types set in the ebitmap than 25476cd6a6acSopenharmony_ci * what's available in the type_val_to_struct mapping 25486cd6a6acSopenharmony_ci */ 25496cd6a6acSopenharmony_ci if (i >= p->p_types.nprim) 25506cd6a6acSopenharmony_ci goto err_types; 25516cd6a6acSopenharmony_ci 25526cd6a6acSopenharmony_ci type = p->type_val_to_struct[i]; 25536cd6a6acSopenharmony_ci 25546cd6a6acSopenharmony_ci if (!type) { 25556cd6a6acSopenharmony_ci goto err_types; 25566cd6a6acSopenharmony_ci } 25576cd6a6acSopenharmony_ci 25586cd6a6acSopenharmony_ci if (type->flavor == TYPE_ATTRIB && 25596cd6a6acSopenharmony_ci (expand || (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE))) { 25606cd6a6acSopenharmony_ci if (ebitmap_union(&types, &type->types)) { 25616cd6a6acSopenharmony_ci goto err_types; 25626cd6a6acSopenharmony_ci } 25636cd6a6acSopenharmony_ci } else { 25646cd6a6acSopenharmony_ci if (ebitmap_set_bit(&types, i, 1)) { 25656cd6a6acSopenharmony_ci goto err_types; 25666cd6a6acSopenharmony_ci } 25676cd6a6acSopenharmony_ci } 25686cd6a6acSopenharmony_ci } 25696cd6a6acSopenharmony_ci 25706cd6a6acSopenharmony_ci /* Now do the same thing for negset */ 25716cd6a6acSopenharmony_ci ebitmap_init(&neg_types); 25726cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&set->negset, tnode, i) { 25736cd6a6acSopenharmony_ci if (p->type_val_to_struct[i] && 25746cd6a6acSopenharmony_ci p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { 25756cd6a6acSopenharmony_ci if (ebitmap_union 25766cd6a6acSopenharmony_ci (&neg_types, 25776cd6a6acSopenharmony_ci &p->type_val_to_struct[i]->types)) { 25786cd6a6acSopenharmony_ci goto err_neg; 25796cd6a6acSopenharmony_ci } 25806cd6a6acSopenharmony_ci } else { 25816cd6a6acSopenharmony_ci if (ebitmap_set_bit(&neg_types, i, 1)) { 25826cd6a6acSopenharmony_ci goto err_neg; 25836cd6a6acSopenharmony_ci } 25846cd6a6acSopenharmony_ci } 25856cd6a6acSopenharmony_ci } 25866cd6a6acSopenharmony_ci 25876cd6a6acSopenharmony_ci if (set->flags & TYPE_STAR) { 25886cd6a6acSopenharmony_ci /* set all types not in neg_types */ 25896cd6a6acSopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) { 25906cd6a6acSopenharmony_ci if (ebitmap_get_bit(&neg_types, i)) 25916cd6a6acSopenharmony_ci continue; 25926cd6a6acSopenharmony_ci if (p->type_val_to_struct[i] && 25936cd6a6acSopenharmony_ci p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) 25946cd6a6acSopenharmony_ci continue; 25956cd6a6acSopenharmony_ci if (ebitmap_set_bit(t, i, 1)) 25966cd6a6acSopenharmony_ci goto err_neg; 25976cd6a6acSopenharmony_ci } 25986cd6a6acSopenharmony_ci goto out; 25996cd6a6acSopenharmony_ci } 26006cd6a6acSopenharmony_ci 26016cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&types, tnode, i) { 26026cd6a6acSopenharmony_ci if (!ebitmap_get_bit(&neg_types, i)) 26036cd6a6acSopenharmony_ci if (ebitmap_set_bit(t, i, 1)) 26046cd6a6acSopenharmony_ci goto err_neg; 26056cd6a6acSopenharmony_ci } 26066cd6a6acSopenharmony_ci 26076cd6a6acSopenharmony_ci if (set->flags & TYPE_COMP) { 26086cd6a6acSopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) { 26096cd6a6acSopenharmony_ci if (p->type_val_to_struct[i] && 26106cd6a6acSopenharmony_ci p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { 26116cd6a6acSopenharmony_ci assert(!ebitmap_get_bit(t, i)); 26126cd6a6acSopenharmony_ci continue; 26136cd6a6acSopenharmony_ci } 26146cd6a6acSopenharmony_ci if (ebitmap_get_bit(t, i)) { 26156cd6a6acSopenharmony_ci if (ebitmap_set_bit(t, i, 0)) 26166cd6a6acSopenharmony_ci goto err_neg; 26176cd6a6acSopenharmony_ci } else { 26186cd6a6acSopenharmony_ci if (ebitmap_set_bit(t, i, 1)) 26196cd6a6acSopenharmony_ci goto err_neg; 26206cd6a6acSopenharmony_ci } 26216cd6a6acSopenharmony_ci } 26226cd6a6acSopenharmony_ci } 26236cd6a6acSopenharmony_ci 26246cd6a6acSopenharmony_ci out: 26256cd6a6acSopenharmony_ci rc = 0; 26266cd6a6acSopenharmony_ci 26276cd6a6acSopenharmony_ci err_neg: 26286cd6a6acSopenharmony_ci ebitmap_destroy(&neg_types); 26296cd6a6acSopenharmony_ci err_types: 26306cd6a6acSopenharmony_ci ebitmap_destroy(&types); 26316cd6a6acSopenharmony_ci 26326cd6a6acSopenharmony_ci return rc; 26336cd6a6acSopenharmony_ci} 26346cd6a6acSopenharmony_ci 26356cd6a6acSopenharmony_cistatic int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, 26366cd6a6acSopenharmony_ci avrule_t * source_rule) 26376cd6a6acSopenharmony_ci{ 26386cd6a6acSopenharmony_ci ebitmap_t stypes, ttypes; 26396cd6a6acSopenharmony_ci avrule_t *avrule; 26406cd6a6acSopenharmony_ci class_perm_node_t *cur_perm, *new_perm, *tail_perm; 26416cd6a6acSopenharmony_ci av_extended_perms_t *xperms = NULL; 26426cd6a6acSopenharmony_ci 26436cd6a6acSopenharmony_ci ebitmap_init(&stypes); 26446cd6a6acSopenharmony_ci ebitmap_init(&ttypes); 26456cd6a6acSopenharmony_ci 26466cd6a6acSopenharmony_ci if (expand_convert_type_set 26476cd6a6acSopenharmony_ci (dest_pol, typemap, &source_rule->stypes, &stypes, 1)) 26486cd6a6acSopenharmony_ci return -1; 26496cd6a6acSopenharmony_ci if (expand_convert_type_set 26506cd6a6acSopenharmony_ci (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1)) 26516cd6a6acSopenharmony_ci return -1; 26526cd6a6acSopenharmony_ci 26536cd6a6acSopenharmony_ci avrule = (avrule_t *) malloc(sizeof(avrule_t)); 26546cd6a6acSopenharmony_ci if (!avrule) 26556cd6a6acSopenharmony_ci return -1; 26566cd6a6acSopenharmony_ci 26576cd6a6acSopenharmony_ci avrule_init(avrule); 26586cd6a6acSopenharmony_ci avrule->specified = source_rule->specified; 26596cd6a6acSopenharmony_ci avrule->line = source_rule->line; 26606cd6a6acSopenharmony_ci avrule->flags = source_rule->flags; 26616cd6a6acSopenharmony_ci avrule->source_line = source_rule->source_line; 26626cd6a6acSopenharmony_ci if (source_rule->source_filename) { 26636cd6a6acSopenharmony_ci avrule->source_filename = strdup(source_rule->source_filename); 26646cd6a6acSopenharmony_ci if (!avrule->source_filename) 26656cd6a6acSopenharmony_ci goto err; 26666cd6a6acSopenharmony_ci } 26676cd6a6acSopenharmony_ci 26686cd6a6acSopenharmony_ci if (ebitmap_cpy(&avrule->stypes.types, &stypes)) 26696cd6a6acSopenharmony_ci goto err; 26706cd6a6acSopenharmony_ci 26716cd6a6acSopenharmony_ci if (ebitmap_cpy(&avrule->ttypes.types, &ttypes)) 26726cd6a6acSopenharmony_ci goto err; 26736cd6a6acSopenharmony_ci 26746cd6a6acSopenharmony_ci cur_perm = source_rule->perms; 26756cd6a6acSopenharmony_ci tail_perm = NULL; 26766cd6a6acSopenharmony_ci while (cur_perm) { 26776cd6a6acSopenharmony_ci new_perm = 26786cd6a6acSopenharmony_ci (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); 26796cd6a6acSopenharmony_ci if (!new_perm) 26806cd6a6acSopenharmony_ci goto err; 26816cd6a6acSopenharmony_ci class_perm_node_init(new_perm); 26826cd6a6acSopenharmony_ci new_perm->tclass = cur_perm->tclass; 26836cd6a6acSopenharmony_ci assert(new_perm->tclass); 26846cd6a6acSopenharmony_ci 26856cd6a6acSopenharmony_ci /* once we have modules with permissions we'll need to map the permissions (and classes) */ 26866cd6a6acSopenharmony_ci new_perm->data = cur_perm->data; 26876cd6a6acSopenharmony_ci 26886cd6a6acSopenharmony_ci if (!avrule->perms) 26896cd6a6acSopenharmony_ci avrule->perms = new_perm; 26906cd6a6acSopenharmony_ci 26916cd6a6acSopenharmony_ci if (tail_perm) 26926cd6a6acSopenharmony_ci tail_perm->next = new_perm; 26936cd6a6acSopenharmony_ci tail_perm = new_perm; 26946cd6a6acSopenharmony_ci cur_perm = cur_perm->next; 26956cd6a6acSopenharmony_ci } 26966cd6a6acSopenharmony_ci 26976cd6a6acSopenharmony_ci /* copy over extended permissions */ 26986cd6a6acSopenharmony_ci if (source_rule->xperms) { 26996cd6a6acSopenharmony_ci xperms = calloc(1, sizeof(av_extended_perms_t)); 27006cd6a6acSopenharmony_ci if (!xperms) 27016cd6a6acSopenharmony_ci goto err; 27026cd6a6acSopenharmony_ci memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t)); 27036cd6a6acSopenharmony_ci avrule->xperms = xperms; 27046cd6a6acSopenharmony_ci } 27056cd6a6acSopenharmony_ci 27066cd6a6acSopenharmony_ci /* just prepend the avrule to the first branch; it'll never be 27076cd6a6acSopenharmony_ci written to disk */ 27086cd6a6acSopenharmony_ci if (!dest_pol->global->branch_list->avrules) 27096cd6a6acSopenharmony_ci dest_pol->global->branch_list->avrules = avrule; 27106cd6a6acSopenharmony_ci else { 27116cd6a6acSopenharmony_ci avrule->next = dest_pol->global->branch_list->avrules; 27126cd6a6acSopenharmony_ci dest_pol->global->branch_list->avrules = avrule; 27136cd6a6acSopenharmony_ci } 27146cd6a6acSopenharmony_ci 27156cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 27166cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 27176cd6a6acSopenharmony_ci 27186cd6a6acSopenharmony_ci return 0; 27196cd6a6acSopenharmony_ci 27206cd6a6acSopenharmony_ci err: 27216cd6a6acSopenharmony_ci ebitmap_destroy(&stypes); 27226cd6a6acSopenharmony_ci ebitmap_destroy(&ttypes); 27236cd6a6acSopenharmony_ci ebitmap_destroy(&avrule->stypes.types); 27246cd6a6acSopenharmony_ci ebitmap_destroy(&avrule->ttypes.types); 27256cd6a6acSopenharmony_ci cur_perm = avrule->perms; 27266cd6a6acSopenharmony_ci while (cur_perm) { 27276cd6a6acSopenharmony_ci tail_perm = cur_perm->next; 27286cd6a6acSopenharmony_ci free(cur_perm); 27296cd6a6acSopenharmony_ci cur_perm = tail_perm; 27306cd6a6acSopenharmony_ci } 27316cd6a6acSopenharmony_ci free(xperms); 27326cd6a6acSopenharmony_ci free(avrule); 27336cd6a6acSopenharmony_ci return -1; 27346cd6a6acSopenharmony_ci} 27356cd6a6acSopenharmony_ci 27366cd6a6acSopenharmony_ci/* 27376cd6a6acSopenharmony_ci * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow 27386cd6a6acSopenharmony_ci * rules are copied or expanded as per the settings in the state object; all 27396cd6a6acSopenharmony_ci * other AV rules are expanded. If neverallow rules are expanded, they are not 27406cd6a6acSopenharmony_ci * copied, otherwise they are copied for later use by the assertion checker. 27416cd6a6acSopenharmony_ci */ 27426cd6a6acSopenharmony_cistatic int copy_and_expand_avrule_block(expand_state_t * state) 27436cd6a6acSopenharmony_ci{ 27446cd6a6acSopenharmony_ci avrule_block_t *curblock = state->base->global; 27456cd6a6acSopenharmony_ci avrule_block_t *prevblock; 27466cd6a6acSopenharmony_ci int retval = -1; 27476cd6a6acSopenharmony_ci 27486cd6a6acSopenharmony_ci if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) { 27496cd6a6acSopenharmony_ci ERR(state->handle, "Out of Memory!"); 27506cd6a6acSopenharmony_ci return -1; 27516cd6a6acSopenharmony_ci } 27526cd6a6acSopenharmony_ci 27536cd6a6acSopenharmony_ci if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) { 27546cd6a6acSopenharmony_ci ERR(state->handle, "Out of Memory!"); 27556cd6a6acSopenharmony_ci return -1; 27566cd6a6acSopenharmony_ci } 27576cd6a6acSopenharmony_ci 27586cd6a6acSopenharmony_ci while (curblock) { 27596cd6a6acSopenharmony_ci avrule_decl_t *decl = curblock->enabled; 27606cd6a6acSopenharmony_ci avrule_t *cur_avrule; 27616cd6a6acSopenharmony_ci 27626cd6a6acSopenharmony_ci if (decl == NULL) { 27636cd6a6acSopenharmony_ci /* nothing was enabled within this block */ 27646cd6a6acSopenharmony_ci goto cont; 27656cd6a6acSopenharmony_ci } 27666cd6a6acSopenharmony_ci 27676cd6a6acSopenharmony_ci /* copy role allows and role trans */ 27686cd6a6acSopenharmony_ci if (copy_role_allows(state, decl->role_allow_rules) != 0 || 27696cd6a6acSopenharmony_ci copy_role_trans(state, decl->role_tr_rules) != 0) { 27706cd6a6acSopenharmony_ci goto cleanup; 27716cd6a6acSopenharmony_ci } 27726cd6a6acSopenharmony_ci 27736cd6a6acSopenharmony_ci if (expand_filename_trans(state, decl->filename_trans_rules)) 27746cd6a6acSopenharmony_ci goto cleanup; 27756cd6a6acSopenharmony_ci 27766cd6a6acSopenharmony_ci /* expand the range transition rules */ 27776cd6a6acSopenharmony_ci if (expand_range_trans(state, decl->range_tr_rules)) 27786cd6a6acSopenharmony_ci goto cleanup; 27796cd6a6acSopenharmony_ci 27806cd6a6acSopenharmony_ci /* copy rules */ 27816cd6a6acSopenharmony_ci cur_avrule = decl->avrules; 27826cd6a6acSopenharmony_ci while (cur_avrule != NULL) { 27836cd6a6acSopenharmony_ci if (!(state->expand_neverallow) 27846cd6a6acSopenharmony_ci && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) { 27856cd6a6acSopenharmony_ci /* copy this over directly so that assertions are checked later */ 27866cd6a6acSopenharmony_ci if (copy_neverallow 27876cd6a6acSopenharmony_ci (state->out, state->typemap, cur_avrule)) 27886cd6a6acSopenharmony_ci ERR(state->handle, 27896cd6a6acSopenharmony_ci "Error while copying neverallow."); 27906cd6a6acSopenharmony_ci } else { 27916cd6a6acSopenharmony_ci if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) 27926cd6a6acSopenharmony_ci state->out->unsupported_format = 1; 27936cd6a6acSopenharmony_ci if (convert_and_expand_rule 27946cd6a6acSopenharmony_ci (state->handle, state->out, state->typemap, 27956cd6a6acSopenharmony_ci cur_avrule, &state->out->te_avtab, NULL, 27966cd6a6acSopenharmony_ci NULL, 0, 27976cd6a6acSopenharmony_ci state->expand_neverallow) != 27986cd6a6acSopenharmony_ci EXPAND_RULE_SUCCESS) { 27996cd6a6acSopenharmony_ci goto cleanup; 28006cd6a6acSopenharmony_ci } 28016cd6a6acSopenharmony_ci } 28026cd6a6acSopenharmony_ci cur_avrule = cur_avrule->next; 28036cd6a6acSopenharmony_ci } 28046cd6a6acSopenharmony_ci 28056cd6a6acSopenharmony_ci /* copy conditional rules */ 28066cd6a6acSopenharmony_ci if (cond_node_copy(state, decl->cond_list)) 28076cd6a6acSopenharmony_ci goto cleanup; 28086cd6a6acSopenharmony_ci 28096cd6a6acSopenharmony_ci cont: 28106cd6a6acSopenharmony_ci prevblock = curblock; 28116cd6a6acSopenharmony_ci curblock = curblock->next; 28126cd6a6acSopenharmony_ci 28136cd6a6acSopenharmony_ci if (state->handle && state->handle->expand_consume_base) { 28146cd6a6acSopenharmony_ci /* set base top avrule block in case there 28156cd6a6acSopenharmony_ci * is an error condition and the policy needs 28166cd6a6acSopenharmony_ci * to be destroyed */ 28176cd6a6acSopenharmony_ci state->base->global = curblock; 28186cd6a6acSopenharmony_ci avrule_block_destroy(prevblock); 28196cd6a6acSopenharmony_ci } 28206cd6a6acSopenharmony_ci } 28216cd6a6acSopenharmony_ci 28226cd6a6acSopenharmony_ci retval = 0; 28236cd6a6acSopenharmony_ci 28246cd6a6acSopenharmony_ci cleanup: 28256cd6a6acSopenharmony_ci return retval; 28266cd6a6acSopenharmony_ci} 28276cd6a6acSopenharmony_ci 28286cd6a6acSopenharmony_ci/* 28296cd6a6acSopenharmony_ci * This function allows external users of the library (such as setools) to 28306cd6a6acSopenharmony_ci * expand only the avrules and optionally perform expansion of neverallow rules 28316cd6a6acSopenharmony_ci * or expand into the same policy for analysis purposes. 28326cd6a6acSopenharmony_ci */ 28336cd6a6acSopenharmony_ciint expand_module_avrules(sepol_handle_t * handle, policydb_t * base, 28346cd6a6acSopenharmony_ci policydb_t * out, uint32_t * typemap, 28356cd6a6acSopenharmony_ci uint32_t * boolmap, uint32_t * rolemap, 28366cd6a6acSopenharmony_ci uint32_t * usermap, int verbose, 28376cd6a6acSopenharmony_ci int expand_neverallow) 28386cd6a6acSopenharmony_ci{ 28396cd6a6acSopenharmony_ci expand_state_t state; 28406cd6a6acSopenharmony_ci 28416cd6a6acSopenharmony_ci expand_state_init(&state); 28426cd6a6acSopenharmony_ci 28436cd6a6acSopenharmony_ci state.base = base; 28446cd6a6acSopenharmony_ci state.out = out; 28456cd6a6acSopenharmony_ci state.typemap = typemap; 28466cd6a6acSopenharmony_ci state.boolmap = boolmap; 28476cd6a6acSopenharmony_ci state.rolemap = rolemap; 28486cd6a6acSopenharmony_ci state.usermap = usermap; 28496cd6a6acSopenharmony_ci state.handle = handle; 28506cd6a6acSopenharmony_ci state.verbose = verbose; 28516cd6a6acSopenharmony_ci state.expand_neverallow = expand_neverallow; 28526cd6a6acSopenharmony_ci 28536cd6a6acSopenharmony_ci return copy_and_expand_avrule_block(&state); 28546cd6a6acSopenharmony_ci} 28556cd6a6acSopenharmony_ci 28566cd6a6acSopenharmony_cistatic void discard_tunables(sepol_handle_t *sh, policydb_t *pol) 28576cd6a6acSopenharmony_ci{ 28586cd6a6acSopenharmony_ci avrule_block_t *block; 28596cd6a6acSopenharmony_ci avrule_decl_t *decl; 28606cd6a6acSopenharmony_ci cond_node_t *cur_node; 28616cd6a6acSopenharmony_ci cond_expr_t *cur_expr; 28626cd6a6acSopenharmony_ci int cur_state, preserve_tunables = 0; 28636cd6a6acSopenharmony_ci avrule_t *tail, *to_be_appended; 28646cd6a6acSopenharmony_ci 28656cd6a6acSopenharmony_ci if (sh && sh->preserve_tunables) 28666cd6a6acSopenharmony_ci preserve_tunables = 1; 28676cd6a6acSopenharmony_ci 28686cd6a6acSopenharmony_ci /* Iterate through all cond_node of all enabled decls, if a cond_node 28696cd6a6acSopenharmony_ci * is about tunable, calculate its state value and concatenate one of 28706cd6a6acSopenharmony_ci * its avrule list to the current decl->avrules list. On the other 28716cd6a6acSopenharmony_ci * hand, the disabled unused branch of a tunable would be discarded. 28726cd6a6acSopenharmony_ci * 28736cd6a6acSopenharmony_ci * Note, such tunable cond_node would be skipped over in expansion, 28746cd6a6acSopenharmony_ci * so we won't have to worry about removing it from decl->cond_list 28756cd6a6acSopenharmony_ci * here :-) 28766cd6a6acSopenharmony_ci * 28776cd6a6acSopenharmony_ci * If tunables are requested to be preserved then they would be 28786cd6a6acSopenharmony_ci * "transformed" as booleans by having their TUNABLE flag cleared. 28796cd6a6acSopenharmony_ci */ 28806cd6a6acSopenharmony_ci for (block = pol->global; block != NULL; block = block->next) { 28816cd6a6acSopenharmony_ci decl = block->enabled; 28826cd6a6acSopenharmony_ci if (decl == NULL || decl->enabled == 0) 28836cd6a6acSopenharmony_ci continue; 28846cd6a6acSopenharmony_ci 28856cd6a6acSopenharmony_ci tail = decl->avrules; 28866cd6a6acSopenharmony_ci while (tail && tail->next) 28876cd6a6acSopenharmony_ci tail = tail->next; 28886cd6a6acSopenharmony_ci 28896cd6a6acSopenharmony_ci for (cur_node = decl->cond_list; cur_node != NULL; 28906cd6a6acSopenharmony_ci cur_node = cur_node->next) { 28916cd6a6acSopenharmony_ci int booleans, tunables, i; 28926cd6a6acSopenharmony_ci cond_bool_datum_t *booldatum; 28936cd6a6acSopenharmony_ci cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH]; 28946cd6a6acSopenharmony_ci 28956cd6a6acSopenharmony_ci booleans = tunables = 0; 28966cd6a6acSopenharmony_ci memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH); 28976cd6a6acSopenharmony_ci 28986cd6a6acSopenharmony_ci for (cur_expr = cur_node->expr; cur_expr != NULL; 28996cd6a6acSopenharmony_ci cur_expr = cur_expr->next) { 29006cd6a6acSopenharmony_ci if (cur_expr->expr_type != COND_BOOL) 29016cd6a6acSopenharmony_ci continue; 29026cd6a6acSopenharmony_ci booldatum = pol->bool_val_to_struct[cur_expr->bool - 1]; 29036cd6a6acSopenharmony_ci if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE) 29046cd6a6acSopenharmony_ci tmp[tunables++] = booldatum; 29056cd6a6acSopenharmony_ci else 29066cd6a6acSopenharmony_ci booleans++; 29076cd6a6acSopenharmony_ci } 29086cd6a6acSopenharmony_ci 29096cd6a6acSopenharmony_ci /* bool_copy_callback() at link phase has ensured 29106cd6a6acSopenharmony_ci * that no mixture of tunables and booleans in one 29116cd6a6acSopenharmony_ci * expression. However, this would be broken by the 29126cd6a6acSopenharmony_ci * request to preserve tunables */ 29136cd6a6acSopenharmony_ci if (!preserve_tunables) 29146cd6a6acSopenharmony_ci assert(!(booleans && tunables)); 29156cd6a6acSopenharmony_ci 29166cd6a6acSopenharmony_ci if (booleans || preserve_tunables) { 29176cd6a6acSopenharmony_ci cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE; 29186cd6a6acSopenharmony_ci if (tunables) { 29196cd6a6acSopenharmony_ci for (i = 0; i < tunables; i++) 29206cd6a6acSopenharmony_ci tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE; 29216cd6a6acSopenharmony_ci } 29226cd6a6acSopenharmony_ci } else { 29236cd6a6acSopenharmony_ci cur_node->flags |= COND_NODE_FLAGS_TUNABLE; 29246cd6a6acSopenharmony_ci cur_state = cond_evaluate_expr(pol, cur_node->expr); 29256cd6a6acSopenharmony_ci if (cur_state == -1) { 29266cd6a6acSopenharmony_ci printf("Expression result was " 29276cd6a6acSopenharmony_ci "undefined, skipping all" 29286cd6a6acSopenharmony_ci "rules\n"); 29296cd6a6acSopenharmony_ci continue; 29306cd6a6acSopenharmony_ci } 29316cd6a6acSopenharmony_ci 29326cd6a6acSopenharmony_ci to_be_appended = (cur_state == 1) ? 29336cd6a6acSopenharmony_ci cur_node->avtrue_list : cur_node->avfalse_list; 29346cd6a6acSopenharmony_ci 29356cd6a6acSopenharmony_ci if (tail) 29366cd6a6acSopenharmony_ci tail->next = to_be_appended; 29376cd6a6acSopenharmony_ci else 29386cd6a6acSopenharmony_ci tail = decl->avrules = to_be_appended; 29396cd6a6acSopenharmony_ci 29406cd6a6acSopenharmony_ci /* Now that the effective branch has been 29416cd6a6acSopenharmony_ci * appended, neutralize its original pointer */ 29426cd6a6acSopenharmony_ci if (cur_state == 1) 29436cd6a6acSopenharmony_ci cur_node->avtrue_list = NULL; 29446cd6a6acSopenharmony_ci else 29456cd6a6acSopenharmony_ci cur_node->avfalse_list = NULL; 29466cd6a6acSopenharmony_ci 29476cd6a6acSopenharmony_ci /* Update the tail of decl->avrules for 29486cd6a6acSopenharmony_ci * further concatenation */ 29496cd6a6acSopenharmony_ci while (tail && tail->next) 29506cd6a6acSopenharmony_ci tail = tail->next; 29516cd6a6acSopenharmony_ci } 29526cd6a6acSopenharmony_ci } 29536cd6a6acSopenharmony_ci } 29546cd6a6acSopenharmony_ci} 29556cd6a6acSopenharmony_ci 29566cd6a6acSopenharmony_ci/* Linking should always be done before calling expand, even if 29576cd6a6acSopenharmony_ci * there is only a base since all optionals are dealt with at link time 29586cd6a6acSopenharmony_ci * the base passed in should be indexed and avrule blocks should be 29596cd6a6acSopenharmony_ci * enabled. 29606cd6a6acSopenharmony_ci */ 29616cd6a6acSopenharmony_ciint expand_module(sepol_handle_t * handle, 29626cd6a6acSopenharmony_ci policydb_t * base, policydb_t * out, int verbose, int check) 29636cd6a6acSopenharmony_ci{ 29646cd6a6acSopenharmony_ci int retval = -1; 29656cd6a6acSopenharmony_ci unsigned int i; 29666cd6a6acSopenharmony_ci expand_state_t state; 29676cd6a6acSopenharmony_ci avrule_block_t *curblock; 29686cd6a6acSopenharmony_ci 29696cd6a6acSopenharmony_ci /* Append tunable's avtrue_list or avfalse_list to the avrules list 29706cd6a6acSopenharmony_ci * of its home decl depending on its state value, so that the effect 29716cd6a6acSopenharmony_ci * rules of a tunable would be added to te_avtab permanently. Whereas 29726cd6a6acSopenharmony_ci * the disabled unused branch would be discarded. 29736cd6a6acSopenharmony_ci * 29746cd6a6acSopenharmony_ci * Originally this function is called at the very end of link phase, 29756cd6a6acSopenharmony_ci * however, we need to keep the linked policy intact for analysis 29766cd6a6acSopenharmony_ci * purpose. */ 29776cd6a6acSopenharmony_ci discard_tunables(handle, base); 29786cd6a6acSopenharmony_ci 29796cd6a6acSopenharmony_ci expand_state_init(&state); 29806cd6a6acSopenharmony_ci 29816cd6a6acSopenharmony_ci state.verbose = verbose; 29826cd6a6acSopenharmony_ci state.typemap = NULL; 29836cd6a6acSopenharmony_ci state.base = base; 29846cd6a6acSopenharmony_ci state.out = out; 29856cd6a6acSopenharmony_ci state.handle = handle; 29866cd6a6acSopenharmony_ci 29876cd6a6acSopenharmony_ci if (base->policy_type != POLICY_BASE) { 29886cd6a6acSopenharmony_ci ERR(handle, "Target of expand was not a base policy."); 29896cd6a6acSopenharmony_ci return -1; 29906cd6a6acSopenharmony_ci } 29916cd6a6acSopenharmony_ci 29926cd6a6acSopenharmony_ci state.out->policy_type = POLICY_KERN; 29936cd6a6acSopenharmony_ci state.out->policyvers = POLICYDB_VERSION_MAX; 29946cd6a6acSopenharmony_ci if (state.base->name) { 29956cd6a6acSopenharmony_ci state.out->name = strdup(state.base->name); 29966cd6a6acSopenharmony_ci } 29976cd6a6acSopenharmony_ci 29986cd6a6acSopenharmony_ci /* Copy mls state from base to out */ 29996cd6a6acSopenharmony_ci out->mls = base->mls; 30006cd6a6acSopenharmony_ci out->handle_unknown = base->handle_unknown; 30016cd6a6acSopenharmony_ci 30026cd6a6acSopenharmony_ci /* Copy target from base to out */ 30036cd6a6acSopenharmony_ci out->target_platform = base->target_platform; 30046cd6a6acSopenharmony_ci 30056cd6a6acSopenharmony_ci /* Copy policy capabilities */ 30066cd6a6acSopenharmony_ci if (ebitmap_cpy(&out->policycaps, &base->policycaps)) { 30076cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 30086cd6a6acSopenharmony_ci goto cleanup; 30096cd6a6acSopenharmony_ci } 30106cd6a6acSopenharmony_ci 30116cd6a6acSopenharmony_ci if ((state.typemap = 30126cd6a6acSopenharmony_ci (uint32_t *) calloc(state.base->p_types.nprim, 30136cd6a6acSopenharmony_ci sizeof(uint32_t))) == NULL) { 30146cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 30156cd6a6acSopenharmony_ci goto cleanup; 30166cd6a6acSopenharmony_ci } 30176cd6a6acSopenharmony_ci 30186cd6a6acSopenharmony_ci state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t)); 30196cd6a6acSopenharmony_ci if (!state.boolmap) { 30206cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 30216cd6a6acSopenharmony_ci goto cleanup; 30226cd6a6acSopenharmony_ci } 30236cd6a6acSopenharmony_ci 30246cd6a6acSopenharmony_ci state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t)); 30256cd6a6acSopenharmony_ci if (!state.rolemap) { 30266cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 30276cd6a6acSopenharmony_ci goto cleanup; 30286cd6a6acSopenharmony_ci } 30296cd6a6acSopenharmony_ci 30306cd6a6acSopenharmony_ci state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t)); 30316cd6a6acSopenharmony_ci if (!state.usermap) { 30326cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 30336cd6a6acSopenharmony_ci goto cleanup; 30346cd6a6acSopenharmony_ci } 30356cd6a6acSopenharmony_ci 30366cd6a6acSopenharmony_ci /* order is important - types must be first */ 30376cd6a6acSopenharmony_ci 30386cd6a6acSopenharmony_ci /* copy types */ 30396cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) { 30406cd6a6acSopenharmony_ci goto cleanup; 30416cd6a6acSopenharmony_ci } 30426cd6a6acSopenharmony_ci 30436cd6a6acSopenharmony_ci /* convert attribute type sets */ 30446cd6a6acSopenharmony_ci if (hashtab_map 30456cd6a6acSopenharmony_ci (state.base->p_types.table, attr_convert_callback, &state)) { 30466cd6a6acSopenharmony_ci goto cleanup; 30476cd6a6acSopenharmony_ci } 30486cd6a6acSopenharmony_ci 30496cd6a6acSopenharmony_ci /* copy commons */ 30506cd6a6acSopenharmony_ci if (hashtab_map 30516cd6a6acSopenharmony_ci (state.base->p_commons.table, common_copy_callback, &state)) { 30526cd6a6acSopenharmony_ci goto cleanup; 30536cd6a6acSopenharmony_ci } 30546cd6a6acSopenharmony_ci 30556cd6a6acSopenharmony_ci /* copy classes, note, this does not copy constraints, constraints can't be 30566cd6a6acSopenharmony_ci * copied until after all the blocks have been processed and attributes are complete */ 30576cd6a6acSopenharmony_ci if (hashtab_map 30586cd6a6acSopenharmony_ci (state.base->p_classes.table, class_copy_callback, &state)) { 30596cd6a6acSopenharmony_ci goto cleanup; 30606cd6a6acSopenharmony_ci } 30616cd6a6acSopenharmony_ci 30626cd6a6acSopenharmony_ci /* copy type bounds */ 30636cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_types.table, 30646cd6a6acSopenharmony_ci type_bounds_copy_callback, &state)) 30656cd6a6acSopenharmony_ci goto cleanup; 30666cd6a6acSopenharmony_ci 30676cd6a6acSopenharmony_ci /* copy aliases */ 30686cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state)) 30696cd6a6acSopenharmony_ci goto cleanup; 30706cd6a6acSopenharmony_ci 30716cd6a6acSopenharmony_ci /* index here so that type indexes are available for role_copy_callback */ 30726cd6a6acSopenharmony_ci if (policydb_index_others(handle, out, verbose)) { 30736cd6a6acSopenharmony_ci ERR(handle, "Error while indexing out symbols"); 30746cd6a6acSopenharmony_ci goto cleanup; 30756cd6a6acSopenharmony_ci } 30766cd6a6acSopenharmony_ci 30776cd6a6acSopenharmony_ci /* copy roles */ 30786cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state)) 30796cd6a6acSopenharmony_ci goto cleanup; 30806cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_roles.table, 30816cd6a6acSopenharmony_ci role_bounds_copy_callback, &state)) 30826cd6a6acSopenharmony_ci goto cleanup; 30836cd6a6acSopenharmony_ci 30846cd6a6acSopenharmony_ci /* copy MLS's sensitivity level and categories - this needs to be done 30856cd6a6acSopenharmony_ci * before expanding users (they need to be indexed too) */ 30866cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)) 30876cd6a6acSopenharmony_ci goto cleanup; 30886cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state)) 30896cd6a6acSopenharmony_ci goto cleanup; 30906cd6a6acSopenharmony_ci if (policydb_index_others(handle, out, verbose)) { 30916cd6a6acSopenharmony_ci ERR(handle, "Error while indexing out symbols"); 30926cd6a6acSopenharmony_ci goto cleanup; 30936cd6a6acSopenharmony_ci } 30946cd6a6acSopenharmony_ci 30956cd6a6acSopenharmony_ci /* copy users */ 30966cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_users.table, user_copy_callback, &state)) 30976cd6a6acSopenharmony_ci goto cleanup; 30986cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_users.table, 30996cd6a6acSopenharmony_ci user_bounds_copy_callback, &state)) 31006cd6a6acSopenharmony_ci goto cleanup; 31016cd6a6acSopenharmony_ci 31026cd6a6acSopenharmony_ci /* copy bools */ 31036cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state)) 31046cd6a6acSopenharmony_ci goto cleanup; 31056cd6a6acSopenharmony_ci 31066cd6a6acSopenharmony_ci if (policydb_index_classes(out)) { 31076cd6a6acSopenharmony_ci ERR(handle, "Error while indexing out classes"); 31086cd6a6acSopenharmony_ci goto cleanup; 31096cd6a6acSopenharmony_ci } 31106cd6a6acSopenharmony_ci if (policydb_index_others(handle, out, verbose)) { 31116cd6a6acSopenharmony_ci ERR(handle, "Error while indexing out symbols"); 31126cd6a6acSopenharmony_ci goto cleanup; 31136cd6a6acSopenharmony_ci } 31146cd6a6acSopenharmony_ci 31156cd6a6acSopenharmony_ci /* loop through all decls and union attributes, roles, users */ 31166cd6a6acSopenharmony_ci for (curblock = state.base->global; curblock != NULL; 31176cd6a6acSopenharmony_ci curblock = curblock->next) { 31186cd6a6acSopenharmony_ci avrule_decl_t *decl = curblock->enabled; 31196cd6a6acSopenharmony_ci 31206cd6a6acSopenharmony_ci if (decl == NULL) { 31216cd6a6acSopenharmony_ci /* nothing was enabled within this block */ 31226cd6a6acSopenharmony_ci continue; 31236cd6a6acSopenharmony_ci } 31246cd6a6acSopenharmony_ci 31256cd6a6acSopenharmony_ci /* convert attribute type sets */ 31266cd6a6acSopenharmony_ci if (hashtab_map 31276cd6a6acSopenharmony_ci (decl->p_types.table, attr_convert_callback, &state)) { 31286cd6a6acSopenharmony_ci goto cleanup; 31296cd6a6acSopenharmony_ci } 31306cd6a6acSopenharmony_ci 31316cd6a6acSopenharmony_ci /* copy roles */ 31326cd6a6acSopenharmony_ci if (hashtab_map 31336cd6a6acSopenharmony_ci (decl->p_roles.table, role_copy_callback, &state)) 31346cd6a6acSopenharmony_ci goto cleanup; 31356cd6a6acSopenharmony_ci 31366cd6a6acSopenharmony_ci /* copy users */ 31376cd6a6acSopenharmony_ci if (hashtab_map 31386cd6a6acSopenharmony_ci (decl->p_users.table, user_copy_callback, &state)) 31396cd6a6acSopenharmony_ci goto cleanup; 31406cd6a6acSopenharmony_ci 31416cd6a6acSopenharmony_ci } 31426cd6a6acSopenharmony_ci 31436cd6a6acSopenharmony_ci /* remap role dominates bitmaps */ 31446cd6a6acSopenharmony_ci if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) { 31456cd6a6acSopenharmony_ci goto cleanup; 31466cd6a6acSopenharmony_ci } 31476cd6a6acSopenharmony_ci 31486cd6a6acSopenharmony_ci /* escalate the type_set_t in a role attribute to all regular roles 31496cd6a6acSopenharmony_ci * that belongs to it. */ 31506cd6a6acSopenharmony_ci if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state)) 31516cd6a6acSopenharmony_ci goto cleanup; 31526cd6a6acSopenharmony_ci 31536cd6a6acSopenharmony_ci if (copy_and_expand_avrule_block(&state) < 0) { 31546cd6a6acSopenharmony_ci ERR(handle, "Error during expand"); 31556cd6a6acSopenharmony_ci goto cleanup; 31566cd6a6acSopenharmony_ci } 31576cd6a6acSopenharmony_ci 31586cd6a6acSopenharmony_ci /* copy constraints */ 31596cd6a6acSopenharmony_ci if (hashtab_map 31606cd6a6acSopenharmony_ci (state.base->p_classes.table, constraint_copy_callback, &state)) { 31616cd6a6acSopenharmony_ci goto cleanup; 31626cd6a6acSopenharmony_ci } 31636cd6a6acSopenharmony_ci 31646cd6a6acSopenharmony_ci cond_optimize_lists(state.out->cond_list); 31656cd6a6acSopenharmony_ci if (evaluate_conds(state.out)) 31666cd6a6acSopenharmony_ci goto cleanup; 31676cd6a6acSopenharmony_ci 31686cd6a6acSopenharmony_ci /* copy ocontexts */ 31696cd6a6acSopenharmony_ci if (ocontext_copy(&state, out->target_platform)) 31706cd6a6acSopenharmony_ci goto cleanup; 31716cd6a6acSopenharmony_ci 31726cd6a6acSopenharmony_ci /* copy genfs */ 31736cd6a6acSopenharmony_ci if (genfs_copy(&state)) 31746cd6a6acSopenharmony_ci goto cleanup; 31756cd6a6acSopenharmony_ci 31766cd6a6acSopenharmony_ci /* Build the type<->attribute maps and remove attributes. */ 31776cd6a6acSopenharmony_ci state.out->attr_type_map = calloc(state.out->p_types.nprim, 31786cd6a6acSopenharmony_ci sizeof(ebitmap_t)); 31796cd6a6acSopenharmony_ci state.out->type_attr_map = calloc(state.out->p_types.nprim, 31806cd6a6acSopenharmony_ci sizeof(ebitmap_t)); 31816cd6a6acSopenharmony_ci if (!state.out->attr_type_map || !state.out->type_attr_map) { 31826cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 31836cd6a6acSopenharmony_ci goto cleanup; 31846cd6a6acSopenharmony_ci } 31856cd6a6acSopenharmony_ci for (i = 0; i < state.out->p_types.nprim; i++) { 31866cd6a6acSopenharmony_ci /* add the type itself as the degenerate case */ 31876cd6a6acSopenharmony_ci if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) { 31886cd6a6acSopenharmony_ci ERR(handle, "Out of memory!"); 31896cd6a6acSopenharmony_ci goto cleanup; 31906cd6a6acSopenharmony_ci } 31916cd6a6acSopenharmony_ci } 31926cd6a6acSopenharmony_ci if (hashtab_map(state.out->p_types.table, type_attr_map, &state)) 31936cd6a6acSopenharmony_ci goto cleanup; 31946cd6a6acSopenharmony_ci if (check) { 31956cd6a6acSopenharmony_ci if (hierarchy_check_constraints(handle, state.out)) 31966cd6a6acSopenharmony_ci goto cleanup; 31976cd6a6acSopenharmony_ci 31986cd6a6acSopenharmony_ci if (check_assertions 31996cd6a6acSopenharmony_ci (handle, state.out, 32006cd6a6acSopenharmony_ci state.out->global->branch_list->avrules)) 32016cd6a6acSopenharmony_ci goto cleanup; 32026cd6a6acSopenharmony_ci } 32036cd6a6acSopenharmony_ci 32046cd6a6acSopenharmony_ci retval = 0; 32056cd6a6acSopenharmony_ci 32066cd6a6acSopenharmony_ci cleanup: 32076cd6a6acSopenharmony_ci free(state.typemap); 32086cd6a6acSopenharmony_ci free(state.boolmap); 32096cd6a6acSopenharmony_ci free(state.rolemap); 32106cd6a6acSopenharmony_ci free(state.usermap); 32116cd6a6acSopenharmony_ci return retval; 32126cd6a6acSopenharmony_ci} 32136cd6a6acSopenharmony_ci 32146cd6a6acSopenharmony_cistatic int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d) 32156cd6a6acSopenharmony_ci{ 32166cd6a6acSopenharmony_ci avtab_ptr_t node; 32176cd6a6acSopenharmony_ci avtab_datum_t *avd; 32186cd6a6acSopenharmony_ci avtab_extended_perms_t *xperms; 32196cd6a6acSopenharmony_ci unsigned int i; 32206cd6a6acSopenharmony_ci unsigned int match = 0; 32216cd6a6acSopenharmony_ci 32226cd6a6acSopenharmony_ci if (k->specified & AVTAB_XPERMS) { 32236cd6a6acSopenharmony_ci /* 32246cd6a6acSopenharmony_ci * AVTAB_XPERMS entries are not necessarily unique. 32256cd6a6acSopenharmony_ci * find node with matching xperms 32266cd6a6acSopenharmony_ci */ 32276cd6a6acSopenharmony_ci node = avtab_search_node(a, k); 32286cd6a6acSopenharmony_ci while (node) { 32296cd6a6acSopenharmony_ci if ((node->datum.xperms->specified == d->xperms->specified) && 32306cd6a6acSopenharmony_ci (node->datum.xperms->driver == d->xperms->driver)) { 32316cd6a6acSopenharmony_ci match = 1; 32326cd6a6acSopenharmony_ci break; 32336cd6a6acSopenharmony_ci } 32346cd6a6acSopenharmony_ci node = avtab_search_node_next(node, k->specified); 32356cd6a6acSopenharmony_ci } 32366cd6a6acSopenharmony_ci if (!match) 32376cd6a6acSopenharmony_ci node = NULL; 32386cd6a6acSopenharmony_ci } else { 32396cd6a6acSopenharmony_ci node = avtab_search_node(a, k); 32406cd6a6acSopenharmony_ci } 32416cd6a6acSopenharmony_ci 32426cd6a6acSopenharmony_ci if (!node || ((k->specified & AVTAB_ENABLED) != 32436cd6a6acSopenharmony_ci (node->key.specified & AVTAB_ENABLED))) { 32446cd6a6acSopenharmony_ci node = avtab_insert_nonunique(a, k, d); 32456cd6a6acSopenharmony_ci if (!node) { 32466cd6a6acSopenharmony_ci ERR(NULL, "Out of memory!"); 32476cd6a6acSopenharmony_ci return -1; 32486cd6a6acSopenharmony_ci } 32496cd6a6acSopenharmony_ci return 0; 32506cd6a6acSopenharmony_ci } 32516cd6a6acSopenharmony_ci 32526cd6a6acSopenharmony_ci avd = &node->datum; 32536cd6a6acSopenharmony_ci xperms = node->datum.xperms; 32546cd6a6acSopenharmony_ci switch (k->specified & ~AVTAB_ENABLED) { 32556cd6a6acSopenharmony_ci case AVTAB_ALLOWED: 32566cd6a6acSopenharmony_ci case AVTAB_AUDITALLOW: 32576cd6a6acSopenharmony_ci avd->data |= d->data; 32586cd6a6acSopenharmony_ci break; 32596cd6a6acSopenharmony_ci case AVTAB_AUDITDENY: 32606cd6a6acSopenharmony_ci avd->data &= d->data; 32616cd6a6acSopenharmony_ci break; 32626cd6a6acSopenharmony_ci case AVTAB_XPERMS_ALLOWED: 32636cd6a6acSopenharmony_ci case AVTAB_XPERMS_AUDITALLOW: 32646cd6a6acSopenharmony_ci case AVTAB_XPERMS_DONTAUDIT: 32656cd6a6acSopenharmony_ci for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) 32666cd6a6acSopenharmony_ci xperms->perms[i] |= d->xperms->perms[i]; 32676cd6a6acSopenharmony_ci break; 32686cd6a6acSopenharmony_ci default: 32696cd6a6acSopenharmony_ci ERR(NULL, "Type conflict!"); 32706cd6a6acSopenharmony_ci return -1; 32716cd6a6acSopenharmony_ci } 32726cd6a6acSopenharmony_ci 32736cd6a6acSopenharmony_ci return 0; 32746cd6a6acSopenharmony_ci} 32756cd6a6acSopenharmony_ci 32766cd6a6acSopenharmony_cistruct expand_avtab_data { 32776cd6a6acSopenharmony_ci avtab_t *expa; 32786cd6a6acSopenharmony_ci policydb_t *p; 32796cd6a6acSopenharmony_ci 32806cd6a6acSopenharmony_ci}; 32816cd6a6acSopenharmony_ci 32826cd6a6acSopenharmony_cistatic int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args) 32836cd6a6acSopenharmony_ci{ 32846cd6a6acSopenharmony_ci struct expand_avtab_data *ptr = args; 32856cd6a6acSopenharmony_ci avtab_t *expa = ptr->expa; 32866cd6a6acSopenharmony_ci policydb_t *p = ptr->p; 32876cd6a6acSopenharmony_ci type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; 32886cd6a6acSopenharmony_ci type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; 32896cd6a6acSopenharmony_ci ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; 32906cd6a6acSopenharmony_ci ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; 32916cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 32926cd6a6acSopenharmony_ci unsigned int i, j; 32936cd6a6acSopenharmony_ci avtab_key_t newkey; 32946cd6a6acSopenharmony_ci int rc; 32956cd6a6acSopenharmony_ci 32966cd6a6acSopenharmony_ci newkey.target_class = k->target_class; 32976cd6a6acSopenharmony_ci newkey.specified = k->specified; 32986cd6a6acSopenharmony_ci 32996cd6a6acSopenharmony_ci if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { 33006cd6a6acSopenharmony_ci /* Both are individual types, no expansion required. */ 33016cd6a6acSopenharmony_ci return expand_avtab_insert(expa, k, d); 33026cd6a6acSopenharmony_ci } 33036cd6a6acSopenharmony_ci 33046cd6a6acSopenharmony_ci if (stype && stype->flavor != TYPE_ATTRIB) { 33056cd6a6acSopenharmony_ci /* Source is an individual type, target is an attribute. */ 33066cd6a6acSopenharmony_ci newkey.source_type = k->source_type; 33076cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 33086cd6a6acSopenharmony_ci newkey.target_type = j + 1; 33096cd6a6acSopenharmony_ci rc = expand_avtab_insert(expa, &newkey, d); 33106cd6a6acSopenharmony_ci if (rc) 33116cd6a6acSopenharmony_ci return -1; 33126cd6a6acSopenharmony_ci } 33136cd6a6acSopenharmony_ci return 0; 33146cd6a6acSopenharmony_ci } 33156cd6a6acSopenharmony_ci 33166cd6a6acSopenharmony_ci if (ttype && ttype->flavor != TYPE_ATTRIB) { 33176cd6a6acSopenharmony_ci /* Target is an individual type, source is an attribute. */ 33186cd6a6acSopenharmony_ci newkey.target_type = k->target_type; 33196cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 33206cd6a6acSopenharmony_ci newkey.source_type = i + 1; 33216cd6a6acSopenharmony_ci rc = expand_avtab_insert(expa, &newkey, d); 33226cd6a6acSopenharmony_ci if (rc) 33236cd6a6acSopenharmony_ci return -1; 33246cd6a6acSopenharmony_ci } 33256cd6a6acSopenharmony_ci return 0; 33266cd6a6acSopenharmony_ci } 33276cd6a6acSopenharmony_ci 33286cd6a6acSopenharmony_ci /* Both source and target type are attributes. */ 33296cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 33306cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 33316cd6a6acSopenharmony_ci newkey.source_type = i + 1; 33326cd6a6acSopenharmony_ci newkey.target_type = j + 1; 33336cd6a6acSopenharmony_ci rc = expand_avtab_insert(expa, &newkey, d); 33346cd6a6acSopenharmony_ci if (rc) 33356cd6a6acSopenharmony_ci return -1; 33366cd6a6acSopenharmony_ci } 33376cd6a6acSopenharmony_ci } 33386cd6a6acSopenharmony_ci 33396cd6a6acSopenharmony_ci return 0; 33406cd6a6acSopenharmony_ci} 33416cd6a6acSopenharmony_ci 33426cd6a6acSopenharmony_ciint expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa) 33436cd6a6acSopenharmony_ci{ 33446cd6a6acSopenharmony_ci struct expand_avtab_data data; 33456cd6a6acSopenharmony_ci 33466cd6a6acSopenharmony_ci if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { 33476cd6a6acSopenharmony_ci ERR(NULL, "Out of memory!"); 33486cd6a6acSopenharmony_ci return -1; 33496cd6a6acSopenharmony_ci } 33506cd6a6acSopenharmony_ci 33516cd6a6acSopenharmony_ci data.expa = expa; 33526cd6a6acSopenharmony_ci data.p = p; 33536cd6a6acSopenharmony_ci return avtab_map(a, expand_avtab_node, &data); 33546cd6a6acSopenharmony_ci} 33556cd6a6acSopenharmony_ci 33566cd6a6acSopenharmony_cistatic int expand_cond_insert(cond_av_list_t ** l, 33576cd6a6acSopenharmony_ci avtab_t * expa, 33586cd6a6acSopenharmony_ci avtab_key_t * k, avtab_datum_t * d) 33596cd6a6acSopenharmony_ci{ 33606cd6a6acSopenharmony_ci avtab_ptr_t node; 33616cd6a6acSopenharmony_ci avtab_datum_t *avd; 33626cd6a6acSopenharmony_ci cond_av_list_t *nl; 33636cd6a6acSopenharmony_ci 33646cd6a6acSopenharmony_ci node = avtab_search_node(expa, k); 33656cd6a6acSopenharmony_ci if (!node || 33666cd6a6acSopenharmony_ci (k->specified & AVTAB_ENABLED) != 33676cd6a6acSopenharmony_ci (node->key.specified & AVTAB_ENABLED)) { 33686cd6a6acSopenharmony_ci node = avtab_insert_nonunique(expa, k, d); 33696cd6a6acSopenharmony_ci if (!node) { 33706cd6a6acSopenharmony_ci ERR(NULL, "Out of memory!"); 33716cd6a6acSopenharmony_ci return -1; 33726cd6a6acSopenharmony_ci } 33736cd6a6acSopenharmony_ci node->parse_context = (void *)1; 33746cd6a6acSopenharmony_ci nl = (cond_av_list_t *) malloc(sizeof(*nl)); 33756cd6a6acSopenharmony_ci if (!nl) { 33766cd6a6acSopenharmony_ci ERR(NULL, "Out of memory!"); 33776cd6a6acSopenharmony_ci return -1; 33786cd6a6acSopenharmony_ci } 33796cd6a6acSopenharmony_ci memset(nl, 0, sizeof(*nl)); 33806cd6a6acSopenharmony_ci nl->node = node; 33816cd6a6acSopenharmony_ci nl->next = *l; 33826cd6a6acSopenharmony_ci *l = nl; 33836cd6a6acSopenharmony_ci return 0; 33846cd6a6acSopenharmony_ci } 33856cd6a6acSopenharmony_ci 33866cd6a6acSopenharmony_ci avd = &node->datum; 33876cd6a6acSopenharmony_ci switch (k->specified & ~AVTAB_ENABLED) { 33886cd6a6acSopenharmony_ci case AVTAB_ALLOWED: 33896cd6a6acSopenharmony_ci case AVTAB_AUDITALLOW: 33906cd6a6acSopenharmony_ci avd->data |= d->data; 33916cd6a6acSopenharmony_ci break; 33926cd6a6acSopenharmony_ci case AVTAB_AUDITDENY: 33936cd6a6acSopenharmony_ci avd->data &= d->data; 33946cd6a6acSopenharmony_ci break; 33956cd6a6acSopenharmony_ci default: 33966cd6a6acSopenharmony_ci ERR(NULL, "Type conflict!"); 33976cd6a6acSopenharmony_ci return -1; 33986cd6a6acSopenharmony_ci } 33996cd6a6acSopenharmony_ci 34006cd6a6acSopenharmony_ci return 0; 34016cd6a6acSopenharmony_ci} 34026cd6a6acSopenharmony_ci 34036cd6a6acSopenharmony_cistatic int expand_cond_av_node(policydb_t * p, 34046cd6a6acSopenharmony_ci avtab_ptr_t node, 34056cd6a6acSopenharmony_ci cond_av_list_t ** newl, avtab_t * expa) 34066cd6a6acSopenharmony_ci{ 34076cd6a6acSopenharmony_ci avtab_key_t *k = &node->key; 34086cd6a6acSopenharmony_ci avtab_datum_t *d = &node->datum; 34096cd6a6acSopenharmony_ci type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; 34106cd6a6acSopenharmony_ci type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; 34116cd6a6acSopenharmony_ci ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; 34126cd6a6acSopenharmony_ci ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; 34136cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 34146cd6a6acSopenharmony_ci unsigned int i, j; 34156cd6a6acSopenharmony_ci avtab_key_t newkey; 34166cd6a6acSopenharmony_ci int rc; 34176cd6a6acSopenharmony_ci 34186cd6a6acSopenharmony_ci newkey.target_class = k->target_class; 34196cd6a6acSopenharmony_ci newkey.specified = k->specified; 34206cd6a6acSopenharmony_ci 34216cd6a6acSopenharmony_ci if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { 34226cd6a6acSopenharmony_ci /* Both are individual types, no expansion required. */ 34236cd6a6acSopenharmony_ci return expand_cond_insert(newl, expa, k, d); 34246cd6a6acSopenharmony_ci } 34256cd6a6acSopenharmony_ci 34266cd6a6acSopenharmony_ci if (stype && stype->flavor != TYPE_ATTRIB) { 34276cd6a6acSopenharmony_ci /* Source is an individual type, target is an attribute. */ 34286cd6a6acSopenharmony_ci newkey.source_type = k->source_type; 34296cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 34306cd6a6acSopenharmony_ci newkey.target_type = j + 1; 34316cd6a6acSopenharmony_ci rc = expand_cond_insert(newl, expa, &newkey, d); 34326cd6a6acSopenharmony_ci if (rc) 34336cd6a6acSopenharmony_ci return -1; 34346cd6a6acSopenharmony_ci } 34356cd6a6acSopenharmony_ci return 0; 34366cd6a6acSopenharmony_ci } 34376cd6a6acSopenharmony_ci 34386cd6a6acSopenharmony_ci if (ttype && ttype->flavor != TYPE_ATTRIB) { 34396cd6a6acSopenharmony_ci /* Target is an individual type, source is an attribute. */ 34406cd6a6acSopenharmony_ci newkey.target_type = k->target_type; 34416cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 34426cd6a6acSopenharmony_ci newkey.source_type = i + 1; 34436cd6a6acSopenharmony_ci rc = expand_cond_insert(newl, expa, &newkey, d); 34446cd6a6acSopenharmony_ci if (rc) 34456cd6a6acSopenharmony_ci return -1; 34466cd6a6acSopenharmony_ci } 34476cd6a6acSopenharmony_ci return 0; 34486cd6a6acSopenharmony_ci } 34496cd6a6acSopenharmony_ci 34506cd6a6acSopenharmony_ci /* Both source and target type are attributes. */ 34516cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 34526cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 34536cd6a6acSopenharmony_ci newkey.source_type = i + 1; 34546cd6a6acSopenharmony_ci newkey.target_type = j + 1; 34556cd6a6acSopenharmony_ci rc = expand_cond_insert(newl, expa, &newkey, d); 34566cd6a6acSopenharmony_ci if (rc) 34576cd6a6acSopenharmony_ci return -1; 34586cd6a6acSopenharmony_ci } 34596cd6a6acSopenharmony_ci } 34606cd6a6acSopenharmony_ci 34616cd6a6acSopenharmony_ci return 0; 34626cd6a6acSopenharmony_ci} 34636cd6a6acSopenharmony_ci 34646cd6a6acSopenharmony_ciint expand_cond_av_list(policydb_t * p, cond_av_list_t * l, 34656cd6a6acSopenharmony_ci cond_av_list_t ** newl, avtab_t * expa) 34666cd6a6acSopenharmony_ci{ 34676cd6a6acSopenharmony_ci cond_av_list_t *cur; 34686cd6a6acSopenharmony_ci avtab_ptr_t node; 34696cd6a6acSopenharmony_ci int rc; 34706cd6a6acSopenharmony_ci 34716cd6a6acSopenharmony_ci if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { 34726cd6a6acSopenharmony_ci ERR(NULL, "Out of memory!"); 34736cd6a6acSopenharmony_ci return -1; 34746cd6a6acSopenharmony_ci } 34756cd6a6acSopenharmony_ci 34766cd6a6acSopenharmony_ci *newl = NULL; 34776cd6a6acSopenharmony_ci for (cur = l; cur; cur = cur->next) { 34786cd6a6acSopenharmony_ci node = cur->node; 34796cd6a6acSopenharmony_ci rc = expand_cond_av_node(p, node, newl, expa); 34806cd6a6acSopenharmony_ci if (rc) 34816cd6a6acSopenharmony_ci return rc; 34826cd6a6acSopenharmony_ci } 34836cd6a6acSopenharmony_ci 34846cd6a6acSopenharmony_ci return 0; 34856cd6a6acSopenharmony_ci} 3486