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