📄 policydb.c
字号:
/* * Implementation of the policy database. * * Author : Stephen Smalley, <sds@epoch.ncsc.mil> *//* * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> * * Added conditional policy language extensions * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. *//* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */#include <asm/byteorder.h>#include <xen/lib.h>#include <xen/types.h>#include <xen/xmalloc.h>#include <xen/string.h>#include <xen/errno.h>#include "security.h"#include "policydb.h"#include "conditional.h"#include "mls.h"#define _DEBUG_HASHES#ifdef DEBUG_HASHESstatic char *symtab_name[SYM_NUM] = { "common prefixes", "classes", "roles", "types", "users", "bools", "levels", "categories",};#endifint flask_mls_enabled = 0;static unsigned int symtab_sizes[SYM_NUM] = { 2, 32, 16, 512, 128, 16, 16, 16,};struct policydb_compat_info { int version; int sym_num; int ocon_num;};/* These need to be updated if SYM_NUM or OCON_NUM changes */static struct policydb_compat_info policydb_compat[] = { { .version = POLICYDB_VERSION_BASE, .sym_num = SYM_NUM - 3, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_BOOL, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_IPV6, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NUM, }, { .version = POLICYDB_VERSION_NLCLASS, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NUM, }, { .version = POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, }, { .version = POLICYDB_VERSION_AVTAB, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, },};static struct policydb_compat_info *policydb_lookup_compat(int version){ int i; struct policydb_compat_info *info = NULL; for ( i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++ ) { if ( policydb_compat[i].version == version ) { info = &policydb_compat[i]; break; } } return info;}/* * Initialize the role table. */static int roles_init(struct policydb *p){ char *key = NULL; int rc; struct role_datum *role; role = xmalloc(struct role_datum); if ( !role ) { rc = -ENOMEM; goto out; } memset(role, 0, sizeof(*role)); role->value = ++p->p_roles.nprim; if ( role->value != OBJECT_R_VAL ) { rc = -EINVAL; goto out_free_role; } key = xmalloc_array(char, strlen(OBJECT_R)+1); if ( !key ) { rc = -ENOMEM; goto out_free_role; } strlcpy(key, OBJECT_R, strlen(OBJECT_R)+1); rc = hashtab_insert(p->p_roles.table, key, role); if ( rc ) goto out_free_key;out: return rc;out_free_key: xfree(key);out_free_role: xfree(role); goto out;}/* * Initialize a policy database structure. */static int policydb_init(struct policydb *p){ int i, rc; memset(p, 0, sizeof(*p)); for ( i = 0; i < SYM_NUM; i++ ) { rc = symtab_init(&p->symtab[i], symtab_sizes[i]); if ( rc ) goto out_free_symtab; } rc = avtab_init(&p->te_avtab); if ( rc ) goto out_free_symtab; rc = roles_init(p); if ( rc ) goto out_free_avtab; rc = cond_policydb_init(p); if ( rc ) goto out_free_avtab;out: return rc;out_free_avtab: avtab_destroy(&p->te_avtab);out_free_symtab: for ( i = 0; i < SYM_NUM; i++ ) hashtab_destroy(p->symtab[i].table); goto out;}/* * The following *_index functions are used to * define the val_to_name and val_to_struct arrays * in a policy database structure. The val_to_name * arrays are used when converting security context * structures into string representations. The * val_to_struct arrays are used when the attributes * of a class, role, or user are needed. */static int common_index(void *key, void *datum, void *datap){ struct policydb *p; struct common_datum *comdatum; comdatum = datum; p = datap; if ( !comdatum->value || comdatum->value > p->p_commons.nprim ) return -EINVAL; p->p_common_val_to_name[comdatum->value - 1] = key; return 0;}static int class_index(void *key, void *datum, void *datap){ struct policydb *p; struct class_datum *cladatum; cladatum = datum; p = datap; if ( !cladatum->value || cladatum->value > p->p_classes.nprim ) return -EINVAL; p->p_class_val_to_name[cladatum->value - 1] = key; p->class_val_to_struct[cladatum->value - 1] = cladatum; return 0;}static int role_index(void *key, void *datum, void *datap){ struct policydb *p; struct role_datum *role; role = datum; p = datap; if ( !role->value || role->value > p->p_roles.nprim ) return -EINVAL; p->p_role_val_to_name[role->value - 1] = key; p->role_val_to_struct[role->value - 1] = role; return 0;}static int type_index(void *key, void *datum, void *datap){ struct policydb *p; struct type_datum *typdatum; typdatum = datum; p = datap; if ( typdatum->primary ) { if ( !typdatum->value || typdatum->value > p->p_types.nprim ) return -EINVAL; p->p_type_val_to_name[typdatum->value - 1] = key; } return 0;}static int user_index(void *key, void *datum, void *datap){ struct policydb *p; struct user_datum *usrdatum; usrdatum = datum; p = datap; if ( !usrdatum->value || usrdatum->value > p->p_users.nprim ) return -EINVAL; p->p_user_val_to_name[usrdatum->value - 1] = key; p->user_val_to_struct[usrdatum->value - 1] = usrdatum; return 0;}static int sens_index(void *key, void *datum, void *datap){ struct policydb *p; struct level_datum *levdatum; levdatum = datum; p = datap; if ( !levdatum->isalias ) { if ( !levdatum->level->sens || levdatum->level->sens > p->p_levels.nprim ) return -EINVAL; p->p_sens_val_to_name[levdatum->level->sens - 1] = key; } return 0;}static int cat_index(void *key, void *datum, void *datap){ struct policydb *p; struct cat_datum *catdatum; catdatum = datum; p = datap; if ( !catdatum->isalias ) { if ( !catdatum->value || catdatum->value > p->p_cats.nprim ) return -EINVAL; p->p_cat_val_to_name[catdatum->value - 1] = key; } return 0;}static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) ={ common_index, class_index, role_index, type_index, user_index, cond_index_bool, sens_index, cat_index,};/* * Define the common val_to_name array and the class * val_to_name and val_to_struct arrays in a policy * database structure. * * Caller must clean up upon failure. */static int policydb_index_classes(struct policydb *p){ int rc; p->p_common_val_to_name = xmalloc_array(char *, p->p_commons.nprim); if ( !p->p_common_val_to_name ) { rc = -ENOMEM; goto out; } rc = hashtab_map(p->p_commons.table, common_index, p); if ( rc ) goto out; p->class_val_to_struct = (void *)xmalloc_array(struct class_datum, p->p_classes.nprim); if ( !p->class_val_to_struct ) { rc = -ENOMEM; goto out; } p->p_class_val_to_name = xmalloc_array(char *, p->p_classes.nprim); if ( !p->p_class_val_to_name ) { rc = -ENOMEM; goto out; } rc = hashtab_map(p->p_classes.table, class_index, p);out: return rc;}#ifdef DEBUG_HASHESstatic void symtab_hash_eval(struct symtab *s){ int i; for ( i = 0; i < SYM_NUM; i++ ) { struct hashtab *h = s[i].table; struct hashtab_info info; hashtab_stat(h, &info); printk(KERN_INFO "%s: %d entries and %d/%d buckets used, " "longest chain length %d\n", symtab_name[i], h->nel, info.slots_used, h->size, info.max_chain_len); }}#endif/* * Define the other val_to_name and val_to_struct arrays * in a policy database structure. * * Caller must clean up on failure. */static int policydb_index_others(struct policydb *p){ int i, rc = 0; printk(KERN_INFO "security: %d users, %d roles, %d types, %d bools", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); if ( flask_mls_enabled ) printk(", %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim); printk("\n"); printk(KERN_INFO "security: %d classes, %d rules\n", p->p_classes.nprim, p->te_avtab.nel);#ifdef DEBUG_HASHES avtab_hash_eval(&p->te_avtab, "rules"); symtab_hash_eval(p->symtab);#endif p->role_val_to_struct = (void *)xmalloc_array(struct role_datum, p->p_roles.nprim); if ( !p->role_val_to_struct ) { rc = -ENOMEM; goto out; } p->user_val_to_struct = (void *)xmalloc_array(struct user_datum, p->p_users.nprim); if ( !p->user_val_to_struct ) { rc = -ENOMEM; goto out; } if ( cond_init_bool_indexes(p) ) { rc = -ENOMEM; goto out; } for ( i = SYM_ROLES; i < SYM_NUM; i++ ) { p->sym_val_to_name[i] = xmalloc_array(char *, p->symtab[i].nprim); if ( !p->sym_val_to_name[i] ) { rc = -ENOMEM; goto out; } rc = hashtab_map(p->symtab[i].table, index_f[i], p); if ( rc ) goto out; }out: return rc;}/* * The following *_destroy functions are used to * free any memory allocated for each kind of * symbol data in the policy database. */static int perm_destroy(void *key, void *datum, void *p){ xfree(key); xfree(datum); return 0;}static int common_destroy(void *key, void *datum, void *p){ struct common_datum *comdatum; xfree(key); comdatum = datum; hashtab_map(comdatum->permissions.table, perm_destroy, NULL); hashtab_destroy(comdatum->permissions.table); xfree(datum); return 0;}static int class_destroy(void *key, void *datum, void *p){ struct class_datum *cladatum; struct constraint_node *constraint, *ctemp; struct constraint_expr *e, *etmp; xfree(key); cladatum = datum; hashtab_map(cladatum->permissions.table, perm_destroy, NULL); hashtab_destroy(cladatum->permissions.table); constraint = cladatum->constraints; while ( constraint ) { e = constraint->expr; while ( e ) { ebitmap_destroy(&e->names); etmp = e; e = e->next; xfree(etmp); } ctemp = constraint; constraint = constraint->next; xfree(ctemp); } constraint = cladatum->validatetrans; while ( constraint ) { e = constraint->expr; while ( e ) { ebitmap_destroy(&e->names); etmp = e; e = e->next; xfree(etmp); } ctemp = constraint; constraint = constraint->next; xfree(ctemp); } xfree(cladatum->comkey); xfree(datum); return 0;}static int role_destroy(void *key, void *datum, void *p){ struct role_datum *role; xfree(key); role = datum; ebitmap_destroy(&role->dominates); ebitmap_destroy(&role->types); xfree(datum); return 0;}static int type_destroy(void *key, void *datum, void *p){ xfree(key); xfree(datum); return 0;}static int user_destroy(void *key, void *datum, void *p){ struct user_datum *usrdatum; xfree(key); usrdatum = datum; ebitmap_destroy(&usrdatum->roles); ebitmap_destroy(&usrdatum->range.level[0].cat); ebitmap_destroy(&usrdatum->range.level[1].cat); ebitmap_destroy(&usrdatum->dfltlevel.cat); xfree(datum); return 0;}static int sens_destroy(void *key, void *datum, void *p){ struct level_datum *levdatum; xfree(key); levdatum = datum; ebitmap_destroy(&levdatum->level->cat); xfree(levdatum->level); xfree(datum); return 0;}static int cat_destroy(void *key, void *datum, void *p){ xfree(key); xfree(datum); return 0;}static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) ={ common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, cond_destroy_bool, sens_destroy, cat_destroy,};static void ocontext_destroy(struct ocontext *c, int i){ context_destroy(&c->context[0]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -