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 static __attribute__((__noreturn__)) 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 if (avrule->specified & AVRULE_XPERMS) {
247 if (avrule->specified & AVRULE_XPERMS_ALLOWED)
248 fprintf(fp, "allowxperm ");
249 else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW)
250 fprintf(fp, "auditallowxperm ");
251 else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT)
252 fprintf(fp, "dontauditxperm ");
253 } else {
254 fprintf(fp, " ERROR: no valid rule type specified\n");
255 return -1;
256 }
257
258 if (display_type_set(&avrule->stypes, 0, policy, fp))
259 return -1;
260
261 if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
262 return -1;
263
264 fprintf(fp, " :");
265 cur = avrule->perms;
266 num_classes = 0;
267 while (cur) {
268 num_classes++;
269 if (num_classes > 1)
270 break;
271 cur = cur->next;
272 }
273
274 if (num_classes > 1)
275 fprintf(fp, " {");
276
277 cur = avrule->perms;
278 while (cur) {
279 display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
280 cur = cur->next;
281 }
282
283 if (num_classes > 1)
284 fprintf(fp, " }");
285 fprintf(fp, " ");
286
287 if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
288 render_access_mask(avrule->perms->data, avrule->perms->tclass,
289 policy, fp);
290 } else if (avrule->specified & AVRULE_TYPE) {
291 display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
292 } else if (avrule->specified & AVRULE_XPERMS) {
293 avtab_extended_perms_t xperms;
294 int i;
295
296 if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION)
297 xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
298 else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER)
299 xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
300 else {
301 fprintf(fp, " ERROR: no valid xperms specified\n");
302 return -1;
303 }
304
305 xperms.driver = avrule->xperms->driver;
306 for (i = 0; i < EXTENDED_PERMS_LEN; i++)
307 xperms.perms[i] = avrule->xperms->perms[i];
308
309 fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms));
310 }
311
312 fprintf(fp, ";\n");
313
314 return 0;
315 }
316
display_type_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)317 int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
318 {
319 type_datum_t *type;
320 FILE *fp;
321 unsigned int i, first_attrib = 1;
322
323 type = (type_datum_t *) datum;
324 fp = (FILE *) data;
325
326 if (type->primary) {
327 display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
328 fprintf(fp, " [%d]: ", type->s.value);
329 } else {
330 /* as that aliases have no value of their own and that
331 * they can never be required by a module, use this
332 * alternative way of displaying a name */
333 fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
334 }
335 if (type->flavor == TYPE_ATTRIB) {
336 fprintf(fp, "attribute for types");
337 for (i = ebitmap_startbit(&type->types);
338 i < ebitmap_length(&type->types); i++) {
339 if (!ebitmap_get_bit(&type->types, i))
340 continue;
341 if (first_attrib) {
342 first_attrib = 0;
343 } else {
344 fprintf(fp, ",");
345 }
346 display_id(&policydb, fp, SYM_TYPES, i, "");
347 }
348 } else if (type->primary) {
349 fprintf(fp, "type");
350 } else {
351 fprintf(fp, "alias for type");
352 display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
353 }
354 fprintf(fp, " flags:%x\n", type->flags);
355
356 return 0;
357 }
358
display_types(policydb_t * p,FILE * fp)359 int display_types(policydb_t * p, FILE * fp)
360 {
361 if (hashtab_map(p->p_types.table, display_type_callback, fp))
362 return -1;
363 return 0;
364 }
365
display_users(policydb_t * p,FILE * fp)366 int display_users(policydb_t * p, FILE * fp)
367 {
368 unsigned int i, j;
369 ebitmap_t *bitmap;
370 for (i = 0; i < p->p_users.nprim; i++) {
371 display_id(p, fp, SYM_USERS, i, "");
372 fprintf(fp, ":");
373 bitmap = &(p->user_val_to_struct[i]->roles.roles);
374 for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
375 j++) {
376 if (ebitmap_get_bit(bitmap, j)) {
377 display_id(p, fp, SYM_ROLES, j, "");
378 }
379 }
380 fprintf(fp, "\n");
381 }
382 return 0;
383 }
384
display_bools(policydb_t * p,FILE * fp)385 int display_bools(policydb_t * p, FILE * fp)
386 {
387 unsigned int i;
388
389 for (i = 0; i < p->p_bools.nprim; i++) {
390 display_id(p, fp, SYM_BOOLS, i, "");
391 fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
392 }
393 return 0;
394 }
395
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)396 void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
397 {
398
399 cond_expr_t *cur;
400 for (cur = exp; cur != NULL; cur = cur->next) {
401 switch (cur->expr_type) {
402 case COND_BOOL:
403 fprintf(fp, "%s ",
404 p->p_bool_val_to_name[cur->bool - 1]);
405 break;
406 case COND_NOT:
407 fprintf(fp, "! ");
408 break;
409 case COND_OR:
410 fprintf(fp, "|| ");
411 break;
412 case COND_AND:
413 fprintf(fp, "&& ");
414 break;
415 case COND_XOR:
416 fprintf(fp, "^ ");
417 break;
418 case COND_EQ:
419 fprintf(fp, "== ");
420 break;
421 case COND_NEQ:
422 fprintf(fp, "!= ");
423 break;
424 default:
425 fprintf(fp, "error!");
426 break;
427 }
428 }
429 }
430
display_policycon(FILE * fp)431 void display_policycon(FILE * fp)
432 {
433 /* There was an attempt to implement this at one time. Look through
434 * git history to find it. */
435 fprintf(fp, "Sorry, not implemented\n");
436 }
437
display_initial_sids(policydb_t * p,FILE * fp)438 void display_initial_sids(policydb_t * p, FILE * fp)
439 {
440 ocontext_t *cur;
441 char *user, *role, *type;
442
443 fprintf(fp, "Initial SIDs:\n");
444 for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
445 user = p->p_user_val_to_name[cur->context[0].user - 1];
446 role = p->p_role_val_to_name[cur->context[0].role - 1];
447 type = p->p_type_val_to_name[cur->context[0].type - 1];
448 fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
449 cur->u.name, cur->sid[0], user, role, type);
450 }
451 #if 0
452 fprintf(fp, "Policy Initial SIDs:\n");
453 for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
454 user = p->p_user_val_to_name[cur->context[0].user - 1];
455 role = p->p_role_val_to_name[cur->context[0].role - 1];
456 type = p->p_type_val_to_name[cur->context[0].type - 1];
457 fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
458 cur->u.name, cur->sid[0], user, role, type);
459 }
460 #endif
461 }
462
display_class_set(ebitmap_t * classes,policydb_t * p,FILE * fp)463 void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
464 {
465 unsigned int i, num = 0;
466
467 for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
468 if (!ebitmap_get_bit(classes, i))
469 continue;
470 num++;
471 if (num > 1) {
472 fprintf(fp, "{");
473 break;
474 }
475 }
476
477 for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
478 if (ebitmap_get_bit(classes, i))
479 display_id(p, fp, SYM_CLASSES, i, "");
480 }
481
482 if (num > 1)
483 fprintf(fp, " }");
484 }
485
display_role_trans(role_trans_rule_t * tr,policydb_t * p,FILE * fp)486 void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
487 {
488 for (; tr; tr = tr->next) {
489 fprintf(fp, "role transition ");
490 display_mod_role_set(&tr->roles, p, fp);
491 display_type_set(&tr->types, 0, p, fp);
492 fprintf(fp, " :");
493 display_class_set(&tr->classes, p, fp);
494 display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
495 fprintf(fp, "\n");
496 }
497 }
498
display_role_allow(role_allow_rule_t * ra,policydb_t * p,FILE * fp)499 void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
500 {
501 for (; ra; ra = ra->next) {
502 fprintf(fp, "role allow ");
503 display_mod_role_set(&ra->roles, p, fp);
504 display_mod_role_set(&ra->new_roles, p, fp);
505 fprintf(fp, "\n");
506 }
507 }
508
display_filename_trans(filename_trans_rule_t * tr,policydb_t * p,FILE * fp)509 static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
510 {
511 fprintf(fp, "filename transition");
512 for (; tr; tr = tr->next) {
513 display_type_set(&tr->stypes, 0, p, fp);
514 display_type_set(&tr->ttypes, 0, p, fp);
515 display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
516 display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
517 fprintf(fp, " %s\n", tr->name);
518 }
519 }
520
role_display_callback(hashtab_key_t key,hashtab_datum_t datum,void * data)521 int role_display_callback(hashtab_key_t key __attribute__((unused)),
522 hashtab_datum_t datum, void *data)
523 {
524 role_datum_t *role;
525 FILE *fp;
526
527 role = (role_datum_t *) datum;
528 fp = (FILE *) data;
529
530 fprintf(fp, "role:");
531 display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
532 fprintf(fp, " types: ");
533 display_type_set(&role->types, 0, &policydb, fp);
534 fprintf(fp, "\n");
535
536 return 0;
537 }
538
display_scope_index(scope_index_t * indices,policydb_t * p,FILE * out_fp)539 static int display_scope_index(scope_index_t * indices, policydb_t * p,
540 FILE * out_fp)
541 {
542 unsigned int i;
543 for (i = 0; i < SYM_NUM; i++) {
544 unsigned int any_found = 0, j;
545 fprintf(out_fp, "%s:", symbol_labels[i]);
546 for (j = ebitmap_startbit(&indices->scope[i]);
547 j < ebitmap_length(&indices->scope[i]); j++) {
548 if (ebitmap_get_bit(&indices->scope[i], j)) {
549 any_found = 1;
550 fprintf(out_fp, " %s",
551 p->sym_val_to_name[i][j]);
552 if (i == SYM_CLASSES) {
553 if (j < indices->class_perms_len) {
554 render_access_bitmap(indices->
555 class_perms_map
556 + j, j + 1,
557 p, out_fp);
558 } else {
559 fprintf(out_fp,
560 "<no perms known>");
561 }
562 }
563 }
564 }
565 if (!any_found) {
566 fprintf(out_fp, " <empty>");
567 }
568 fprintf(out_fp, "\n");
569 }
570 return 0;
571 }
572
573 #if 0
574 int display_cond_expressions(policydb_t * p, FILE * fp)
575 {
576 cond_node_t *cur;
577 cond_av_list_t *av_cur;
578 for (cur = p->cond_list; cur != NULL; cur = cur->next) {
579 fprintf(fp, "expression: ");
580 display_expr(p, cur->expr, fp);
581 fprintf(fp, "current state: %d\n", cur->cur_state);
582 fprintf(fp, "True list:\n");
583 for (av_cur = cur->true_list; av_cur != NULL;
584 av_cur = av_cur->next) {
585 fprintf(fp, "\t");
586 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
587 RENDER_CONDITIONAL, p, fp);
588 }
589 fprintf(fp, "False list:\n");
590 for (av_cur = cur->false_list; av_cur != NULL;
591 av_cur = av_cur->next) {
592 fprintf(fp, "\t");
593 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
594 RENDER_CONDITIONAL, p, fp);
595 }
596 }
597 return 0;
598 }
599
600 int change_bool(char *name, int state, policydb_t * p, FILE * fp)
601 {
602 cond_bool_datum_t *bool;
603
604 bool = hashtab_search(p->p_bools.table, name);
605 if (bool == NULL) {
606 fprintf(fp, "Could not find bool %s\n", name);
607 return -1;
608 }
609 bool->state = state;
610 evaluate_conds(p);
611 return 0;
612 }
613 #endif
614
display_avdecl(avrule_decl_t * decl,int field,policydb_t * policy,FILE * out_fp)615 int display_avdecl(avrule_decl_t * decl, int field,
616 policydb_t * policy, FILE * out_fp)
617 {
618 fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
619 (decl->enabled ? " [enabled]" : ""));
620 switch (field) {
621 case DISPLAY_AVBLOCK_COND_AVTAB:{
622 cond_list_t *cond = decl->cond_list;
623 avrule_t *avrule;
624 while (cond) {
625 fprintf(out_fp, "expression: ");
626 display_expr(&policydb, cond->expr, out_fp);
627 fprintf(out_fp, "current state: %d\n",
628 cond->cur_state);
629 fprintf(out_fp, "True list:\n");
630 avrule = cond->avtrue_list;
631 while (avrule) {
632 display_avrule(avrule,
633 &policydb, out_fp);
634 avrule = avrule->next;
635 }
636 fprintf(out_fp, "False list:\n");
637 avrule = cond->avfalse_list;
638 while (avrule) {
639 display_avrule(avrule,
640 &policydb, out_fp);
641 avrule = avrule->next;
642 }
643 cond = cond->next;
644 }
645 break;
646 }
647 case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
648 avrule_t *avrule = decl->avrules;
649 if (avrule == NULL) {
650 fprintf(out_fp, " <empty>\n");
651 }
652 while (avrule != NULL) {
653 if (display_avrule(avrule, policy, out_fp))
654 return -1;
655 avrule = avrule->next;
656 }
657 break;
658 }
659 case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{ /* role_type_node */
660 break;
661 }
662 case DISPLAY_AVBLOCK_ROLE_TRANS:{
663 display_role_trans(decl->role_tr_rules, policy, out_fp);
664 break;
665 }
666 case DISPLAY_AVBLOCK_ROLE_ALLOW:{
667 display_role_allow(decl->role_allow_rules, policy,
668 out_fp);
669 break;
670 }
671 case DISPLAY_AVBLOCK_REQUIRES:{
672 if (display_scope_index
673 (&decl->required, policy, out_fp)) {
674 return -1;
675 }
676 break;
677 }
678 case DISPLAY_AVBLOCK_DECLARES:{
679 if (display_scope_index
680 (&decl->declared, policy, out_fp)) {
681 return -1;
682 }
683 break;
684 }
685 case DISPLAY_AVBLOCK_FILENAME_TRANS:
686 display_filename_trans(decl->filename_trans_rules, policy,
687 out_fp);
688 break;
689 default:{
690 assert(0);
691 }
692 }
693 return 0; /* should never get here */
694 }
695
display_avblock(int field,policydb_t * policy,FILE * out_fp)696 int display_avblock(int field, policydb_t * policy,
697 FILE * out_fp)
698 {
699 avrule_block_t *block = policydb.global;
700 while (block != NULL) {
701 fprintf(out_fp, "--- begin avrule block ---\n");
702 avrule_decl_t *decl = block->branch_list;
703 while (decl != NULL) {
704 if (display_avdecl(decl, field, policy, out_fp)) {
705 return -1;
706 }
707 decl = decl->next;
708 }
709 block = block->next;
710 }
711 return 0;
712 }
713
display_handle_unknown(policydb_t * p,FILE * out_fp)714 int display_handle_unknown(policydb_t * p, FILE * out_fp)
715 {
716 if (p->handle_unknown == ALLOW_UNKNOWN)
717 fprintf(out_fp, "Allow unknown classes and perms\n");
718 else if (p->handle_unknown == DENY_UNKNOWN)
719 fprintf(out_fp, "Deny unknown classes and perms\n");
720 else if (p->handle_unknown == REJECT_UNKNOWN)
721 fprintf(out_fp, "Reject unknown classes and perms\n");
722 return 0;
723 }
724
read_policy(char * filename,policydb_t * policy)725 static int read_policy(char *filename, policydb_t * policy)
726 {
727 FILE *in_fp;
728 struct policy_file f;
729 int retval;
730 uint32_t buf[1];
731
732 if ((in_fp = fopen(filename, "rb")) == NULL) {
733 fprintf(stderr, "Can't open '%s': %s\n",
734 filename, strerror(errno));
735 exit(1);
736 }
737 policy_file_init(&f);
738 f.type = PF_USE_STDIO;
739 f.fp = in_fp;
740
741 /* peek at the first byte. if they are indicative of a
742 package use the package reader, otherwise use the normal
743 policy reader */
744 if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
745 fprintf(stderr, "Could not read from policy.\n");
746 exit(1);
747 }
748 rewind(in_fp);
749 if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
750 sepol_module_package_t *package;
751 if (sepol_module_package_create(&package)) {
752 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
753 exit(1);
754 }
755 package->policy = (sepol_policydb_t *) policy;
756 package->file_contexts = NULL;
757 retval =
758 sepol_module_package_read(package,
759 (sepol_policy_file_t *) & f, 1);
760 free(package->file_contexts);
761 } else {
762 if (policydb_init(policy)) {
763 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
764 exit(1);
765 }
766 retval = policydb_read(policy, &f, 1);
767 }
768 fclose(in_fp);
769 return retval;
770 }
771
link_module(policydb_t * base,FILE * out_fp)772 static void link_module(policydb_t * base, FILE * out_fp)
773 {
774 char module_name[80] = { 0 };
775 int ret;
776 policydb_t module, *mods = &module;
777
778 if (base->policy_type != POLICY_BASE) {
779 printf("Can only link if initial file was a base policy.\n");
780 return;
781 }
782 printf("\nModule filename: ");
783 if (fgets(module_name, sizeof(module_name), stdin) == NULL) {
784 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
785 strerror(errno));
786 exit(1);
787 }
788
789 module_name[strlen(module_name) - 1] = '\0'; /* remove LF */
790 if (module_name[0] == '\0') {
791 return;
792 }
793
794 /* read the binary policy */
795 fprintf(out_fp, "Reading module...\n");
796 if (read_policy(module_name, mods)) {
797 fprintf(stderr,
798 "%s: error(s) encountered while loading policy\n",
799 module_name);
800 exit(1);
801 }
802 if (module.policy_type != POLICY_MOD) {
803 fprintf(stderr, "This file is not a loadable policy module.\n");
804 exit(1);
805 }
806 if (policydb_index_classes(&module) ||
807 policydb_index_others(NULL, &module, 0)) {
808 fprintf(stderr, "Could not index module.\n");
809 exit(1);
810 }
811 ret = link_modules(NULL, base, &mods, 1, 0);
812 if (ret != 0) {
813 printf("Link failed (error %d)\n", ret);
814 printf("(You will probably need to restart dismod.)\n");
815 }
816 policydb_destroy(&module);
817 return;
818 }
819
display_policycaps(policydb_t * p,FILE * fp)820 static void display_policycaps(policydb_t * p, FILE * fp)
821 {
822 ebitmap_node_t *node;
823 const char *capname;
824 char buf[64];
825 unsigned int i;
826
827 fprintf(fp, "policy capabilities:\n");
828 ebitmap_for_each_bit(&p->policycaps, node, i) {
829 if (ebitmap_node_get_bit(node, i)) {
830 capname = sepol_polcap_getname(i);
831 if (capname == NULL) {
832 snprintf(buf, sizeof(buf), "unknown (%d)", i);
833 capname = buf;
834 }
835 fprintf(fp, "\t%s\n", capname);
836 }
837 }
838 }
839
menu(void)840 int menu(void)
841 {
842 printf("\nSelect a command:\n");
843 printf("1) display unconditional AVTAB\n");
844 printf("2) display conditional AVTAB\n");
845 printf("3) display users\n");
846 printf("4) display bools\n");
847 printf("5) display roles\n");
848 printf("6) display types, attributes, and aliases\n");
849 printf("7) display role transitions\n");
850 printf("8) display role allows\n");
851 printf("9) Display policycon\n");
852 printf("0) Display initial SIDs\n");
853 printf("\n");
854 printf("a) Display avrule requirements\n");
855 printf("b) Display avrule declarations\n");
856 printf("c) Display policy capabilities\n");
857 printf("l) Link in a module\n");
858 printf("u) Display the unknown handling setting\n");
859 printf("F) Display filename_trans rules\n");
860 printf("\n");
861 printf("f) set output file\n");
862 printf("m) display menu\n");
863 printf("q) quit\n");
864 return 0;
865 }
866
main(int argc,char ** argv)867 int main(int argc, char **argv)
868 {
869 FILE *out_fp = stdout;
870 char ans[81], OutfileName[121];
871
872 if (argc != 2)
873 usage(argv[0]);
874
875 /* read the binary policy */
876 fprintf(out_fp, "Reading policy...\n");
877 if (policydb_init(&policydb)) {
878 fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
879 exit(1);
880 }
881 if (read_policy(argv[1], &policydb)) {
882 fprintf(stderr,
883 "%s: error(s) encountered while loading policy\n",
884 argv[0]);
885 exit(1);
886 }
887
888 if (policydb.policy_type != POLICY_BASE &&
889 policydb.policy_type != POLICY_MOD) {
890 fprintf(stderr,
891 "This file is neither a base nor loadable policy module.\n");
892 exit(1);
893 }
894
895 if (policydb_index_classes(&policydb)) {
896 fprintf(stderr, "Error indexing classes\n");
897 exit(1);
898 }
899
900 if (policydb_index_others(NULL, &policydb, 1)) {
901 fprintf(stderr, "Error indexing others\n");
902 exit(1);
903 }
904
905 if (policydb.policy_type == POLICY_BASE) {
906 printf("Binary base policy file loaded.\n\n");
907 } else {
908 printf("Binary policy module file loaded.\n");
909 printf("Module name: %s\n", policydb.name);
910 printf("Module version: %s\n", policydb.version);
911 printf("\n");
912 }
913
914 menu();
915 for (;;) {
916 printf("\nCommand (\'m\' for menu): ");
917 if (fgets(ans, sizeof(ans), stdin) == NULL) {
918 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
919 strerror(errno));
920 continue;
921 }
922
923 switch (ans[0]) {
924
925 case '1':
926 fprintf(out_fp, "unconditional avtab:\n");
927 display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
928 &policydb, out_fp);
929 break;
930 case '2':
931 fprintf(out_fp, "conditional avtab:\n");
932 display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
933 &policydb, out_fp);
934 break;
935 case '3':
936 display_users(&policydb, out_fp);
937 break;
938 case '4':
939 display_bools(&policydb, out_fp);
940 break;
941 case '5':
942 if (hashtab_map
943 (policydb.p_roles.table, role_display_callback,
944 out_fp))
945 exit(1);
946 break;
947 case '6':
948 if (display_types(&policydb, out_fp)) {
949 fprintf(stderr, "Error displaying types\n");
950 exit(1);
951 }
952 break;
953 case '7':
954 fprintf(out_fp, "role transitions:\n");
955 display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
956 &policydb, out_fp);
957 break;
958 case '8':
959 fprintf(out_fp, "role allows:\n");
960 display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
961 &policydb, out_fp);
962 break;
963 case '9':
964 display_policycon(out_fp);
965 break;
966 case '0':
967 display_initial_sids(&policydb, out_fp);
968 break;
969 case 'a':
970 fprintf(out_fp, "avrule block requirements:\n");
971 display_avblock(DISPLAY_AVBLOCK_REQUIRES,
972 &policydb, out_fp);
973 break;
974 case 'b':
975 fprintf(out_fp, "avrule block declarations:\n");
976 display_avblock(DISPLAY_AVBLOCK_DECLARES,
977 &policydb, out_fp);
978 break;
979 case 'c':
980 display_policycaps(&policydb, out_fp);
981 break;
982 case 'u':
983 case 'U':
984 display_handle_unknown(&policydb, out_fp);
985 break;
986 case 'f':
987 printf
988 ("\nFilename for output (<CR> for screen output): ");
989 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
990 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
991 strerror(errno));
992 break;
993 }
994 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
995 if (strlen(OutfileName) == 0)
996 out_fp = stdout;
997 else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
998 fprintf(stderr, "Cannot open output file %s\n",
999 OutfileName);
1000 out_fp = stdout;
1001 }
1002 if (out_fp != stdout)
1003 printf("\nOutput to file: %s\n", OutfileName);
1004 break;
1005 case 'F':
1006 fprintf(out_fp, "filename_trans rules:\n");
1007 display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
1008 &policydb, out_fp);
1009 break;
1010 case 'l':
1011 link_module(&policydb, out_fp);
1012 break;
1013 case 'q':
1014 policydb_destroy(&policydb);
1015 exit(0);
1016 break;
1017 case 'm':
1018 menu();
1019 break;
1020 default:
1021 printf("\nInvalid choice\n");
1022 menu();
1023 break;
1024
1025 }
1026 }
1027 exit(EXIT_SUCCESS);
1028 }
1029