1 2 /* Authors: Frank Mayer <mayerf (at) tresys.com> and Karl MacMillan <kmacmillan (at) tresys.com> 3 * 4 * Copyright (C) 2003 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 * displaypol.c 12 * 13 * Test program to the contents of a binary policy in text 14 * form. This program currently only displays the 15 * avtab (including conditional avtab) rules. 16 * 17 * displaypol binary_pol_file 18 */ 19 20 #include <sepol/policydb/policydb.h> 21 #include <sepol/policydb/avtab.h> 22 #include <sepol/policydb/services.h> 23 #include <sepol/policydb/conditional.h> 24 #include <sepol/policydb/util.h> 25 #include <sepol/policydb/polcaps.h> 26 #include <getopt.h> 27 #include <assert.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 #include <sys/mman.h> 33 #include <errno.h> 34 #include <stdio.h> 35 #include <fcntl.h> 36 37 static policydb_t policydb; 38 39 void usage(const char *progname) 40 { 41 printf("usage: %s binary_pol_file\n\n", progname); 42 exit(1); 43 } 44 45 int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, 46 FILE * fp) 47 { 48 char *perm; 49 fprintf(fp, "{"); 50 perm = sepol_av_to_string(p, key->target_class, mask); 51 if (perm) 52 fprintf(fp, "%s ", perm); 53 fprintf(fp, "}"); 54 return 0; 55 } 56 57 #define operation_perm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) 58 #define next_bit_in_range(i, p) \ 59 ((i + 1 < sizeof(p)*8) && operation_perm_test((i + 1), p)) 60 61 int render_operations(avtab_operations_t *ops, avtab_key_t * key, FILE * fp) 62 { 63 uint16_t value; 64 uint16_t low_bit; 65 uint16_t low_value; 66 unsigned int bit; 67 unsigned int in_range = 0; 68 69 fprintf(fp, "{ "); 70 for (bit = 0; bit < sizeof(ops->perms)*8; bit++) { 71 if (!operation_perm_test(bit, ops->perms)) 72 continue; 73 74 if (in_range && next_bit_in_range(bit, ops->perms)) { 75 /* continue until high value found */ 76 continue; 77 } else if (next_bit_in_range(bit, ops->perms)) { 78 /* low value */ 79 low_bit = bit; 80 in_range = 1; 81 continue; 82 } 83 84 if (key->specified & AVTAB_OPNUM) { 85 value = ops->type<<8 | bit; 86 low_value = ops->type<<8 | low_bit; 87 if (in_range) 88 fprintf(fp, "0x%hx-0x%hx ", low_value, value); 89 else 90 fprintf(fp, "0x%hx ", value); 91 } else if (key->specified & AVTAB_OPTYPE) { 92 value = bit << 8; 93 low_value = low_bit << 8; 94 if (in_range) 95 fprintf(fp, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); 96 else 97 fprintf(fp, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); 98 99 } 100 if (in_range) 101 in_range = 0; 102 } 103 fprintf(fp, "}"); 104 return 0; 105 } 106 107 int render_type(uint32_t type, policydb_t * p, FILE * fp) 108 { 109 fprintf(fp, "%s", p->p_type_val_to_name[type - 1]); 110 return 0; 111 } 112 113 int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) 114 { 115 char *stype, *ttype, *tclass; 116 stype = p->p_type_val_to_name[key->source_type - 1]; 117 ttype = p->p_type_val_to_name[key->target_type - 1]; 118 tclass = p->p_class_val_to_name[key->target_class - 1]; 119 if (stype && ttype) 120 fprintf(fp, "%s %s : %s ", stype, ttype, tclass); 121 else if (stype) 122 fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass); 123 else if (ttype) 124 fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass); 125 else 126 fprintf(fp, "%u %u : %s ", key->source_type, key->target_type, 127 tclass); 128 return 0; 129 } 130 131 /* 'what' values for this function */ 132 #define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */ 133 #define RENDER_ENABLED 0x0002 134 #define RENDER_DISABLED 0x0004 135 #define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED) 136 137 int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, 138 policydb_t * p, FILE * fp) 139 { 140 if (!(what & RENDER_UNCONDITIONAL)) { 141 if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED) 142 && !(key-> 143 specified & 144 AVTAB_ENABLED)) 145 || ((what & RENDER_DISABLED) 146 && (key-> 147 specified & 148 AVTAB_ENABLED)))) { 149 return 0; /* doesn't match selection criteria */ 150 } 151 } 152 153 if (!(what & RENDER_UNCONDITIONAL)) { 154 if (key->specified & AVTAB_ENABLED) 155 fprintf(fp, "[enabled] "); 156 else if (!(key->specified & AVTAB_ENABLED)) 157 fprintf(fp, "[disabled] "); 158 } 159 160 if (key->specified & AVTAB_AV) { 161 if (key->specified & AVTAB_ALLOWED) { 162 fprintf(fp, "allow "); 163 render_key(key, p, fp); 164 render_access_mask(datum->data, key, p, fp); 165 fprintf(fp, ";\n"); 166 } 167 if (key->specified & AVTAB_AUDITALLOW) { 168 fprintf(fp, "auditallow "); 169 render_key(key, p, fp); 170 render_access_mask(datum->data, key, p, fp); 171 fprintf(fp, ";\n"); 172 } 173 if (key->specified & AVTAB_AUDITDENY) { 174 fprintf(fp, "dontaudit "); 175 render_key(key, p, fp); 176 /* We inverse the mask for dontaudit since the mask is internally stored 177 * as a auditdeny mask */ 178 render_access_mask(~datum->data, key, p, fp); 179 fprintf(fp, ";\n"); 180 } 181 } else if (key->specified & AVTAB_TYPE) { 182 if (key->specified & AVTAB_TRANSITION) { 183 fprintf(fp, "type_transition "); 184 render_key(key, p, fp); 185 render_type(datum->data, p, fp); 186 fprintf(fp, ";\n"); 187 } 188 if (key->specified & AVTAB_MEMBER) { 189 fprintf(fp, "type_member "); 190 render_key(key, p, fp); 191 render_type(datum->data, p, fp); 192 fprintf(fp, ";\n"); 193 } 194 if (key->specified & AVTAB_CHANGE) { 195 fprintf(fp, "type_change "); 196 render_key(key, p, fp); 197 render_type(datum->data, p, fp); 198 fprintf(fp, ";\n"); 199 } 200 } else if (key->specified & AVTAB_OP) { 201 if (key->specified & (AVTAB_OPNUM_ALLOWED|AVTAB_OPTYPE_ALLOWED)) 202 fprintf(fp, "allow "); 203 else if (key->specified & (AVTAB_OPNUM_AUDITALLOW|AVTAB_OPTYPE_AUDITALLOW)) 204 fprintf(fp, "auditallow "); 205 else if (key->specified & (AVTAB_OPNUM_DONTAUDIT|AVTAB_OPTYPE_DONTAUDIT)) 206 fprintf(fp, "dontaudit "); 207 render_key(key, p, fp); 208 render_operations(datum->ops, key, fp); 209 fprintf(fp, ";\n"); 210 } else { 211 fprintf(fp, " ERROR: no valid rule type specified\n"); 212 return -1; 213 } 214 return 0; 215 } 216 217 int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) 218 { 219 unsigned int i; 220 avtab_ptr_t cur; 221 222 /* hmm...should have used avtab_map. */ 223 for (i = 0; i < a->nslot; i++) { 224 for (cur = a->htable[i]; cur; cur = cur->next) { 225 render_av_rule(&cur->key, &cur->datum, what, p, fp); 226 } 227 } 228 fprintf(fp, "\n"); 229 return 0; 230 } 231 232 int display_bools(policydb_t * p, FILE * fp) 233 { 234 unsigned int i; 235 236 for (i = 0; i < p->p_bools.nprim; i++) { 237 fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i], 238 p->bool_val_to_struct[i]->state); 239 } 240 return 0; 241 } 242 243 void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) 244 { 245 246 cond_expr_t *cur; 247 for (cur = exp; cur != NULL; cur = cur->next) { 248 switch (cur->expr_type) { 249 case COND_BOOL: 250 fprintf(fp, "%s ", 251 p->p_bool_val_to_name[cur->bool - 1]); 252 break; 253 case COND_NOT: 254 fprintf(fp, "! "); 255 break; 256 case COND_OR: 257 fprintf(fp, "|| "); 258 break; 259 case COND_AND: 260 fprintf(fp, "&& "); 261 break; 262 case COND_XOR: 263 fprintf(fp, "^ "); 264 break; 265 case COND_EQ: 266 fprintf(fp, "== "); 267 break; 268 case COND_NEQ: 269 fprintf(fp, "!= "); 270 break; 271 default: 272 fprintf(fp, "error!"); 273 break; 274 } 275 } 276 } 277 278 int display_cond_expressions(policydb_t * p, FILE * fp) 279 { 280 cond_node_t *cur; 281 cond_av_list_t *av_cur; 282 283 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 284 fprintf(fp, "expression: "); 285 display_expr(p, cur->expr, fp); 286 fprintf(fp, "current state: %d\n", cur->cur_state); 287 fprintf(fp, "True list:\n"); 288 for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) { 289 fprintf(fp, "\t"); 290 render_av_rule(&av_cur->node->key, &av_cur->node->datum, 291 RENDER_CONDITIONAL, p, fp); 292 } 293 fprintf(fp, "False list:\n"); 294 for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) { 295 fprintf(fp, "\t"); 296 render_av_rule(&av_cur->node->key, &av_cur->node->datum, 297 RENDER_CONDITIONAL, p, fp); 298 } 299 } 300 return 0; 301 } 302 303 int display_handle_unknown(policydb_t * p, FILE * out_fp) 304 { 305 if (p->handle_unknown == ALLOW_UNKNOWN) 306 fprintf(out_fp, "Allow unknown classes and permisions\n"); 307 else if (p->handle_unknown == DENY_UNKNOWN) 308 fprintf(out_fp, "Deny unknown classes and permisions\n"); 309 else if (p->handle_unknown == REJECT_UNKNOWN) 310 fprintf(out_fp, "Reject unknown classes and permisions\n"); 311 return 0; 312 } 313 314 int change_bool(char *name, int state, policydb_t * p, FILE * fp) 315 { 316 cond_bool_datum_t *bool; 317 318 bool = hashtab_search(p->p_bools.table, name); 319 if (bool == NULL) { 320 fprintf(fp, "Could not find bool %s\n", name); 321 return -1; 322 } 323 bool->state = state; 324 evaluate_conds(p); 325 return 0; 326 } 327 328 static void display_policycaps(policydb_t * p, FILE * fp) 329 { 330 ebitmap_node_t *node; 331 const char *capname; 332 char buf[64]; 333 unsigned int i; 334 335 fprintf(fp, "policy capabilities:\n"); 336 ebitmap_for_each_bit(&p->policycaps, node, i) { 337 if (ebitmap_node_get_bit(node, i)) { 338 capname = sepol_polcap_getname(i); 339 if (capname == NULL) { 340 snprintf(buf, sizeof(buf), "unknown (%d)", i); 341 capname = buf; 342 } 343 fprintf(fp, "\t%s\n", capname); 344 } 345 } 346 } 347 348 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type, 349 uint32_t symbol_value, const char *prefix) 350 { 351 const char *id = p->sym_val_to_name[symbol_type][symbol_value]; 352 fprintf(fp, " %s%s", prefix, id); 353 } 354 355 static void display_permissive(policydb_t *p, FILE *fp) 356 { 357 ebitmap_node_t *node; 358 unsigned int i; 359 360 fprintf(fp, "permissive sids:\n"); 361 ebitmap_for_each_bit(&p->permissive_map, node, i) { 362 if (ebitmap_node_get_bit(node, i)) { 363 fprintf(fp, "\t"); 364 display_id(p, fp, SYM_TYPES, i - 1, ""); 365 fprintf(fp, "\n"); 366 } 367 } 368 } 369 370 static void display_role_trans(policydb_t *p, FILE *fp) 371 { 372 role_trans_t *rt; 373 374 fprintf(fp, "role_trans rules:\n"); 375 for (rt = p->role_tr; rt; rt = rt->next) { 376 display_id(p, fp, SYM_ROLES, rt->role - 1, ""); 377 display_id(p, fp, SYM_TYPES, rt->type - 1, ""); 378 display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":"); 379 display_id(p, fp, SYM_ROLES, rt->new_role - 1, ""); 380 fprintf(fp, "\n"); 381 } 382 } 383 384 static void display_filename_trans(policydb_t *p, FILE *fp) 385 { 386 filename_trans_t *ft; 387 388 fprintf(fp, "filename_trans rules:\n"); 389 for (ft = p->filename_trans; ft; ft = ft->next) { 390 display_id(p, fp, SYM_TYPES, ft->stype - 1, ""); 391 display_id(p, fp, SYM_TYPES, ft->ttype - 1, ""); 392 display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":"); 393 display_id(p, fp, SYM_TYPES, ft->otype - 1, ""); 394 fprintf(fp, " %s\n", ft->name); 395 } 396 } 397 398 int menu(void) 399 { 400 printf("\nSelect a command:\n"); 401 printf("1) display unconditional AVTAB\n"); 402 printf("2) display conditional AVTAB (entirely)\n"); 403 printf("3) display conditional AVTAG (only ENABLED rules)\n"); 404 printf("4) display conditional AVTAB (only DISABLED rules)\n"); 405 printf("5) display conditional bools\n"); 406 printf("6) display conditional expressions\n"); 407 printf("7) change a boolean value\n"); 408 printf("8) display role transitions\n"); 409 printf("\n"); 410 printf("c) display policy capabilities\n"); 411 printf("p) display the list of permissive types\n"); 412 printf("u) display unknown handling setting\n"); 413 printf("F) display filename_trans rules\n"); 414 printf("\n"); 415 printf("f) set output file\n"); 416 printf("m) display menu\n"); 417 printf("q) quit\n"); 418 return 0; 419 } 420 421 int main(int argc, char **argv) 422 { 423 FILE *out_fp = stdout; 424 char ans[81], OutfileName[121]; 425 int fd, ret; 426 struct stat sb; 427 void *map; 428 char *name; 429 int state; 430 struct policy_file pf; 431 432 if (argc != 2) 433 usage(argv[0]); 434 435 fd = open(argv[1], O_RDONLY); 436 if (fd < 0) { 437 fprintf(stderr, "Can't open '%s': %s\n", 438 argv[1], strerror(errno)); 439 exit(1); 440 } 441 if (fstat(fd, &sb) < 0) { 442 fprintf(stderr, "Can't stat '%s': %s\n", 443 argv[1], strerror(errno)); 444 exit(1); 445 } 446 map = 447 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 448 if (map == MAP_FAILED) { 449 fprintf(stderr, "Can't map '%s': %s\n", 450 argv[1], strerror(errno)); 451 exit(1); 452 } 453 454 /* read the binary policy */ 455 fprintf(out_fp, "Reading policy...\n"); 456 policy_file_init(&pf); 457 pf.type = PF_USE_MEMORY; 458 pf.data = map; 459 pf.len = sb.st_size; 460 if (policydb_init(&policydb)) { 461 fprintf(stderr, "%s: Out of memory!\n", argv[0]); 462 exit(1); 463 } 464 ret = policydb_read(&policydb, &pf, 1); 465 if (ret) { 466 fprintf(stderr, 467 "%s: error(s) encountered while parsing configuration\n", 468 argv[0]); 469 exit(1); 470 } 471 472 fprintf(stdout, "binary policy file loaded\n\n"); 473 close(fd); 474 475 menu(); 476 for (;;) { 477 printf("\nCommand (\'m\' for menu): "); 478 if (fgets(ans, sizeof(ans), stdin) == NULL) { 479 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 480 strerror(errno)); 481 continue; 482 } 483 switch (ans[0]) { 484 485 case '1': 486 display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL, 487 &policydb, out_fp); 488 break; 489 case '2': 490 display_avtab(&policydb.te_cond_avtab, 491 RENDER_CONDITIONAL, &policydb, out_fp); 492 break; 493 case '3': 494 display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED, 495 &policydb, out_fp); 496 break; 497 case '4': 498 display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED, 499 &policydb, out_fp); 500 break; 501 case '5': 502 display_bools(&policydb, out_fp); 503 break; 504 case '6': 505 display_cond_expressions(&policydb, out_fp); 506 break; 507 case '7': 508 printf("name? "); 509 if (fgets(ans, sizeof(ans), stdin) == NULL) { 510 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 511 strerror(errno)); 512 break; 513 } 514 ans[strlen(ans) - 1] = 0; 515 516 name = malloc((strlen(ans) + 1) * sizeof(char)); 517 if (name == NULL) { 518 fprintf(stderr, "couldn't malloc string.\n"); 519 break; 520 } 521 strcpy(name, ans); 522 523 printf("state? "); 524 if (fgets(ans, sizeof(ans), stdin) == NULL) { 525 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 526 strerror(errno)); 527 break; 528 } 529 ans[strlen(ans) - 1] = 0; 530 531 if (atoi(ans)) 532 state = 1; 533 else 534 state = 0; 535 536 change_bool(name, state, &policydb, out_fp); 537 free(name); 538 break; 539 case '8': 540 display_role_trans(&policydb, out_fp); 541 break; 542 case 'c': 543 display_policycaps(&policydb, out_fp); 544 break; 545 case 'p': 546 display_permissive(&policydb, out_fp); 547 break; 548 case 'u': 549 case 'U': 550 display_handle_unknown(&policydb, out_fp); 551 break; 552 case 'f': 553 printf 554 ("\nFilename for output (<CR> for screen output): "); 555 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) { 556 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 557 strerror(errno)); 558 break; 559 } 560 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ 561 if (strlen(OutfileName) == 0) 562 out_fp = stdout; 563 else if ((out_fp = fopen(OutfileName, "w")) == NULL) { 564 fprintf(stderr, "Cannot open output file %s\n", 565 OutfileName); 566 out_fp = stdout; 567 } 568 if (out_fp != stdout) 569 printf("\nOutput to file: %s\n", OutfileName); 570 break; 571 case 'F': 572 display_filename_trans(&policydb, out_fp); 573 break; 574 case 'q': 575 policydb_destroy(&policydb); 576 exit(0); 577 break; 578 case 'm': 579 menu(); 580 break; 581 default: 582 printf("\nInvalid choice\n"); 583 menu(); 584 break; 585 586 } 587 } 588 } 589 590 /* FLASK */ 591