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