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