platform_external_selinux/checkpolicy/test/dispol.c
Jeff Vander Stoep 915fa8f08f checkpolicy: switch operations to extended perms
The ioctl operations code is being renamed to the more generic
"extended permissions." This commit brings the policy compiler
up to date with the kernel patch.

Signed-off-by: Jeff Vander Stoep <jeffv@google.com>
2015-06-15 09:21:20 -04:00

599 lines
15 KiB
C

/* 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/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(const 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;
}
#define xperms_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
#define next_bit_in_range(i, p) \
((i + 1 < sizeof(p)*8) && xperms_test((i + 1), p))
int render_ioctl(avtab_extended_perms_t * xperms, FILE * fp)
{
uint16_t value;
uint16_t low_bit;
uint16_t low_value;
unsigned int bit;
unsigned int in_range = 0;
fprintf(fp, "{ ");
for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
if (!xperms_test(bit, xperms->perms))
continue;
if (in_range && next_bit_in_range(bit, xperms->perms)) {
/* continue until high value found */
continue;
} else if (next_bit_in_range(bit, xperms->perms)) {
/* low value */
low_bit = bit;
in_range = 1;
continue;
}
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
value = xperms->driver<<8 | bit;
low_value = xperms->driver<<8 | low_bit;
if (in_range)
fprintf(fp, "0x%hx-0x%hx ", low_value, value);
else
fprintf(fp, "0x%hx ", value);
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
low_value = low_bit << 8;
if (in_range)
fprintf(fp, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff));
else
fprintf(fp, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff));
}
if (in_range)
in_range = 0;
}
fprintf(fp, "}");
return 0;
}
int render_xperms(avtab_extended_perms_t * xperms, FILE * fp)
{
if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) ||
(xperms->specified == AVTAB_XPERMS_IOCTLDRIVER))
render_ioctl(xperms, 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 if (key->specified & AVTAB_XPERMS) {
if (key->specified & AVTAB_XPERMS_ALLOWED)
fprintf(fp, "allowxperm ");
else if (key->specified & AVTAB_XPERMS_AUDITALLOW)
fprintf(fp, "auditallowxperm ");
else if (key->specified & AVTAB_XPERMS_DONTAUDIT)
fprintf(fp, "dontauditxperm ");
render_key(key, p, fp);
render_xperms(datum->xperms, 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)
{
unsigned int i;
avtab_ptr_t cur;
/* hmm...should have used avtab_map. */
for (i = 0; i < a->nslot; i++) {
for (cur = a->htable[i]; cur; cur = cur->next) {
render_av_rule(&cur->key, &cur->datum, what, p, fp);
}
}
fprintf(fp, "\n");
return 0;
}
int display_bools(policydb_t * p, FILE * fp)
{
unsigned 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;
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 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];
unsigned 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, const char *prefix)
{
const 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;
unsigned 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");
}
}
}
static void display_role_trans(policydb_t *p, FILE *fp)
{
role_trans_t *rt;
fprintf(fp, "role_trans rules:\n");
for (rt = p->role_tr; rt; rt = rt->next) {
display_id(p, fp, SYM_ROLES, rt->role - 1, "");
display_id(p, fp, SYM_TYPES, rt->type - 1, "");
display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
fprintf(fp, "\n");
}
}
static void display_filename_trans(policydb_t *p, FILE *fp)
{
filename_trans_t *ft;
fprintf(fp, "filename_trans rules:\n");
for (ft = p->filename_trans; ft; ft = ft->next) {
display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
fprintf(fp, " %s\n", ft->name);
}
}
int menu(void)
{
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("8) display role transitions\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) display filename_trans rules\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];
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): ");
if (fgets(ans, sizeof(ans), stdin) == NULL) {
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
strerror(errno));
continue;
}
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? ");
if (fgets(ans, sizeof(ans), stdin) == NULL) {
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
strerror(errno));
break;
}
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? ");
if (fgets(ans, sizeof(ans), stdin) == NULL) {
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
strerror(errno));
break;
}
ans[strlen(ans) - 1] = 0;
if (atoi(ans))
state = 1;
else
state = 0;
change_bool(name, state, &policydb, out_fp);
free(name);
break;
case '8':
display_role_trans(&policydb, out_fp);
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): ");
if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
strerror(errno));
break;
}
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 'F':
display_filename_trans(&policydb, out_fp);
break;
case 'q':
policydb_destroy(&policydb);
exit(0);
break;
case 'm':
menu();
break;
default:
printf("\nInvalid choice\n");
menu();
break;
}
}
}
/* FLASK */