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