2
/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
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.
13
* Test program to the contents of a binary policy in text
16
* dismod binary_mod_file
22
#include <sys/types.h>
30
#include <sepol/policydb.h>
31
#include <sepol/services.h>
32
#include <sepol/conditional.h>
33
#include <sepol/flask.h>
34
#include <sepol/link.h>
35
#include <sepol/module.h>
40
#if __BYTE_ORDER == __LITTLE_ENDIAN
41
#define le32_to_cpu(x) (x)
43
#define le32_to_cpu(x) bswap_32(x)
46
static policydb_t policydb;
47
extern unsigned int ss_initialized;
49
int policyvers = MOD_POLICYDB_VERSION_BASE;
51
static const char *symbol_labels[9] = {
53
"classes", "roles ", "types ", "users ", "bools ",
54
"levels ", "cats ", "attribs"
57
void usage(char *progname)
59
printf("usage: %s binary_pol_file\n\n", progname);
63
/* borrowed from checkpolicy.c */
64
static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
67
perm_datum_t *perdatum;
69
valuep = (unsigned int *) p;
70
perdatum = (perm_datum_t *) datum;
72
if (*valuep == perdatum->value)
78
static void render_access_mask(uint32_t mask, uint32_t class, policydb_t *p, FILE *fp)
81
class_datum_t *cladatum;
83
cladatum = p->class_val_to_struct[class - 1];
85
for (i = 1; i <= sizeof(mask) * 8; i++) {
86
if (mask & (1 << (i - 1))) {
87
perm = (char *) hashtab_map(cladatum->permissions.table,
90
if (!perm && cladatum->comdatum) {
91
perm = (char *) hashtab_map(cladatum->comdatum->permissions.table,
95
fprintf(fp, " %s", perm);
101
static void render_access_bitmap(ebitmap_t *map, uint32_t class, policydb_t *p, FILE *fp)
105
class_datum_t *cladatum;
107
cladatum = p->class_val_to_struct[class - 1];
109
for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
110
if (ebitmap_get_bit(map, i)) {
112
perm = (char *) hashtab_map(cladatum->permissions.table,
113
find_perm, &perm_value);
115
if (!perm && cladatum->comdatum) {
116
perm = (char *) hashtab_map(cladatum->comdatum->permissions.table,
117
find_perm, &perm_value);
120
fprintf(fp, " %s", perm);
126
static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type, uint32_t symbol_value, char *prefix) {
127
char *id = p->sym_val_to_name[symbol_type][symbol_value];
128
scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
129
assert(scope != NULL);
130
if (scope->scope == SCOPE_REQ) {
131
fprintf(fp, " [%s%s]", prefix, id);
134
fprintf(fp, " %s%s", prefix, id);
138
int display_type_set(type_set_t *set, uint32_t flags, policydb_t *policy, FILE *fp)
142
if (set->flags & TYPE_STAR) {
145
} else if (set->flags & TYPE_COMP) {
150
if (flags & RULE_SELF) {
154
for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); i++) {
155
if (!ebitmap_get_bit(&set->types, i))
162
if (num_types <= 1) {
163
for (i = ebitmap_startbit(&set->negset); i < ebitmap_length(&set->negset); i++) {
164
if (!ebitmap_get_bit(&set->negset, i))
175
for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); i++) {
176
if (!ebitmap_get_bit(&set->types, i))
178
display_id(policy, fp, SYM_TYPES, i, "");
182
for (i = ebitmap_startbit(&set->negset); i < ebitmap_length(&set->negset); i++) {
183
if (!ebitmap_get_bit(&set->negset, i))
185
display_id(policy, fp, SYM_TYPES, i, "-");
189
if (flags & RULE_SELF) {
190
fprintf(fp, " self");
201
int display_mod_role_set(role_set_t *roles, policydb_t *p, FILE *fp)
205
if (roles->flags & ROLE_STAR) {
208
} else if (roles->flags & ROLE_COMP) {
212
for (i = ebitmap_startbit(&roles->roles); i < ebitmap_length(&roles->roles); i++) {
213
if (!ebitmap_get_bit(&roles->roles, i))
222
for (i = ebitmap_startbit(&roles->roles); i < ebitmap_length(&roles->roles); i++) {
223
if (ebitmap_get_bit(&roles->roles, i))
224
display_id(p, fp, SYM_ROLES, i, "");
235
/* 'what' values for this function */
236
#define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */
237
#define RENDER_ENABLED 0x0002
238
#define RENDER_DISABLED 0x0004
239
#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED)
241
int display_avrule(avrule_t *avrule, uint32_t what, policydb_t *policy, FILE *fp)
243
class_perm_node_t *cur;
246
if (avrule == NULL) {
247
fprintf(fp, " <empty>\n");
250
if( avrule->specified & AVRULE_AV) {
251
if(avrule->specified & AVRULE_ALLOWED) {
252
fprintf(fp, " allow");
254
if(avrule->specified & AVRULE_AUDITALLOW) {
255
fprintf(fp, " auditallow ");
257
if(avrule->specified & AVRULE_DONTAUDIT) {
258
fprintf(fp, " dontaudit");
260
} else if( avrule->specified & AVRULE_TYPE){
261
if(avrule->specified & AVRULE_TRANSITION) {
262
fprintf(fp, " type_transition");
264
if(avrule->specified & AVRULE_MEMBER) {
265
fprintf(fp, " type_member");
267
if(avrule->specified & AVRULE_CHANGE) {
268
fprintf(fp, " type_change");
270
} else if (avrule->specified & AVRULE_NEVERALLOW) {
271
fprintf(fp, " neverallow");
273
fprintf(fp, " ERROR: no valid rule type specified\n");
277
if (display_type_set(&avrule->stypes, 0, policy, fp))
280
if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
298
display_id(policy, fp, SYM_CLASSES, cur->class - 1, "");
306
if( avrule->specified & AVRULE_AV) {
307
render_access_mask(avrule->perms->data, avrule->perms->class, policy, fp);
308
} else if ( avrule->specified & AVRULE_TYPE) {
309
display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
317
int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
321
int i, first_attrib = 1;
323
type = (type_datum_t *)datum;
327
display_id(&policydb, fp, SYM_TYPES, type->value - 1, "");
328
fprintf(fp, " [%d]: ", type->value);
331
/* as that aliases have no value of their own and that
332
* they can never be required by a module, use this
333
* alternative way of displaying a name */
334
fprintf(fp, " %s [%d]: ", (char *) key, type->value);
337
fprintf(fp, "attribute for types");
338
for (i = ebitmap_startbit(&type->types); i < ebitmap_length(&type->types); i++) {
339
if (!ebitmap_get_bit(&type->types, i))
347
display_id(&policydb, fp, SYM_TYPES, i, "");
349
} else if (type->primary) {
352
fprintf(fp, "alias for type");
353
display_id(&policydb, fp, SYM_TYPES, type->value - 1, "");
360
int display_types(policydb_t *p, FILE *fp)
362
if (hashtab_map(p->p_types.table, display_type_callback, fp))
367
int display_users(policydb_t *p, FILE *fp)
371
for (i = 0; i < p->p_users.nprim; i++) {
372
display_id(p, fp, SYM_USERS, i, "");
374
bitmap = &(p->user_val_to_struct[i]->roles.roles);
375
for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap); j++) {
376
if (ebitmap_get_bit (bitmap, j)) {
377
display_id(p, fp, SYM_ROLES, j, "");
385
int display_bools(policydb_t *p, FILE *fp)
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);
396
void display_expr(policydb_t *p, cond_expr_t *exp, FILE *fp)
400
for (cur = exp; cur != NULL; cur = cur->next) {
401
switch (cur->expr_type) {
403
fprintf(fp, "%s ", p->p_bool_val_to_name[cur->bool - 1]);
424
fprintf(fp, "error!");
430
void display_policycon(policydb_t *p, FILE *fp)
437
for (i = 0; i < POLICYCON_NUM; i++) {
438
fprintf(fp, "%s:", symbol_labels[i]);
439
for(cur = p->policycon[i].head; cur != NULL; cur = cur->next) {
440
if (*(cur->u.name) == '\0') {
446
fprintf(fp, "\n%16s - %s:%s:%s", name, p->p_user_val_to_name[cur->context[0].user -1],
447
p->p_role_val_to_name[cur->context[0].role -1],
448
p->p_type_val_to_name[cur->context[0].type -1]);
455
void display_initial_sids(policydb_t *p, FILE *fp)
458
char *user, *role, *type;
460
fprintf (fp, "Initial SIDs:\n");
461
for (cur = p->ocontexts [OCON_ISID]; cur != NULL; cur = cur->next) {
462
user = p->p_user_val_to_name [cur->context [0].user - 1];
463
role = p->p_role_val_to_name [cur->context [0].role - 1];
464
type = p->p_type_val_to_name [cur->context [0].type - 1];
465
fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
466
cur->u.name, cur->sid [0], user, role, type);
469
fprintf (fp, "Policy Initial SIDs:\n");
470
for (cur = p->ocontexts [OCON_POLICYISID]; cur != NULL; cur = cur->next) {
471
user = p->p_user_val_to_name [cur->context [0].user - 1];
472
role = p->p_role_val_to_name [cur->context [0].role - 1];
473
type = p->p_type_val_to_name [cur->context [0].type - 1];
474
fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
475
cur->u.name, cur->sid [0], user, role, type);
480
void display_role_trans(role_trans_rule_t *tr, policydb_t *p, FILE *fp)
482
for (; tr; tr = tr->next) {
483
fprintf(fp, "role transition ");
484
display_mod_role_set(&tr->roles, p, fp);
485
display_type_set(&tr->types, 0, p, fp);
486
display_id(p, fp, SYM_ROLES, tr->new_role - 1, " :");
491
void display_role_allow(role_allow_rule_t *ra, policydb_t *p, FILE *fp)
493
for (; ra; ra = ra->next) {
494
fprintf(fp, "role allow ");
495
display_mod_role_set(&ra->roles, p, fp);
496
display_mod_role_set(&ra->new_roles, p, fp);
501
int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
508
role = (role_datum_t*)datum;
511
fprintf(fp, "role:");
512
display_id(&policydb, fp, SYM_ROLES, role->value - 1, "");
513
fprintf(fp, " types: ");
514
display_type_set(&role->types, 0, &policydb, fp);
521
static int display_scope_index(scope_index_t *indices, policydb_t *p, FILE *out_fp) {
523
for (i = 0; i < SYM_NUM; i++) {
524
int any_found = 0, j;
525
fprintf(out_fp, "%s:", symbol_labels[i]);
526
for (j = ebitmap_startbit(&indices->scope[i]);
527
j < ebitmap_length(&indices->scope[i]);
529
if (ebitmap_get_bit(&indices->scope[i], j)) {
531
fprintf(out_fp, " %s", p->sym_val_to_name[i][j]);
532
if (i == SYM_CLASSES) {
533
if (j < indices->class_perms_len) {
534
render_access_bitmap(indices->class_perms_map + j, j + 1, p, out_fp);
537
fprintf(out_fp, "<no perms known>");
543
fprintf(out_fp, " <empty>");
545
fprintf(out_fp, "\n");
552
int display_cond_expressions(policydb_t *p, FILE *fp)
555
cond_av_list_t *av_cur;
556
for (cur = p->cond_list; cur != NULL; cur = cur->next) {
557
fprintf(fp, "expression: ");
558
display_expr(p, cur->expr, fp);
559
fprintf(fp, "current state: %d\n", cur->cur_state);
560
fprintf(fp, "True list:\n");
561
for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) {
563
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
564
RENDER_CONDITIONAL, p, fp);
566
fprintf(fp, "False list:\n");
567
for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) {
569
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
570
RENDER_CONDITIONAL, p, fp);
576
int change_bool(char *name, int state, policydb_t *p, FILE *fp)
578
cond_bool_datum_t *bool;
580
bool = hashtab_search(p->p_bools.table, name);
582
fprintf(fp, "Could not find bool %s\n", name);
591
int display_avdecl(avrule_decl_t *decl, int field, uint32_t what, policydb_t *policy, FILE *out_fp) {
592
fprintf(out_fp, "decl %u:%s\n", decl->decl_id, (decl->enabled ? " [enabled]" : ""));
595
cond_list_t *cond = decl->cond_list;
598
fprintf(out_fp, "expression: ");
599
display_expr(&policydb, cond->expr, out_fp);
600
fprintf(out_fp, "current state: %d\n", cond->cur_state);
601
fprintf(out_fp, "True list:\n");
602
avrule = cond->avtrue_list;
604
display_avrule(avrule, RENDER_UNCONDITIONAL, &policydb, out_fp);
605
avrule = avrule->next;
607
fprintf(out_fp, "False list:\n");
608
avrule = cond->avfalse_list;
610
display_avrule(avrule, RENDER_UNCONDITIONAL, &policydb, out_fp);
611
avrule = avrule->next;
618
avrule_t *avrule = decl->avrules;
619
if (avrule == NULL) {
620
fprintf(out_fp, " <empty>\n");
622
while (avrule != NULL) {
623
if (display_avrule(avrule, what, policy, out_fp)) {
626
avrule = avrule->next;
630
case 2: { /* role_type_node */
634
display_role_trans(decl->role_tr_rules, policy, out_fp);
638
display_role_allow(decl->role_allow_rules, policy, out_fp);
642
if (display_scope_index(&decl->required, policy, out_fp)) {
648
if (display_scope_index(&decl->declared, policy, out_fp)) {
657
return 0; /* should never get here */
660
int display_avblock(int field, uint32_t what, policydb_t *policy, FILE *out_fp) {
661
avrule_block_t *block = policydb.global;
662
while (block != NULL) {
663
fprintf(out_fp, "--- begin avrule block ---\n");
664
avrule_decl_t *decl = block->branch_list;
665
while (decl != NULL) {
666
if (display_avdecl(decl, field, what, policy, out_fp)) {
676
static int read_policy(char *filename, policydb_t *policy) {
678
struct policy_file f;
682
if ((in_fp = fopen(filename, "rb")) == NULL) {
683
fprintf(stderr, "Can't open '%s': %s\n",
684
filename, strerror(errno));
687
f.type = PF_USE_STDIO;
690
/* peek at the first byte. if they are indicative of a
691
package use the package reader, otherwise use the normal
693
if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
694
fprintf(stderr, "Could not read from policy.\n");
698
if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
699
sepol_module_package_t package;
700
package.policy = policy;
701
package.file_contexts = NULL;
702
retval = sepol_module_package_read(&package, &f, 1);
703
free(package.file_contexts);
706
retval = policydb_read(policy, &f, 1);
712
static void link_module(policydb_t *base, FILE *out_fp) {
713
char module_name[80] = {0};
714
char error_buf[128] = {0};
716
policydb_t module, *mods = &module;
718
if (base->policy_type != POLICY_BASE) {
719
printf("Can only link if initial file was a base policy.\n");
722
printf("\nModule filename: ");
723
fgets(module_name, sizeof(module_name), stdin);
724
module_name[strlen(module_name)-1] = '\0'; /* remove LF */
725
if (module_name[0] == '\0') {
729
/* read the binary policy */
730
fprintf(out_fp, "Reading module...\n");
731
if (read_policy(module_name, mods)) {
732
fprintf(stderr, "%s: error(s) encountered while loading policy\n", module_name);
735
if (module.policy_type != POLICY_MOD) {
736
fprintf(stderr, "This file is not a loadable policy module.\n");
739
if (policydb_index_classes(&module) ||
740
policydb_index_others(&module, 0)) {
741
fprintf(stderr, "Could not index module.\n");
744
ret = link_modules(base, &mods, 1, 0, error_buf, sizeof(error_buf));
746
printf("Link failed (error %d): %s\n", ret, error_buf);
747
printf("(You will probably need to restart dismod.)\n");
749
policydb_destroy(&module);
754
printf("\nSelect a command:\n");
755
printf("1) display unconditional AVTAB\n");
756
printf("2) display conditional AVTAB\n");
757
printf("3) display users\n");
758
printf("4) display bools\n");
759
printf("5) display roles\n");
760
printf("6) display types, attributes, and aliases\n");
761
printf("7) display role transitions\n");
762
printf("8) display role allows\n");
763
printf("9) Display policycon\n");
764
printf("0) Display initial SIDs\n");
766
printf("a) Display avrule requirements\n");
767
printf("b) Display avrule declarations\n");
768
printf("l) Link in a module\n");
770
printf("f) set output file\n");
771
printf("m) display menu\n");
777
int main(int argc, char **argv)
779
FILE *out_fp = stdout;
780
char ans[81], OutfileName[121];
785
/* read the binary policy */
786
fprintf(out_fp, "Reading policy...\n");
787
if (read_policy(argv[1], &policydb)) {
788
fprintf(stderr, "%s: error(s) encountered while loading policy\n", argv[0]);
792
if (policydb.policy_type != POLICY_BASE &&
793
policydb.policy_type != POLICY_MOD) {
794
fprintf(stderr, "This file is neither a base nor loadable policy module.\n");
798
if (policydb_index_classes(&policydb)) {
799
fprintf(stderr, "Error indexing classes\n");
803
if (policydb_index_others(&policydb, 1)) {
804
fprintf(stderr, "Error indexing others\n");
808
if (policydb.policy_type == POLICY_BASE) {
809
printf("Binary base policy file loaded.\n\n");
812
printf("Binary policy module file loaded.\n");
813
printf("Module name: %s\n", policydb.name);
814
printf("Module version: %s\n", policydb.version);
820
printf("\nCommand (\'m\' for menu): ");
821
fgets(ans, sizeof(ans), stdin);
825
fprintf(out_fp, "unconditional avtab:\n");
826
display_avblock(1, RENDER_UNCONDITIONAL, &policydb, out_fp);
830
fprintf(out_fp, "conditional avtab:\n");
831
display_avblock(0, RENDER_UNCONDITIONAL, &policydb, out_fp);
834
display_users(&policydb, out_fp);
837
display_bools(&policydb, out_fp);
840
if (hashtab_map(policydb.p_roles.table, role_display_callback, out_fp))
844
if (display_types(&policydb, out_fp)) {
845
fprintf(stderr, "Error displaying types\n");
850
fprintf(out_fp, "role transitions:\n");
851
display_avblock(3, 0, &policydb, out_fp);
854
fprintf(out_fp, "role allows:\n");
855
display_avblock(4, 0, &policydb, out_fp);
858
display_policycon(&policydb, out_fp);
861
display_initial_sids(&policydb, out_fp);
864
fprintf(out_fp, "avrule block requirements:\n");
865
display_avblock(5, 0, &policydb, out_fp);
868
fprintf(out_fp, "avrule block declarations:\n");
869
display_avblock(6, 0, &policydb, out_fp);
872
printf("\nFilename for output (<CR> for screen output): ");
873
fgets(OutfileName, sizeof(OutfileName), stdin);
874
OutfileName[strlen(OutfileName)-1] = '\0'; /* fix_string (remove LF) */
875
if (strlen(OutfileName) == 0)
877
else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
878
fprintf (stderr, "Cannot open output file %s\n", OutfileName);
881
if (out_fp != stdout)
882
printf("\nOutput to file: %s\n", OutfileName);
885
link_module(&policydb, out_fp);
888
policydb_destroy(&policydb);
895
printf("\nInvalid choice\n");