| /* |
| * Copyright 2011 Tresys Technology, LLC. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS |
| * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * The views and conclusions contained in the software and documentation are those |
| * of the authors and should not be interpreted as representing official policies, |
| * either expressed or implied, of Tresys Technology, LLC. |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "cil_internal.h" |
| #include "cil_log.h" |
| #include "cil_mem.h" |
| #include "cil_tree.h" |
| #include "cil_list.h" |
| #include "cil_symtab.h" |
| #include "cil_copy_ast.h" |
| #include "cil_build_ast.h" |
| #include "cil_strpool.h" |
| |
| struct cil_args_copy { |
| struct cil_tree_node *dest; |
| struct cil_db *db; |
| }; |
| |
| void cil_copy_list(struct cil_list *data, struct cil_list **copy) |
| { |
| struct cil_list *new; |
| struct cil_list_item *orig_item; |
| |
| cil_list_init(&new, data->flavor); |
| |
| cil_list_for_each(orig_item, data) { |
| switch (orig_item->flavor) { |
| case CIL_STRING: |
| cil_list_append(new, CIL_STRING, orig_item->data); |
| break; |
| case CIL_LIST: { |
| struct cil_list *new_sub = NULL; |
| cil_copy_list((struct cil_list*)orig_item->data, &new_sub); |
| cil_list_append(new, CIL_LIST, new_sub); |
| break; |
| } |
| case CIL_PARAM: { |
| struct cil_param *po = orig_item->data; |
| struct cil_param *pn; |
| cil_param_init(&pn); |
| pn->str = po->str; |
| pn->flavor = po->flavor; |
| cil_list_append(new, CIL_PARAM, pn); |
| } |
| break; |
| |
| default: |
| cil_list_append(new, orig_item->flavor, orig_item->data); |
| break; |
| } |
| } |
| |
| *copy = new; |
| } |
| |
| int cil_copy_node(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| char *new = NULL; |
| |
| if (data != NULL) { |
| new = data; |
| } |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_block *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_block *new; |
| cil_block_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum;; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_blockabstract(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_blockabstract *orig = data; |
| struct cil_blockabstract *new = NULL; |
| |
| cil_blockabstract_init(&new); |
| |
| new->block_str = orig->block_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_blockinherit(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_blockinherit *orig = data; |
| struct cil_blockinherit *new = NULL; |
| |
| cil_blockinherit_init(&new); |
| |
| new->block_str = orig->block_str; |
| new->block = orig->block; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_policycap(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_policycap *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_policycap *new; |
| cil_policycap_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_perm(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_perm *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_perm *new; |
| cil_perm_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_classperms(struct cil_classperms *orig, struct cil_classperms **new) |
| { |
| cil_classperms_init(new); |
| (*new)->class_str = orig->class_str; |
| cil_copy_list(orig->perm_strs, &((*new)->perm_strs)); |
| } |
| |
| void cil_copy_classperms_set(struct cil_classperms_set *orig, struct cil_classperms_set **new) |
| { |
| cil_classperms_set_init(new); |
| (*new)->set_str = orig->set_str; |
| } |
| |
| void cil_copy_classperms_list(struct cil_list *orig, struct cil_list **new) |
| { |
| struct cil_list_item *orig_item; |
| |
| if (orig == NULL) { |
| return; |
| } |
| |
| cil_list_init(new, CIL_LIST_ITEM); |
| cil_list_for_each(orig_item, orig) { |
| if (orig_item->flavor == CIL_CLASSPERMS) { |
| struct cil_classperms *cp; |
| cil_copy_classperms(orig_item->data, &cp); |
| cil_list_append(*new, CIL_CLASSPERMS, cp); |
| } else { |
| struct cil_classperms_set *cp_set; |
| cil_copy_classperms_set(orig_item->data, &cp_set); |
| cil_list_append(*new, CIL_CLASSPERMS_SET, cp_set); |
| } |
| } |
| } |
| |
| int cil_copy_classmapping(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_classmapping *orig = data; |
| struct cil_classmapping *new = NULL; |
| |
| cil_classmapping_init(&new); |
| |
| new->map_class_str = orig->map_class_str; |
| new->map_perm_str = orig->map_perm_str; |
| |
| cil_copy_classperms_list(orig->classperms, &new->classperms); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_class(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_class *orig = data; |
| struct cil_class *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_class: class cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_class_init(&new); |
| |
| new->common = NULL; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_classorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_classorder *orig = data; |
| struct cil_classorder *new = NULL; |
| |
| cil_classorder_init(&new); |
| if (orig->class_list_str != NULL) { |
| cil_copy_list(orig->class_list_str, &new->class_list_str); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_classpermission(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_classpermission *orig = data; |
| struct cil_classpermission *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| if (key != NULL) { |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "classpermission cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| } |
| |
| cil_classpermission_init(&new); |
| |
| cil_copy_classperms_list(orig->classperms, &new->classperms); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_classpermissionset *orig = data; |
| struct cil_classpermissionset *new = NULL; |
| |
| cil_classpermissionset_init(&new); |
| |
| new->set_str = orig->set_str; |
| |
| cil_copy_classperms_list(orig->classperms, &new->classperms); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_classcommon(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_classcommon *orig = data; |
| struct cil_classcommon *new = NULL; |
| |
| cil_classcommon_init(&new); |
| |
| new->class_str = orig->class_str; |
| new->common_str = orig->common_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_sid(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_sid *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_sid *new; |
| cil_sid_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_sidcontext *orig = data; |
| struct cil_sidcontext *new = NULL; |
| |
| cil_sidcontext_init(&new); |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_sidorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_sidorder *orig = data; |
| struct cil_sidorder *new = NULL; |
| |
| cil_sidorder_init(&new); |
| if (orig->sid_list_str != NULL) { |
| cil_copy_list(orig->sid_list_str, &new->sid_list_str); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_user(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_user *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_user *new; |
| cil_user_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_userattribute *orig = data; |
| struct cil_userattribute *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| cil_userattribute_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_userattributeset *orig = data; |
| struct cil_userattributeset *new = NULL; |
| |
| cil_userattributeset_init(&new); |
| |
| new->attr_str = orig->attr_str; |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_userrole *orig = data; |
| struct cil_userrole *new = NULL; |
| |
| cil_userrole_init(&new); |
| |
| new->user_str = orig->user_str; |
| new->role_str = orig->role_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_userlevel *orig = data; |
| struct cil_userlevel *new = NULL; |
| |
| cil_userlevel_init(&new); |
| |
| new->user_str = orig->user_str; |
| |
| if (orig->level_str != NULL) { |
| new->level_str = orig->level_str; |
| } else { |
| cil_copy_fill_level(db, orig->level, &new->level); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userrange(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_userrange *orig = data; |
| struct cil_userrange *new = NULL; |
| |
| cil_userrange_init(&new); |
| |
| new->user_str = orig->user_str; |
| |
| if (orig->range_str != NULL) { |
| new->range_str = orig->range_str; |
| } else { |
| cil_levelrange_init(&new->range); |
| cil_copy_fill_levelrange(db, orig->range, new->range); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_userprefix(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_userprefix *orig = data; |
| struct cil_userprefix *new = NULL; |
| |
| cil_userprefix_init(&new); |
| |
| new->user_str = orig->user_str; |
| new->prefix_str = orig->prefix_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_role(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_role *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_role *new; |
| cil_role_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_roletype(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_roletype *orig = data; |
| struct cil_roletype *new = NULL; |
| |
| cil_roletype_init(&new); |
| |
| new->role_str = orig->role_str; |
| new->type_str = orig->type_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_roleattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_roleattribute *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_roleattribute *new; |
| cil_roleattribute_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_roleattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_roleattributeset *orig = data; |
| struct cil_roleattributeset *new = NULL; |
| |
| cil_roleattributeset_init(&new); |
| |
| new->attr_str = orig->attr_str; |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_roleallow *orig = data; |
| struct cil_roleallow *new = NULL; |
| |
| cil_roleallow_init(&new); |
| |
| new->src_str = orig->src_str; |
| new->tgt_str = orig->tgt_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_type(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_type *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_type *new; |
| cil_type_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_typepermissive(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_typepermissive *orig = data; |
| struct cil_typepermissive *new = NULL; |
| |
| cil_typepermissive_init(&new); |
| |
| new->type_str = orig->type_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_typeattribute *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_typeattribute *new; |
| cil_typeattribute_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_typeattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_typeattributeset *orig = data; |
| struct cil_typeattributeset *new = NULL; |
| |
| cil_typeattributeset_init(&new); |
| |
| new->attr_str = orig->attr_str; |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_alias(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_alias *orig = data; |
| struct cil_alias *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_alias: alias cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_alias_init(&new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_aliasactual(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused))symtab_t *symtab) |
| { |
| struct cil_aliasactual *orig = data; |
| struct cil_aliasactual *new = NULL; |
| |
| cil_aliasactual_init(&new); |
| |
| new->alias_str = orig->alias_str; |
| new->actual_str = orig->actual_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_roletransition(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_roletransition *orig = data; |
| struct cil_roletransition *new = NULL; |
| |
| cil_roletransition_init(&new); |
| |
| new->src_str = orig->src_str; |
| new->tgt_str = orig->tgt_str; |
| new->obj_str = orig->obj_str; |
| new->result_str = orig->result_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_nametypetransition(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_nametypetransition *orig = data; |
| struct cil_nametypetransition *new = NULL; |
| |
| cil_nametypetransition_init(&new); |
| |
| new->src_str = orig->src_str; |
| new->tgt_str = orig->tgt_str; |
| new->obj_str = orig->obj_str; |
| new->name_str = orig->name_str; |
| new->result_str = orig->result_str; |
| |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_rangetransition(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_rangetransition *orig = data; |
| struct cil_rangetransition *new = NULL; |
| |
| cil_rangetransition_init(&new); |
| |
| new->src_str = orig->src_str; |
| new->exec_str = orig->exec_str; |
| new->obj_str = orig->obj_str; |
| |
| if (orig->range_str != NULL) { |
| new->range_str = orig->range_str; |
| } else { |
| cil_levelrange_init(&new->range); |
| cil_copy_fill_levelrange(db, orig->range, new->range); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_bool(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_bool *orig = data; |
| struct cil_bool *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_bool: boolean cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_bool_init(&new); |
| new->value = orig->value; |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_tunable(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_tunable *orig = data; |
| struct cil_tunable *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_tunable: tunable cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_tunable_init(&new); |
| new->value = orig->value; |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_fill_permissionx(struct cil_db *db, struct cil_permissionx *orig, struct cil_permissionx *new) |
| { |
| new->kind = orig->kind; |
| new->obj_str = orig->obj_str; |
| cil_copy_expr(db, orig->expr_str, &new->expr_str); |
| } |
| |
| int cil_copy_avrule(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_avrule *orig = data; |
| struct cil_avrule *new = NULL; |
| |
| cil_avrule_init(&new); |
| |
| new->is_extended = orig->is_extended; |
| new->rule_kind = orig->rule_kind; |
| new->src_str = orig->src_str; |
| new->tgt_str = orig->tgt_str; |
| |
| if (!new->is_extended) { |
| cil_copy_classperms_list(orig->perms.classperms, &new->perms.classperms); |
| } else { |
| if (new->perms.x.permx_str != NULL) { |
| new->perms.x.permx_str = orig->perms.x.permx_str; |
| } else { |
| cil_permissionx_init(&new->perms.x.permx); |
| cil_copy_fill_permissionx(db, orig->perms.x.permx, new->perms.x.permx); |
| } |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_permissionx(struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_permissionx *orig = data; |
| struct cil_permissionx *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_permissionx: permissionx cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_permissionx_init(&new); |
| cil_copy_fill_permissionx(db, orig, new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_type_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_type_rule *orig = data; |
| struct cil_type_rule *new = NULL; |
| |
| cil_type_rule_init(&new); |
| |
| new->rule_kind = orig->rule_kind; |
| new->src_str = orig->src_str; |
| new->tgt_str = orig->tgt_str; |
| new->obj_str = orig->obj_str; |
| new->result_str = orig->result_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_sens(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_sens *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_sens *new; |
| cil_sens_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_cat(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_cat *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_cat *new; |
| cil_cat_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_cats(struct cil_db *db, struct cil_cats *orig, struct cil_cats **new) |
| { |
| cil_cats_init(new); |
| cil_copy_expr(db, orig->str_expr, &(*new)->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &(*new)->datum_expr); |
| } |
| |
| int cil_copy_catset(struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_catset *orig = data; |
| struct cil_catset *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_catset: categoryset cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_catset_init(&new); |
| |
| cil_copy_cats(db, orig->cats, &new->cats); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_senscat(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_senscat *orig = data; |
| struct cil_senscat *new = NULL; |
| |
| cil_senscat_init(&new); |
| |
| new->sens_str = orig->sens_str; |
| |
| cil_copy_cats(db, orig->cats, &new->cats); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_catorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_catorder *orig = data; |
| struct cil_catorder *new = NULL; |
| |
| cil_catorder_init(&new); |
| if (orig->cat_list_str != NULL) { |
| cil_copy_list(orig->cat_list_str, &new->cat_list_str); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_sensitivityorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_sensorder *orig = data; |
| struct cil_sensorder *new = NULL; |
| |
| cil_sensorder_init(&new); |
| if (orig->sens_list_str != NULL) { |
| cil_copy_list(orig->sens_list_str, &new->sens_list_str); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new) |
| { |
| cil_level_init(new); |
| |
| (*new)->sens_str = orig->sens_str; |
| |
| if (orig->cats != NULL) { |
| cil_copy_cats(db, orig->cats, &(*new)->cats); |
| } |
| } |
| |
| int cil_copy_level(struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_level *orig = data; |
| struct cil_level *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| if (key != NULL) { |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_level: level cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| } |
| |
| cil_copy_fill_level(db, orig, &new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_fill_levelrange(struct cil_db *db, struct cil_levelrange *data, struct cil_levelrange *new) |
| { |
| if (data->low_str != NULL) { |
| new->low_str = data->low_str; |
| } else { |
| cil_copy_fill_level(db, data->low, &new->low); |
| } |
| |
| if (data->high_str != NULL) { |
| new->high_str = data->high_str; |
| } else { |
| cil_copy_fill_level(db, data->high, &new->high); |
| } |
| } |
| |
| int cil_copy_levelrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_levelrange *orig = data; |
| struct cil_levelrange *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| if (key != NULL) { |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_levelrange: levelrange cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| } |
| |
| cil_levelrange_init(&new); |
| cil_copy_fill_levelrange(db, orig, new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_fill_context(struct cil_db *db, struct cil_context *data, struct cil_context *new) |
| { |
| new->user_str = data->user_str; |
| new->role_str = data->role_str; |
| new->type_str = data->type_str; |
| |
| if (data->range_str != NULL) { |
| new->range_str = data->range_str; |
| } else { |
| cil_levelrange_init(&new->range); |
| cil_copy_fill_levelrange(db, data->range, new->range); |
| } |
| } |
| |
| int cil_copy_context(struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_context *orig = data; |
| struct cil_context *new = NULL; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| if (key != NULL) { |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_context: context cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| } |
| |
| cil_context_init(&new); |
| cil_copy_fill_context(db, orig, new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_netifcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_netifcon *orig = data; |
| struct cil_netifcon *new = NULL; |
| |
| cil_netifcon_init(&new); |
| |
| new->interface_str = orig->interface_str; |
| |
| if (orig->if_context_str != NULL) { |
| new->if_context_str = orig->if_context_str; |
| } else { |
| cil_context_init(&new->if_context); |
| cil_copy_fill_context(db, orig->if_context, new->if_context); |
| } |
| |
| if (orig->packet_context_str != NULL) { |
| new->packet_context_str = orig->packet_context_str; |
| } else { |
| cil_context_init(&new->packet_context); |
| cil_copy_fill_context(db, orig->packet_context, new->packet_context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_genfscon *orig = data; |
| struct cil_genfscon *new = NULL; |
| |
| cil_genfscon_init(&new); |
| |
| new->fs_str = orig->fs_str; |
| new->path_str = orig->path_str; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_filecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_filecon *orig = data; |
| struct cil_filecon *new = NULL; |
| |
| cil_filecon_init(&new); |
| |
| new->path_str = orig->path_str; |
| new->type = orig->type; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else if (orig->context != NULL) { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_nodecon *orig = data; |
| struct cil_nodecon *new = NULL; |
| |
| cil_nodecon_init(&new); |
| |
| if (orig->addr_str != NULL) { |
| new->addr_str = orig->addr_str; |
| } else { |
| cil_ipaddr_init(&new->addr); |
| cil_copy_fill_ipaddr(orig->addr, new->addr); |
| } |
| |
| if (orig->mask_str != NULL) { |
| new->mask_str = orig->mask_str; |
| } else { |
| cil_ipaddr_init(&new->mask); |
| cil_copy_fill_ipaddr(orig->mask, new->mask); |
| } |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_portcon *orig = data; |
| struct cil_portcon *new = NULL; |
| |
| cil_portcon_init(&new); |
| |
| new->proto = orig->proto; |
| new->port_low = orig->port_low; |
| new->port_high = orig->port_high; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_pirqcon *orig = data; |
| struct cil_pirqcon *new = NULL; |
| |
| cil_pirqcon_init(&new); |
| |
| new->pirq = orig->pirq; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_iomemcon *orig = data; |
| struct cil_iomemcon *new = NULL; |
| |
| cil_iomemcon_init(&new); |
| |
| new->iomem_low = orig->iomem_low; |
| new->iomem_high = orig->iomem_high; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_ioportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_ioportcon *orig = data; |
| struct cil_ioportcon *new = NULL; |
| |
| cil_ioportcon_init(&new); |
| |
| new->ioport_low = orig->ioport_low; |
| new->ioport_high = orig->ioport_high; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_pcidevicecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_pcidevicecon *orig = data; |
| struct cil_pcidevicecon *new = NULL; |
| |
| cil_pcidevicecon_init(&new); |
| |
| new->dev = orig->dev; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_devicetreecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_devicetreecon *orig = data; |
| struct cil_devicetreecon *new = NULL; |
| |
| cil_devicetreecon_init(&new); |
| |
| new->path = orig->path; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_fsuse(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_fsuse *orig = data; |
| struct cil_fsuse *new = NULL; |
| |
| cil_fsuse_init(&new); |
| |
| new->type = orig->type; |
| new->fs_str = orig->fs_str; |
| |
| if (orig->context_str != NULL) { |
| new->context_str = orig->context_str; |
| } else { |
| cil_context_init(&new->context); |
| cil_copy_fill_context(db, orig->context, new->context); |
| } |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_expr(struct cil_db *db, struct cil_list *orig, struct cil_list **new) |
| { |
| struct cil_list_item *curr; |
| |
| if (orig == NULL) { |
| *new = NULL; |
| return SEPOL_OK; |
| } |
| |
| cil_list_init(new, orig->flavor); |
| |
| cil_list_for_each(curr, orig) { |
| switch (curr->flavor) { |
| case CIL_LIST: { |
| struct cil_list *sub_list; |
| cil_copy_expr(db, curr->data, &sub_list); |
| cil_list_append(*new, CIL_LIST, sub_list); |
| break; |
| } |
| case CIL_STRING: |
| cil_list_append(*new, CIL_STRING, curr->data); |
| break; |
| case CIL_DATUM: |
| cil_list_append(*new, curr->flavor, curr->data); |
| break; |
| case CIL_OP: |
| cil_list_append(*new, curr->flavor, curr->data); |
| break; |
| case CIL_CONS_OPERAND: |
| cil_list_append(*new, curr->flavor, curr->data); |
| break; |
| default: |
| cil_log(CIL_INFO, "Unknown flavor %d in expression being copied\n",curr->flavor); |
| cil_list_append(*new, curr->flavor, curr->data); |
| break; |
| } |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_constrain(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_constrain *orig = data; |
| struct cil_constrain *new = NULL; |
| |
| cil_constrain_init(&new); |
| cil_copy_classperms_list(orig->classperms, &new->classperms); |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_validatetrans(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_validatetrans *orig = data; |
| struct cil_validatetrans *new = NULL; |
| |
| cil_validatetrans_init(&new); |
| |
| new->class_str = orig->class_str; |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_call(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_call *orig = data; |
| struct cil_call *new = NULL; |
| int rc = SEPOL_ERR; |
| |
| cil_call_init(&new); |
| |
| new->macro_str = orig->macro_str; |
| new->macro = orig->macro; |
| |
| if (orig->args_tree != NULL) { |
| cil_tree_init(&new->args_tree); |
| rc = cil_copy_ast(db, orig->args_tree->root, new->args_tree->root); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| new->copied = orig->copied; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_destroy_call(new); |
| return rc; |
| } |
| |
| int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_macro *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_macro *new; |
| cil_macro_init(&new); |
| if (orig->params != NULL) { |
| cil_copy_list(orig->params, &new->params); |
| } |
| |
| *copy = new; |
| |
| } else { |
| struct cil_list_item *curr_orig = NULL; |
| struct cil_list_item *curr_new = NULL; |
| struct cil_param *param_orig = NULL; |
| struct cil_param *param_new = NULL; |
| |
| if (((struct cil_macro*)datum)->params != NULL) { |
| curr_new = ((struct cil_macro*)datum)->params->head; |
| } |
| |
| if (orig->params != NULL) { |
| curr_orig = orig->params->head; |
| } |
| |
| if (curr_orig != NULL && curr_new != NULL) { |
| while (curr_orig != NULL) { |
| if (curr_new == NULL) { |
| goto exit; |
| } |
| |
| param_orig = (struct cil_param*)curr_orig->data; |
| param_new = (struct cil_param*)curr_new->data; |
| if (param_orig->str != param_new->str) { |
| goto exit; |
| } else if (param_orig->flavor != param_new->flavor) { |
| goto exit; |
| } |
| |
| curr_orig = curr_orig->next; |
| curr_new = curr_new->next; |
| } |
| |
| if (curr_new != NULL) { |
| goto exit; |
| } |
| } else if (!(curr_orig == NULL && curr_new == NULL)) { |
| goto exit; |
| } |
| |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_optional *orig = data; |
| char *key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum == NULL) { |
| struct cil_optional *new; |
| cil_optional_init(&new); |
| *copy = new; |
| } else { |
| *copy = datum; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_copy_fill_ipaddr(struct cil_ipaddr *data, struct cil_ipaddr *new) |
| { |
| new->family = data->family; |
| memcpy(&new->ip, &data->ip, sizeof(data->ip)); |
| } |
| |
| int cil_copy_ipaddr(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) |
| { |
| struct cil_ipaddr *orig = data; |
| struct cil_ipaddr *new = NULL; |
| char * key = orig->datum.name; |
| struct cil_symtab_datum *datum = NULL; |
| |
| cil_symtab_get_datum(symtab, key, &datum); |
| if (datum != NULL) { |
| cil_log(CIL_INFO, "cil_copy_ipaddr: ipaddress cannot be redefined\n"); |
| return SEPOL_ERR; |
| } |
| |
| cil_ipaddr_init(&new); |
| cil_copy_fill_ipaddr(orig, new); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_condblock(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_condblock *orig = data; |
| struct cil_condblock *new = *copy; |
| cil_condblock_init(&new); |
| new->flavor = orig->flavor; |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_boolif(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_booleanif *orig = data; |
| struct cil_booleanif *new = NULL; |
| |
| cil_boolif_init(&new); |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| new->preserved_tunable = orig->preserved_tunable; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_tunif(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_tunableif *orig = data; |
| struct cil_tunableif *new = NULL; |
| |
| cil_tunif_init(&new); |
| |
| cil_copy_expr(db, orig->str_expr, &new->str_expr); |
| cil_copy_expr(db, orig->datum_expr, &new->datum_expr); |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_default(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_default *orig = data; |
| struct cil_default *new = NULL; |
| |
| cil_default_init(&new); |
| |
| new->flavor = orig->flavor; |
| |
| if (orig->class_strs != NULL) { |
| cil_copy_list(orig->class_strs, &new->class_strs); |
| } |
| |
| new->object = orig->object; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_defaultrange(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_defaultrange *orig = data; |
| struct cil_defaultrange *new = NULL; |
| |
| cil_defaultrange_init(&new); |
| |
| if (orig->class_strs != NULL) { |
| cil_copy_list(orig->class_strs, &new->class_strs); |
| } |
| |
| new->object_range = orig->object_range; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_handleunknown(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_handleunknown *orig = data; |
| struct cil_handleunknown *new = NULL; |
| |
| cil_handleunknown_init(&new); |
| new->handle_unknown = orig->handle_unknown; |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_mls(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_mls *orig = data; |
| struct cil_mls *new = NULL; |
| |
| cil_mls_init(&new); |
| new->value = orig->value; |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_bounds(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_bounds *orig = data; |
| struct cil_bounds *new = NULL; |
| |
| cil_bounds_init(&new); |
| |
| new->parent_str = orig->parent_str; |
| new->child_str = orig->child_str; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) |
| { |
| struct cil_src_info *orig = data; |
| struct cil_src_info *new = NULL; |
| |
| cil_src_info_init(&new); |
| |
| new->is_cil = orig->is_cil; |
| new->path = orig->path; |
| |
| *copy = new; |
| |
| return SEPOL_OK; |
| } |
| |
| int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_tree_node *parent = NULL; |
| struct cil_tree_node *new = NULL; |
| struct cil_db *db = NULL; |
| struct cil_args_copy *args = NULL; |
| struct cil_tree_node *namespace = NULL; |
| struct cil_param *param = NULL; |
| enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; |
| symtab_t *symtab = NULL; |
| void *data = NULL; |
| int (*copy_func)(struct cil_db *db, void *data, void **copy, symtab_t *symtab) = NULL; |
| struct cil_blockinherit *blockinherit = NULL; |
| |
| if (orig == NULL || extra_args == NULL) { |
| goto exit; |
| } |
| |
| args = extra_args; |
| parent = args->dest; |
| db = args->db; |
| |
| |
| switch (orig->flavor) { |
| case CIL_BLOCK: |
| copy_func = &cil_copy_block; |
| break; |
| case CIL_BLOCKABSTRACT: |
| copy_func = &cil_copy_blockabstract; |
| break; |
| case CIL_BLOCKINHERIT: |
| copy_func = &cil_copy_blockinherit; |
| break; |
| case CIL_POLICYCAP: |
| copy_func = &cil_copy_policycap; |
| break; |
| case CIL_PERM: |
| case CIL_MAP_PERM: |
| copy_func = &cil_copy_perm; |
| break; |
| case CIL_CLASSMAPPING: |
| copy_func = &cil_copy_classmapping; |
| break; |
| case CIL_CLASS: |
| case CIL_COMMON: |
| case CIL_MAP_CLASS: |
| copy_func = &cil_copy_class; |
| break; |
| case CIL_CLASSORDER: |
| copy_func = &cil_copy_classorder; |
| break; |
| case CIL_CLASSPERMISSION: |
| copy_func = &cil_copy_classpermission; |
| break; |
| case CIL_CLASSPERMISSIONSET: |
| copy_func = &cil_copy_classpermissionset; |
| break; |
| case CIL_CLASSCOMMON: |
| copy_func = &cil_copy_classcommon; |
| break; |
| case CIL_SID: |
| copy_func = &cil_copy_sid; |
| break; |
| case CIL_SIDCONTEXT: |
| copy_func = &cil_copy_sidcontext; |
| break; |
| case CIL_SIDORDER: |
| copy_func = &cil_copy_sidorder; |
| break; |
| case CIL_USER: |
| copy_func = &cil_copy_user; |
| break; |
| case CIL_USERATTRIBUTE: |
| copy_func = &cil_copy_userattribute; |
| break; |
| case CIL_USERATTRIBUTESET: |
| copy_func = &cil_copy_userattributeset; |
| break; |
| case CIL_USERROLE: |
| copy_func = &cil_copy_userrole; |
| break; |
| case CIL_USERLEVEL: |
| copy_func = &cil_copy_userlevel; |
| break; |
| case CIL_USERRANGE: |
| copy_func = &cil_copy_userrange; |
| break; |
| case CIL_USERBOUNDS: |
| copy_func = &cil_copy_bounds; |
| break; |
| case CIL_USERPREFIX: |
| copy_func = &cil_copy_userprefix; |
| break; |
| case CIL_ROLE: |
| copy_func = &cil_copy_role; |
| break; |
| case CIL_ROLETYPE: |
| copy_func = &cil_copy_roletype; |
| break; |
| case CIL_ROLEBOUNDS: |
| copy_func = &cil_copy_bounds; |
| break; |
| case CIL_ROLEATTRIBUTE: |
| copy_func = &cil_copy_roleattribute; |
| break; |
| case CIL_ROLEATTRIBUTESET: |
| copy_func = &cil_copy_roleattributeset; |
| break; |
| case CIL_ROLEALLOW: |
| copy_func = &cil_copy_roleallow; |
| break; |
| case CIL_TYPE: |
| copy_func = &cil_copy_type; |
| break; |
| case CIL_TYPEBOUNDS: |
| copy_func = &cil_copy_bounds; |
| break; |
| case CIL_TYPEPERMISSIVE: |
| copy_func = cil_copy_typepermissive; |
| break; |
| case CIL_TYPEATTRIBUTE: |
| copy_func = &cil_copy_typeattribute; |
| break; |
| case CIL_TYPEATTRIBUTESET: |
| copy_func = &cil_copy_typeattributeset; |
| break; |
| case CIL_TYPEALIAS: |
| copy_func = &cil_copy_alias; |
| break; |
| case CIL_TYPEALIASACTUAL: |
| copy_func = &cil_copy_aliasactual; |
| break; |
| case CIL_ROLETRANSITION: |
| copy_func = &cil_copy_roletransition; |
| break; |
| case CIL_NAMETYPETRANSITION: |
| copy_func = &cil_copy_nametypetransition; |
| break; |
| case CIL_RANGETRANSITION: |
| copy_func = &cil_copy_rangetransition; |
| break; |
| case CIL_TUNABLE: |
| copy_func = &cil_copy_tunable; |
| break; |
| case CIL_BOOL: |
| copy_func = &cil_copy_bool; |
| break; |
| case CIL_AVRULE: |
| case CIL_AVRULEX: |
| copy_func = &cil_copy_avrule; |
| break; |
| case CIL_PERMISSIONX: |
| copy_func = &cil_copy_permissionx; |
| break; |
| case CIL_TYPE_RULE: |
| copy_func = &cil_copy_type_rule; |
| break; |
| case CIL_SENS: |
| copy_func = &cil_copy_sens; |
| break; |
| case CIL_SENSALIAS: |
| copy_func = &cil_copy_alias; |
| break; |
| case CIL_SENSALIASACTUAL: |
| copy_func = &cil_copy_aliasactual; |
| break; |
| case CIL_CAT: |
| copy_func = &cil_copy_cat; |
| break; |
| case CIL_CATALIAS: |
| copy_func = &cil_copy_alias; |
| break; |
| case CIL_CATALIASACTUAL: |
| copy_func = &cil_copy_aliasactual; |
| break; |
| case CIL_CATSET: |
| copy_func = &cil_copy_catset; |
| break; |
| case CIL_SENSCAT: |
| copy_func = &cil_copy_senscat; |
| break; |
| case CIL_CATORDER: |
| copy_func = &cil_copy_catorder; |
| break; |
| case CIL_SENSITIVITYORDER: |
| copy_func = &cil_copy_sensitivityorder; |
| break; |
| case CIL_LEVEL: |
| copy_func = &cil_copy_level; |
| break; |
| case CIL_LEVELRANGE: |
| copy_func = &cil_copy_levelrange; |
| break; |
| case CIL_CONTEXT: |
| copy_func = &cil_copy_context; |
| break; |
| case CIL_NETIFCON: |
| copy_func = &cil_copy_netifcon; |
| break; |
| case CIL_GENFSCON: |
| copy_func = &cil_copy_genfscon; |
| break; |
| case CIL_FILECON: |
| copy_func = &cil_copy_filecon; |
| break; |
| case CIL_NODECON: |
| copy_func = &cil_copy_nodecon; |
| break; |
| case CIL_PORTCON: |
| copy_func = &cil_copy_portcon; |
| break; |
| case CIL_PIRQCON: |
| copy_func = &cil_copy_pirqcon; |
| break; |
| case CIL_IOMEMCON: |
| copy_func = &cil_copy_iomemcon; |
| break; |
| case CIL_IOPORTCON: |
| copy_func = &cil_copy_ioportcon; |
| break; |
| case CIL_PCIDEVICECON: |
| copy_func = &cil_copy_pcidevicecon; |
| break; |
| case CIL_DEVICETREECON: |
| copy_func = &cil_copy_devicetreecon; |
| break; |
| case CIL_FSUSE: |
| copy_func = &cil_copy_fsuse; |
| break; |
| case CIL_CONSTRAIN: |
| case CIL_MLSCONSTRAIN: |
| copy_func = &cil_copy_constrain; |
| break; |
| case CIL_VALIDATETRANS: |
| case CIL_MLSVALIDATETRANS: |
| copy_func = &cil_copy_validatetrans; |
| break; |
| case CIL_CALL: |
| copy_func = &cil_copy_call; |
| break; |
| case CIL_MACRO: |
| copy_func = &cil_copy_macro; |
| break; |
| case CIL_NODE: |
| copy_func = &cil_copy_node; |
| break; |
| case CIL_OPTIONAL: |
| copy_func = &cil_copy_optional; |
| break; |
| case CIL_IPADDR: |
| copy_func = &cil_copy_ipaddr; |
| break; |
| case CIL_CONDBLOCK: |
| copy_func = &cil_copy_condblock; |
| break; |
| case CIL_BOOLEANIF: |
| copy_func = &cil_copy_boolif; |
| break; |
| case CIL_TUNABLEIF: |
| copy_func = &cil_copy_tunif; |
| break; |
| case CIL_DEFAULTUSER: |
| case CIL_DEFAULTROLE: |
| case CIL_DEFAULTTYPE: |
| copy_func = &cil_copy_default; |
| break; |
| case CIL_DEFAULTRANGE: |
| copy_func = &cil_copy_defaultrange; |
| break; |
| case CIL_HANDLEUNKNOWN: |
| copy_func = &cil_copy_handleunknown; |
| break; |
| case CIL_MLS: |
| copy_func = &cil_copy_mls; |
| break; |
| case CIL_SRC_INFO: |
| copy_func = &cil_copy_src_info; |
| break; |
| default: |
| goto exit; |
| } |
| |
| if (orig->flavor >= CIL_MIN_DECLARATIVE) { |
| rc = cil_flavor_to_symtab_index(orig->flavor, &sym_index); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_get_symtab(parent, &symtab, sym_index); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| rc = (*copy_func)(db, orig->data, &data, symtab); |
| if (rc == SEPOL_OK) { |
| cil_tree_node_init(&new); |
| |
| new->parent = parent; |
| new->line = orig->line; |
| new->hll_line = orig->hll_line; |
| new->flavor = orig->flavor; |
| new->data = data; |
| |
| if (orig->flavor >= CIL_MIN_DECLARATIVE) { |
| rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new); |
| |
| namespace = new; |
| while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) { |
| namespace = namespace->parent; |
| } |
| |
| if (namespace->flavor == CIL_MACRO) { |
| struct cil_macro *macro = namespace->data; |
| struct cil_list *param_list = macro->params; |
| if (param_list != NULL) { |
| struct cil_list_item *item; |
| cil_list_for_each(item, param_list) { |
| param = item->data; |
| if (param->flavor == new->flavor) { |
| if (param->str == ((struct cil_symtab_datum*)new->data)->name) { |
| cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name); |
| cil_tree_log(namespace, CIL_ERR, "Note: macro declaration"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (new->flavor == CIL_BLOCKINHERIT) { |
| blockinherit = new->data; |
| // if a blockinherit statement is copied before blockinherit are |
| // resolved (like in an in-statement), the block will not have been |
| // resolved yet, so there's nothing to append yet. This is fine, |
| // the copied blockinherit statement will be handled later, as if |
| // it wasn't in an in-statement |
| if (blockinherit->block != NULL) { |
| cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new); |
| } |
| } |
| |
| if (parent->cl_head == NULL) { |
| parent->cl_head = new; |
| parent->cl_tail = new; |
| } else { |
| parent->cl_tail->next = new; |
| parent->cl_tail = new; |
| } |
| |
| if (orig->cl_head != NULL) { |
| args->dest = new; |
| } |
| } else { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_node_destroy(&new); |
| return rc; |
| } |
| |
| int __cil_copy_last_child_helper(__attribute__((unused)) struct cil_tree_node *orig, void *extra_args) |
| { |
| struct cil_tree_node *node = NULL; |
| struct cil_args_copy *args = NULL; |
| |
| args = extra_args; |
| node = args->dest; |
| |
| if (node->flavor != CIL_ROOT) { |
| args->dest = node->parent; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| // dest is the parent node to copy into |
| // if the copy is for a call to a macro, dest should be a pointer to the call |
| int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_node *dest) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_args_copy extra_args; |
| |
| extra_args.dest = dest; |
| extra_args.db = db; |
| |
| rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |