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 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 permisions\n"); 256 else if (p->handle_unknown == DENY_UNKNOWN) 257 fprintf(out_fp, "Deny unknown classes and permisions\n"); 258 else if (p->handle_unknown == REJECT_UNKNOWN) 259 fprintf(out_fp, "Reject unknown classes and permisions\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 static void display_filename_trans(policydb_t *p, FILE *fp) 334 { 335 filename_trans_t *ft; 336 337 fprintf(fp, "filename_trans rules:\n"); 338 for (ft = p->filename_trans; ft; ft = ft->next) { 339 display_id(p, fp, SYM_TYPES, ft->stype - 1, ""); 340 display_id(p, fp, SYM_TYPES, ft->ttype - 1, ""); 341 display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":"); 342 display_id(p, fp, SYM_TYPES, ft->otype - 1, ""); 343 fprintf(fp, " %s\n", ft->name); 344 } 345 } 346 347 int menu(void) 348 { 349 printf("\nSelect a command:\n"); 350 printf("1) display unconditional AVTAB\n"); 351 printf("2) display conditional AVTAB (entirely)\n"); 352 printf("3) display conditional AVTAG (only ENABLED rules)\n"); 353 printf("4) display conditional AVTAB (only DISABLED rules)\n"); 354 printf("5) display conditional bools\n"); 355 printf("6) display conditional expressions\n"); 356 printf("7) change a boolean value\n"); 357 printf("8) display role transitions\n"); 358 printf("\n"); 359 printf("c) display policy capabilities\n"); 360 printf("p) display the list of permissive types\n"); 361 printf("u) display unknown handling setting\n"); 362 printf("F) display filename_trans rules\n"); 363 printf("\n"); 364 printf("f) set output file\n"); 365 printf("m) display menu\n"); 366 printf("q) quit\n"); 367 return 0; 368 } 369 370 int main(int argc, char **argv) 371 { 372 FILE *out_fp = stdout; 373 char ans[81], OutfileName[121]; 374 int fd, ret; 375 struct stat sb; 376 void *map; 377 char *name; 378 int state; 379 struct policy_file pf; 380 381 if (argc != 2) 382 usage(argv[0]); 383 384 fd = open(argv[1], O_RDONLY); 385 if (fd < 0) { 386 fprintf(stderr, "Can't open '%s': %s\n", 387 argv[1], strerror(errno)); 388 exit(1); 389 } 390 if (fstat(fd, &sb) < 0) { 391 fprintf(stderr, "Can't stat '%s': %s\n", 392 argv[1], strerror(errno)); 393 exit(1); 394 } 395 map = 396 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 397 if (map == MAP_FAILED) { 398 fprintf(stderr, "Can't map '%s': %s\n", 399 argv[1], strerror(errno)); 400 exit(1); 401 } 402 403 /* read the binary policy */ 404 fprintf(out_fp, "Reading policy...\n"); 405 policy_file_init(&pf); 406 pf.type = PF_USE_MEMORY; 407 pf.data = map; 408 pf.len = sb.st_size; 409 if (policydb_init(&policydb)) { 410 fprintf(stderr, "%s: Out of memory!\n", argv[0]); 411 exit(1); 412 } 413 ret = policydb_read(&policydb, &pf, 1); 414 if (ret) { 415 fprintf(stderr, 416 "%s: error(s) encountered while parsing configuration\n", 417 argv[0]); 418 exit(1); 419 } 420 421 fprintf(stdout, "binary policy file loaded\n\n"); 422 close(fd); 423 424 menu(); 425 for (;;) { 426 printf("\nCommand (\'m\' for menu): "); 427 if (fgets(ans, sizeof(ans), stdin) == NULL) { 428 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 429 strerror(errno)); 430 continue; 431 } 432 switch (ans[0]) { 433 434 case '1': 435 display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL, 436 &policydb, out_fp); 437 break; 438 case '2': 439 display_avtab(&policydb.te_cond_avtab, 440 RENDER_CONDITIONAL, &policydb, out_fp); 441 break; 442 case '3': 443 display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED, 444 &policydb, out_fp); 445 break; 446 case '4': 447 display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED, 448 &policydb, out_fp); 449 break; 450 case '5': 451 display_bools(&policydb, out_fp); 452 break; 453 case '6': 454 display_cond_expressions(&policydb, out_fp); 455 break; 456 case '7': 457 printf("name? "); 458 if (fgets(ans, sizeof(ans), stdin) == NULL) { 459 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 460 strerror(errno)); 461 break; 462 } 463 ans[strlen(ans) - 1] = 0; 464 465 name = malloc((strlen(ans) + 1) * sizeof(char)); 466 if (name == NULL) { 467 fprintf(stderr, "couldn't malloc string.\n"); 468 break; 469 } 470 strcpy(name, ans); 471 472 printf("state? "); 473 if (fgets(ans, sizeof(ans), stdin) == NULL) { 474 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 475 strerror(errno)); 476 break; 477 } 478 ans[strlen(ans) - 1] = 0; 479 480 if (atoi(ans)) 481 state = 1; 482 else 483 state = 0; 484 485 change_bool(name, state, &policydb, out_fp); 486 free(name); 487 break; 488 case '8': 489 display_role_trans(&policydb, out_fp); 490 break; 491 case 'c': 492 display_policycaps(&policydb, out_fp); 493 break; 494 case 'p': 495 display_permissive(&policydb, out_fp); 496 break; 497 case 'u': 498 case 'U': 499 display_handle_unknown(&policydb, out_fp); 500 break; 501 case 'f': 502 printf 503 ("\nFilename for output (<CR> for screen output): "); 504 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) { 505 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, 506 strerror(errno)); 507 break; 508 } 509 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ 510 if (strlen(OutfileName) == 0) 511 out_fp = stdout; 512 else if ((out_fp = fopen(OutfileName, "w")) == NULL) { 513 fprintf(stderr, "Cannot open output file %s\n", 514 OutfileName); 515 out_fp = stdout; 516 } 517 if (out_fp != stdout) 518 printf("\nOutput to file: %s\n", OutfileName); 519 break; 520 case 'F': 521 display_filename_trans(&policydb, out_fp); 522 break; 523 case 'q': 524 policydb_destroy(&policydb); 525 exit(0); 526 break; 527 case 'm': 528 menu(); 529 break; 530 default: 531 printf("\nInvalid choice\n"); 532 menu(); 533 break; 534 535 } 536 } 537 } 538 539 /* FLASK */ 540