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