/*
* 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_expandtypeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_expandtypeattribute *orig = data;
struct cil_expandtypeattribute *new = NULL;
fprintf(stderr, "%s %u\n", __func__, __LINE__);
cil_expandtypeattribute_init(&new);
if (orig->attr_strs != NULL) {
cil_copy_list(orig->attr_strs, &new->attr_strs);
}
if (orig->attr_datums != NULL) {
cil_copy_list(orig->attr_datums, &new->attr_datums);
}
new->expand = orig->expand;
*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_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_ibpkeycon *orig = data;
struct cil_ibpkeycon *new = NULL;
cil_ibpkeycon_init(&new);
new->subnet_prefix_str = orig->subnet_prefix_str;
new->pkey_low = orig->pkey_low;
new->pkey_high = orig->pkey_high;
if (orig->context_str) {
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_ibendportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_ibendportcon *orig = data;
struct cil_ibendportcon *new = NULL;
cil_ibendportcon_init(&new);
new->dev_name_str = orig->dev_name_str;
new->port = orig->port;
if (orig->context_str) {
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_EXPANDTYPEATTRIBUTE:
copy_func = &cil_copy_expandtypeattribute;
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_IBPKEYCON:
copy_func = &cil_copy_ibpkeycon;
break;
case CIL_IBENDPORTCON:
copy_func = &cil_copy_ibendportcon;
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) {
/* Check the flavor of data if was found in the destination symtab */
if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) {
cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name);
cil_tree_log(NODE(data), CIL_ERR, "Note: conflicting declaration");
new->flavor = FLAVOR(data);
rc = SEPOL_ERR;
goto exit;
}
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;
}