diff options
Diffstat (limited to 'checkpolicy/test')
-rw-r--r-- | checkpolicy/test/Makefile | 21 | ||||
-rw-r--r-- | checkpolicy/test/dismod.c | 957 | ||||
-rw-r--r-- | checkpolicy/test/dispol.c | 511 |
3 files changed, 1489 insertions, 0 deletions
diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile new file mode 100644 index 00000000..fe1bf5d2 --- /dev/null +++ b/checkpolicy/test/Makefile @@ -0,0 +1,21 @@ +# +# Makefile for building the dispol program +# +PREFIX ?= $(DESTDIR)/usr +BINDIR=$(PREFIX)/bin +LIBDIR=$(PREFIX)/lib +INCLUDEDIR ?= $(PREFIX)/include + +CFLAGS ?= -g -Wall -O2 -pipe +override CFLAGS += -I$(INCLUDEDIR) + +LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR) + +all: dispol dismod + +dispol: dispol.o + +dismod: dismod.o + +clean: + -rm -f dispol dismod *.o diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c new file mode 100644 index 00000000..705f1cbc --- /dev/null +++ b/checkpolicy/test/dismod.c @@ -0,0 +1,957 @@ + +/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> + * + * Copyright (C) 2003,2004,2005 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. + */ + +/* + * dismod.c + * + * Test program to the contents of a binary policy in text + * form. + * + * dismod binary_mod_file + */ + +#include <getopt.h> +#include <assert.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/services.h> +#include <sepol/policydb/conditional.h> +#include <sepol/policydb/flask.h> +#include <sepol/policydb/link.h> +#include <sepol/policydb/module.h> +#include <sepol/policydb/util.h> +#include <sepol/policydb/polcaps.h> + +#include <byteswap.h> +#include <endian.h> + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define le32_to_cpu(x) (x) +#else +#define le32_to_cpu(x) bswap_32(x) +#endif + +static policydb_t policydb; +extern unsigned int ss_initialized; + +int policyvers = MOD_POLICYDB_VERSION_BASE; + +static const char *symbol_labels[9] = { + "commons", + "classes", "roles ", "types ", "users ", "bools ", + "levels ", "cats ", "attribs" +}; + +void usage(char *progname) +{ + printf("usage: %s binary_pol_file\n\n", progname); + exit(1); +} + +static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p, + FILE * fp) +{ + char *perm; + fprintf(fp, "{"); + perm = sepol_av_to_string(p, class, mask); + if (perm) + fprintf(fp, "%s ", perm); + fprintf(fp, "}"); +} + +static void render_access_bitmap(ebitmap_t * map, uint32_t class, + policydb_t * p, FILE * fp) +{ + unsigned int i; + char *perm; + fprintf(fp, "{"); + for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) { + if (ebitmap_get_bit(map, i)) { + perm = sepol_av_to_string(p, class, 1 << i); + if (perm) + fprintf(fp, " %s", perm); + } + } + fprintf(fp, " }"); +} + +static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type, + uint32_t symbol_value, char *prefix) +{ + char *id = p->sym_val_to_name[symbol_type][symbol_value]; + scope_datum_t *scope = + (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id); + assert(scope != NULL); + if (scope->scope == SCOPE_REQ) { + fprintf(fp, " [%s%s]", prefix, id); + } else { + fprintf(fp, " %s%s", prefix, id); + } +} + +int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy, + FILE * fp) +{ + int i, num_types; + + if (set->flags & TYPE_STAR) { + fprintf(fp, " * "); + return 0; + } else if (set->flags & TYPE_COMP) { + fprintf(fp, " ~"); + } + + num_types = 0; + if (flags & RULE_SELF) { + num_types++; + } + + for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); + i++) { + if (!ebitmap_get_bit(&set->types, i)) + continue; + num_types++; + if (num_types > 1) + break; + } + + if (num_types <= 1) { + for (i = ebitmap_startbit(&set->negset); + i < ebitmap_length(&set->negset); i++) { + if (!ebitmap_get_bit(&set->negset, i)) + continue; + num_types++; + if (num_types > 1) + break; + } + } + + if (num_types > 1) + fprintf(fp, "{"); + + for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); + i++) { + if (!ebitmap_get_bit(&set->types, i)) + continue; + display_id(policy, fp, SYM_TYPES, i, ""); + } + + for (i = ebitmap_startbit(&set->negset); + i < ebitmap_length(&set->negset); i++) { + if (!ebitmap_get_bit(&set->negset, i)) + continue; + display_id(policy, fp, SYM_TYPES, i, "-"); + } + + if (flags & RULE_SELF) { + fprintf(fp, " self"); + } + + if (num_types > 1) + fprintf(fp, " }"); + + return 0; +} + +int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp) +{ + int i, num = 0; + + if (roles->flags & ROLE_STAR) { + fprintf(fp, " * "); + return 0; + } else if (roles->flags & ROLE_COMP) { + fprintf(fp, " ~"); + } + + for (i = ebitmap_startbit(&roles->roles); + i < ebitmap_length(&roles->roles); i++) { + if (!ebitmap_get_bit(&roles->roles, i)) + continue; + num++; + if (num > 1) { + fprintf(fp, "{"); + break; + } + } + + for (i = ebitmap_startbit(&roles->roles); + i < ebitmap_length(&roles->roles); i++) { + if (ebitmap_get_bit(&roles->roles, i)) + display_id(p, fp, SYM_ROLES, i, ""); + } + + if (num > 1) + fprintf(fp, " }"); + + return 0; + +} + +/* 'what' values for this function */ +#define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */ +#define RENDER_ENABLED 0x0002 +#define RENDER_DISABLED 0x0004 +#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED) + +int display_avrule(avrule_t * avrule, uint32_t what, policydb_t * policy, + FILE * fp) +{ + class_perm_node_t *cur; + int num_classes; + + if (avrule == NULL) { + fprintf(fp, " <empty>\n"); + return 0; + } + if (avrule->specified & AVRULE_AV) { + if (avrule->specified & AVRULE_ALLOWED) { + fprintf(fp, " allow"); + } + if (avrule->specified & AVRULE_AUDITALLOW) { + fprintf(fp, " auditallow "); + } + if (avrule->specified & AVRULE_DONTAUDIT) { + fprintf(fp, " dontaudit"); + } + } else if (avrule->specified & AVRULE_TYPE) { + if (avrule->specified & AVRULE_TRANSITION) { + fprintf(fp, " type_transition"); + } + if (avrule->specified & AVRULE_MEMBER) { + fprintf(fp, " type_member"); + } + if (avrule->specified & AVRULE_CHANGE) { + fprintf(fp, " type_change"); + } + } else if (avrule->specified & AVRULE_NEVERALLOW) { + fprintf(fp, " neverallow"); + } else { + fprintf(fp, " ERROR: no valid rule type specified\n"); + return -1; + } + + if (display_type_set(&avrule->stypes, 0, policy, fp)) + return -1; + + if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp)) + return -1; + + fprintf(fp, " :"); + cur = avrule->perms; + num_classes = 0; + while (cur) { + num_classes++; + if (num_classes > 1) + break; + cur = cur->next; + } + + if (num_classes > 1) + fprintf(fp, " {"); + + cur = avrule->perms; + while (cur) { + display_id(policy, fp, SYM_CLASSES, cur->class - 1, ""); + cur = cur->next; + } + + if (num_classes > 1) + fprintf(fp, " }"); + fprintf(fp, " "); + + if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) { + render_access_mask(avrule->perms->data, avrule->perms->class, + policy, fp); + } else if (avrule->specified & AVRULE_TYPE) { + display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); + } + + fprintf(fp, ";\n"); + + return 0; +} + +int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) +{ + type_datum_t *type; + FILE *fp; + int i, first_attrib = 1; + + type = (type_datum_t *) datum; + fp = (FILE *) data; + + if (type->primary) { + display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, ""); + fprintf(fp, " [%d]: ", type->s.value); + } else { + /* as that aliases have no value of their own and that + * they can never be required by a module, use this + * alternative way of displaying a name */ + fprintf(fp, " %s [%d]: ", (char *)key, type->s.value); + } + if (type->flavor == TYPE_ATTRIB) { + fprintf(fp, "attribute for types"); + for (i = ebitmap_startbit(&type->types); + i < ebitmap_length(&type->types); i++) { + if (!ebitmap_get_bit(&type->types, i)) + continue; + if (first_attrib) { + first_attrib = 0; + } else { + fprintf(fp, ","); + } + display_id(&policydb, fp, SYM_TYPES, i, ""); + } + } else if (type->primary) { + fprintf(fp, "type"); + } else { + fprintf(fp, "alias for type"); + display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, ""); + } + fprintf(fp, " flags:%x\n", type->flags); + + return 0; +} + +int display_types(policydb_t * p, FILE * fp) +{ + if (hashtab_map(p->p_types.table, display_type_callback, fp)) + return -1; + return 0; +} + +int display_users(policydb_t * p, FILE * fp) +{ + int i, j; + ebitmap_t *bitmap; + for (i = 0; i < p->p_users.nprim; i++) { + display_id(p, fp, SYM_USERS, i, ""); + fprintf(fp, ":"); + bitmap = &(p->user_val_to_struct[i]->roles.roles); + for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap); + j++) { + if (ebitmap_get_bit(bitmap, j)) { + display_id(p, fp, SYM_ROLES, j, ""); + } + } + fprintf(fp, "\n"); + } + return 0; +} + +int display_bools(policydb_t * p, FILE * fp) +{ + int i; + + for (i = 0; i < p->p_bools.nprim; i++) { + display_id(p, fp, SYM_BOOLS, i, ""); + fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state); + } + return 0; +} + +void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) +{ + + cond_expr_t *cur; + for (cur = exp; cur != NULL; cur = cur->next) { + switch (cur->expr_type) { + case COND_BOOL: + fprintf(fp, "%s ", + p->p_bool_val_to_name[cur->bool - 1]); + break; + case COND_NOT: + fprintf(fp, "! "); + break; + case COND_OR: + fprintf(fp, "|| "); + break; + case COND_AND: + fprintf(fp, "&& "); + break; + case COND_XOR: + fprintf(fp, "^ "); + break; + case COND_EQ: + fprintf(fp, "== "); + break; + case COND_NEQ: + fprintf(fp, "!= "); + break; + default: + fprintf(fp, "error!"); + break; + } + } +} + +void display_policycon(policydb_t * p, FILE * fp) +{ +#if 0 + int i; + ocontext_t *cur; + char *name; + + for (i = 0; i < POLICYCON_NUM; i++) { + fprintf(fp, "%s:", symbol_labels[i]); + for (cur = p->policycon[i].head; cur != NULL; cur = cur->next) { + if (*(cur->u.name) == '\0') { + name = "{default}"; + } else { + name = cur->u.name; + } + fprintf(fp, "\n%16s - %s:%s:%s", name, + p->p_user_val_to_name[cur->context[0].user - 1], + p->p_role_val_to_name[cur->context[0].role - 1], + p->p_type_val_to_name[cur->context[0].type - + 1]); + } + fprintf(fp, "\n"); + } +#endif +} + +void display_initial_sids(policydb_t * p, FILE * fp) +{ + ocontext_t *cur; + char *user, *role, *type; + + fprintf(fp, "Initial SIDs:\n"); + for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) { + user = p->p_user_val_to_name[cur->context[0].user - 1]; + role = p->p_role_val_to_name[cur->context[0].role - 1]; + type = p->p_type_val_to_name[cur->context[0].type - 1]; + fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n", + cur->u.name, cur->sid[0], user, role, type); + } +#if 0 + fprintf(fp, "Policy Initial SIDs:\n"); + for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) { + user = p->p_user_val_to_name[cur->context[0].user - 1]; + role = p->p_role_val_to_name[cur->context[0].role - 1]; + type = p->p_type_val_to_name[cur->context[0].type - 1]; + fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n", + cur->u.name, cur->sid[0], user, role, type); + } +#endif +} + +void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp) +{ + for (; tr; tr = tr->next) { + fprintf(fp, "role transition "); + display_mod_role_set(&tr->roles, p, fp); + display_type_set(&tr->types, 0, p, fp); + display_id(p, fp, SYM_ROLES, tr->new_role - 1, " :"); + fprintf(fp, "\n"); + } +} + +void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp) +{ + for (; ra; ra = ra->next) { + fprintf(fp, "role allow "); + display_mod_role_set(&ra->roles, p, fp); + display_mod_role_set(&ra->new_roles, p, fp); + fprintf(fp, "\n"); + } +} + +int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) +{ + char *id; + role_datum_t *role; + FILE *fp; + + id = key; + role = (role_datum_t *) datum; + fp = (FILE *) data; + + fprintf(fp, "role:"); + display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, ""); + fprintf(fp, " types: "); + display_type_set(&role->types, 0, &policydb, fp); + fprintf(fp, "\n"); + + return 0; +} + +static int display_scope_index(scope_index_t * indices, policydb_t * p, + FILE * out_fp) +{ + int i; + for (i = 0; i < SYM_NUM; i++) { + int any_found = 0, j; + fprintf(out_fp, "%s:", symbol_labels[i]); + for (j = ebitmap_startbit(&indices->scope[i]); + j < ebitmap_length(&indices->scope[i]); j++) { + if (ebitmap_get_bit(&indices->scope[i], j)) { + any_found = 1; + fprintf(out_fp, " %s", + p->sym_val_to_name[i][j]); + if (i == SYM_CLASSES) { + if (j < indices->class_perms_len) { + render_access_bitmap(indices-> + class_perms_map + + j, j + 1, + p, out_fp); + } else { + fprintf(out_fp, + "<no perms known>"); + } + } + } + } + if (!any_found) { + fprintf(out_fp, " <empty>"); + } + fprintf(out_fp, "\n"); + } + return 0; +} + +#if 0 +int display_cond_expressions(policydb_t * p, FILE * fp) +{ + cond_node_t *cur; + cond_av_list_t *av_cur; + for (cur = p->cond_list; cur != NULL; cur = cur->next) { + fprintf(fp, "expression: "); + display_expr(p, cur->expr, fp); + fprintf(fp, "current state: %d\n", cur->cur_state); + fprintf(fp, "True list:\n"); + for (av_cur = cur->true_list; av_cur != NULL; + av_cur = av_cur->next) { + fprintf(fp, "\t"); + render_av_rule(&av_cur->node->key, &av_cur->node->datum, + RENDER_CONDITIONAL, p, fp); + } + fprintf(fp, "False list:\n"); + for (av_cur = cur->false_list; av_cur != NULL; + av_cur = av_cur->next) { + fprintf(fp, "\t"); + render_av_rule(&av_cur->node->key, &av_cur->node->datum, + RENDER_CONDITIONAL, p, fp); + } + } + return 0; +} + +int change_bool(char *name, int state, policydb_t * p, FILE * fp) +{ + cond_bool_datum_t *bool; + + bool = hashtab_search(p->p_bools.table, name); + if (bool == NULL) { + fprintf(fp, "Could not find bool %s\n", name); + return -1; + } + bool->state = state; + evaluate_conds(p); + return 0; +} +#endif + +int display_avdecl(avrule_decl_t * decl, int field, uint32_t what, + policydb_t * policy, FILE * out_fp) +{ + fprintf(out_fp, "decl %u:%s\n", decl->decl_id, + (decl->enabled ? " [enabled]" : "")); + switch (field) { + case 0:{ + cond_list_t *cond = decl->cond_list; + avrule_t *avrule; + while (cond) { + fprintf(out_fp, "expression: "); + display_expr(&policydb, cond->expr, out_fp); + fprintf(out_fp, "current state: %d\n", + cond->cur_state); + fprintf(out_fp, "True list:\n"); + avrule = cond->avtrue_list; + while (avrule) { + display_avrule(avrule, + RENDER_UNCONDITIONAL, + &policydb, out_fp); + avrule = avrule->next; + } + fprintf(out_fp, "False list:\n"); + avrule = cond->avfalse_list; + while (avrule) { + display_avrule(avrule, + RENDER_UNCONDITIONAL, + &policydb, out_fp); + avrule = avrule->next; + } + cond = cond->next; + } + break; + } + case 1:{ + avrule_t *avrule = decl->avrules; + if (avrule == NULL) { + fprintf(out_fp, " <empty>\n"); + } + while (avrule != NULL) { + if (display_avrule + (avrule, what, policy, out_fp)) { + return -1; + } + avrule = avrule->next; + } + break; + } + case 2:{ /* role_type_node */ + break; + } + case 3:{ + display_role_trans(decl->role_tr_rules, policy, out_fp); + break; + } + case 4:{ + display_role_allow(decl->role_allow_rules, policy, + out_fp); + break; + } + case 5:{ + if (display_scope_index + (&decl->required, policy, out_fp)) { + return -1; + } + break; + } + case 6:{ + if (display_scope_index + (&decl->declared, policy, out_fp)) { + return -1; + } + break; + } + default:{ + assert(0); + } + } + return 0; /* should never get here */ +} + +int display_avblock(int field, uint32_t what, policydb_t * policy, + FILE * out_fp) +{ + avrule_block_t *block = policydb.global; + while (block != NULL) { + fprintf(out_fp, "--- begin avrule block ---\n"); + avrule_decl_t *decl = block->branch_list; + while (decl != NULL) { + if (display_avdecl(decl, field, what, policy, out_fp)) { + return -1; + } + decl = decl->next; + } + block = block->next; + } + return 0; +} + +int display_handle_unknown(policydb_t * p, FILE * out_fp) +{ + if (p->handle_unknown == ALLOW_UNKNOWN) + fprintf(out_fp, "Allow unknown classes and perms\n"); + else if (p->handle_unknown == DENY_UNKNOWN) + fprintf(out_fp, "Deny unknown classes and perms\n"); + else if (p->handle_unknown == REJECT_UNKNOWN) + fprintf(out_fp, "Reject unknown classes and perms\n"); + return 0; +} + +static int read_policy(char *filename, policydb_t * policy) +{ + FILE *in_fp; + struct policy_file f; + int retval; + uint32_t buf[1]; + + if ((in_fp = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "Can't open '%s': %s\n", + filename, strerror(errno)); + exit(1); + } + policy_file_init(&f); + f.type = PF_USE_STDIO; + f.fp = in_fp; + + /* peek at the first byte. if they are indicative of a + package use the package reader, otherwise use the normal + policy reader */ + if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) { + fprintf(stderr, "Could not read from policy.\n"); + exit(1); + } + rewind(in_fp); + if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) { + sepol_module_package_t *package; + if (sepol_module_package_create(&package)) { + fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); + exit(1); + } + package->policy = (sepol_policydb_t *) policy; + package->file_contexts = NULL; + retval = + sepol_module_package_read(package, + (sepol_policy_file_t *) & f, 1); + free(package->file_contexts); + } else { + if (policydb_init(policy)) { + fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); + exit(1); + } + retval = policydb_read(policy, &f, 1); + } + fclose(in_fp); + return retval; +} + +static void link_module(policydb_t * base, FILE * out_fp) +{ + char module_name[80] = { 0 }; + int ret; + policydb_t module, *mods = &module; + + if (base->policy_type != POLICY_BASE) { + printf("Can only link if initial file was a base policy.\n"); + return; + } + printf("\nModule filename: "); + fgets(module_name, sizeof(module_name), stdin); + module_name[strlen(module_name) - 1] = '\0'; /* remove LF */ + if (module_name[0] == '\0') { + return; + } + + /* read the binary policy */ + fprintf(out_fp, "Reading module...\n"); + if (read_policy(module_name, mods)) { + fprintf(stderr, + "%s: error(s) encountered while loading policy\n", + module_name); + exit(1); + } + if (module.policy_type != POLICY_MOD) { + fprintf(stderr, "This file is not a loadable policy module.\n"); + exit(1); + } + if (policydb_index_classes(&module) || + policydb_index_others(NULL, &module, 0)) { + fprintf(stderr, "Could not index module.\n"); + exit(1); + } + ret = link_modules(NULL, base, &mods, 1, 0); + if (ret != 0) { + printf("Link failed (error %d)\n", ret); + printf("(You will probably need to restart dismod.)\n"); + } + policydb_destroy(&module); + return; +} + +static void display_policycaps(policydb_t * p, FILE * fp) +{ + ebitmap_node_t *node; + const char *capname; + char buf[64]; + int i; + + fprintf(fp, "policy capabilities:\n"); + ebitmap_for_each_bit(&p->policycaps, node, i) { + if (ebitmap_node_get_bit(node, i)) { + capname = sepol_polcap_getname(i); + if (capname == NULL) { + snprintf(buf, sizeof(buf), "unknown (%d)", i); + capname = buf; + } + fprintf(fp, "\t%s\n", capname); + } + } +} + +int menu() +{ + printf("\nSelect a command:\n"); + printf("1) display unconditional AVTAB\n"); + printf("2) display conditional AVTAB\n"); + printf("3) display users\n"); + printf("4) display bools\n"); + printf("5) display roles\n"); + printf("6) display types, attributes, and aliases\n"); + printf("7) display role transitions\n"); + printf("8) display role allows\n"); + printf("9) Display policycon\n"); + printf("0) Display initial SIDs\n"); + printf("\n"); + printf("a) Display avrule requirements\n"); + printf("b) Display avrule declarations\n"); + printf("c) Display policy capabilities\n"); + printf("l) Link in a module\n"); + printf("u) Display the unknown handling setting\n"); + printf("\n"); + printf("f) set output file\n"); + printf("m) display menu\n"); + printf("q) quit\n"); + return 0; +} + +int main(int argc, char **argv) +{ + FILE *out_fp = stdout; + char ans[81], OutfileName[121]; + + if (argc != 2) + usage(argv[0]); + + /* read the binary policy */ + fprintf(out_fp, "Reading policy...\n"); + policydb_init(&policydb); + if (read_policy(argv[1], &policydb)) { + fprintf(stderr, + "%s: error(s) encountered while loading policy\n", + argv[0]); + exit(1); + } + + if (policydb.policy_type != POLICY_BASE && + policydb.policy_type != POLICY_MOD) { + fprintf(stderr, + "This file is neither a base nor loadable policy module.\n"); + exit(1); + } + + if (policydb_index_classes(&policydb)) { + fprintf(stderr, "Error indexing classes\n"); + exit(1); + } + + if (policydb_index_others(NULL, &policydb, 1)) { + fprintf(stderr, "Error indexing others\n"); + exit(1); + } + + if (policydb.policy_type == POLICY_BASE) { + printf("Binary base policy file loaded.\n\n"); + } else { + printf("Binary policy module file loaded.\n"); + printf("Module name: %s\n", policydb.name); + printf("Module version: %s\n", policydb.version); + printf("\n"); + } + + menu(); + for (;;) { + printf("\nCommand (\'m\' for menu): "); + fgets(ans, sizeof(ans), stdin); + switch (ans[0]) { + + case '1':{ + fprintf(out_fp, "unconditional avtab:\n"); + display_avblock(1, RENDER_UNCONDITIONAL, + &policydb, out_fp); + break; + } + case '2': + fprintf(out_fp, "conditional avtab:\n"); + display_avblock(0, RENDER_UNCONDITIONAL, &policydb, + out_fp); + break; + case '3': + display_users(&policydb, out_fp); + break; + case '4': + display_bools(&policydb, out_fp); + break; + case '5': + if (hashtab_map + (policydb.p_roles.table, role_display_callback, + out_fp)) + exit(1); + break; + case '6': + if (display_types(&policydb, out_fp)) { + fprintf(stderr, "Error displaying types\n"); + exit(1); + } + break; + case '7': + fprintf(out_fp, "role transitions:\n"); + display_avblock(3, 0, &policydb, out_fp); + break; + case '8': + fprintf(out_fp, "role allows:\n"); + display_avblock(4, 0, &policydb, out_fp); + break; + case '9': + display_policycon(&policydb, out_fp); + break; + case '0': + display_initial_sids(&policydb, out_fp); + break; + case 'a': + fprintf(out_fp, "avrule block requirements:\n"); + display_avblock(5, 0, &policydb, out_fp); + break; + case 'b': + fprintf(out_fp, "avrule block declarations:\n"); + display_avblock(6, 0, &policydb, out_fp); + break; + case 'c': + display_policycaps(&policydb, out_fp); + break; + case 'u': + case 'U': + display_handle_unknown(&policydb, out_fp); + break; + case 'f': + printf + ("\nFilename for output (<CR> for screen output): "); + fgets(OutfileName, sizeof(OutfileName), stdin); + OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ + if (strlen(OutfileName) == 0) + out_fp = stdout; + else if ((out_fp = fopen(OutfileName, "w")) == NULL) { + fprintf(stderr, "Cannot open output file %s\n", + OutfileName); + out_fp = stdout; + } + if (out_fp != stdout) + printf("\nOutput to file: %s\n", OutfileName); + break; + case 'l': + link_module(&policydb, out_fp); + break; + case 'q': + policydb_destroy(&policydb); + exit(0); + break; + case 'm': + menu(); + break; + default: + printf("\nInvalid choice\n"); + menu(); + break; + + } + } + exit(EXIT_SUCCESS); +} diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c new file mode 100644 index 00000000..f8c05e67 --- /dev/null +++ b/checkpolicy/test/dispol.c @@ -0,0 +1,511 @@ + +/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> + * + * Copyright (C) 2003 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. + */ + +/* + * displaypol.c + * + * Test program to the contents of a binary policy in text + * form. This program currently only displays the + * avtab (including conditional avtab) rules. + * + * displaypol binary_pol_file + */ + +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/avtab.h> +#include <sepol/policydb/services.h> +#include <sepol/policydb/conditional.h> +#include <sepol/policydb/expand.h> +#include <sepol/policydb/util.h> +#include <sepol/policydb/polcaps.h> +#include <getopt.h> +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> + +static policydb_t policydb; + +void usage(char *progname) +{ + printf("usage: %s binary_pol_file\n\n", progname); + exit(1); +} + +int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, + FILE * fp) +{ + char *perm; + fprintf(fp, "{"); + perm = sepol_av_to_string(p, key->target_class, mask); + if (perm) + fprintf(fp, "%s ", perm); + fprintf(fp, "}"); + return 0; +} + +int render_type(uint32_t type, policydb_t * p, FILE * fp) +{ + fprintf(fp, "%s", p->p_type_val_to_name[type - 1]); + return 0; +} + +int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) +{ + char *stype, *ttype, *tclass; + stype = p->p_type_val_to_name[key->source_type - 1]; + ttype = p->p_type_val_to_name[key->target_type - 1]; + tclass = p->p_class_val_to_name[key->target_class - 1]; + if (stype && ttype) + fprintf(fp, "%s %s : %s ", stype, ttype, tclass); + else if (stype) + fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass); + else if (ttype) + fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass); + else + fprintf(fp, "%u %u : %s ", key->source_type, key->target_type, + tclass); + return 0; +} + +/* 'what' values for this function */ +#define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */ +#define RENDER_ENABLED 0x0002 +#define RENDER_DISABLED 0x0004 +#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED) + +int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, + policydb_t * p, FILE * fp) +{ + if (!(what & RENDER_UNCONDITIONAL)) { + if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED) + && !(key-> + specified & + AVTAB_ENABLED)) + || ((what & RENDER_DISABLED) + && (key-> + specified & + AVTAB_ENABLED)))) { + return 0; /* doesn't match selection criteria */ + } + } + + if (!(what & RENDER_UNCONDITIONAL)) { + if (key->specified & AVTAB_ENABLED) + fprintf(fp, "[enabled] "); + else if (!(key->specified & AVTAB_ENABLED)) + fprintf(fp, "[disabled] "); + } + + if (key->specified & AVTAB_AV) { + if (key->specified & AVTAB_ALLOWED) { + fprintf(fp, "allow "); + render_key(key, p, fp); + render_access_mask(datum->data, key, p, fp); + fprintf(fp, ";\n"); + } + if (key->specified & AVTAB_AUDITALLOW) { + fprintf(fp, "auditallow "); + render_key(key, p, fp); + render_access_mask(datum->data, key, p, fp); + fprintf(fp, ";\n"); + } + if (key->specified & AVTAB_AUDITDENY) { + fprintf(fp, "dontaudit "); + render_key(key, p, fp); + /* We inverse the mask for dontaudit since the mask is internally stored + * as a auditdeny mask */ + render_access_mask(~datum->data, key, p, fp); + fprintf(fp, ";\n"); + } + } else if (key->specified & AVTAB_TYPE) { + if (key->specified & AVTAB_TRANSITION) { + fprintf(fp, "type_transition "); + render_key(key, p, fp); + render_type(datum->data, p, fp); + fprintf(fp, ";\n"); + } + if (key->specified & AVTAB_MEMBER) { + fprintf(fp, "type_member "); + render_key(key, p, fp); + render_type(datum->data, p, fp); + fprintf(fp, ";\n"); + } + if (key->specified & AVTAB_CHANGE) { + fprintf(fp, "type_change "); + render_key(key, p, fp); + render_type(datum->data, p, fp); + fprintf(fp, ";\n"); + } + } else { + fprintf(fp, " ERROR: no valid rule type specified\n"); + return -1; + } + return 0; +} + +int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) +{ + int i; + avtab_ptr_t cur; + avtab_t expa; + + if (avtab_init(&expa)) + goto oom; + if (expand_avtab(p, a, &expa)) { + avtab_destroy(&expa); + goto oom; + } + + /* hmm...should have used avtab_map. */ + for (i = 0; i < expa.nslot; i++) { + for (cur = expa.htable[i]; cur; cur = cur->next) { + render_av_rule(&cur->key, &cur->datum, what, p, fp); + } + } + avtab_destroy(&expa); + fprintf(fp, "\n"); + return 0; + oom: + fprintf(stderr, "out of memory\n"); + return 1; +} + +int display_bools(policydb_t * p, FILE * fp) +{ + int i; + + for (i = 0; i < p->p_bools.nprim; i++) { + fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i], + p->bool_val_to_struct[i]->state); + } + return 0; +} + +void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) +{ + + cond_expr_t *cur; + for (cur = exp; cur != NULL; cur = cur->next) { + switch (cur->expr_type) { + case COND_BOOL: + fprintf(fp, "%s ", + p->p_bool_val_to_name[cur->bool - 1]); + break; + case COND_NOT: + fprintf(fp, "! "); + break; + case COND_OR: + fprintf(fp, "|| "); + break; + case COND_AND: + fprintf(fp, "&& "); + break; + case COND_XOR: + fprintf(fp, "^ "); + break; + case COND_EQ: + fprintf(fp, "== "); + break; + case COND_NEQ: + fprintf(fp, "!= "); + break; + default: + fprintf(fp, "error!"); + break; + } + } +} + +int display_cond_expressions(policydb_t * p, FILE * fp) +{ + cond_node_t *cur; + cond_av_list_t *av_cur, *expl = NULL; + avtab_t expa; + + for (cur = p->cond_list; cur != NULL; cur = cur->next) { + fprintf(fp, "expression: "); + display_expr(p, cur->expr, fp); + fprintf(fp, "current state: %d\n", cur->cur_state); + fprintf(fp, "True list:\n"); + if (avtab_init(&expa)) + goto oom; + if (expand_cond_av_list(p, cur->true_list, &expl, &expa)) { + avtab_destroy(&expa); + goto oom; + } + for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) { + fprintf(fp, "\t"); + render_av_rule(&av_cur->node->key, &av_cur->node->datum, + RENDER_CONDITIONAL, p, fp); + } + cond_av_list_destroy(expl); + avtab_destroy(&expa); + fprintf(fp, "False list:\n"); + if (avtab_init(&expa)) + goto oom; + if (expand_cond_av_list(p, cur->false_list, &expl, &expa)) { + avtab_destroy(&expa); + goto oom; + } + for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) { + fprintf(fp, "\t"); + render_av_rule(&av_cur->node->key, &av_cur->node->datum, + RENDER_CONDITIONAL, p, fp); + } + cond_av_list_destroy(expl); + avtab_destroy(&expa); + } + return 0; + + oom: + fprintf(stderr, "out of memory\n"); + return 1; +} + +int display_handle_unknown(policydb_t * p, FILE * out_fp) +{ + if (p->handle_unknown == ALLOW_UNKNOWN) + fprintf(out_fp, "Allow unknown classes and permisions\n"); + else if (p->handle_unknown == DENY_UNKNOWN) + fprintf(out_fp, "Deny unknown classes and permisions\n"); + else if (p->handle_unknown == REJECT_UNKNOWN) + fprintf(out_fp, "Reject unknown classes and permisions\n"); + return 0; +} + +int change_bool(char *name, int state, policydb_t * p, FILE * fp) +{ + cond_bool_datum_t *bool; + + bool = hashtab_search(p->p_bools.table, name); + if (bool == NULL) { + fprintf(fp, "Could not find bool %s\n", name); + return -1; + } + bool->state = state; + evaluate_conds(p); + return 0; +} + +static void display_policycaps(policydb_t * p, FILE * fp) +{ + ebitmap_node_t *node; + const char *capname; + char buf[64]; + int i; + + fprintf(fp, "policy capabilities:\n"); + ebitmap_for_each_bit(&p->policycaps, node, i) { + if (ebitmap_node_get_bit(node, i)) { + capname = sepol_polcap_getname(i); + if (capname == NULL) { + snprintf(buf, sizeof(buf), "unknown (%d)", i); + capname = buf; + } + fprintf(fp, "\t%s\n", capname); + } + } +} + +static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type, + uint32_t symbol_value, char *prefix) +{ + char *id = p->sym_val_to_name[symbol_type][symbol_value]; + fprintf(fp, " %s%s", prefix, id); +} + +static void display_permissive(policydb_t *p, FILE *fp) +{ + ebitmap_node_t *node; + int i; + + fprintf(fp, "permissive sids:\n"); + ebitmap_for_each_bit(&p->permissive_map, node, i) { + if (ebitmap_node_get_bit(node, i)) { + fprintf(fp, "\t"); + display_id(p, fp, SYM_TYPES, i - 1, ""); + fprintf(fp, "\n"); + } + } +} + +int menu() +{ + printf("\nSelect a command:\n"); + printf("1) display unconditional AVTAB\n"); + printf("2) display conditional AVTAB (entirely)\n"); + printf("3) display conditional AVTAG (only ENABLED rules)\n"); + printf("4) display conditional AVTAB (only DISABLED rules)\n"); + printf("5) display conditional bools\n"); + printf("6) display conditional expressions\n"); + printf("7) change a boolean value\n"); + printf("\n"); + printf("c) display policy capabilities\n"); + printf("p) display the list of permissive types\n"); + printf("u) display unknown handling setting\n"); + printf("f) set output file\n"); + printf("m) display menu\n"); + printf("q) quit\n"); + return 0; +} + +int main(int argc, char **argv) +{ + FILE *out_fp = stdout; + char ans[81], OutfileName[121]; + int fd, ret; + struct stat sb; + void *map; + char *name; + int state; + struct policy_file pf; + + if (argc != 2) + usage(argv[0]); + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open '%s': %s\n", + argv[1], strerror(errno)); + exit(1); + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", + argv[1], strerror(errno)); + exit(1); + } + map = + mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Can't map '%s': %s\n", + argv[1], strerror(errno)); + exit(1); + } + + /* read the binary policy */ + fprintf(out_fp, "Reading policy...\n"); + policy_file_init(&pf); + pf.type = PF_USE_MEMORY; + pf.data = map; + pf.len = sb.st_size; + if (policydb_init(&policydb)) { + fprintf(stderr, "%s: Out of memory!\n", argv[0]); + exit(1); + } + ret = policydb_read(&policydb, &pf, 1); + if (ret) { + fprintf(stderr, + "%s: error(s) encountered while parsing configuration\n", + argv[0]); + exit(1); + } + + fprintf(stdout, "binary policy file loaded\n\n"); + close(fd); + + menu(); + for (;;) { + printf("\nCommand (\'m\' for menu): "); + fgets(ans, sizeof(ans), stdin); + switch (ans[0]) { + + case '1': + display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL, + &policydb, out_fp); + break; + case '2': + display_avtab(&policydb.te_cond_avtab, + RENDER_CONDITIONAL, &policydb, out_fp); + break; + case '3': + display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED, + &policydb, out_fp); + break; + case '4': + display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED, + &policydb, out_fp); + break; + case '5': + display_bools(&policydb, out_fp); + break; + case '6': + display_cond_expressions(&policydb, out_fp); + break; + case '7': + printf("name? "); + fgets(ans, sizeof(ans), stdin); + ans[strlen(ans) - 1] = 0; + + name = malloc((strlen(ans) + 1) * sizeof(char)); + if (name == NULL) { + fprintf(stderr, "couldn't malloc string.\n"); + break; + } + strcpy(name, ans); + + printf("state? "); + fgets(ans, sizeof(ans), stdin); + ans[strlen(ans) - 1] = 0; + + if (atoi(ans)) + state = 1; + else + state = 0; + + change_bool(name, state, &policydb, out_fp); + free(name); + break; + case 'c': + display_policycaps(&policydb, out_fp); + break; + case 'p': + display_permissive(&policydb, out_fp); + break; + case 'u': + case 'U': + display_handle_unknown(&policydb, out_fp); + break; + case 'f': + printf + ("\nFilename for output (<CR> for screen output): "); + fgets(OutfileName, sizeof(OutfileName), stdin); + OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ + if (strlen(OutfileName) == 0) + out_fp = stdout; + else if ((out_fp = fopen(OutfileName, "w")) == NULL) { + fprintf(stderr, "Cannot open output file %s\n", + OutfileName); + out_fp = stdout; + } + if (out_fp != stdout) + printf("\nOutput to file: %s\n", OutfileName); + break; + case 'q': + policydb_destroy(&policydb); + exit(0); + break; + case 'm': + menu(); + break; + default: + printf("\nInvalid choice\n"); + menu(); + break; + + } + } +} + +/* FLASK */ |