Home | History | Annotate | Download | only in test
      1 
      2 /* Authors: Frank Mayer <mayerf (at) tresys.com> and Karl MacMillan <kmacmillan (at) tresys.com>
      3  *
      4  * Copyright (C) 2003,2004,2005 Tresys Technology, LLC
      5  *	This program is free software; you can redistribute it and/or modify
      6  *  	it under the terms of the GNU General Public License as published by
      7  *	the Free Software Foundation, version 2.
      8  */
      9 
     10 /*
     11  * dismod.c
     12  *
     13  * Test program to the contents of a binary policy in text
     14  * form.
     15  *
     16  * 	dismod binary_mod_file
     17  */
     18 
     19 #include <getopt.h>
     20 #include <assert.h>
     21 #include <sys/stat.h>
     22 #include <sys/types.h>
     23 #include <sys/mman.h>
     24 #include <errno.h>
     25 #include <stdio.h>
     26 #include <fcntl.h>
     27 #include <stdlib.h>
     28 #include <unistd.h>
     29 
     30 #include <sepol/policydb/policydb.h>
     31 #include <sepol/policydb/services.h>
     32 #include <sepol/policydb/conditional.h>
     33 #include <sepol/policydb/flask.h>
     34 #include <sepol/policydb/link.h>
     35 #include <sepol/policydb/module.h>
     36 #include <sepol/policydb/util.h>
     37 #include <sepol/policydb/polcaps.h>
     38 
     39 #include <byteswap.h>
     40 #include <endian.h>
     41 
     42 #if __BYTE_ORDER == __LITTLE_ENDIAN
     43 #define le32_to_cpu(x) (x)
     44 #else
     45 #define le32_to_cpu(x) bswap_32(x)
     46 #endif
     47 
     48 #define DISPLAY_AVBLOCK_COND_AVTAB	0
     49 #define DISPLAY_AVBLOCK_UNCOND_AVTAB	1
     50 #define DISPLAY_AVBLOCK_ROLE_TYPE_NODE	2 /* unused? */
     51 #define DISPLAY_AVBLOCK_ROLE_TRANS	3
     52 #define DISPLAY_AVBLOCK_ROLE_ALLOW	4
     53 #define DISPLAY_AVBLOCK_REQUIRES	5
     54 #define DISPLAY_AVBLOCK_DECLARES	6
     55 #define DISPLAY_AVBLOCK_FILENAME_TRANS	7
     56 
     57 static policydb_t policydb;
     58 extern unsigned int ss_initialized;
     59 
     60 int policyvers = MOD_POLICYDB_VERSION_BASE;
     61 
     62 static const char *symbol_labels[9] = {
     63 	"commons",
     64 	"classes", "roles  ", "types  ", "users  ", "bools  ",
     65 	"levels ", "cats   ", "attribs"
     66 };
     67 
     68 void usage(const char *progname)
     69 {
     70 	printf("usage:  %s binary_pol_file\n\n", progname);
     71 	exit(1);
     72 }
     73 
     74 static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p,
     75 			       FILE * fp)
     76 {
     77 	char *perm;
     78 	fprintf(fp, "{");
     79 	perm = sepol_av_to_string(p, class, mask);
     80 	if (perm)
     81 		fprintf(fp, "%s ", perm);
     82 	fprintf(fp, "}");
     83 }
     84 
     85 static void render_access_bitmap(ebitmap_t * map, uint32_t class,
     86 				 policydb_t * p, FILE * fp)
     87 {
     88 	unsigned int i;
     89 	char *perm;
     90 	fprintf(fp, "{");
     91 	for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
     92 		if (ebitmap_get_bit(map, i)) {
     93 			perm = sepol_av_to_string(p, class, 1 << i);
     94 			if (perm)
     95 				fprintf(fp, " %s", perm);
     96 		}
     97 	}
     98 	fprintf(fp, " }");
     99 }
    100 
    101 static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
    102 		       uint32_t symbol_value, const char *prefix)
    103 {
    104 	char *id = p->sym_val_to_name[symbol_type][symbol_value];
    105 	scope_datum_t *scope =
    106 	    (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
    107 	assert(scope != NULL);
    108 	if (scope->scope == SCOPE_REQ) {
    109 		fprintf(fp, " [%s%s]", prefix, id);
    110 	} else {
    111 		fprintf(fp, " %s%s", prefix, id);
    112 	}
    113 }
    114 
    115 int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
    116 		     FILE * fp)
    117 {
    118 	unsigned int i, num_types;
    119 
    120 	if (set->flags & TYPE_STAR) {
    121 		fprintf(fp, " * ");
    122 		return 0;
    123 	} else if (set->flags & TYPE_COMP) {
    124 		fprintf(fp, " ~");
    125 	}
    126 
    127 	num_types = 0;
    128 	if (flags & RULE_SELF) {
    129 		num_types++;
    130 	}
    131 
    132 	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
    133 	     i++) {
    134 		if (!ebitmap_get_bit(&set->types, i))
    135 			continue;
    136 		num_types++;
    137 		if (num_types > 1)
    138 			break;
    139 	}
    140 
    141 	if (num_types <= 1) {
    142 		for (i = ebitmap_startbit(&set->negset);
    143 		     i < ebitmap_length(&set->negset); i++) {
    144 			if (!ebitmap_get_bit(&set->negset, i))
    145 				continue;
    146 			num_types++;
    147 			if (num_types > 1)
    148 				break;
    149 		}
    150 	}
    151 
    152 	if (num_types > 1)
    153 		fprintf(fp, "{");
    154 
    155 	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
    156 	     i++) {
    157 		if (!ebitmap_get_bit(&set->types, i))
    158 			continue;
    159 		display_id(policy, fp, SYM_TYPES, i, "");
    160 	}
    161 
    162 	for (i = ebitmap_startbit(&set->negset);
    163 	     i < ebitmap_length(&set->negset); i++) {
    164 		if (!ebitmap_get_bit(&set->negset, i))
    165 			continue;
    166 		display_id(policy, fp, SYM_TYPES, i, "-");
    167 	}
    168 
    169 	if (flags & RULE_SELF) {
    170 		fprintf(fp, " self");
    171 	}
    172 
    173 	if (num_types > 1)
    174 		fprintf(fp, " }");
    175 
    176 	return 0;
    177 }
    178 
    179 int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
    180 {
    181 	unsigned int i, num = 0;
    182 
    183 	if (roles->flags & ROLE_STAR) {
    184 		fprintf(fp, " * ");
    185 		return 0;
    186 	} else if (roles->flags & ROLE_COMP) {
    187 		fprintf(fp, " ~");
    188 	}
    189 
    190 	for (i = ebitmap_startbit(&roles->roles);
    191 	     i < ebitmap_length(&roles->roles); i++) {
    192 		if (!ebitmap_get_bit(&roles->roles, i))
    193 			continue;
    194 		num++;
    195 		if (num > 1) {
    196 			fprintf(fp, "{");
    197 			break;
    198 		}
    199 	}
    200 
    201 	for (i = ebitmap_startbit(&roles->roles);
    202 	     i < ebitmap_length(&roles->roles); i++) {
    203 		if (ebitmap_get_bit(&roles->roles, i))
    204 			display_id(p, fp, SYM_ROLES, i, "");
    205 	}
    206 
    207 	if (num > 1)
    208 		fprintf(fp, " }");
    209 
    210 	return 0;
    211 
    212 }
    213 
    214 int display_avrule(avrule_t * avrule, policydb_t * policy,
    215 		   FILE * fp)
    216 {
    217 	class_perm_node_t *cur;
    218 	int num_classes;
    219 
    220 	if (avrule == NULL) {
    221 		fprintf(fp, "  <empty>\n");
    222 		return 0;
    223 	}
    224 	if (avrule->specified & AVRULE_AV) {
    225 		if (avrule->specified & AVRULE_ALLOWED) {
    226 			fprintf(fp, "  allow");
    227 		}
    228 		if (avrule->specified & AVRULE_AUDITALLOW) {
    229 			fprintf(fp, "  auditallow ");
    230 		}
    231 		if (avrule->specified & AVRULE_DONTAUDIT) {
    232 			fprintf(fp, "  dontaudit");
    233 		}
    234 	} else if (avrule->specified & AVRULE_TYPE) {
    235 		if (avrule->specified & AVRULE_TRANSITION) {
    236 			fprintf(fp, "  type_transition");
    237 		}
    238 		if (avrule->specified & AVRULE_MEMBER) {
    239 			fprintf(fp, "  type_member");
    240 		}
    241 		if (avrule->specified & AVRULE_CHANGE) {
    242 			fprintf(fp, "  type_change");
    243 		}
    244 	} else if (avrule->specified & AVRULE_NEVERALLOW) {
    245 		fprintf(fp, "  neverallow");
    246 	} else {
    247 		fprintf(fp, "     ERROR: no valid rule type specified\n");
    248 		return -1;
    249 	}
    250 
    251 	if (display_type_set(&avrule->stypes, 0, policy, fp))
    252 		return -1;
    253 
    254 	if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
    255 		return -1;
    256 
    257 	fprintf(fp, " :");
    258 	cur = avrule->perms;
    259 	num_classes = 0;
    260 	while (cur) {
    261 		num_classes++;
    262 		if (num_classes > 1)
    263 			break;
    264 		cur = cur->next;
    265 	}
    266 
    267 	if (num_classes > 1)
    268 		fprintf(fp, " {");
    269 
    270 	cur = avrule->perms;
    271 	while (cur) {
    272 		display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
    273 		cur = cur->next;
    274 	}
    275 
    276 	if (num_classes > 1)
    277 		fprintf(fp, " }");
    278 	fprintf(fp, " ");
    279 
    280 	if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
    281 		render_access_mask(avrule->perms->data, avrule->perms->tclass,
    282 				   policy, fp);
    283 	} else if (avrule->specified & AVRULE_TYPE) {
    284 		display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
    285 	}
    286 
    287 	fprintf(fp, ";\n");
    288 
    289 	return 0;
    290 }
    291 
    292 int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
    293 {
    294 	type_datum_t *type;
    295 	FILE *fp;
    296 	unsigned int i, first_attrib = 1;
    297 
    298 	type = (type_datum_t *) datum;
    299 	fp = (FILE *) data;
    300 
    301 	if (type->primary) {
    302 		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
    303 		fprintf(fp, " [%d]: ", type->s.value);
    304 	} else {
    305 		/* as that aliases have no value of their own and that
    306 		 * they can never be required by a module, use this
    307 		 * alternative way of displaying a name */
    308 		fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
    309 	}
    310 	if (type->flavor == TYPE_ATTRIB) {
    311 		fprintf(fp, "attribute for types");
    312 		for (i = ebitmap_startbit(&type->types);
    313 		     i < ebitmap_length(&type->types); i++) {
    314 			if (!ebitmap_get_bit(&type->types, i))
    315 				continue;
    316 			if (first_attrib) {
    317 				first_attrib = 0;
    318 			} else {
    319 				fprintf(fp, ",");
    320 			}
    321 			display_id(&policydb, fp, SYM_TYPES, i, "");
    322 		}
    323 	} else if (type->primary) {
    324 		fprintf(fp, "type");
    325 	} else {
    326 		fprintf(fp, "alias for type");
    327 		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
    328 	}
    329 	fprintf(fp, " flags:%x\n", type->flags);
    330 
    331 	return 0;
    332 }
    333 
    334 int display_types(policydb_t * p, FILE * fp)
    335 {
    336 	if (hashtab_map(p->p_types.table, display_type_callback, fp))
    337 		return -1;
    338 	return 0;
    339 }
    340 
    341 int display_users(policydb_t * p, FILE * fp)
    342 {
    343 	unsigned int i, j;
    344 	ebitmap_t *bitmap;
    345 	for (i = 0; i < p->p_users.nprim; i++) {
    346 		display_id(p, fp, SYM_USERS, i, "");
    347 		fprintf(fp, ":");
    348 		bitmap = &(p->user_val_to_struct[i]->roles.roles);
    349 		for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
    350 		     j++) {
    351 			if (ebitmap_get_bit(bitmap, j)) {
    352 				display_id(p, fp, SYM_ROLES, j, "");
    353 			}
    354 		}
    355 		fprintf(fp, "\n");
    356 	}
    357 	return 0;
    358 }
    359 
    360 int display_bools(policydb_t * p, FILE * fp)
    361 {
    362 	unsigned int i;
    363 
    364 	for (i = 0; i < p->p_bools.nprim; i++) {
    365 		display_id(p, fp, SYM_BOOLS, i, "");
    366 		fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
    367 	}
    368 	return 0;
    369 }
    370 
    371 void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
    372 {
    373 
    374 	cond_expr_t *cur;
    375 	for (cur = exp; cur != NULL; cur = cur->next) {
    376 		switch (cur->expr_type) {
    377 		case COND_BOOL:
    378 			fprintf(fp, "%s ",
    379 				p->p_bool_val_to_name[cur->bool - 1]);
    380 			break;
    381 		case COND_NOT:
    382 			fprintf(fp, "! ");
    383 			break;
    384 		case COND_OR:
    385 			fprintf(fp, "|| ");
    386 			break;
    387 		case COND_AND:
    388 			fprintf(fp, "&& ");
    389 			break;
    390 		case COND_XOR:
    391 			fprintf(fp, "^ ");
    392 			break;
    393 		case COND_EQ:
    394 			fprintf(fp, "== ");
    395 			break;
    396 		case COND_NEQ:
    397 			fprintf(fp, "!= ");
    398 			break;
    399 		default:
    400 			fprintf(fp, "error!");
    401 			break;
    402 		}
    403 	}
    404 }
    405 
    406 void display_policycon(FILE * fp)
    407 {
    408 	/* There was an attempt to implement this at one time.  Look through
    409 	 * git history to find it. */
    410 	fprintf(fp, "Sorry, not implemented\n");
    411 }
    412 
    413 void display_initial_sids(policydb_t * p, FILE * fp)
    414 {
    415 	ocontext_t *cur;
    416 	char *user, *role, *type;
    417 
    418 	fprintf(fp, "Initial SIDs:\n");
    419 	for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
    420 		user = p->p_user_val_to_name[cur->context[0].user - 1];
    421 		role = p->p_role_val_to_name[cur->context[0].role - 1];
    422 		type = p->p_type_val_to_name[cur->context[0].type - 1];
    423 		fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
    424 			cur->u.name, cur->sid[0], user, role, type);
    425 	}
    426 #if 0
    427 	fprintf(fp, "Policy Initial SIDs:\n");
    428 	for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
    429 		user = p->p_user_val_to_name[cur->context[0].user - 1];
    430 		role = p->p_role_val_to_name[cur->context[0].role - 1];
    431 		type = p->p_type_val_to_name[cur->context[0].type - 1];
    432 		fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
    433 			cur->u.name, cur->sid[0], user, role, type);
    434 	}
    435 #endif
    436 }
    437 
    438 void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
    439 {
    440 	unsigned int i, num = 0;
    441 
    442 	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
    443 		if (!ebitmap_get_bit(classes, i))
    444 			continue;
    445 		num++;
    446 		if (num > 1) {
    447 			fprintf(fp, "{");
    448 			break;
    449 		}
    450 	}
    451 
    452 	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
    453 		if (ebitmap_get_bit(classes, i))
    454 			display_id(p, fp, SYM_CLASSES, i, "");
    455 	}
    456 
    457 	if (num > 1)
    458 		fprintf(fp, " }");
    459 }
    460 
    461 void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
    462 {
    463 	for (; tr; tr = tr->next) {
    464 		fprintf(fp, "role transition ");
    465 		display_mod_role_set(&tr->roles, p, fp);
    466 		display_type_set(&tr->types, 0, p, fp);
    467 		fprintf(fp, " :");
    468 		display_class_set(&tr->classes, p, fp);
    469 		display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
    470 		fprintf(fp, "\n");
    471 	}
    472 }
    473 
    474 void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
    475 {
    476 	for (; ra; ra = ra->next) {
    477 		fprintf(fp, "role allow ");
    478 		display_mod_role_set(&ra->roles, p, fp);
    479 		display_mod_role_set(&ra->new_roles, p, fp);
    480 		fprintf(fp, "\n");
    481 	}
    482 }
    483 
    484 static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
    485 {
    486 	fprintf(fp, "filename transition");
    487 	for (; tr; tr = tr->next) {
    488 		display_type_set(&tr->stypes, 0, p, fp);
    489 		display_type_set(&tr->ttypes, 0, p, fp);
    490 		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
    491 		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
    492 		fprintf(fp, " %s\n", tr->name);
    493 	}
    494 }
    495 
    496 int role_display_callback(hashtab_key_t key __attribute__((unused)),
    497 			  hashtab_datum_t datum, void *data)
    498 {
    499 	role_datum_t *role;
    500 	FILE *fp;
    501 
    502 	role = (role_datum_t *) datum;
    503 	fp = (FILE *) data;
    504 
    505 	fprintf(fp, "role:");
    506 	display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
    507 	fprintf(fp, " types: ");
    508 	display_type_set(&role->types, 0, &policydb, fp);
    509 	fprintf(fp, "\n");
    510 
    511 	return 0;
    512 }
    513 
    514 static int display_scope_index(scope_index_t * indices, policydb_t * p,
    515 			       FILE * out_fp)
    516 {
    517 	unsigned int i;
    518 	for (i = 0; i < SYM_NUM; i++) {
    519 		unsigned int any_found = 0, j;
    520 		fprintf(out_fp, "%s:", symbol_labels[i]);
    521 		for (j = ebitmap_startbit(&indices->scope[i]);
    522 		     j < ebitmap_length(&indices->scope[i]); j++) {
    523 			if (ebitmap_get_bit(&indices->scope[i], j)) {
    524 				any_found = 1;
    525 				fprintf(out_fp, " %s",
    526 					p->sym_val_to_name[i][j]);
    527 				if (i == SYM_CLASSES) {
    528 					if (j < indices->class_perms_len) {
    529 						render_access_bitmap(indices->
    530 								     class_perms_map
    531 								     + j, j + 1,
    532 								     p, out_fp);
    533 					} else {
    534 						fprintf(out_fp,
    535 							"<no perms known>");
    536 					}
    537 				}
    538 			}
    539 		}
    540 		if (!any_found) {
    541 			fprintf(out_fp, " <empty>");
    542 		}
    543 		fprintf(out_fp, "\n");
    544 	}
    545 	return 0;
    546 }
    547 
    548 #if 0
    549 int display_cond_expressions(policydb_t * p, FILE * fp)
    550 {
    551 	cond_node_t *cur;
    552 	cond_av_list_t *av_cur;
    553 	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
    554 		fprintf(fp, "expression: ");
    555 		display_expr(p, cur->expr, fp);
    556 		fprintf(fp, "current state: %d\n", cur->cur_state);
    557 		fprintf(fp, "True list:\n");
    558 		for (av_cur = cur->true_list; av_cur != NULL;
    559 		     av_cur = av_cur->next) {
    560 			fprintf(fp, "\t");
    561 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
    562 				       RENDER_CONDITIONAL, p, fp);
    563 		}
    564 		fprintf(fp, "False list:\n");
    565 		for (av_cur = cur->false_list; av_cur != NULL;
    566 		     av_cur = av_cur->next) {
    567 			fprintf(fp, "\t");
    568 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
    569 				       RENDER_CONDITIONAL, p, fp);
    570 		}
    571 	}
    572 	return 0;
    573 }
    574 
    575 int change_bool(char *name, int state, policydb_t * p, FILE * fp)
    576 {
    577 	cond_bool_datum_t *bool;
    578 
    579 	bool = hashtab_search(p->p_bools.table, name);
    580 	if (bool == NULL) {
    581 		fprintf(fp, "Could not find bool %s\n", name);
    582 		return -1;
    583 	}
    584 	bool->state = state;
    585 	evaluate_conds(p);
    586 	return 0;
    587 }
    588 #endif
    589 
    590 int display_avdecl(avrule_decl_t * decl, int field,
    591 		   policydb_t * policy, FILE * out_fp)
    592 {
    593 	fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
    594 		(decl->enabled ? " [enabled]" : ""));
    595 	switch (field) {
    596 	case DISPLAY_AVBLOCK_COND_AVTAB:{
    597 			cond_list_t *cond = decl->cond_list;
    598 			avrule_t *avrule;
    599 			while (cond) {
    600 				fprintf(out_fp, "expression: ");
    601 				display_expr(&policydb, cond->expr, out_fp);
    602 				fprintf(out_fp, "current state: %d\n",
    603 					cond->cur_state);
    604 				fprintf(out_fp, "True list:\n");
    605 				avrule = cond->avtrue_list;
    606 				while (avrule) {
    607 					display_avrule(avrule,
    608 						       &policydb, out_fp);
    609 					avrule = avrule->next;
    610 				}
    611 				fprintf(out_fp, "False list:\n");
    612 				avrule = cond->avfalse_list;
    613 				while (avrule) {
    614 					display_avrule(avrule,
    615 						       &policydb, out_fp);
    616 					avrule = avrule->next;
    617 				}
    618 				cond = cond->next;
    619 			}
    620 			break;
    621 		}
    622 	case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
    623 			avrule_t *avrule = decl->avrules;
    624 			if (avrule == NULL) {
    625 				fprintf(out_fp, "  <empty>\n");
    626 			}
    627 			while (avrule != NULL) {
    628 				if (display_avrule(avrule, policy, out_fp))
    629 					return -1;
    630 				avrule = avrule->next;
    631 			}
    632 			break;
    633 		}
    634 	case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{	/* role_type_node */
    635 			break;
    636 		}
    637 	case DISPLAY_AVBLOCK_ROLE_TRANS:{
    638 			display_role_trans(decl->role_tr_rules, policy, out_fp);
    639 			break;
    640 		}
    641 	case DISPLAY_AVBLOCK_ROLE_ALLOW:{
    642 			display_role_allow(decl->role_allow_rules, policy,
    643 					   out_fp);
    644 			break;
    645 		}
    646 	case DISPLAY_AVBLOCK_REQUIRES:{
    647 			if (display_scope_index
    648 			    (&decl->required, policy, out_fp)) {
    649 				return -1;
    650 			}
    651 			break;
    652 		}
    653 	case DISPLAY_AVBLOCK_DECLARES:{
    654 			if (display_scope_index
    655 			    (&decl->declared, policy, out_fp)) {
    656 				return -1;
    657 			}
    658 			break;
    659 		}
    660 	case DISPLAY_AVBLOCK_FILENAME_TRANS:
    661 		display_filename_trans(decl->filename_trans_rules, policy,
    662 				       out_fp);
    663 		break;
    664 	default:{
    665 			assert(0);
    666 		}
    667 	}
    668 	return 0;		/* should never get here */
    669 }
    670 
    671 int display_avblock(int field, policydb_t * policy,
    672 		    FILE * out_fp)
    673 {
    674 	avrule_block_t *block = policydb.global;
    675 	while (block != NULL) {
    676 		fprintf(out_fp, "--- begin avrule block ---\n");
    677 		avrule_decl_t *decl = block->branch_list;
    678 		while (decl != NULL) {
    679 			if (display_avdecl(decl, field, policy, out_fp)) {
    680 				return -1;
    681 			}
    682 			decl = decl->next;
    683 		}
    684 		block = block->next;
    685 	}
    686 	return 0;
    687 }
    688 
    689 int display_handle_unknown(policydb_t * p, FILE * out_fp)
    690 {
    691 	if (p->handle_unknown == ALLOW_UNKNOWN)
    692 		fprintf(out_fp, "Allow unknown classes and perms\n");
    693 	else if (p->handle_unknown == DENY_UNKNOWN)
    694 		fprintf(out_fp, "Deny unknown classes and perms\n");
    695 	else if (p->handle_unknown == REJECT_UNKNOWN)
    696 		fprintf(out_fp, "Reject unknown classes and perms\n");
    697 	return 0;
    698 }
    699 
    700 static int read_policy(char *filename, policydb_t * policy)
    701 {
    702 	FILE *in_fp;
    703 	struct policy_file f;
    704 	int retval;
    705 	uint32_t buf[1];
    706 
    707 	if ((in_fp = fopen(filename, "rb")) == NULL) {
    708 		fprintf(stderr, "Can't open '%s':  %s\n",
    709 			filename, strerror(errno));
    710 		exit(1);
    711 	}
    712 	policy_file_init(&f);
    713 	f.type = PF_USE_STDIO;
    714 	f.fp = in_fp;
    715 
    716 	/* peek at the first byte.  if they are indicative of a
    717 	   package use the package reader, otherwise use the normal
    718 	   policy reader */
    719 	if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
    720 		fprintf(stderr, "Could not read from policy.\n");
    721 		exit(1);
    722 	}
    723 	rewind(in_fp);
    724 	if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
    725 		sepol_module_package_t *package;
    726 		if (sepol_module_package_create(&package)) {
    727 			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
    728 			exit(1);
    729 		}
    730 		package->policy = (sepol_policydb_t *) policy;
    731 		package->file_contexts = NULL;
    732 		retval =
    733 		    sepol_module_package_read(package,
    734 					      (sepol_policy_file_t *) & f, 1);
    735 		free(package->file_contexts);
    736 	} else {
    737 		if (policydb_init(policy)) {
    738 			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
    739 			exit(1);
    740 		}
    741 		retval = policydb_read(policy, &f, 1);
    742 	}
    743 	fclose(in_fp);
    744 	return retval;
    745 }
    746 
    747 static void link_module(policydb_t * base, FILE * out_fp)
    748 {
    749 	char module_name[80] = { 0 };
    750 	int ret;
    751 	policydb_t module, *mods = &module;
    752 
    753 	if (base->policy_type != POLICY_BASE) {
    754 		printf("Can only link if initial file was a base policy.\n");
    755 		return;
    756 	}
    757 	printf("\nModule filename: ");
    758 	if (fgets(module_name, sizeof(module_name), stdin) == NULL) {
    759 		fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
    760 				strerror(errno));
    761 		exit(1);
    762 	}
    763 
    764 	module_name[strlen(module_name) - 1] = '\0';	/* remove LF */
    765 	if (module_name[0] == '\0') {
    766 		return;
    767 	}
    768 
    769 	/* read the binary policy */
    770 	fprintf(out_fp, "Reading module...\n");
    771 	if (read_policy(module_name, mods)) {
    772 		fprintf(stderr,
    773 			"%s:  error(s) encountered while loading policy\n",
    774 			module_name);
    775 		exit(1);
    776 	}
    777 	if (module.policy_type != POLICY_MOD) {
    778 		fprintf(stderr, "This file is not a loadable policy module.\n");
    779 		exit(1);
    780 	}
    781 	if (policydb_index_classes(&module) ||
    782 	    policydb_index_others(NULL, &module, 0)) {
    783 		fprintf(stderr, "Could not index module.\n");
    784 		exit(1);
    785 	}
    786 	ret = link_modules(NULL, base, &mods, 1, 0);
    787 	if (ret != 0) {
    788 		printf("Link failed (error %d)\n", ret);
    789 		printf("(You will probably need to restart dismod.)\n");
    790 	}
    791 	policydb_destroy(&module);
    792 	return;
    793 }
    794 
    795 static void display_policycaps(policydb_t * p, FILE * fp)
    796 {
    797 	ebitmap_node_t *node;
    798 	const char *capname;
    799 	char buf[64];
    800 	unsigned int i;
    801 
    802 	fprintf(fp, "policy capabilities:\n");
    803 	ebitmap_for_each_bit(&p->policycaps, node, i) {
    804 		if (ebitmap_node_get_bit(node, i)) {
    805 			capname = sepol_polcap_getname(i);
    806 			if (capname == NULL) {
    807 				snprintf(buf, sizeof(buf), "unknown (%d)", i);
    808 				capname = buf;
    809 			}
    810 			fprintf(fp, "\t%s\n", capname);
    811 		}
    812 	}
    813 }
    814 
    815 int menu(void)
    816 {
    817 	printf("\nSelect a command:\n");
    818 	printf("1)  display unconditional AVTAB\n");
    819 	printf("2)  display conditional AVTAB\n");
    820 	printf("3)  display users\n");
    821 	printf("4)  display bools\n");
    822 	printf("5)  display roles\n");
    823 	printf("6)  display types, attributes, and aliases\n");
    824 	printf("7)  display role transitions\n");
    825 	printf("8)  display role allows\n");
    826 	printf("9)  Display policycon\n");
    827 	printf("0)  Display initial SIDs\n");
    828 	printf("\n");
    829 	printf("a)  Display avrule requirements\n");
    830 	printf("b)  Display avrule declarations\n");
    831 	printf("c)  Display policy capabilities\n");
    832 	printf("l)  Link in a module\n");
    833 	printf("u)  Display the unknown handling setting\n");
    834 	printf("F)  Display filename_trans rules\n");
    835 	printf("\n");
    836 	printf("f)  set output file\n");
    837 	printf("m)  display menu\n");
    838 	printf("q)  quit\n");
    839 	return 0;
    840 }
    841 
    842 int main(int argc, char **argv)
    843 {
    844 	FILE *out_fp = stdout;
    845 	char ans[81], OutfileName[121];
    846 
    847 	if (argc != 2)
    848 		usage(argv[0]);
    849 
    850 	/* read the binary policy */
    851 	fprintf(out_fp, "Reading policy...\n");
    852 	if (policydb_init(&policydb)) {
    853 		fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
    854 		exit(1);
    855 	}
    856 	if (read_policy(argv[1], &policydb)) {
    857 		fprintf(stderr,
    858 			"%s:  error(s) encountered while loading policy\n",
    859 			argv[0]);
    860 		exit(1);
    861 	}
    862 
    863 	if (policydb.policy_type != POLICY_BASE &&
    864 	    policydb.policy_type != POLICY_MOD) {
    865 		fprintf(stderr,
    866 			"This file is neither a base nor loadable policy module.\n");
    867 		exit(1);
    868 	}
    869 
    870 	if (policydb_index_classes(&policydb)) {
    871 		fprintf(stderr, "Error indexing classes\n");
    872 		exit(1);
    873 	}
    874 
    875 	if (policydb_index_others(NULL, &policydb, 1)) {
    876 		fprintf(stderr, "Error indexing others\n");
    877 		exit(1);
    878 	}
    879 
    880 	if (policydb.policy_type == POLICY_BASE) {
    881 		printf("Binary base policy file loaded.\n\n");
    882 	} else {
    883 		printf("Binary policy module file loaded.\n");
    884 		printf("Module name: %s\n", policydb.name);
    885 		printf("Module version: %s\n", policydb.version);
    886 		printf("\n");
    887 	}
    888 
    889 	menu();
    890 	for (;;) {
    891 		printf("\nCommand (\'m\' for menu):  ");
    892 		if (fgets(ans, sizeof(ans), stdin) == NULL) {
    893 			fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
    894 					strerror(errno));
    895 			continue;
    896 		}
    897 
    898 		switch (ans[0]) {
    899 
    900 		case '1':
    901 			fprintf(out_fp, "unconditional avtab:\n");
    902 			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
    903 					&policydb, out_fp);
    904 			break;
    905 		case '2':
    906 			fprintf(out_fp, "conditional avtab:\n");
    907 			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
    908 					&policydb, out_fp);
    909 			break;
    910 		case '3':
    911 			display_users(&policydb, out_fp);
    912 			break;
    913 		case '4':
    914 			display_bools(&policydb, out_fp);
    915 			break;
    916 		case '5':
    917 			if (hashtab_map
    918 			    (policydb.p_roles.table, role_display_callback,
    919 			     out_fp))
    920 				exit(1);
    921 			break;
    922 		case '6':
    923 			if (display_types(&policydb, out_fp)) {
    924 				fprintf(stderr, "Error displaying types\n");
    925 				exit(1);
    926 			}
    927 			break;
    928 		case '7':
    929 			fprintf(out_fp, "role transitions:\n");
    930 			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
    931 					&policydb, out_fp);
    932 			break;
    933 		case '8':
    934 			fprintf(out_fp, "role allows:\n");
    935 			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
    936 					&policydb, out_fp);
    937 			break;
    938 		case '9':
    939 			display_policycon(out_fp);
    940 			break;
    941 		case '0':
    942 			display_initial_sids(&policydb, out_fp);
    943 			break;
    944 		case 'a':
    945 			fprintf(out_fp, "avrule block requirements:\n");
    946 			display_avblock(DISPLAY_AVBLOCK_REQUIRES,
    947 					&policydb, out_fp);
    948 			break;
    949 		case 'b':
    950 			fprintf(out_fp, "avrule block declarations:\n");
    951 			display_avblock(DISPLAY_AVBLOCK_DECLARES,
    952 					&policydb, out_fp);
    953 			break;
    954 		case 'c':
    955 			display_policycaps(&policydb, out_fp);
    956 			break;
    957 		case 'u':
    958 		case 'U':
    959 			display_handle_unknown(&policydb, out_fp);
    960 			break;
    961 		case 'f':
    962 			printf
    963 			    ("\nFilename for output (<CR> for screen output): ");
    964 			if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
    965 				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
    966 						strerror(errno));
    967 				break;
    968 			}
    969 			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
    970 			if (strlen(OutfileName) == 0)
    971 				out_fp = stdout;
    972 			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
    973 				fprintf(stderr, "Cannot open output file %s\n",
    974 					OutfileName);
    975 				out_fp = stdout;
    976 			}
    977 			if (out_fp != stdout)
    978 				printf("\nOutput to file: %s\n", OutfileName);
    979 			break;
    980 		case 'F':
    981 			fprintf(out_fp, "filename_trans rules:\n");
    982 			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
    983 					&policydb, out_fp);
    984 			break;
    985 		case 'l':
    986 			link_module(&policydb, out_fp);
    987 			break;
    988 		case 'q':
    989 			policydb_destroy(&policydb);
    990 			exit(0);
    991 			break;
    992 		case 'm':
    993 			menu();
    994 			break;
    995 		default:
    996 			printf("\nInvalid choice\n");
    997 			menu();
    998 			break;
    999 
   1000 		}
   1001 	}
   1002 	exit(EXIT_SUCCESS);
   1003 }
   1004