📄 policydb.c
字号:
/* * Implementation of the policy database. * * Author : Stephen Smalley, <sds@epoch.ncsc.mil> *//* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> * * Added conditional policy language extensions * * 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. */#include <linux/kernel.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/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", mls_symtab_names "bools"};#endifint policydb_loaded_version;static unsigned int symtab_sizes[SYM_NUM] = { 2, 32, 16, 512, 128, mls_symtab_sizes 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 - 1, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_BOOL, .sym_num = SYM_NUM, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_IPV6, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, }, { .version = POLICYDB_VERSION_NLCLASS, .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. */int roles_init(struct policydb *p){ char *key = NULL; int rc; struct role_datum *role; role = kmalloc(sizeof(*role), GFP_KERNEL); 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 = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto out_free_role; } strcpy(key, OBJECT_R); rc = hashtab_insert(p->p_roles.table, key, role); if (rc) goto out_free_key;out: return rc;out_free_key: kfree(key);out_free_role: kfree(role); goto out;}/* * Initialize a policy database structure. */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 (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) ={ common_index, class_index, role_index, type_index, user_index, mls_index_f cond_index_bool};/* * 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. */int policydb_index_classes(struct policydb *p){ int rc; p->p_common_val_to_name = kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL); 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 = kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL); if (!p->class_val_to_struct) { rc = -ENOMEM; goto out; } p->p_class_val_to_name = kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL); 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. */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); mls_policydb_index_others(p); 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 = kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)), GFP_KERNEL); if (!p->role_val_to_struct) { rc = -ENOMEM; goto out; } p->user_val_to_struct = kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)), GFP_KERNEL); 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] = kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL); 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){ kfree(key); kfree(datum); return 0;}static int common_destroy(void *key, void *datum, void *p){ struct common_datum *comdatum; kfree(key); comdatum = datum; hashtab_map(comdatum->permissions.table, perm_destroy, NULL); hashtab_destroy(comdatum->permissions.table); kfree(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; kfree(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; kfree(etmp); } ctemp = constraint; constraint = constraint->next; kfree(ctemp); } kfree(cladatum->comkey); kfree(datum); return 0;}static int role_destroy(void *key, void *datum, void *p){ struct role_datum *role; kfree(key); role = datum; ebitmap_destroy(&role->dominates); ebitmap_destroy(&role->types); kfree(datum); return 0;}static int type_destroy(void *key, void *datum, void *p){ kfree(key); kfree(datum); return 0;}static int user_destroy(void *key, void *datum, void *p){ struct user_datum *usrdatum; kfree(key); usrdatum = datum; ebitmap_destroy(&usrdatum->roles); mls_user_destroy(usrdatum); kfree(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, mls_destroy_f cond_destroy_bool};void ocontext_destroy(struct ocontext *c, int i){ context_destroy(&c->context[0]); context_destroy(&c->context[1]); if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF || i == OCON_FSUSE) kfree(c->u.name); kfree(c);}/* * Free any memory allocated by a policy database structure. */void policydb_destroy(struct policydb *p){ struct ocontext *c, *ctmp; struct genfs *g, *gtmp; int i; for (i = 0; i < SYM_NUM; i++) { hashtab_map(p->symtab[i].table, destroy_f[i], NULL); hashtab_destroy(p->symtab[i].table); } for (i = 0; i < SYM_NUM; i++) { if (p->sym_val_to_name[i]) kfree(p->sym_val_to_name[i]); } if (p->class_val_to_struct) kfree(p->class_val_to_struct); if (p->role_val_to_struct) kfree(p->role_val_to_struct); if (p->user_val_to_struct) kfree(p->user_val_to_struct); avtab_destroy(&p->te_avtab); for (i = 0; i < OCON_NUM; i++) { c = p->ocontexts[i]; while (c) { ctmp = c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -