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