diff options
Diffstat (limited to 'libqpol/src/expand.c')
-rw-r--r-- | libqpol/src/expand.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/libqpol/src/expand.c b/libqpol/src/expand.c new file mode 100644 index 0000000..7aa5bdb --- /dev/null +++ b/libqpol/src/expand.c @@ -0,0 +1,190 @@ +/** + * @file + * + * Provides a way for setools to expand policy. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * + * Copyright (C) 2006-2008 Tresys Technology, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include <sepol/policydb/expand.h> +#include <sepol/policydb.h> +#include <stdlib.h> +#include "qpol_internal.h" +#include "expand.h" + +static int expand_type_attr_map(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *ptr) +{ + type_datum_t *type = NULL, *orig_type; + policydb_t *db = (policydb_t *) ptr; + ebitmap_node_t *node = NULL; + uint32_t bit = 0; + + type = (type_datum_t *) datum; + /* if this is an attribute go through its list + * of types and put in reverse mappings */ + if (type->flavor == TYPE_ATTRIB) { + ebitmap_for_each_bit(&type->types, node, bit) { + if (ebitmap_node_get_bit(node, bit)) { + orig_type = db->type_val_to_struct[bit]; + if (ebitmap_set_bit(&orig_type->types, type->s.value - 1, 1)) { + return -1; + } + } + } + } + return 0; +} + +static int expand_type_permissive_map(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *ptr) +{ +#ifdef HAVE_SEPOL_PERMISSIVE_TYPES + type_datum_t *type = (type_datum_t *) datum; + policydb_t *db = (policydb_t *) ptr; + + type = (type_datum_t *) datum; + /* if this type is marked as permissive, then set its + corresponding bit in the permissive map. note that unlike + other bitmaps, this one does not subtract 1 in the + bitmap. */ + if (type->flags & TYPE_FLAGS_PERMISSIVE) { + uint32_t value; + if (type->flavor == TYPE_ALIAS) { + /* aliases that came from modules should use the value + * referenced to by that alias */ + value = type->primary; + } else { + value = type->s.value; + } + if (ebitmap_set_bit(&db->permissive_map, value, 1)) { + return -1; + } + } +#endif + return 0; +} + +int qpol_expand_module(qpol_policy_t * base, int neverallows) +{ + unsigned int i; + uint32_t *typemap = NULL, *boolmap = NULL, *rolemap = NULL, *usermap = NULL; + policydb_t *db; + int rt, error = 0; + + INFO(base, "%s", "Expanding policy. (Step 3 of 5)"); + if (base == NULL) { + ERR(base, "%s", strerror(EINVAL)); + errno = EINVAL; + return -1; + } + db = &base->p->p; + + /* activate the global branch before expansion */ + db->global->branch_list->enabled = 1; + db->global->enabled = db->global->branch_list; + + /* expand out the types to include all the attributes */ + if (hashtab_map(db->p_types.table, expand_type_attr_map, (db))) { + error = errno; + ERR(base, "%s", "Error expanding attributes for types."); + goto err; + } +#ifdef HAVE_SEPOL_PERMISSIVE_TYPES + /* fill in the permissive types bitmap. this is normally done + * in type_copy_callback(), but types are not copied in + * expand_module_avrules() */ + if (hashtab_map(db->p_types.table, expand_type_permissive_map, (db))) { + error = errno; + ERR(base, "%s", "Error expanding attributes for types."); + goto err; + } +#endif + + /* Build the typemap such that we can expand into the same policy */ + typemap = (uint32_t *) calloc(db->p_types.nprim, sizeof(uint32_t)); + if (typemap == NULL) { + error = errno; + ERR(base, "%s", strerror(errno)); + goto err; + } + for (i = 0; i < db->p_types.nprim; i++) { + typemap[i] = i + 1; + } + +#ifdef HAVE_SEPOL_BOOLMAP + boolmap = (uint32_t *) calloc(db->p_bools.nprim, sizeof(uint32_t)); + if (boolmap == NULL) { + error = errno; + ERR(base, "%s", strerror(errno)); + goto err; + } + for (i = 0; i < db->p_bools.nprim; i++) { + boolmap[i] = i + 1; + } + +#ifdef HAVE_SEPOL_USER_ROLE_MAPPING + rolemap = (uint32_t *) calloc(db->p_roles.nprim, sizeof(uint32_t)); + if (rolemap == NULL) { + error = errno; + ERR(base, "%s", strerror(errno)); + goto err; + } + for (i = 0; i < db->p_roles.nprim; i++) { + rolemap[i] = i + 1; + } + usermap = (uint32_t *) calloc(db->p_users.nprim, sizeof(uint32_t)); + if (usermap == NULL) { + error = errno; + ERR(base, "%s", strerror(errno)); + goto err; + } + for (i = 0; i < db->p_users.nprim; i++) { + usermap[i] = i + 1; + } + rt = expand_module_avrules(base->sh, db, db, typemap, boolmap, rolemap, usermap, 0, neverallows); +#else + rt = expand_module_avrules(base->sh, db, db, typemap, boolmap, 0, neverallows); +#endif // end of user/role mapping + +#else + rt = expand_module_avrules(base->sh, db, db, typemap, 0, neverallows); +#endif // end of boolean mapping + if (rt < 0) { + error = errno; + goto err; + } + rt = 0; + + exit: + free(typemap); + free(boolmap); + free(rolemap); + free(usermap); + errno = error; + return rt; + err: + rt = -1; + /* libsepol does not always set errno correctly, so have a + default errno here */ + if (!error) + error = EIO; + goto exit; +} |