• 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 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  * displaypol.c
12  *
13  * Test program to the contents of a binary policy in text
14  * form.  This program currently only displays the
15  * avtab (including conditional avtab) rules.
16  *
17  * 	displaypol binary_pol_file
18  */
19 
20 #include <sepol/policydb/policydb.h>
21 #include <sepol/policydb/avtab.h>
22 #include <sepol/policydb/services.h>
23 #include <sepol/policydb/conditional.h>
24 #include <sepol/policydb/expand.h>
25 #include <sepol/policydb/util.h>
26 #include <sepol/policydb/polcaps.h>
27 #include <getopt.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/mman.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <fcntl.h>
37 
38 static policydb_t policydb;
39 
usage(char * progname)40 void usage(char *progname)
41 {
42 	printf("usage:  %s binary_pol_file\n\n", progname);
43 	exit(1);
44 }
45 
render_access_mask(uint32_t mask,avtab_key_t * key,policydb_t * p,FILE * fp)46 int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
47 		       FILE * fp)
48 {
49 	char *perm;
50 	fprintf(fp, "{");
51 	perm = sepol_av_to_string(p, key->target_class, mask);
52 	if (perm)
53 		fprintf(fp, "%s ", perm);
54 	fprintf(fp, "}");
55 	return 0;
56 }
57 
render_type(uint32_t type,policydb_t * p,FILE * fp)58 int render_type(uint32_t type, policydb_t * p, FILE * fp)
59 {
60 	fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
61 	return 0;
62 }
63 
render_key(avtab_key_t * key,policydb_t * p,FILE * fp)64 int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
65 {
66 	char *stype, *ttype, *tclass;
67 	stype = p->p_type_val_to_name[key->source_type - 1];
68 	ttype = p->p_type_val_to_name[key->target_type - 1];
69 	tclass = p->p_class_val_to_name[key->target_class - 1];
70 	if (stype && ttype)
71 		fprintf(fp, "%s %s : %s ", stype, ttype, tclass);
72 	else if (stype)
73 		fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass);
74 	else if (ttype)
75 		fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass);
76 	else
77 		fprintf(fp, "%u %u : %s ", key->source_type, key->target_type,
78 			tclass);
79 	return 0;
80 }
81 
82 /* 'what' values for this function */
83 #define	RENDER_UNCONDITIONAL	0x0001	/* render all regardless of enabled state */
84 #define RENDER_ENABLED		0x0002
85 #define RENDER_DISABLED		0x0004
86 #define RENDER_CONDITIONAL	(RENDER_ENABLED|RENDER_DISABLED)
87 
render_av_rule(avtab_key_t * key,avtab_datum_t * datum,uint32_t what,policydb_t * p,FILE * fp)88 int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
89 		   policydb_t * p, FILE * fp)
90 {
91 	if (!(what & RENDER_UNCONDITIONAL)) {
92 		if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED)
93 						    && !(key->
94 							 specified &
95 							 AVTAB_ENABLED))
96 						   || ((what & RENDER_DISABLED)
97 						       && (key->
98 							   specified &
99 							   AVTAB_ENABLED)))) {
100 			return 0;	/* doesn't match selection criteria */
101 		}
102 	}
103 
104 	if (!(what & RENDER_UNCONDITIONAL)) {
105 		if (key->specified & AVTAB_ENABLED)
106 			fprintf(fp, "[enabled] ");
107 		else if (!(key->specified & AVTAB_ENABLED))
108 			fprintf(fp, "[disabled] ");
109 	}
110 
111 	if (key->specified & AVTAB_AV) {
112 		if (key->specified & AVTAB_ALLOWED) {
113 			fprintf(fp, "allow ");
114 			render_key(key, p, fp);
115 			render_access_mask(datum->data, key, p, fp);
116 			fprintf(fp, ";\n");
117 		}
118 		if (key->specified & AVTAB_AUDITALLOW) {
119 			fprintf(fp, "auditallow ");
120 			render_key(key, p, fp);
121 			render_access_mask(datum->data, key, p, fp);
122 			fprintf(fp, ";\n");
123 		}
124 		if (key->specified & AVTAB_AUDITDENY) {
125 			fprintf(fp, "dontaudit ");
126 			render_key(key, p, fp);
127 			/* We inverse the mask for dontaudit since the mask is internally stored
128 			 * as a auditdeny mask */
129 			render_access_mask(~datum->data, key, p, fp);
130 			fprintf(fp, ";\n");
131 		}
132 	} else if (key->specified & AVTAB_TYPE) {
133 		if (key->specified & AVTAB_TRANSITION) {
134 			fprintf(fp, "type_transition ");
135 			render_key(key, p, fp);
136 			render_type(datum->data, p, fp);
137 			fprintf(fp, ";\n");
138 		}
139 		if (key->specified & AVTAB_MEMBER) {
140 			fprintf(fp, "type_member ");
141 			render_key(key, p, fp);
142 			render_type(datum->data, p, fp);
143 			fprintf(fp, ";\n");
144 		}
145 		if (key->specified & AVTAB_CHANGE) {
146 			fprintf(fp, "type_change ");
147 			render_key(key, p, fp);
148 			render_type(datum->data, p, fp);
149 			fprintf(fp, ";\n");
150 		}
151 	} else {
152 		fprintf(fp, "     ERROR: no valid rule type specified\n");
153 		return -1;
154 	}
155 	return 0;
156 }
157 
display_avtab(avtab_t * a,uint32_t what,policydb_t * p,FILE * fp)158 int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
159 {
160 	unsigned int i;
161 	avtab_ptr_t cur;
162 	avtab_t expa;
163 
164 	if (avtab_init(&expa))
165 		goto oom;
166 	if (expand_avtab(p, a, &expa)) {
167 		avtab_destroy(&expa);
168 		goto oom;
169 	}
170 
171 	/* hmm...should have used avtab_map. */
172 	for (i = 0; i < expa.nslot; i++) {
173 		for (cur = expa.htable[i]; cur; cur = cur->next) {
174 			render_av_rule(&cur->key, &cur->datum, what, p, fp);
175 		}
176 	}
177 	avtab_destroy(&expa);
178 	fprintf(fp, "\n");
179 	return 0;
180       oom:
181 	fprintf(stderr, "out of memory\n");
182 	return 1;
183 }
184 
display_bools(policydb_t * p,FILE * fp)185 int display_bools(policydb_t * p, FILE * fp)
186 {
187 	unsigned int i;
188 
189 	for (i = 0; i < p->p_bools.nprim; i++) {
190 		fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i],
191 			p->bool_val_to_struct[i]->state);
192 	}
193 	return 0;
194 }
195 
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)196 void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
197 {
198 
199 	cond_expr_t *cur;
200 	for (cur = exp; cur != NULL; cur = cur->next) {
201 		switch (cur->expr_type) {
202 		case COND_BOOL:
203 			fprintf(fp, "%s ",
204 				p->p_bool_val_to_name[cur->bool - 1]);
205 			break;
206 		case COND_NOT:
207 			fprintf(fp, "! ");
208 			break;
209 		case COND_OR:
210 			fprintf(fp, "|| ");
211 			break;
212 		case COND_AND:
213 			fprintf(fp, "&& ");
214 			break;
215 		case COND_XOR:
216 			fprintf(fp, "^ ");
217 			break;
218 		case COND_EQ:
219 			fprintf(fp, "== ");
220 			break;
221 		case COND_NEQ:
222 			fprintf(fp, "!= ");
223 			break;
224 		default:
225 			fprintf(fp, "error!");
226 			break;
227 		}
228 	}
229 }
230 
display_cond_expressions(policydb_t * p,FILE * fp)231 int display_cond_expressions(policydb_t * p, FILE * fp)
232 {
233 	cond_node_t *cur;
234 	cond_av_list_t *av_cur, *expl = NULL;
235 	avtab_t expa;
236 
237 	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
238 		fprintf(fp, "expression: ");
239 		display_expr(p, cur->expr, fp);
240 		fprintf(fp, "current state: %d\n", cur->cur_state);
241 		fprintf(fp, "True list:\n");
242 		if (avtab_init(&expa))
243 			goto oom;
244 		if (expand_cond_av_list(p, cur->true_list, &expl, &expa)) {
245 			avtab_destroy(&expa);
246 			goto oom;
247 		}
248 		for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) {
249 			fprintf(fp, "\t");
250 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
251 				       RENDER_CONDITIONAL, p, fp);
252 		}
253 		cond_av_list_destroy(expl);
254 		avtab_destroy(&expa);
255 		fprintf(fp, "False list:\n");
256 		if (avtab_init(&expa))
257 			goto oom;
258 		if (expand_cond_av_list(p, cur->false_list, &expl, &expa)) {
259 			avtab_destroy(&expa);
260 			goto oom;
261 		}
262 		for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) {
263 			fprintf(fp, "\t");
264 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
265 				       RENDER_CONDITIONAL, p, fp);
266 		}
267 		cond_av_list_destroy(expl);
268 		avtab_destroy(&expa);
269 	}
270 	return 0;
271 
272       oom:
273 	fprintf(stderr, "out of memory\n");
274 	return 1;
275 }
276 
display_handle_unknown(policydb_t * p,FILE * out_fp)277 int display_handle_unknown(policydb_t * p, FILE * out_fp)
278 {
279 	if (p->handle_unknown == ALLOW_UNKNOWN)
280 		fprintf(out_fp, "Allow unknown classes and permisions\n");
281 	else if (p->handle_unknown == DENY_UNKNOWN)
282 		fprintf(out_fp, "Deny unknown classes and permisions\n");
283 	else if (p->handle_unknown == REJECT_UNKNOWN)
284 		fprintf(out_fp, "Reject unknown classes and permisions\n");
285 	return 0;
286 }
287 
change_bool(char * name,int state,policydb_t * p,FILE * fp)288 int change_bool(char *name, int state, policydb_t * p, FILE * fp)
289 {
290 	cond_bool_datum_t *bool;
291 
292 	bool = hashtab_search(p->p_bools.table, name);
293 	if (bool == NULL) {
294 		fprintf(fp, "Could not find bool %s\n", name);
295 		return -1;
296 	}
297 	bool->state = state;
298 	evaluate_conds(p);
299 	return 0;
300 }
301 
display_policycaps(policydb_t * p,FILE * fp)302 static void display_policycaps(policydb_t * p, FILE * fp)
303 {
304 	ebitmap_node_t *node;
305 	const char *capname;
306 	char buf[64];
307 	unsigned int i;
308 
309 	fprintf(fp, "policy capabilities:\n");
310 	ebitmap_for_each_bit(&p->policycaps, node, i) {
311 		if (ebitmap_node_get_bit(node, i)) {
312 			capname = sepol_polcap_getname(i);
313 			if (capname == NULL) {
314 				snprintf(buf, sizeof(buf), "unknown (%d)", i);
315 				capname = buf;
316 			}
317 			fprintf(fp, "\t%s\n", capname);
318 		}
319 	}
320 }
321 
display_id(policydb_t * p,FILE * fp,uint32_t symbol_type,uint32_t symbol_value,char * prefix)322 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
323 		       uint32_t symbol_value, char *prefix)
324 {
325 	char *id = p->sym_val_to_name[symbol_type][symbol_value];
326 	fprintf(fp, " %s%s", prefix, id);
327 }
328 
display_permissive(policydb_t * p,FILE * fp)329 static void display_permissive(policydb_t *p, FILE *fp)
330 {
331 	ebitmap_node_t *node;
332 	unsigned int i;
333 
334 	fprintf(fp, "permissive sids:\n");
335 	ebitmap_for_each_bit(&p->permissive_map, node, i) {
336 		if (ebitmap_node_get_bit(node, i)) {
337 			fprintf(fp, "\t");
338 			display_id(p, fp, SYM_TYPES, i - 1, "");
339 			fprintf(fp, "\n");
340 		}
341 	}
342 }
343 
display_role_trans(policydb_t * p,FILE * fp)344 static void display_role_trans(policydb_t *p, FILE *fp)
345 {
346 	role_trans_t *rt;
347 
348 	fprintf(fp, "role_trans rules:\n");
349 	for (rt = p->role_tr; rt; rt = rt->next) {
350 		display_id(p, fp, SYM_ROLES, rt->role - 1, "");
351 		display_id(p, fp, SYM_TYPES, rt->type - 1, "");
352 		display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
353 		display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
354 		fprintf(fp, "\n");
355 	}
356 }
357 
display_filename_trans(policydb_t * p,FILE * fp)358 static void display_filename_trans(policydb_t *p, FILE *fp)
359 {
360 	filename_trans_t *ft;
361 
362 	fprintf(fp, "filename_trans rules:\n");
363 	for (ft = p->filename_trans; ft; ft = ft->next) {
364 		display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
365 		display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
366 		display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
367 		display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
368 		fprintf(fp, " %s\n", ft->name);
369 	}
370 }
371 
menu()372 int menu()
373 {
374 	printf("\nSelect a command:\n");
375 	printf("1)  display unconditional AVTAB\n");
376 	printf("2)  display conditional AVTAB (entirely)\n");
377 	printf("3)  display conditional AVTAG (only ENABLED rules)\n");
378 	printf("4)  display conditional AVTAB (only DISABLED rules)\n");
379 	printf("5)  display conditional bools\n");
380 	printf("6)  display conditional expressions\n");
381 	printf("7)  change a boolean value\n");
382 	printf("8)  display role transitions\n");
383 	printf("\n");
384 	printf("c)  display policy capabilities\n");
385 	printf("p)  display the list of permissive types\n");
386 	printf("u)  display unknown handling setting\n");
387 	printf("F)  display filename_trans rules\n");
388 	printf("\n");
389 	printf("f)  set output file\n");
390 	printf("m)  display menu\n");
391 	printf("q)  quit\n");
392 	return 0;
393 }
394 
main(int argc,char ** argv)395 int main(int argc, char **argv)
396 {
397 	FILE *out_fp = stdout;
398 	char ans[81], OutfileName[121];
399 	int fd, ret;
400 	struct stat sb;
401 	void *map;
402 	char *name;
403 	int state;
404 	struct policy_file pf;
405 
406 	if (argc != 2)
407 		usage(argv[0]);
408 
409 	fd = open(argv[1], O_RDONLY);
410 	if (fd < 0) {
411 		fprintf(stderr, "Can't open '%s':  %s\n",
412 			argv[1], strerror(errno));
413 		exit(1);
414 	}
415 	if (fstat(fd, &sb) < 0) {
416 		fprintf(stderr, "Can't stat '%s':  %s\n",
417 			argv[1], strerror(errno));
418 		exit(1);
419 	}
420 	map =
421 	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
422 	if (map == MAP_FAILED) {
423 		fprintf(stderr, "Can't map '%s':  %s\n",
424 			argv[1], strerror(errno));
425 		exit(1);
426 	}
427 
428 	/* read the binary policy */
429 	fprintf(out_fp, "Reading policy...\n");
430 	policy_file_init(&pf);
431 	pf.type = PF_USE_MEMORY;
432 	pf.data = map;
433 	pf.len = sb.st_size;
434 	if (policydb_init(&policydb)) {
435 		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
436 		exit(1);
437 	}
438 	ret = policydb_read(&policydb, &pf, 1);
439 	if (ret) {
440 		fprintf(stderr,
441 			"%s:  error(s) encountered while parsing configuration\n",
442 			argv[0]);
443 		exit(1);
444 	}
445 
446 	fprintf(stdout, "binary policy file loaded\n\n");
447 	close(fd);
448 
449 	menu();
450 	for (;;) {
451 		printf("\nCommand (\'m\' for menu):  ");
452 		fgets(ans, sizeof(ans), stdin);
453 		switch (ans[0]) {
454 
455 		case '1':
456 			display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
457 				      &policydb, out_fp);
458 			break;
459 		case '2':
460 			display_avtab(&policydb.te_cond_avtab,
461 				      RENDER_CONDITIONAL, &policydb, out_fp);
462 			break;
463 		case '3':
464 			display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
465 				      &policydb, out_fp);
466 			break;
467 		case '4':
468 			display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
469 				      &policydb, out_fp);
470 			break;
471 		case '5':
472 			display_bools(&policydb, out_fp);
473 			break;
474 		case '6':
475 			display_cond_expressions(&policydb, out_fp);
476 			break;
477 		case '7':
478 			printf("name? ");
479 			fgets(ans, sizeof(ans), stdin);
480 			ans[strlen(ans) - 1] = 0;
481 
482 			name = malloc((strlen(ans) + 1) * sizeof(char));
483 			if (name == NULL) {
484 				fprintf(stderr, "couldn't malloc string.\n");
485 				break;
486 			}
487 			strcpy(name, ans);
488 
489 			printf("state? ");
490 			fgets(ans, sizeof(ans), stdin);
491 			ans[strlen(ans) - 1] = 0;
492 
493 			if (atoi(ans))
494 				state = 1;
495 			else
496 				state = 0;
497 
498 			change_bool(name, state, &policydb, out_fp);
499 			free(name);
500 			break;
501 		case '8':
502 			display_role_trans(&policydb, out_fp);
503 			break;
504 		case 'c':
505 			display_policycaps(&policydb, out_fp);
506 			break;
507 		case 'p':
508 			display_permissive(&policydb, out_fp);
509 			break;
510 		case 'u':
511 		case 'U':
512 			display_handle_unknown(&policydb, out_fp);
513 			break;
514 		case 'f':
515 			printf
516 			    ("\nFilename for output (<CR> for screen output): ");
517 			fgets(OutfileName, sizeof(OutfileName), stdin);
518 			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
519 			if (strlen(OutfileName) == 0)
520 				out_fp = stdout;
521 			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
522 				fprintf(stderr, "Cannot open output file %s\n",
523 					OutfileName);
524 				out_fp = stdout;
525 			}
526 			if (out_fp != stdout)
527 				printf("\nOutput to file: %s\n", OutfileName);
528 			break;
529 		case 'F':
530 			display_filename_trans(&policydb, out_fp);
531 			break;
532 		case 'q':
533 			policydb_destroy(&policydb);
534 			exit(0);
535 			break;
536 		case 'm':
537 			menu();
538 			break;
539 		default:
540 			printf("\nInvalid choice\n");
541 			menu();
542 			break;
543 
544 		}
545 	}
546 }
547 
548 /* FLASK */
549