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