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