1 2/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@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 57static policydb_t policydb; 58extern unsigned int ss_initialized; 59 60int policyvers = MOD_POLICYDB_VERSION_BASE; 61 62static const char *symbol_labels[9] = { 63 "commons", 64 "classes", "roles ", "types ", "users ", "bools ", 65 "levels ", "cats ", "attribs" 66}; 67 68void usage(char *progname) 69{ 70 printf("usage: %s binary_pol_file\n\n", progname); 71 exit(1); 72} 73 74static 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 85static 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 101static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type, 102 uint32_t symbol_value, 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 115int 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 179int 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 214int 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->class - 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->class, 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 292int 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 334int 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 341int 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 360int 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 371void 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 406void 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 413void 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 438void 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 461void 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 474void 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 484static 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 496int 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 514static 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 549int 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 575int 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 590int 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 671int 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 689int 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 700static 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 747static 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 fgets(module_name, sizeof(module_name), stdin); 759 module_name[strlen(module_name) - 1] = '\0'; /* remove LF */ 760 if (module_name[0] == '\0') { 761 return; 762 } 763 764 /* read the binary policy */ 765 fprintf(out_fp, "Reading module...\n"); 766 if (read_policy(module_name, mods)) { 767 fprintf(stderr, 768 "%s: error(s) encountered while loading policy\n", 769 module_name); 770 exit(1); 771 } 772 if (module.policy_type != POLICY_MOD) { 773 fprintf(stderr, "This file is not a loadable policy module.\n"); 774 exit(1); 775 } 776 if (policydb_index_classes(&module) || 777 policydb_index_others(NULL, &module, 0)) { 778 fprintf(stderr, "Could not index module.\n"); 779 exit(1); 780 } 781 ret = link_modules(NULL, base, &mods, 1, 0); 782 if (ret != 0) { 783 printf("Link failed (error %d)\n", ret); 784 printf("(You will probably need to restart dismod.)\n"); 785 } 786 policydb_destroy(&module); 787 return; 788} 789 790static void display_policycaps(policydb_t * p, FILE * fp) 791{ 792 ebitmap_node_t *node; 793 const char *capname; 794 char buf[64]; 795 unsigned int i; 796 797 fprintf(fp, "policy capabilities:\n"); 798 ebitmap_for_each_bit(&p->policycaps, node, i) { 799 if (ebitmap_node_get_bit(node, i)) { 800 capname = sepol_polcap_getname(i); 801 if (capname == NULL) { 802 snprintf(buf, sizeof(buf), "unknown (%d)", i); 803 capname = buf; 804 } 805 fprintf(fp, "\t%s\n", capname); 806 } 807 } 808} 809 810int menu() 811{ 812 printf("\nSelect a command:\n"); 813 printf("1) display unconditional AVTAB\n"); 814 printf("2) display conditional AVTAB\n"); 815 printf("3) display users\n"); 816 printf("4) display bools\n"); 817 printf("5) display roles\n"); 818 printf("6) display types, attributes, and aliases\n"); 819 printf("7) display role transitions\n"); 820 printf("8) display role allows\n"); 821 printf("9) Display policycon\n"); 822 printf("0) Display initial SIDs\n"); 823 printf("\n"); 824 printf("a) Display avrule requirements\n"); 825 printf("b) Display avrule declarations\n"); 826 printf("c) Display policy capabilities\n"); 827 printf("l) Link in a module\n"); 828 printf("u) Display the unknown handling setting\n"); 829 printf("F) Display filename_trans rules\n"); 830 printf("\n"); 831 printf("f) set output file\n"); 832 printf("m) display menu\n"); 833 printf("q) quit\n"); 834 return 0; 835} 836 837int main(int argc, char **argv) 838{ 839 FILE *out_fp = stdout; 840 char ans[81], OutfileName[121]; 841 842 if (argc != 2) 843 usage(argv[0]); 844 845 /* read the binary policy */ 846 fprintf(out_fp, "Reading policy...\n"); 847 if (policydb_init(&policydb)) { 848 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); 849 exit(1); 850 } 851 if (read_policy(argv[1], &policydb)) { 852 fprintf(stderr, 853 "%s: error(s) encountered while loading policy\n", 854 argv[0]); 855 exit(1); 856 } 857 858 if (policydb.policy_type != POLICY_BASE && 859 policydb.policy_type != POLICY_MOD) { 860 fprintf(stderr, 861 "This file is neither a base nor loadable policy module.\n"); 862 exit(1); 863 } 864 865 if (policydb_index_classes(&policydb)) { 866 fprintf(stderr, "Error indexing classes\n"); 867 exit(1); 868 } 869 870 if (policydb_index_others(NULL, &policydb, 1)) { 871 fprintf(stderr, "Error indexing others\n"); 872 exit(1); 873 } 874 875 if (policydb.policy_type == POLICY_BASE) { 876 printf("Binary base policy file loaded.\n\n"); 877 } else { 878 printf("Binary policy module file loaded.\n"); 879 printf("Module name: %s\n", policydb.name); 880 printf("Module version: %s\n", policydb.version); 881 printf("\n"); 882 } 883 884 menu(); 885 for (;;) { 886 printf("\nCommand (\'m\' for menu): "); 887 fgets(ans, sizeof(ans), stdin); 888 switch (ans[0]) { 889 890 case '1': 891 fprintf(out_fp, "unconditional avtab:\n"); 892 display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB, 893 &policydb, out_fp); 894 break; 895 case '2': 896 fprintf(out_fp, "conditional avtab:\n"); 897 display_avblock(DISPLAY_AVBLOCK_COND_AVTAB, 898 &policydb, out_fp); 899 break; 900 case '3': 901 display_users(&policydb, out_fp); 902 break; 903 case '4': 904 display_bools(&policydb, out_fp); 905 break; 906 case '5': 907 if (hashtab_map 908 (policydb.p_roles.table, role_display_callback, 909 out_fp)) 910 exit(1); 911 break; 912 case '6': 913 if (display_types(&policydb, out_fp)) { 914 fprintf(stderr, "Error displaying types\n"); 915 exit(1); 916 } 917 break; 918 case '7': 919 fprintf(out_fp, "role transitions:\n"); 920 display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, 921 &policydb, out_fp); 922 break; 923 case '8': 924 fprintf(out_fp, "role allows:\n"); 925 display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, 926 &policydb, out_fp); 927 break; 928 case '9': 929 display_policycon(out_fp); 930 break; 931 case '0': 932 display_initial_sids(&policydb, out_fp); 933 break; 934 case 'a': 935 fprintf(out_fp, "avrule block requirements:\n"); 936 display_avblock(DISPLAY_AVBLOCK_REQUIRES, 937 &policydb, out_fp); 938 break; 939 case 'b': 940 fprintf(out_fp, "avrule block declarations:\n"); 941 display_avblock(DISPLAY_AVBLOCK_DECLARES, 942 &policydb, out_fp); 943 break; 944 case 'c': 945 display_policycaps(&policydb, out_fp); 946 break; 947 case 'u': 948 case 'U': 949 display_handle_unknown(&policydb, out_fp); 950 break; 951 case 'f': 952 printf 953 ("\nFilename for output (<CR> for screen output): "); 954 fgets(OutfileName, sizeof(OutfileName), stdin); 955 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ 956 if (strlen(OutfileName) == 0) 957 out_fp = stdout; 958 else if ((out_fp = fopen(OutfileName, "w")) == NULL) { 959 fprintf(stderr, "Cannot open output file %s\n", 960 OutfileName); 961 out_fp = stdout; 962 } 963 if (out_fp != stdout) 964 printf("\nOutput to file: %s\n", OutfileName); 965 break; 966 case 'F': 967 fprintf(out_fp, "filename_trans rules:\n"); 968 display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS, 969 &policydb, out_fp); 970 break; 971 case 'l': 972 link_module(&policydb, out_fp); 973 break; 974 case 'q': 975 policydb_destroy(&policydb); 976 exit(0); 977 break; 978 case 'm': 979 menu(); 980 break; 981 default: 982 printf("\nInvalid choice\n"); 983 menu(); 984 break; 985 986 } 987 } 988 exit(EXIT_SUCCESS); 989} 990