#include "cil_internal.h" #include "cil_log.h" #include "cil_list.h" #include "cil_symtab.h" static inline void cil_reset_classperms_list(struct cil_list *cp_list); static inline void cil_reset_level(struct cil_level *level); static inline void cil_reset_levelrange(struct cil_levelrange *levelrange); static inline void cil_reset_context(struct cil_context *context); static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_perm *perm = (struct cil_perm *)d; perm->value -= *((int *)args); return SEPOL_OK; } static void cil_reset_class(struct cil_class *class) { if (class->common != NULL) { struct cil_class *common = class->common; cil_symtab_map(&common->perms, __class_reset_perm_values, &common->num_perms); /* during a re-resolve, we need to reset the common, so a classcommon * statement isn't seen as a duplicate */ class->num_perms -= common->num_perms; class->common = NULL; /* Must make this NULL or there will be an error when re-resolving */ } class->ordered = CIL_FALSE; } static void cil_reset_perm(struct cil_perm *perm) { cil_reset_classperms_list(perm->classperms); } static inline void cil_reset_classperms(struct cil_classperms *cp) { if (cp == NULL) { return; } cil_list_destroy(&cp->perms, CIL_FALSE); } static void cil_reset_classpermission(struct cil_classpermission *cp) { if (cp == NULL) { return; } cil_reset_classperms_list(cp->classperms); } static void cil_reset_classperms_set(struct cil_classperms_set *cp_set) { cil_reset_classpermission(cp_set->set); } static inline void cil_reset_classperms_list(struct cil_list *cp_list) { struct cil_list_item *curr; if (cp_list == NULL) { return; } cil_list_for_each(curr, cp_list) { if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP */ cil_reset_classperms(curr->data); } else if (curr->flavor == CIL_CLASSPERMS_SET) { /* SET */ cil_reset_classperms_set(curr->data); } } } static void cil_reset_classpermissionset(struct cil_classpermissionset *cps) { cil_reset_classperms_list(cps->classperms); } static void cil_reset_classmapping(struct cil_classmapping *cm) { cil_reset_classperms_list(cm->classperms); } static void cil_reset_alias(struct cil_alias *alias) { /* reset actual to NULL during a re-resolve */ alias->actual = NULL; } static void cil_reset_user(struct cil_user *user) { /* reset the bounds to NULL during a re-resolve */ user->bounds = NULL; user->dftlevel = NULL; user->range = NULL; cil_list_destroy(&user->roles, CIL_FALSE); } static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser) { if (selinuxuser->range_str == NULL) { cil_reset_levelrange(selinuxuser->range); } } static void cil_reset_role(struct cil_role *role) { /* reset the bounds to NULL during a re-resolve */ role->bounds = NULL; } static void cil_reset_roleattr(struct cil_roleattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributeroles statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } } static void cil_reset_roleattributeset(struct cil_roleattributeset *ras) { cil_list_destroy(&ras->datum_expr, CIL_FALSE); } static void cil_reset_type(struct cil_type *type) { /* reset the bounds to NULL during a re-resolve */ type->bounds = NULL; } static void cil_reset_typeattr(struct cil_typeattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributetypes statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } attr->used = CIL_FALSE; } static void cil_reset_typeattributeset(struct cil_typeattributeset *tas) { cil_list_destroy(&tas->datum_expr, CIL_FALSE); } static void cil_reset_avrule(struct cil_avrule *rule) { cil_reset_classperms_list(rule->classperms); } static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans->range_str == NULL) { cil_reset_levelrange(rangetrans->range); } } static void cil_reset_sens(struct cil_sens *sens) { /* during a re-resolve, we need to reset the categories associated with * this sensitivity from a (sensitivitycategory) statement */ cil_list_destroy(&sens->cats_list, CIL_FALSE); sens->ordered = CIL_FALSE; } static void cil_reset_cat(struct cil_cat *cat) { cat->ordered = CIL_FALSE; } static inline void cil_reset_cats(struct cil_cats *cats) { if (cats != NULL) { cats->evaluated = CIL_FALSE; cil_list_destroy(&cats->datum_expr, CIL_FALSE); } } static void cil_reset_senscat(struct cil_senscat *senscat) { cil_reset_cats(senscat->cats); } static void cil_reset_catset(struct cil_catset *catset) { cil_reset_cats(catset->cats); } static inline void cil_reset_level(struct cil_level *level) { cil_reset_cats(level->cats); } static inline void cil_reset_levelrange(struct cil_levelrange *levelrange) { if (levelrange->low_str == NULL) { cil_reset_level(levelrange->low); } if (levelrange->high_str == NULL) { cil_reset_level(levelrange->high); } } static inline void cil_reset_userlevel(struct cil_userlevel *userlevel) { if (userlevel->level_str == NULL) { cil_reset_level(userlevel->level); } } static inline void cil_reset_userrange(struct cil_userrange *userrange) { if (userrange->range_str == NULL) { cil_reset_levelrange(userrange->range); } } static inline void cil_reset_context(struct cil_context *context) { if (context->range_str == NULL) { cil_reset_levelrange(context->range); } } static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext) { if (sidcontext->context_str == NULL) { cil_reset_context(sidcontext->context); } } static void cil_reset_filecon(struct cil_filecon *filecon) { if (filecon->context_str == NULL && filecon->context != NULL) { cil_reset_context(filecon->context); } } static void cil_reset_portcon(struct cil_portcon *portcon) { if (portcon->context_str == NULL) { cil_reset_context(portcon->context); } } static void cil_reset_nodecon(struct cil_nodecon *nodecon) { if (nodecon->context_str == NULL) { cil_reset_context(nodecon->context); } } static void cil_reset_genfscon(struct cil_genfscon *genfscon) { if (genfscon->context_str == NULL) { cil_reset_context(genfscon->context); } } static void cil_reset_netifcon(struct cil_netifcon *netifcon) { if (netifcon->if_context_str == NULL) { cil_reset_context(netifcon->if_context); } if (netifcon->packet_context_str == NULL) { cil_reset_context(netifcon->packet_context); } } static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon->context_str == NULL) { cil_reset_context(pirqcon->context); } } static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon->context_str == NULL) { cil_reset_context(iomemcon->context); } } static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon->context_str == NULL) { cil_reset_context(ioportcon->context); } } static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon->context_str == NULL) { cil_reset_context(pcidevicecon->context); } } static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon->context_str == NULL) { cil_reset_context(devicetreecon->context); } } static void cil_reset_fsuse(struct cil_fsuse *fsuse) { if (fsuse->context_str == NULL) { cil_reset_context(fsuse->context); } } static void cil_reset_sid(struct cil_sid *sid) { /* reset the context to NULL during a re-resolve */ sid->context = NULL; sid->ordered = CIL_FALSE; } static void cil_reset_constrain(struct cil_constrain *con) { cil_reset_classperms_list(con->classperms); cil_list_destroy(&con->datum_expr, CIL_FALSE); } static void cil_reset_validatetrans(struct cil_validatetrans *vt) { cil_list_destroy(&vt->datum_expr, CIL_FALSE); } static void cil_reset_default(struct cil_default *def) { cil_list_destroy(&def->class_datums, CIL_FALSE); } static void cil_reset_defaultrange(struct cil_defaultrange *def) { cil_list_destroy(&def->class_datums, CIL_FALSE); } static void cil_reset_booleanif(struct cil_booleanif *bif) { cil_list_destroy(&bif->datum_expr, CIL_FALSE); } int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args) { switch (node->flavor) { case CIL_CLASS: cil_reset_class(node->data); break; case CIL_PERM: case CIL_MAP_PERM: cil_reset_perm(node->data); break; case CIL_CLASSPERMISSION: cil_reset_classpermission(node->data); break; case CIL_CLASSPERMISSIONSET: cil_reset_classpermissionset(node->data); break; case CIL_CLASSMAPPING: cil_reset_classmapping(node->data); break; case CIL_TYPEALIAS: case CIL_SENSALIAS: case CIL_CATALIAS: cil_reset_alias(node->data); break; case CIL_USERRANGE: cil_reset_userrange(node->data); break; case CIL_USERLEVEL: cil_reset_userlevel(node->data); break; case CIL_USER: cil_reset_user(node->data); break; case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSER: cil_reset_selinuxuser(node->data); break; case CIL_ROLE: cil_reset_role(node->data); break; case CIL_ROLEATTRIBUTE: cil_reset_roleattr(node->data); break; case CIL_ROLEATTRIBUTESET: cil_reset_roleattributeset(node->data); break; case CIL_TYPE: cil_reset_type(node->data); break; case CIL_TYPEATTRIBUTE: cil_reset_typeattr(node->data); break; case CIL_TYPEATTRIBUTESET: cil_reset_typeattributeset(node->data); break; case CIL_RANGETRANSITION: cil_reset_rangetransition(node->data); break; case CIL_AVRULE: cil_reset_avrule(node->data); break; case CIL_SENS: cil_reset_sens(node->data); break; case CIL_CAT: cil_reset_cat(node->data); break; case CIL_SENSCAT: cil_reset_senscat(node->data); break; case CIL_CATSET: cil_reset_catset(node->data); break; case CIL_LEVEL: cil_reset_level(node->data); break; case CIL_LEVELRANGE: cil_reset_levelrange(node->data); break; case CIL_CONTEXT: cil_reset_context(node->data); break; case CIL_SIDCONTEXT: cil_reset_sidcontext(node->data); break; case CIL_FILECON: cil_reset_filecon(node->data); break; case CIL_PORTCON: cil_reset_portcon(node->data); break; case CIL_NODECON: cil_reset_nodecon(node->data); break; case CIL_GENFSCON: cil_reset_genfscon(node->data); break; case CIL_NETIFCON: cil_reset_netifcon(node->data); break; case CIL_PIRQCON: cil_reset_pirqcon(node->data); break; case CIL_IOMEMCON: cil_reset_iomemcon(node->data); break; case CIL_IOPORTCON: cil_reset_ioportcon(node->data); break; case CIL_PCIDEVICECON: cil_reset_pcidevicecon(node->data); break; case CIL_DEVICETREECON: cil_reset_devicetreecon(node->data); break; case CIL_FSUSE: cil_reset_fsuse(node->data); break; case CIL_SID: cil_reset_sid(node->data); break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: cil_reset_constrain(node->data); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: cil_reset_validatetrans(node->data); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: cil_reset_default(node->data); break; case CIL_DEFAULTRANGE: cil_reset_defaultrange(node->data); break; case CIL_BOOLEANIF: cil_reset_booleanif(node->data); break; case CIL_TUNABLEIF: case CIL_CALL: break; /* Not effected by optional block disabling */ case CIL_MACRO: case CIL_SIDORDER: case CIL_CLASSORDER: case CIL_CATORDER: case CIL_SENSITIVITYORDER: break; /* Nothing to reset */ default: break; } return SEPOL_OK; } int cil_reset_ast(struct cil_tree_node *current) { int rc = SEPOL_ERR; rc = cil_tree_walk(current, __cil_reset_node, NULL, NULL, NULL); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to reset AST\n"); return SEPOL_ERR; } return SEPOL_OK; }