xref: /aosp_15_r20/external/selinux/checkpolicy/test/dispol.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /* Authors: Frank Mayer <[email protected]> and Karl MacMillan <[email protected]>
2  *
3  * Copyright (C) 2003 Tresys Technology, LLC
4  *	This program is free software; you can redistribute it and/or modify
5  *  	it under the terms of the GNU General Public License as published by
6  *	the Free Software Foundation, version 2.
7  */
8 
9 /*
10  * displaypol.c
11  *
12  * Test program to the contents of a binary policy in text
13  * form.  This program currently only displays the
14  * avtab (including conditional avtab) rules.
15  *
16  * 	displaypol binary_pol_file
17  */
18 
19 #include <sepol/policydb/policydb.h>
20 #include <sepol/policydb/avtab.h>
21 #include <sepol/policydb/services.h>
22 #include <sepol/policydb/conditional.h>
23 #include <sepol/policydb/util.h>
24 #include <sepol/policydb/polcaps.h>
25 #include <getopt.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 
36 static const struct command {
37 	enum {
38 		EOL    = 0,
39 		HEADER = 1,
40 		CMD    = 1 << 1,
41 		NOOPT  = 1 << 2,
42 	} meta;
43 	char cmd;
44 	const char *desc;
45 } commands[] = {
46 	{HEADER, 0, "\nSelect a command:"},
47 	{CMD,       '1',  "display unconditional AVTAB" },
48 	{CMD,       '2',  "display conditional AVTAB (entirely)"},
49 	{CMD,       '3',  "display conditional AVTAB (only ENABLED rules)"},
50 	{CMD,       '4',  "display conditional AVTAB (only DISABLED rules)"},
51 	{CMD,       '5',  "display booleans"},
52 	{CMD,       '6',  "display conditional expressions"},
53 	{CMD|NOOPT, '7',  "change a boolean value"},
54 	{CMD,       '8',  "display role transitions"},
55 	{HEADER, 0, ""},
56 	{CMD,       'c',  "display policy capabilities"},
57 	{CMD,       'C',  "display classes"},
58 	{CMD,       'u',  "display users"},
59 	{CMD,       'r',  "display roles"},
60 	{CMD,       't',  "display types"},
61 	{CMD,       'a',  "display type attributes"},
62 	{CMD,       'p',  "display the list of permissive types"},
63 	{CMD,       'U',  "display unknown handling setting"},
64 	{CMD,       'F',  "display filename_trans rules"},
65 	{HEADER, 0, ""},
66 	{CMD|NOOPT, 'f',  "set output file"},
67 	{CMD|NOOPT, 'm',  "display menu"},
68 	{CMD|NOOPT, 'q',  "quit"},
69 	{EOL,   0, "" },
70 };
71 
usage(const char * progname)72 static __attribute__((__noreturn__)) void usage(const char *progname)
73 {
74 	puts("Usage:");
75 	printf(" %s [OPTIONS] binary_pol_file\n\n", progname);
76 	puts("Options:");
77 	puts(" -h, --help   print this help message");
78 	puts(" -a, --actions ACTIONS   run non-interactively");
79 	puts("");
80 	puts("Actions:");
81 	for (unsigned int i = 0; commands[i].meta != EOL; i++) {
82 		if (commands[i].meta == HEADER
83 		    || commands[i].meta & NOOPT)
84 			continue;
85 		printf("  %c    %s\n", commands[i].cmd, commands[i].desc);
86 	}
87 	puts("");
88 	exit(1);
89 }
90 
render_access_mask(uint32_t mask,avtab_key_t * key,policydb_t * p,FILE * fp)91 static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
92 		       FILE * fp)
93 {
94 	char *perm = sepol_av_to_string(p, key->target_class, mask);
95 	fprintf(fp, "{");
96 	fprintf(fp, "%s ", perm ?: "<format-failure>");
97 	fprintf(fp, "}");
98 	free(perm);
99 	return 0;
100 }
101 
render_type(uint32_t type,policydb_t * p,FILE * fp)102 static int render_type(uint32_t type, policydb_t * p, FILE * fp)
103 {
104 	fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
105 	return 0;
106 }
107 
render_key(avtab_key_t * key,policydb_t * p,FILE * fp)108 static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
109 {
110 	char *stype, *ttype, *tclass;
111 	stype = p->p_type_val_to_name[key->source_type - 1];
112 	ttype = p->p_type_val_to_name[key->target_type - 1];
113 	tclass = p->p_class_val_to_name[key->target_class - 1];
114 	if (stype && ttype)
115 		fprintf(fp, "%s %s : %s ", stype, ttype, tclass);
116 	else if (stype)
117 		fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass);
118 	else if (ttype)
119 		fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass);
120 	else
121 		fprintf(fp, "%u %u : %s ", key->source_type, key->target_type,
122 			tclass);
123 	return 0;
124 }
125 
126 /* 'what' values for this function */
127 #define	RENDER_UNCONDITIONAL	0x0001	/* render all regardless of enabled state */
128 #define RENDER_ENABLED		0x0002
129 #define RENDER_DISABLED		0x0004
130 #define RENDER_CONDITIONAL	(RENDER_ENABLED|RENDER_DISABLED)
131 
render_av_rule(avtab_key_t * key,avtab_datum_t * datum,uint32_t what,policydb_t * p,FILE * fp)132 static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
133 		   policydb_t * p, FILE * fp)
134 {
135 	if (!(what & RENDER_UNCONDITIONAL)) {
136 		if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED)
137 						    && !(key->
138 							 specified &
139 							 AVTAB_ENABLED))
140 						   || ((what & RENDER_DISABLED)
141 						       && (key->
142 							   specified &
143 							   AVTAB_ENABLED)))) {
144 			return 0;	/* doesn't match selection criteria */
145 		}
146 	}
147 
148 	if (!(what & RENDER_UNCONDITIONAL)) {
149 		if (key->specified & AVTAB_ENABLED)
150 			fprintf(fp, "[enabled] ");
151 		else if (!(key->specified & AVTAB_ENABLED))
152 			fprintf(fp, "[disabled] ");
153 	}
154 
155 	if (key->specified & AVTAB_AV) {
156 		if (key->specified & AVTAB_ALLOWED) {
157 			fprintf(fp, "allow ");
158 			render_key(key, p, fp);
159 			render_access_mask(datum->data, key, p, fp);
160 			fprintf(fp, ";\n");
161 		}
162 		if (key->specified & AVTAB_AUDITALLOW) {
163 			fprintf(fp, "auditallow ");
164 			render_key(key, p, fp);
165 			render_access_mask(datum->data, key, p, fp);
166 			fprintf(fp, ";\n");
167 		}
168 		if (key->specified & AVTAB_AUDITDENY) {
169 			fprintf(fp, "dontaudit ");
170 			render_key(key, p, fp);
171 			/* We inverse the mask for dontaudit since the mask is internally stored
172 			 * as a auditdeny mask */
173 			render_access_mask(~datum->data, key, p, fp);
174 			fprintf(fp, ";\n");
175 		}
176 	} else if (key->specified & AVTAB_TYPE) {
177 		if (key->specified & AVTAB_TRANSITION) {
178 			fprintf(fp, "type_transition ");
179 			render_key(key, p, fp);
180 			render_type(datum->data, p, fp);
181 			fprintf(fp, ";\n");
182 		}
183 		if (key->specified & AVTAB_MEMBER) {
184 			fprintf(fp, "type_member ");
185 			render_key(key, p, fp);
186 			render_type(datum->data, p, fp);
187 			fprintf(fp, ";\n");
188 		}
189 		if (key->specified & AVTAB_CHANGE) {
190 			fprintf(fp, "type_change ");
191 			render_key(key, p, fp);
192 			render_type(datum->data, p, fp);
193 			fprintf(fp, ";\n");
194 		}
195 	} else if (key->specified & AVTAB_XPERMS) {
196 		char *perms;
197 
198 		if (key->specified & AVTAB_XPERMS_ALLOWED)
199 			fprintf(fp, "allowxperm ");
200 		else if (key->specified & AVTAB_XPERMS_AUDITALLOW)
201 			fprintf(fp, "auditallowxperm ");
202 		else if (key->specified & AVTAB_XPERMS_DONTAUDIT)
203 			fprintf(fp, "dontauditxperm ");
204 		render_key(key, p, fp);
205 		perms = sepol_extended_perms_to_string(datum->xperms);
206 		if (!perms) {
207 			fprintf(fp, "     ERROR: failed to format xperms\n");
208 			return -1;
209 		}
210 		fprintf(fp, "%s;\n", perms);
211 		free(perms);
212 	} else {
213 		fprintf(fp, "     ERROR: no valid rule type specified\n");
214 		return -1;
215 	}
216 	return 0;
217 }
218 
display_avtab(avtab_t * a,uint32_t what,policydb_t * p,FILE * fp)219 static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
220 {
221 	unsigned int i;
222 	avtab_ptr_t cur;
223 
224 	/* hmm...should have used avtab_map. */
225 	for (i = 0; i < a->nslot; i++) {
226 		for (cur = a->htable[i]; cur; cur = cur->next) {
227 			render_av_rule(&cur->key, &cur->datum, what, p, fp);
228 		}
229 	}
230 	fprintf(fp, "\n");
231 	return 0;
232 }
233 
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)234 static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
235 {
236 
237 	cond_expr_t *cur;
238 	for (cur = exp; cur != NULL; cur = cur->next) {
239 		switch (cur->expr_type) {
240 		case COND_BOOL:
241 			fprintf(fp, "%s ",
242 				p->p_bool_val_to_name[cur->boolean - 1]);
243 			break;
244 		case COND_NOT:
245 			fprintf(fp, "! ");
246 			break;
247 		case COND_OR:
248 			fprintf(fp, "|| ");
249 			break;
250 		case COND_AND:
251 			fprintf(fp, "&& ");
252 			break;
253 		case COND_XOR:
254 			fprintf(fp, "^ ");
255 			break;
256 		case COND_EQ:
257 			fprintf(fp, "== ");
258 			break;
259 		case COND_NEQ:
260 			fprintf(fp, "!= ");
261 			break;
262 		default:
263 			fprintf(fp, "error!");
264 			break;
265 		}
266 	}
267 }
268 
display_cond_expressions(policydb_t * p,FILE * fp)269 static int display_cond_expressions(policydb_t * p, FILE * fp)
270 {
271 	cond_node_t *cur;
272 	cond_av_list_t *av_cur;
273 
274 	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
275 		fprintf(fp, "expression: ");
276 		display_expr(p, cur->expr, fp);
277 		fprintf(fp, "current state: %d\n", cur->cur_state);
278 		fprintf(fp, "True list:\n");
279 		for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) {
280 			fprintf(fp, "\t");
281 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
282 				       RENDER_CONDITIONAL, p, fp);
283 		}
284 		fprintf(fp, "False list:\n");
285 		for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) {
286 			fprintf(fp, "\t");
287 			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
288 				       RENDER_CONDITIONAL, p, fp);
289 		}
290 	}
291 	return 0;
292 }
293 
display_handle_unknown(policydb_t * p,FILE * out_fp)294 static int display_handle_unknown(policydb_t * p, FILE * out_fp)
295 {
296 	if (p->handle_unknown == ALLOW_UNKNOWN)
297 		fprintf(out_fp, "Allow unknown classes and permissions\n");
298 	else if (p->handle_unknown == DENY_UNKNOWN)
299 		fprintf(out_fp, "Deny unknown classes and permissions\n");
300 	else if (p->handle_unknown == REJECT_UNKNOWN)
301 		fprintf(out_fp, "Reject unknown classes and permissions\n");
302 	else
303 		fprintf(out_fp, "<INVALID SETTING!>\n");
304 	return 0;
305 }
306 
change_bool(char * name,int state,policydb_t * p,FILE * fp)307 static int change_bool(char *name, int state, policydb_t * p, FILE * fp)
308 {
309 	cond_bool_datum_t *boolean;
310 
311 	boolean = hashtab_search(p->p_bools.table, name);
312 	if (boolean == NULL) {
313 		fprintf(fp, "Could not find bool %s\n", name);
314 		return -1;
315 	}
316 	boolean->state = state;
317 	evaluate_conds(p);
318 	return 0;
319 }
320 
display_booleans(policydb_t * p,FILE * fp)321 static int display_booleans(policydb_t * p, FILE *fp)
322 {
323 	uint32_t i;
324 
325 	fprintf(fp, "booleans (#%u):\n", p->p_bools.table->nel);
326 	for (i = 0; i < p->p_bools.nprim; i++) {
327 		fprintf(fp, "\t%s : %d\n", p->p_bool_val_to_name[i],
328 			p->bool_val_to_struct[i]->state);
329 	}
330 	return 0;
331 }
332 
display_policycaps(policydb_t * p,FILE * fp)333 static void display_policycaps(policydb_t * p, FILE * fp)
334 {
335 	ebitmap_node_t *node;
336 	const char *capname;
337 	char buf[64];
338 	unsigned int i;
339 
340 	fprintf(fp, "policy capabilities:\n");
341 	ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
342 		capname = sepol_polcap_getname(i);
343 		if (capname == NULL) {
344 			snprintf(buf, sizeof(buf), "unknown (%u)", i);
345 			capname = buf;
346 		}
347 		fprintf(fp, "\t%s\n", capname);
348 	}
349 }
350 
display_classes(policydb_t * p,FILE * fp)351 static int display_classes(policydb_t * p, FILE *fp)
352 {
353 	uint32_t i;
354 
355 	fprintf(fp, "classes (#%u):\n", p->p_classes.table->nel);
356 	for (i = 0; i < p->p_classes.nprim; i++) {
357 		if (!p->p_class_val_to_name[i])
358 			continue;
359 
360 		fprintf(fp, "\t%s\n", p->p_class_val_to_name[i]);
361 	}
362 	return 0;
363 }
364 
display_id(policydb_t * p,FILE * fp,uint32_t symbol_type,uint32_t symbol_value,const char * prefix)365 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
366 		       uint32_t symbol_value, const char *prefix)
367 {
368 	const char *id = p->sym_val_to_name[symbol_type][symbol_value];
369 	fprintf(fp, " %s%s", prefix, id);
370 }
371 
display_permissive(policydb_t * p,FILE * fp)372 static void display_permissive(policydb_t *p, FILE *fp)
373 {
374 	ebitmap_node_t *node;
375 	unsigned int i;
376 
377 	fprintf(fp, "permissive sids (#%u):\n", ebitmap_cardinality(&p->permissive_map));
378 	ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
379 		fprintf(fp, "\t");
380 		display_id(p, fp, SYM_TYPES, i - 1, "");
381 		fprintf(fp, "\n");
382 	}
383 }
384 
display_users(policydb_t * p,FILE * fp)385 static int display_users(policydb_t * p, FILE *fp)
386 {
387 	uint32_t i;
388 
389 	fprintf(fp, "users (#%u):\n", p->p_users.table->nel);
390 	for (i = 0; i < p->p_users.nprim; i++) {
391 		if (!p->p_user_val_to_name[i])
392 			continue;
393 
394 		fprintf(fp, "\t%s\n", p->p_user_val_to_name[i]);
395 	}
396 	return 0;
397 }
398 
display_roles(policydb_t * p,FILE * fp)399 static int display_roles(policydb_t * p, FILE *fp)
400 {
401 	uint32_t i;
402 
403 	fprintf(fp, "roles (#%u):\n", p->p_roles.table->nel);
404 	for (i = 0; i < p->p_roles.nprim; i++) {
405 		if (!p->p_role_val_to_name[i])
406 			continue;
407 
408 		fprintf(fp, "\t%s\n", p->p_role_val_to_name[i]);
409 	}
410 	return 0;
411 }
412 
display_types(policydb_t * p,FILE * fp)413 static int display_types(policydb_t * p, FILE *fp)
414 {
415 	uint32_t i;
416 
417 	fprintf(fp, "types (out of #%u):\n", p->p_types.table->nel);
418 	for (i = 0; i < p->p_types.nprim; i++) {
419 		if (!p->p_type_val_to_name[i])
420 			continue;
421 
422 		if (p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
423 			continue;
424 
425 		fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
426 	}
427 	return 0;
428 }
429 
display_attributes(policydb_t * p,FILE * fp)430 static int display_attributes(policydb_t * p, FILE *fp)
431 {
432 	uint32_t i;
433 
434 	fprintf(fp, "attributes (out of #%u):\n", p->p_types.table->nel);
435 	for (i = 0; i < p->p_types.nprim; i++) {
436 		if (!p->p_type_val_to_name[i])
437 			continue;
438 
439 		if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB)
440 			continue;
441 
442 		fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
443 	}
444 	return 0;
445 }
446 
display_role_trans(policydb_t * p,FILE * fp)447 static void display_role_trans(policydb_t *p, FILE *fp)
448 {
449 	role_trans_t *rt;
450 
451 	fprintf(fp, "role_trans rules:\n");
452 	for (rt = p->role_tr; rt; rt = rt->next) {
453 		display_id(p, fp, SYM_ROLES, rt->role - 1, "");
454 		display_id(p, fp, SYM_TYPES, rt->type - 1, "");
455 		display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
456 		display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
457 		fprintf(fp, "\n");
458 	}
459 }
460 
461 struct filenametr_display_args {
462 	policydb_t *p;
463 	FILE *fp;
464 };
465 
filenametr_display(hashtab_key_t key,hashtab_datum_t datum,void * ptr)466 static int filenametr_display(hashtab_key_t key,
467 			      hashtab_datum_t datum,
468 			      void *ptr)
469 {
470 	struct filename_trans_key *ft = (struct filename_trans_key *)key;
471 	struct filename_trans_datum *ftdatum = datum;
472 	struct filenametr_display_args *args = ptr;
473 	policydb_t *p = args->p;
474 	FILE *fp = args->fp;
475 	ebitmap_node_t *node;
476 	uint32_t bit;
477 
478 	do {
479 		ebitmap_for_each_positive_bit(&ftdatum->stypes, node, bit) {
480 			display_id(p, fp, SYM_TYPES, bit, "");
481 			display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
482 			display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
483 			display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, "");
484 			fprintf(fp, " %s\n", ft->name);
485 		}
486 		ftdatum = ftdatum->next;
487 	} while (ftdatum);
488 
489 	return 0;
490 }
491 
492 
display_filename_trans(policydb_t * p,FILE * fp)493 static void display_filename_trans(policydb_t *p, FILE *fp)
494 {
495 	struct filenametr_display_args args;
496 
497 	fprintf(fp, "filename_trans rules:\n");
498 	args.p = p;
499 	args.fp = fp;
500 	hashtab_map(p->filename_trans, filenametr_display, &args);
501 }
502 
menu(void)503 static int menu(void)
504 {
505 	unsigned int i;
506 	for (i = 0; commands[i].meta != EOL; i++) {
507 		if (commands[i].meta == HEADER)
508 			printf("%s\n", commands[i].desc);
509 		else if (commands[i].meta & CMD)
510 			printf("%c) %s\n", commands[i].cmd, commands[i].desc);
511 	}
512 	return 0;
513 }
514 
main(int argc,char ** argv)515 int main(int argc, char **argv)
516 {
517 	char *ops = NULL;
518 	char *bpol;
519 	FILE *out_fp = stdout;
520 	char ans[81], OutfileName[121];
521 	int fd, ret;
522 	struct stat sb;
523 	void *map;
524 	char *name;
525 	int state;
526 	struct policy_file pf;
527 	policydb_t policydb;
528 
529 	if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
530 		usage(argv[0]);
531 
532 	bpol = argv[1];
533 	if (strcmp (bpol, "--actions") == 0 || strcmp (bpol, "-a") == 0) {
534 		if (argc != 4) {
535 			fprintf(stderr, "%s: unexpected number of arguments\n", argv[0]);
536 			usage(argv[0]);
537 		}
538 		ops = argv[2];
539 		bpol = argv[3];
540 	} else if (bpol[0] == '-') {
541 		fprintf(stderr, "%s: unknown option: %s\n", argv[0], bpol);
542 		usage(argv[0]);
543 	}
544 
545 	fd = open(bpol, O_RDONLY);
546 	if (fd < 0) {
547 		fprintf(stderr, "Can't open '%s':  %s\n",
548 			bpol, strerror(errno));
549 		exit(1);
550 	}
551 	if (fstat(fd, &sb) < 0) {
552 		fprintf(stderr, "Can't stat '%s':  %s\n",
553 			bpol, strerror(errno));
554 		exit(1);
555 	}
556 	map =
557 	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
558 	if (map == MAP_FAILED) {
559 		fprintf(stderr, "Can't map '%s':  %s\n",
560 			bpol, strerror(errno));
561 		exit(1);
562 	}
563 
564 	/* read the binary policy */
565 	if (!ops)
566 		fprintf(out_fp, "Reading policy...\n");
567 	policy_file_init(&pf);
568 	pf.type = PF_USE_MEMORY;
569 	pf.data = map;
570 	pf.len = sb.st_size;
571 	if (policydb_init(&policydb)) {
572 		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
573 		exit(1);
574 	}
575 	ret = policydb_read(&policydb, &pf, ops? 0: 1);
576 	if (ret) {
577 		fprintf(stderr,
578 			"%s:  error(s) encountered while parsing configuration\n",
579 			argv[0]);
580 		exit(1);
581 	}
582 
583 	if (!ops)
584 		fprintf(stdout, "binary policy file loaded\n\n");
585 	close(fd);
586 
587 	if (!ops)
588 		menu();
589 	for (;;) {
590 		if (ops) {
591 			puts("");
592 			ans[0] = *ops? *ops++: 'q';
593 			ans[1] = '\0';
594 		} else {
595 			printf("\nCommand (\'m\' for menu):  ");
596 			if (fgets(ans, sizeof(ans), stdin) == NULL) {
597 				if (feof(stdin))
598 					break;
599 				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
600 					strerror(errno));
601 				continue;
602 			}
603 		}
604 		switch (ans[0]) {
605 
606 		case '1':
607 			display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
608 				      &policydb, out_fp);
609 			break;
610 		case '2':
611 			display_avtab(&policydb.te_cond_avtab,
612 				      RENDER_CONDITIONAL, &policydb, out_fp);
613 			break;
614 		case '3':
615 			display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
616 				      &policydb, out_fp);
617 			break;
618 		case '4':
619 			display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
620 				      &policydb, out_fp);
621 			break;
622 		case '5':
623 			display_booleans(&policydb, out_fp);
624 			break;
625 		case '6':
626 			display_cond_expressions(&policydb, out_fp);
627 			break;
628 		case '7':
629 			printf("name? ");
630 			if (fgets(ans, sizeof(ans), stdin) == NULL) {
631 				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
632 						strerror(errno));
633 				break;
634 			}
635 			ans[strlen(ans) - 1] = 0;
636 
637 			name = strdup(ans);
638 			if (name == NULL) {
639 				fprintf(stderr, "couldn't strdup string.\n");
640 				break;
641 			}
642 
643 			printf("state? ");
644 			if (fgets(ans, sizeof(ans), stdin) == NULL) {
645 				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
646 						strerror(errno));
647 				break;
648 			}
649 			ans[strlen(ans) - 1] = 0;
650 
651 			if (atoi(ans))
652 				state = 1;
653 			else
654 				state = 0;
655 
656 			change_bool(name, state, &policydb, out_fp);
657 			free(name);
658 			break;
659 		case '8':
660 			display_role_trans(&policydb, out_fp);
661 			break;
662 		case 'a':
663 			display_attributes(&policydb, out_fp);
664 			break;
665 		case 'c':
666 			display_policycaps(&policydb, out_fp);
667 			break;
668 		case 'C':
669 			display_classes(&policydb, out_fp);
670 			break;
671 		case 'p':
672 			display_permissive(&policydb, out_fp);
673 			break;
674 		case 'r':
675 			display_roles(&policydb, out_fp);
676 			break;
677 		case 't':
678 			display_types(&policydb, out_fp);
679 			break;
680 		case 'u':
681 			display_users(&policydb, out_fp);
682 			break;
683 		case 'U':
684 			display_handle_unknown(&policydb, out_fp);
685 			break;
686 		case 'f':
687 			printf
688 			    ("\nFilename for output (<CR> for screen output): ");
689 			if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
690 				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
691 						strerror(errno));
692 				break;
693 			}
694 			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
695 			if (strlen(OutfileName) == 0)
696 				out_fp = stdout;
697 			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
698 				fprintf(stderr, "Cannot open output file %s\n",
699 					OutfileName);
700 				out_fp = stdout;
701 			}
702 			if (out_fp != stdout)
703 				printf("\nOutput to file: %s\n", OutfileName);
704 			break;
705 		case 'F':
706 			display_filename_trans(&policydb, out_fp);
707 			break;
708 		case 'q':
709 			policydb_destroy(&policydb);
710 			exit(0);
711 			break;
712 		case 'm':
713 			menu();
714 			break;
715 		default:
716 			printf("\nInvalid choice\n");
717 			menu();
718 			break;
719 
720 		}
721 	}
722 }
723 
724 /* FLASK */
725