1
2 /* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
3 *
4 * Copyright (C) 2003,2004,2005 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 * dismod.c
12 *
13 * Test program to the contents of a binary policy in text
14 * form.
15 *
16 * dismod binary_mod_file
17 */
18
19 #include <getopt.h>
20 #include <assert.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/mman.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29
30 #include <sepol/policydb/policydb.h>
31 #include <sepol/policydb/services.h>
32 #include <sepol/policydb/conditional.h>
33 #include <sepol/policydb/flask.h>
34 #include <sepol/policydb/link.h>
35 #include <sepol/policydb/module.h>
36 #include <sepol/policydb/util.h>
37 #include <sepol/policydb/polcaps.h>
38
39 #include <byteswap.h>
40 #include <endian.h>
41
42 #if __BYTE_ORDER == __LITTLE_ENDIAN
43 #define le32_to_cpu(x) (x)
44 #else
45 #define le32_to_cpu(x) bswap_32(x)
46 #endif
47
48 #define DISPLAY_AVBLOCK_COND_AVTAB 0
49 #define DISPLAY_AVBLOCK_UNCOND_AVTAB 1
50 #define DISPLAY_AVBLOCK_ROLE_TYPE_NODE 2 /* unused? */
51 #define DISPLAY_AVBLOCK_ROLE_TRANS 3
52 #define DISPLAY_AVBLOCK_ROLE_ALLOW 4
53 #define DISPLAY_AVBLOCK_REQUIRES 5
54 #define DISPLAY_AVBLOCK_DECLARES 6
55 #define DISPLAY_AVBLOCK_FILENAME_TRANS 7
56
57 static policydb_t policydb;
58 extern unsigned int ss_initialized;
59
60 int policyvers = MOD_POLICYDB_VERSION_BASE;
61
62 static const char *symbol_labels[9] = {
63 "commons",
64 "classes", "roles ", "types ", "users ", "bools ",
65 "levels ", "cats ", "attribs"
66 };
67
usage(const char * progname)68 void usage(const char *progname)
69 {
70 printf("usage: %s binary_pol_file\n\n", progname);
71 exit(1);
72 }
73
render_access_mask(uint32_t mask,uint32_t class,policydb_t * p,FILE * fp)74 static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p,
75 FILE * fp)
76 {
77 char *perm;
78 fprintf(fp, "{");
79 perm = sepol_av_to_string(p, class, mask);
80 if (perm)
81 fprintf(fp, "%s ", perm);
82 fprintf(fp, "}");
83 }
84
render_access_bitmap(ebitmap_t * map,uint32_t class,policydb_t * p,FILE * fp)85 static void render_access_bitmap(ebitmap_t * map, uint32_t class,
86 policydb_t * p, FILE * fp)
87 {
88 unsigned int i;
89 char *perm;
90 fprintf(fp, "{");
91 for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
92 if (ebitmap_get_bit(map, i)) {
93 perm = sepol_av_to_string(p, class, 1 << i);
94 if (perm)
95 fprintf(fp, " %s", perm);
96 }
97 }
98 fprintf(fp, " }");
99 }
100
display_id(policydb_t * p,FILE * fp,uint32_t symbol_type,uint32_t symbol_value,const char * prefix)101 static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
102 uint32_t symbol_value, const char *prefix)
103 {
104 char *id = p->sym_val_to_name[symbol_type][symbol_value];
105 scope_datum_t *scope =
106 (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
107 assert(scope != NULL);
108 if (scope->scope == SCOPE_REQ) {
109 fprintf(fp, " [%s%s]", prefix, id);
110 } else {
111 fprintf(fp, " %s%s", prefix, id);
112 }
113 }
114
display_type_set(type_set_t * set,uint32_t flags,policydb_t * policy,FILE * fp)115 int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
116 FILE * fp)
117 {
118 unsigned int i, num_types;
119
120 if (set->flags & TYPE_STAR) {
121 fprintf(fp, " * ");
122 return 0;
123 } else if (set->flags & TYPE_COMP) {
124 fprintf(fp, " ~");
125 }
126
127 num_types = 0;
128 if (flags & RULE_SELF) {
129 num_types++;
130 }
131
132 for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
133 i++) {
134 if (!ebitmap_get_bit(&set->types, i))
135 continue;
136 num_types++;
137 if (num_types > 1)
138 break;
139 }
140
141 if (num_types <= 1) {
142 for (i = ebitmap_startbit(&set->negset);
143 i < ebitmap_length(&set->negset); i++) {
144 if (!ebitmap_get_bit(&set->negset, i))
145 continue;
146 num_types++;
147 if (num_types > 1)
148 break;
149 }
150 }
151
152 if (num_types > 1)
153 fprintf(fp, "{");
154
155 for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
156 i++) {
157 if (!ebitmap_get_bit(&set->types, i))
158 continue;
159 display_id(policy, fp, SYM_TYPES, i, "");
160 }
161
162 for (i = ebitmap_startbit(&set->negset);
163 i < ebitmap_length(&set->negset); i++) {
164 if (!ebitmap_get_bit(&set->negset, i))
165 continue;
166 display_id(policy, fp, SYM_TYPES, i, "-");
167 }
168
169 if (flags & RULE_SELF) {
170 fprintf(fp, " self");
171 }
172
173 if (num_types > 1)
174 fprintf(fp, " }");
175
176 return 0;
177 }
178
display_mod_role_set(role_set_t * roles,policydb_t * p,FILE * fp)179 int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
180 {
181 unsigned int i, num = 0;
182
183 if (roles->flags & ROLE_STAR) {
184 fprintf(fp, " * ");
185 return 0;
186 } else if (roles->flags & ROLE_COMP) {
187 fprintf(fp, " ~");
188 }
189
190 for (i = ebitmap_startbit(&roles->roles);
191 i < ebitmap_length(&roles->roles); i++) {
192 if (!ebitmap_get_bit(&roles->roles, i))
193 continue;
194 num++;
195 if (num > 1) {
196 fprintf(fp, "{");
197 break;
198 }
199 }
200
201 for (i = ebitmap_startbit(&roles->roles);
202 i < ebitmap_length(&roles->roles); i++) {
203 if (ebitmap_get_bit(&roles->roles, i))
204 display_id(p, fp, SYM_ROLES, i, "");
205 }
206
207 if (num > 1)
208 fprintf(fp, " }");
209
210 return 0;
211
212 }
213
display_avrule(avrule_t * avrule,policydb_t * policy,FILE * fp)214 int display_avrule(avrule_t * avrule, policydb_t * policy,
215 FILE * fp)
216 {
217 class_perm_node_t *cur;
218 int num_classes;
219
220 if (avrule == NULL) {
221 fprintf(fp, " <empty>\n");
222 return 0;
223 }
224 if (avrule->specified & AVRULE_AV) {
225 if (avrule->specified & AVRULE_ALLOWED) {
226 fprintf(fp, " allow");
227 }
228 if (avrule->specified & AVRULE_AUDITALLOW) {
229 fprintf(fp, " auditallow ");
230 }
231 if (avrule->specified & AVRULE_DONTAUDIT) {
232 fprintf(fp, " dontaudit");
233 }
234 } else if (avrule->specified & AVRULE_TYPE) {
235 if (avrule->specified & AVRULE_TRANSITION) {
236 fprintf(fp, " type_transition");
237 }
238 if (avrule->specified & AVRULE_MEMBER) {
239 fprintf(fp, " type_member");
240 }
241 if (avrule->specified & AVRULE_CHANGE) {
242 fprintf(fp, " type_change");
243 }
244 } else if (avrule->specified & AVRULE_NEVERALLOW) {
245 fprintf(fp, " neverallow");
246 } else {
247 fprintf(fp, " ERROR: no valid rule type specified\n");
248 return -1;
249 }
250
251 if (display_type_set(&avrule->stypes, 0, policy, fp))
252 return -1;
253
254 if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
255 return -1;
256
257 fprintf(fp, " :");
258 cur = avrule->perms;
259 num_classes = 0;
260 while (cur) {
261 num_classes++;
262 if (num_classes > 1)
263 break;
264 cur = cur->next;
265 }
266
267 if (num_classes > 1)
268 fprintf(fp, " {");
269
270 cur = avrule->perms;
271 while (cur) {
272 display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
273 cur = cur->next;
274 }
275
276 if (num_classes > 1)
277 fprintf(fp, " }");
278 fprintf(fp, " ");
279
280 if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
281 render_access_mask(avrule->perms->data, avrule->perms->tclass,
282 policy, fp);
283 } else if (avrule->specified & AVRULE_TYPE) {
284 display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
285 }
286
287 fprintf(fp, ";\n");
288
289 return 0;
290 }
291
display_type_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)292 int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
293 {
294 type_datum_t *type;
295 FILE *fp;
296 unsigned int i, first_attrib = 1;
297
298 type = (type_datum_t *) datum;
299 fp = (FILE *) data;
300
301 if (type->primary) {
302 display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
303 fprintf(fp, " [%d]: ", type->s.value);
304 } else {
305 /* as that aliases have no value of their own and that
306 * they can never be required by a module, use this
307 * alternative way of displaying a name */
308 fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
309 }
310 if (type->flavor == TYPE_ATTRIB) {
311 fprintf(fp, "attribute for types");
312 for (i = ebitmap_startbit(&type->types);
313 i < ebitmap_length(&type->types); i++) {
314 if (!ebitmap_get_bit(&type->types, i))
315 continue;
316 if (first_attrib) {
317 first_attrib = 0;
318 } else {
319 fprintf(fp, ",");
320 }
321 display_id(&policydb, fp, SYM_TYPES, i, "");
322 }
323 } else if (type->primary) {
324 fprintf(fp, "type");
325 } else {
326 fprintf(fp, "alias for type");
327 display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
328 }
329 fprintf(fp, " flags:%x\n", type->flags);
330
331 return 0;
332 }
333
display_types(policydb_t * p,FILE * fp)334 int display_types(policydb_t * p, FILE * fp)
335 {
336 if (hashtab_map(p->p_types.table, display_type_callback, fp))
337 return -1;
338 return 0;
339 }
340
display_users(policydb_t * p,FILE * fp)341 int display_users(policydb_t * p, FILE * fp)
342 {
343 unsigned int i, j;
344 ebitmap_t *bitmap;
345 for (i = 0; i < p->p_users.nprim; i++) {
346 display_id(p, fp, SYM_USERS, i, "");
347 fprintf(fp, ":");
348 bitmap = &(p->user_val_to_struct[i]->roles.roles);
349 for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
350 j++) {
351 if (ebitmap_get_bit(bitmap, j)) {
352 display_id(p, fp, SYM_ROLES, j, "");
353 }
354 }
355 fprintf(fp, "\n");
356 }
357 return 0;
358 }
359
display_bools(policydb_t * p,FILE * fp)360 int display_bools(policydb_t * p, FILE * fp)
361 {
362 unsigned int i;
363
364 for (i = 0; i < p->p_bools.nprim; i++) {
365 display_id(p, fp, SYM_BOOLS, i, "");
366 fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
367 }
368 return 0;
369 }
370
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)371 void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
372 {
373
374 cond_expr_t *cur;
375 for (cur = exp; cur != NULL; cur = cur->next) {
376 switch (cur->expr_type) {
377 case COND_BOOL:
378 fprintf(fp, "%s ",
379 p->p_bool_val_to_name[cur->bool - 1]);
380 break;
381 case COND_NOT:
382 fprintf(fp, "! ");
383 break;
384 case COND_OR:
385 fprintf(fp, "|| ");
386 break;
387 case COND_AND:
388 fprintf(fp, "&& ");
389 break;
390 case COND_XOR:
391 fprintf(fp, "^ ");
392 break;
393 case COND_EQ:
394 fprintf(fp, "== ");
395 break;
396 case COND_NEQ:
397 fprintf(fp, "!= ");
398 break;
399 default:
400 fprintf(fp, "error!");
401 break;
402 }
403 }
404 }
405
display_policycon(FILE * fp)406 void display_policycon(FILE * fp)
407 {
408 /* There was an attempt to implement this at one time. Look through
409 * git history to find it. */
410 fprintf(fp, "Sorry, not implemented\n");
411 }
412
display_initial_sids(policydb_t * p,FILE * fp)413 void display_initial_sids(policydb_t * p, FILE * fp)
414 {
415 ocontext_t *cur;
416 char *user, *role, *type;
417
418 fprintf(fp, "Initial SIDs:\n");
419 for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
420 user = p->p_user_val_to_name[cur->context[0].user - 1];
421 role = p->p_role_val_to_name[cur->context[0].role - 1];
422 type = p->p_type_val_to_name[cur->context[0].type - 1];
423 fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
424 cur->u.name, cur->sid[0], user, role, type);
425 }
426 #if 0
427 fprintf(fp, "Policy Initial SIDs:\n");
428 for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
429 user = p->p_user_val_to_name[cur->context[0].user - 1];
430 role = p->p_role_val_to_name[cur->context[0].role - 1];
431 type = p->p_type_val_to_name[cur->context[0].type - 1];
432 fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
433 cur->u.name, cur->sid[0], user, role, type);
434 }
435 #endif
436 }
437
display_class_set(ebitmap_t * classes,policydb_t * p,FILE * fp)438 void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
439 {
440 unsigned int i, num = 0;
441
442 for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
443 if (!ebitmap_get_bit(classes, i))
444 continue;
445 num++;
446 if (num > 1) {
447 fprintf(fp, "{");
448 break;
449 }
450 }
451
452 for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
453 if (ebitmap_get_bit(classes, i))
454 display_id(p, fp, SYM_CLASSES, i, "");
455 }
456
457 if (num > 1)
458 fprintf(fp, " }");
459 }
460
display_role_trans(role_trans_rule_t * tr,policydb_t * p,FILE * fp)461 void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
462 {
463 for (; tr; tr = tr->next) {
464 fprintf(fp, "role transition ");
465 display_mod_role_set(&tr->roles, p, fp);
466 display_type_set(&tr->types, 0, p, fp);
467 fprintf(fp, " :");
468 display_class_set(&tr->classes, p, fp);
469 display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
470 fprintf(fp, "\n");
471 }
472 }
473
display_role_allow(role_allow_rule_t * ra,policydb_t * p,FILE * fp)474 void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
475 {
476 for (; ra; ra = ra->next) {
477 fprintf(fp, "role allow ");
478 display_mod_role_set(&ra->roles, p, fp);
479 display_mod_role_set(&ra->new_roles, p, fp);
480 fprintf(fp, "\n");
481 }
482 }
483
display_filename_trans(filename_trans_rule_t * tr,policydb_t * p,FILE * fp)484 static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
485 {
486 fprintf(fp, "filename transition");
487 for (; tr; tr = tr->next) {
488 display_type_set(&tr->stypes, 0, p, fp);
489 display_type_set(&tr->ttypes, 0, p, fp);
490 display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
491 display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
492 fprintf(fp, " %s\n", tr->name);
493 }
494 }
495
role_display_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)496 int role_display_callback(hashtab_key_t key __attribute__((unused)),
497 hashtab_datum_t datum, void *data)
498 {
499 role_datum_t *role;
500 FILE *fp;
501
502 role = (role_datum_t *) datum;
503 fp = (FILE *) data;
504
505 fprintf(fp, "role:");
506 display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
507 fprintf(fp, " types: ");
508 display_type_set(&role->types, 0, &policydb, fp);
509 fprintf(fp, "\n");
510
511 return 0;
512 }
513
display_scope_index(scope_index_t * indices,policydb_t * p,FILE * out_fp)514 static int display_scope_index(scope_index_t * indices, policydb_t * p,
515 FILE * out_fp)
516 {
517 unsigned int i;
518 for (i = 0; i < SYM_NUM; i++) {
519 unsigned int any_found = 0, j;
520 fprintf(out_fp, "%s:", symbol_labels[i]);
521 for (j = ebitmap_startbit(&indices->scope[i]);
522 j < ebitmap_length(&indices->scope[i]); j++) {
523 if (ebitmap_get_bit(&indices->scope[i], j)) {
524 any_found = 1;
525 fprintf(out_fp, " %s",
526 p->sym_val_to_name[i][j]);
527 if (i == SYM_CLASSES) {
528 if (j < indices->class_perms_len) {
529 render_access_bitmap(indices->
530 class_perms_map
531 + j, j + 1,
532 p, out_fp);
533 } else {
534 fprintf(out_fp,
535 "<no perms known>");
536 }
537 }
538 }
539 }
540 if (!any_found) {
541 fprintf(out_fp, " <empty>");
542 }
543 fprintf(out_fp, "\n");
544 }
545 return 0;
546 }
547
548 #if 0
549 int display_cond_expressions(policydb_t * p, FILE * fp)
550 {
551 cond_node_t *cur;
552 cond_av_list_t *av_cur;
553 for (cur = p->cond_list; cur != NULL; cur = cur->next) {
554 fprintf(fp, "expression: ");
555 display_expr(p, cur->expr, fp);
556 fprintf(fp, "current state: %d\n", cur->cur_state);
557 fprintf(fp, "True list:\n");
558 for (av_cur = cur->true_list; av_cur != NULL;
559 av_cur = av_cur->next) {
560 fprintf(fp, "\t");
561 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
562 RENDER_CONDITIONAL, p, fp);
563 }
564 fprintf(fp, "False list:\n");
565 for (av_cur = cur->false_list; av_cur != NULL;
566 av_cur = av_cur->next) {
567 fprintf(fp, "\t");
568 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
569 RENDER_CONDITIONAL, p, fp);
570 }
571 }
572 return 0;
573 }
574
575 int change_bool(char *name, int state, policydb_t * p, FILE * fp)
576 {
577 cond_bool_datum_t *bool;
578
579 bool = hashtab_search(p->p_bools.table, name);
580 if (bool == NULL) {
581 fprintf(fp, "Could not find bool %s\n", name);
582 return -1;
583 }
584 bool->state = state;
585 evaluate_conds(p);
586 return 0;
587 }
588 #endif
589
display_avdecl(avrule_decl_t * decl,int field,policydb_t * policy,FILE * out_fp)590 int display_avdecl(avrule_decl_t * decl, int field,
591 policydb_t * policy, FILE * out_fp)
592 {
593 fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
594 (decl->enabled ? " [enabled]" : ""));
595 switch (field) {
596 case DISPLAY_AVBLOCK_COND_AVTAB:{
597 cond_list_t *cond = decl->cond_list;
598 avrule_t *avrule;
599 while (cond) {
600 fprintf(out_fp, "expression: ");
601 display_expr(&policydb, cond->expr, out_fp);
602 fprintf(out_fp, "current state: %d\n",
603 cond->cur_state);
604 fprintf(out_fp, "True list:\n");
605 avrule = cond->avtrue_list;
606 while (avrule) {
607 display_avrule(avrule,
608 &policydb, out_fp);
609 avrule = avrule->next;
610 }
611 fprintf(out_fp, "False list:\n");
612 avrule = cond->avfalse_list;
613 while (avrule) {
614 display_avrule(avrule,
615 &policydb, out_fp);
616 avrule = avrule->next;
617 }
618 cond = cond->next;
619 }
620 break;
621 }
622 case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
623 avrule_t *avrule = decl->avrules;
624 if (avrule == NULL) {
625 fprintf(out_fp, " <empty>\n");
626 }
627 while (avrule != NULL) {
628 if (display_avrule(avrule, policy, out_fp))
629 return -1;
630 avrule = avrule->next;
631 }
632 break;
633 }
634 case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{ /* role_type_node */
635 break;
636 }
637 case DISPLAY_AVBLOCK_ROLE_TRANS:{
638 display_role_trans(decl->role_tr_rules, policy, out_fp);
639 break;
640 }
641 case DISPLAY_AVBLOCK_ROLE_ALLOW:{
642 display_role_allow(decl->role_allow_rules, policy,
643 out_fp);
644 break;
645 }
646 case DISPLAY_AVBLOCK_REQUIRES:{
647 if (display_scope_index
648 (&decl->required, policy, out_fp)) {
649 return -1;
650 }
651 break;
652 }
653 case DISPLAY_AVBLOCK_DECLARES:{
654 if (display_scope_index
655 (&decl->declared, policy, out_fp)) {
656 return -1;
657 }
658 break;
659 }
660 case DISPLAY_AVBLOCK_FILENAME_TRANS:
661 display_filename_trans(decl->filename_trans_rules, policy,
662 out_fp);
663 break;
664 default:{
665 assert(0);
666 }
667 }
668 return 0; /* should never get here */
669 }
670
display_avblock(int field,policydb_t * policy,FILE * out_fp)671 int display_avblock(int field, policydb_t * policy,
672 FILE * out_fp)
673 {
674 avrule_block_t *block = policydb.global;
675 while (block != NULL) {
676 fprintf(out_fp, "--- begin avrule block ---\n");
677 avrule_decl_t *decl = block->branch_list;
678 while (decl != NULL) {
679 if (display_avdecl(decl, field, policy, out_fp)) {
680 return -1;
681 }
682 decl = decl->next;
683 }
684 block = block->next;
685 }
686 return 0;
687 }
688
display_handle_unknown(policydb_t * p,FILE * out_fp)689 int display_handle_unknown(policydb_t * p, FILE * out_fp)
690 {
691 if (p->handle_unknown == ALLOW_UNKNOWN)
692 fprintf(out_fp, "Allow unknown classes and perms\n");
693 else if (p->handle_unknown == DENY_UNKNOWN)
694 fprintf(out_fp, "Deny unknown classes and perms\n");
695 else if (p->handle_unknown == REJECT_UNKNOWN)
696 fprintf(out_fp, "Reject unknown classes and perms\n");
697 return 0;
698 }
699
read_policy(char * filename,policydb_t * policy)700 static int read_policy(char *filename, policydb_t * policy)
701 {
702 FILE *in_fp;
703 struct policy_file f;
704 int retval;
705 uint32_t buf[1];
706
707 if ((in_fp = fopen(filename, "rb")) == NULL) {
708 fprintf(stderr, "Can't open '%s': %s\n",
709 filename, strerror(errno));
710 exit(1);
711 }
712 policy_file_init(&f);
713 f.type = PF_USE_STDIO;
714 f.fp = in_fp;
715
716 /* peek at the first byte. if they are indicative of a
717 package use the package reader, otherwise use the normal
718 policy reader */
719 if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
720 fprintf(stderr, "Could not read from policy.\n");
721 exit(1);
722 }
723 rewind(in_fp);
724 if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
725 sepol_module_package_t *package;
726 if (sepol_module_package_create(&package)) {
727 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
728 exit(1);
729 }
730 package->policy = (sepol_policydb_t *) policy;
731 package->file_contexts = NULL;
732 retval =
733 sepol_module_package_read(package,
734 (sepol_policy_file_t *) & f, 1);
735 free(package->file_contexts);
736 } else {
737 if (policydb_init(policy)) {
738 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
739 exit(1);
740 }
741 retval = policydb_read(policy, &f, 1);
742 }
743 fclose(in_fp);
744 return retval;
745 }
746
link_module(policydb_t * base,FILE * out_fp)747 static void link_module(policydb_t * base, FILE * out_fp)
748 {
749 char module_name[80] = { 0 };
750 int ret;
751 policydb_t module, *mods = &module;
752
753 if (base->policy_type != POLICY_BASE) {
754 printf("Can only link if initial file was a base policy.\n");
755 return;
756 }
757 printf("\nModule filename: ");
758 if (fgets(module_name, sizeof(module_name), stdin) == NULL) {
759 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
760 strerror(errno));
761 exit(1);
762 }
763
764 module_name[strlen(module_name) - 1] = '\0'; /* remove LF */
765 if (module_name[0] == '\0') {
766 return;
767 }
768
769 /* read the binary policy */
770 fprintf(out_fp, "Reading module...\n");
771 if (read_policy(module_name, mods)) {
772 fprintf(stderr,
773 "%s: error(s) encountered while loading policy\n",
774 module_name);
775 exit(1);
776 }
777 if (module.policy_type != POLICY_MOD) {
778 fprintf(stderr, "This file is not a loadable policy module.\n");
779 exit(1);
780 }
781 if (policydb_index_classes(&module) ||
782 policydb_index_others(NULL, &module, 0)) {
783 fprintf(stderr, "Could not index module.\n");
784 exit(1);
785 }
786 ret = link_modules(NULL, base, &mods, 1, 0);
787 if (ret != 0) {
788 printf("Link failed (error %d)\n", ret);
789 printf("(You will probably need to restart dismod.)\n");
790 }
791 policydb_destroy(&module);
792 return;
793 }
794
display_policycaps(policydb_t * p,FILE * fp)795 static void display_policycaps(policydb_t * p, FILE * fp)
796 {
797 ebitmap_node_t *node;
798 const char *capname;
799 char buf[64];
800 unsigned int i;
801
802 fprintf(fp, "policy capabilities:\n");
803 ebitmap_for_each_bit(&p->policycaps, node, i) {
804 if (ebitmap_node_get_bit(node, i)) {
805 capname = sepol_polcap_getname(i);
806 if (capname == NULL) {
807 snprintf(buf, sizeof(buf), "unknown (%d)", i);
808 capname = buf;
809 }
810 fprintf(fp, "\t%s\n", capname);
811 }
812 }
813 }
814
menu(void)815 int menu(void)
816 {
817 printf("\nSelect a command:\n");
818 printf("1) display unconditional AVTAB\n");
819 printf("2) display conditional AVTAB\n");
820 printf("3) display users\n");
821 printf("4) display bools\n");
822 printf("5) display roles\n");
823 printf("6) display types, attributes, and aliases\n");
824 printf("7) display role transitions\n");
825 printf("8) display role allows\n");
826 printf("9) Display policycon\n");
827 printf("0) Display initial SIDs\n");
828 printf("\n");
829 printf("a) Display avrule requirements\n");
830 printf("b) Display avrule declarations\n");
831 printf("c) Display policy capabilities\n");
832 printf("l) Link in a module\n");
833 printf("u) Display the unknown handling setting\n");
834 printf("F) Display filename_trans rules\n");
835 printf("\n");
836 printf("f) set output file\n");
837 printf("m) display menu\n");
838 printf("q) quit\n");
839 return 0;
840 }
841
main(int argc,char ** argv)842 int main(int argc, char **argv)
843 {
844 FILE *out_fp = stdout;
845 char ans[81], OutfileName[121];
846
847 if (argc != 2)
848 usage(argv[0]);
849
850 /* read the binary policy */
851 fprintf(out_fp, "Reading policy...\n");
852 if (policydb_init(&policydb)) {
853 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
854 exit(1);
855 }
856 if (read_policy(argv[1], &policydb)) {
857 fprintf(stderr,
858 "%s: error(s) encountered while loading policy\n",
859 argv[0]);
860 exit(1);
861 }
862
863 if (policydb.policy_type != POLICY_BASE &&
864 policydb.policy_type != POLICY_MOD) {
865 fprintf(stderr,
866 "This file is neither a base nor loadable policy module.\n");
867 exit(1);
868 }
869
870 if (policydb_index_classes(&policydb)) {
871 fprintf(stderr, "Error indexing classes\n");
872 exit(1);
873 }
874
875 if (policydb_index_others(NULL, &policydb, 1)) {
876 fprintf(stderr, "Error indexing others\n");
877 exit(1);
878 }
879
880 if (policydb.policy_type == POLICY_BASE) {
881 printf("Binary base policy file loaded.\n\n");
882 } else {
883 printf("Binary policy module file loaded.\n");
884 printf("Module name: %s\n", policydb.name);
885 printf("Module version: %s\n", policydb.version);
886 printf("\n");
887 }
888
889 menu();
890 for (;;) {
891 printf("\nCommand (\'m\' for menu): ");
892 if (fgets(ans, sizeof(ans), stdin) == NULL) {
893 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
894 strerror(errno));
895 continue;
896 }
897
898 switch (ans[0]) {
899
900 case '1':
901 fprintf(out_fp, "unconditional avtab:\n");
902 display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
903 &policydb, out_fp);
904 break;
905 case '2':
906 fprintf(out_fp, "conditional avtab:\n");
907 display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
908 &policydb, out_fp);
909 break;
910 case '3':
911 display_users(&policydb, out_fp);
912 break;
913 case '4':
914 display_bools(&policydb, out_fp);
915 break;
916 case '5':
917 if (hashtab_map
918 (policydb.p_roles.table, role_display_callback,
919 out_fp))
920 exit(1);
921 break;
922 case '6':
923 if (display_types(&policydb, out_fp)) {
924 fprintf(stderr, "Error displaying types\n");
925 exit(1);
926 }
927 break;
928 case '7':
929 fprintf(out_fp, "role transitions:\n");
930 display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
931 &policydb, out_fp);
932 break;
933 case '8':
934 fprintf(out_fp, "role allows:\n");
935 display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
936 &policydb, out_fp);
937 break;
938 case '9':
939 display_policycon(out_fp);
940 break;
941 case '0':
942 display_initial_sids(&policydb, out_fp);
943 break;
944 case 'a':
945 fprintf(out_fp, "avrule block requirements:\n");
946 display_avblock(DISPLAY_AVBLOCK_REQUIRES,
947 &policydb, out_fp);
948 break;
949 case 'b':
950 fprintf(out_fp, "avrule block declarations:\n");
951 display_avblock(DISPLAY_AVBLOCK_DECLARES,
952 &policydb, out_fp);
953 break;
954 case 'c':
955 display_policycaps(&policydb, out_fp);
956 break;
957 case 'u':
958 case 'U':
959 display_handle_unknown(&policydb, out_fp);
960 break;
961 case 'f':
962 printf
963 ("\nFilename for output (<CR> for screen output): ");
964 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
965 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
966 strerror(errno));
967 break;
968 }
969 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
970 if (strlen(OutfileName) == 0)
971 out_fp = stdout;
972 else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
973 fprintf(stderr, "Cannot open output file %s\n",
974 OutfileName);
975 out_fp = stdout;
976 }
977 if (out_fp != stdout)
978 printf("\nOutput to file: %s\n", OutfileName);
979 break;
980 case 'F':
981 fprintf(out_fp, "filename_trans rules:\n");
982 display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
983 &policydb, out_fp);
984 break;
985 case 'l':
986 link_module(&policydb, out_fp);
987 break;
988 case 'q':
989 policydb_destroy(&policydb);
990 exit(0);
991 break;
992 case 'm':
993 menu();
994 break;
995 default:
996 printf("\nInvalid choice\n");
997 menu();
998 break;
999
1000 }
1001 }
1002 exit(EXIT_SUCCESS);
1003 }
1004