1
2 /* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@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
usage(const char * progname)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
render_access_mask(uint32_t mask,avtab_key_t * key,policydb_t * p,FILE * fp)45 static 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
render_type(uint32_t type,policydb_t * p,FILE * fp)57 static 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
render_key(avtab_key_t * key,policydb_t * p,FILE * fp)63 static 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
render_av_rule(avtab_key_t * key,avtab_datum_t * datum,uint32_t what,policydb_t * p,FILE * fp)87 static 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
display_avtab(avtab_t * a,uint32_t what,policydb_t * p,FILE * fp)166 static 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
display_bools(policydb_t * p,FILE * fp)181 static 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
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)192 static 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
display_cond_expressions(policydb_t * p,FILE * fp)227 static 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
display_handle_unknown(policydb_t * p,FILE * out_fp)252 static 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
change_bool(char * name,int state,policydb_t * p,FILE * fp)263 static 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
display_policycaps(policydb_t * p,FILE * fp)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_positive_bit(&p->policycaps, node, i) {
286 capname = sepol_polcap_getname(i);
287 if (capname == NULL) {
288 snprintf(buf, sizeof(buf), "unknown (%u)", i);
289 capname = buf;
290 }
291 fprintf(fp, "\t%s\n", capname);
292 }
293 }
294
display_id(policydb_t * p,FILE * fp,uint32_t symbol_type,uint32_t symbol_value,const char * prefix)295 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
296 uint32_t symbol_value, const char *prefix)
297 {
298 const char *id = p->sym_val_to_name[symbol_type][symbol_value];
299 fprintf(fp, " %s%s", prefix, id);
300 }
301
display_permissive(policydb_t * p,FILE * fp)302 static void display_permissive(policydb_t *p, FILE *fp)
303 {
304 ebitmap_node_t *node;
305 unsigned int i;
306
307 fprintf(fp, "permissive sids:\n");
308 ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
309 fprintf(fp, "\t");
310 display_id(p, fp, SYM_TYPES, i - 1, "");
311 fprintf(fp, "\n");
312 }
313 }
314
display_role_trans(policydb_t * p,FILE * fp)315 static void display_role_trans(policydb_t *p, FILE *fp)
316 {
317 role_trans_t *rt;
318
319 fprintf(fp, "role_trans rules:\n");
320 for (rt = p->role_tr; rt; rt = rt->next) {
321 display_id(p, fp, SYM_ROLES, rt->role - 1, "");
322 display_id(p, fp, SYM_TYPES, rt->type - 1, "");
323 display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
324 display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
325 fprintf(fp, "\n");
326 }
327 }
328
329 struct filenametr_display_args {
330 policydb_t *p;
331 FILE *fp;
332 };
333
filenametr_display(hashtab_key_t key,hashtab_datum_t datum,void * ptr)334 static int filenametr_display(hashtab_key_t key,
335 hashtab_datum_t datum,
336 void *ptr)
337 {
338 struct filename_trans_key *ft = (struct filename_trans_key *)key;
339 struct filename_trans_datum *ftdatum = datum;
340 struct filenametr_display_args *args = ptr;
341 policydb_t *p = args->p;
342 FILE *fp = args->fp;
343 ebitmap_node_t *node;
344 uint32_t bit;
345
346 do {
347 ebitmap_for_each_positive_bit(&ftdatum->stypes, node, bit) {
348 display_id(p, fp, SYM_TYPES, bit, "");
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 }
354 ftdatum = ftdatum->next;
355 } while (ftdatum);
356
357 return 0;
358 }
359
360
display_filename_trans(policydb_t * p,FILE * fp)361 static void display_filename_trans(policydb_t *p, FILE *fp)
362 {
363 struct filenametr_display_args args;
364
365 fprintf(fp, "filename_trans rules:\n");
366 args.p = p;
367 args.fp = fp;
368 hashtab_map(p->filename_trans, filenametr_display, &args);
369 }
370
menu(void)371 static int menu(void)
372 {
373 printf("\nSelect a command:\n");
374 printf("1) display unconditional AVTAB\n");
375 printf("2) display conditional AVTAB (entirely)\n");
376 printf("3) display conditional AVTAB (only ENABLED rules)\n");
377 printf("4) display conditional AVTAB (only DISABLED rules)\n");
378 printf("5) display conditional bools\n");
379 printf("6) display conditional expressions\n");
380 printf("7) change a boolean value\n");
381 printf("8) display role transitions\n");
382 printf("\n");
383 printf("c) display policy capabilities\n");
384 printf("p) display the list of permissive types\n");
385 printf("u) display unknown handling setting\n");
386 printf("F) display filename_trans rules\n");
387 printf("\n");
388 printf("f) set output file\n");
389 printf("m) display menu\n");
390 printf("q) quit\n");
391 return 0;
392 }
393
main(int argc,char ** argv)394 int main(int argc, char **argv)
395 {
396 FILE *out_fp = stdout;
397 char ans[81], OutfileName[121];
398 int fd, ret;
399 struct stat sb;
400 void *map;
401 char *name;
402 int state;
403 struct policy_file pf;
404
405 if (argc != 2)
406 usage(argv[0]);
407
408 fd = open(argv[1], O_RDONLY);
409 if (fd < 0) {
410 fprintf(stderr, "Can't open '%s': %s\n",
411 argv[1], strerror(errno));
412 exit(1);
413 }
414 if (fstat(fd, &sb) < 0) {
415 fprintf(stderr, "Can't stat '%s': %s\n",
416 argv[1], strerror(errno));
417 exit(1);
418 }
419 map =
420 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
421 if (map == MAP_FAILED) {
422 fprintf(stderr, "Can't map '%s': %s\n",
423 argv[1], strerror(errno));
424 exit(1);
425 }
426
427 /* read the binary policy */
428 fprintf(out_fp, "Reading policy...\n");
429 policy_file_init(&pf);
430 pf.type = PF_USE_MEMORY;
431 pf.data = map;
432 pf.len = sb.st_size;
433 if (policydb_init(&policydb)) {
434 fprintf(stderr, "%s: Out of memory!\n", argv[0]);
435 exit(1);
436 }
437 ret = policydb_read(&policydb, &pf, 1);
438 if (ret) {
439 fprintf(stderr,
440 "%s: error(s) encountered while parsing configuration\n",
441 argv[0]);
442 exit(1);
443 }
444
445 fprintf(stdout, "binary policy file loaded\n\n");
446 close(fd);
447
448 menu();
449 for (;;) {
450 printf("\nCommand (\'m\' for menu): ");
451 if (fgets(ans, sizeof(ans), stdin) == NULL) {
452 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
453 strerror(errno));
454 continue;
455 }
456 switch (ans[0]) {
457
458 case '1':
459 display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
460 &policydb, out_fp);
461 break;
462 case '2':
463 display_avtab(&policydb.te_cond_avtab,
464 RENDER_CONDITIONAL, &policydb, out_fp);
465 break;
466 case '3':
467 display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
468 &policydb, out_fp);
469 break;
470 case '4':
471 display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
472 &policydb, out_fp);
473 break;
474 case '5':
475 display_bools(&policydb, out_fp);
476 break;
477 case '6':
478 display_cond_expressions(&policydb, out_fp);
479 break;
480 case '7':
481 printf("name? ");
482 if (fgets(ans, sizeof(ans), stdin) == NULL) {
483 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
484 strerror(errno));
485 break;
486 }
487 ans[strlen(ans) - 1] = 0;
488
489 name = malloc((strlen(ans) + 1) * sizeof(char));
490 if (name == NULL) {
491 fprintf(stderr, "couldn't malloc string.\n");
492 break;
493 }
494 strcpy(name, ans);
495
496 printf("state? ");
497 if (fgets(ans, sizeof(ans), stdin) == NULL) {
498 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
499 strerror(errno));
500 break;
501 }
502 ans[strlen(ans) - 1] = 0;
503
504 if (atoi(ans))
505 state = 1;
506 else
507 state = 0;
508
509 change_bool(name, state, &policydb, out_fp);
510 free(name);
511 break;
512 case '8':
513 display_role_trans(&policydb, out_fp);
514 break;
515 case 'c':
516 display_policycaps(&policydb, out_fp);
517 break;
518 case 'p':
519 display_permissive(&policydb, out_fp);
520 break;
521 case 'u':
522 case 'U':
523 display_handle_unknown(&policydb, out_fp);
524 break;
525 case 'f':
526 printf
527 ("\nFilename for output (<CR> for screen output): ");
528 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
529 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
530 strerror(errno));
531 break;
532 }
533 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
534 if (strlen(OutfileName) == 0)
535 out_fp = stdout;
536 else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
537 fprintf(stderr, "Cannot open output file %s\n",
538 OutfileName);
539 out_fp = stdout;
540 }
541 if (out_fp != stdout)
542 printf("\nOutput to file: %s\n", OutfileName);
543 break;
544 case 'F':
545 display_filename_trans(&policydb, out_fp);
546 break;
547 case 'q':
548 policydb_destroy(&policydb);
549 exit(0);
550 break;
551 case 'm':
552 menu();
553 break;
554 default:
555 printf("\nInvalid choice\n");
556 menu();
557 break;
558
559 }
560 }
561 }
562
563 /* FLASK */
564