16cd6a6acSopenharmony_ci
26cd6a6acSopenharmony_ci/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
36cd6a6acSopenharmony_ci *
46cd6a6acSopenharmony_ci * Copyright (C) 2003,2004,2005 Tresys Technology, LLC
56cd6a6acSopenharmony_ci *	This program is free software; you can redistribute it and/or modify
66cd6a6acSopenharmony_ci *  	it under the terms of the GNU General Public License as published by
76cd6a6acSopenharmony_ci *	the Free Software Foundation, version 2.
86cd6a6acSopenharmony_ci */
96cd6a6acSopenharmony_ci
106cd6a6acSopenharmony_ci/*
116cd6a6acSopenharmony_ci * dismod.c
126cd6a6acSopenharmony_ci *
136cd6a6acSopenharmony_ci * Test program to the contents of a binary policy in text
146cd6a6acSopenharmony_ci * form.
156cd6a6acSopenharmony_ci *
166cd6a6acSopenharmony_ci * 	dismod binary_mod_file
176cd6a6acSopenharmony_ci */
186cd6a6acSopenharmony_ci
196cd6a6acSopenharmony_ci#include <getopt.h>
206cd6a6acSopenharmony_ci#include <assert.h>
216cd6a6acSopenharmony_ci#include <sys/stat.h>
226cd6a6acSopenharmony_ci#include <sys/types.h>
236cd6a6acSopenharmony_ci#include <sys/mman.h>
246cd6a6acSopenharmony_ci#include <errno.h>
256cd6a6acSopenharmony_ci#include <stdio.h>
266cd6a6acSopenharmony_ci#include <fcntl.h>
276cd6a6acSopenharmony_ci#include <stdlib.h>
286cd6a6acSopenharmony_ci#include <unistd.h>
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
316cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
326cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
336cd6a6acSopenharmony_ci#include <sepol/policydb/link.h>
346cd6a6acSopenharmony_ci#include <sepol/policydb/module.h>
356cd6a6acSopenharmony_ci#include <sepol/policydb/util.h>
366cd6a6acSopenharmony_ci#include <sepol/policydb/polcaps.h>
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_ci#include <byteswap.h>
396cd6a6acSopenharmony_ci#include <endian.h>
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_ci#if __BYTE_ORDER == __LITTLE_ENDIAN
426cd6a6acSopenharmony_ci#define le32_to_cpu(x) (x)
436cd6a6acSopenharmony_ci#else
446cd6a6acSopenharmony_ci#define le32_to_cpu(x) bswap_32(x)
456cd6a6acSopenharmony_ci#endif
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_COND_AVTAB	0
486cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_UNCOND_AVTAB	1
496cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_ROLE_TYPE_NODE	2 /* unused? */
506cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_ROLE_TRANS	3
516cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_ROLE_ALLOW	4
526cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_REQUIRES	5
536cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_DECLARES	6
546cd6a6acSopenharmony_ci#define DISPLAY_AVBLOCK_FILENAME_TRANS	7
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_cistatic policydb_t policydb;
576cd6a6acSopenharmony_ciextern unsigned int ss_initialized;
586cd6a6acSopenharmony_ci
596cd6a6acSopenharmony_ciint policyvers = MOD_POLICYDB_VERSION_BASE;
606cd6a6acSopenharmony_ci
616cd6a6acSopenharmony_cistatic const char *symbol_labels[9] = {
626cd6a6acSopenharmony_ci	"commons",
636cd6a6acSopenharmony_ci	"classes", "roles  ", "types  ", "users  ", "bools  ",
646cd6a6acSopenharmony_ci	"levels ", "cats   ", "attribs"
656cd6a6acSopenharmony_ci};
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_cistatic __attribute__((__noreturn__)) void usage(const char *progname)
686cd6a6acSopenharmony_ci{
696cd6a6acSopenharmony_ci	printf("usage:  %s binary_pol_file\n\n", progname);
706cd6a6acSopenharmony_ci	exit(1);
716cd6a6acSopenharmony_ci}
726cd6a6acSopenharmony_ci
736cd6a6acSopenharmony_cistatic void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p,
746cd6a6acSopenharmony_ci			       FILE * fp)
756cd6a6acSopenharmony_ci{
766cd6a6acSopenharmony_ci	char *perm;
776cd6a6acSopenharmony_ci	fprintf(fp, "{");
786cd6a6acSopenharmony_ci	perm = sepol_av_to_string(p, class, mask);
796cd6a6acSopenharmony_ci	if (perm)
806cd6a6acSopenharmony_ci		fprintf(fp, "%s ", perm);
816cd6a6acSopenharmony_ci	fprintf(fp, "}");
826cd6a6acSopenharmony_ci}
836cd6a6acSopenharmony_ci
846cd6a6acSopenharmony_cistatic void render_access_bitmap(ebitmap_t * map, uint32_t class,
856cd6a6acSopenharmony_ci				 policydb_t * p, FILE * fp)
866cd6a6acSopenharmony_ci{
876cd6a6acSopenharmony_ci	unsigned int i;
886cd6a6acSopenharmony_ci	char *perm;
896cd6a6acSopenharmony_ci	fprintf(fp, "{");
906cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
916cd6a6acSopenharmony_ci		if (ebitmap_get_bit(map, i)) {
926cd6a6acSopenharmony_ci			perm = sepol_av_to_string(p, class, UINT32_C(1) << i);
936cd6a6acSopenharmony_ci			if (perm)
946cd6a6acSopenharmony_ci				fprintf(fp, " %s", perm);
956cd6a6acSopenharmony_ci		}
966cd6a6acSopenharmony_ci	}
976cd6a6acSopenharmony_ci	fprintf(fp, " }");
986cd6a6acSopenharmony_ci}
996cd6a6acSopenharmony_ci
1006cd6a6acSopenharmony_cistatic void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
1016cd6a6acSopenharmony_ci		       uint32_t symbol_value, const char *prefix)
1026cd6a6acSopenharmony_ci{
1036cd6a6acSopenharmony_ci	char *id = p->sym_val_to_name[symbol_type][symbol_value];
1046cd6a6acSopenharmony_ci	scope_datum_t *scope =
1056cd6a6acSopenharmony_ci	    (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
1066cd6a6acSopenharmony_ci	assert(scope != NULL);
1076cd6a6acSopenharmony_ci	if (scope->scope == SCOPE_REQ) {
1086cd6a6acSopenharmony_ci		fprintf(fp, " [%s%s]", prefix, id);
1096cd6a6acSopenharmony_ci	} else {
1106cd6a6acSopenharmony_ci		fprintf(fp, " %s%s", prefix, id);
1116cd6a6acSopenharmony_ci	}
1126cd6a6acSopenharmony_ci}
1136cd6a6acSopenharmony_ci
1146cd6a6acSopenharmony_cistatic int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
1156cd6a6acSopenharmony_ci		     FILE * fp)
1166cd6a6acSopenharmony_ci{
1176cd6a6acSopenharmony_ci	unsigned int i, num_types;
1186cd6a6acSopenharmony_ci
1196cd6a6acSopenharmony_ci	if (set->flags & TYPE_STAR) {
1206cd6a6acSopenharmony_ci		fprintf(fp, " * ");
1216cd6a6acSopenharmony_ci		return 0;
1226cd6a6acSopenharmony_ci	} else if (set->flags & TYPE_COMP) {
1236cd6a6acSopenharmony_ci		fprintf(fp, " ~");
1246cd6a6acSopenharmony_ci	}
1256cd6a6acSopenharmony_ci
1266cd6a6acSopenharmony_ci	num_types = 0;
1276cd6a6acSopenharmony_ci	if (flags & RULE_SELF) {
1286cd6a6acSopenharmony_ci		num_types++;
1296cd6a6acSopenharmony_ci	}
1306cd6a6acSopenharmony_ci
1316cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
1326cd6a6acSopenharmony_ci	     i++) {
1336cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(&set->types, i))
1346cd6a6acSopenharmony_ci			continue;
1356cd6a6acSopenharmony_ci		num_types++;
1366cd6a6acSopenharmony_ci		if (num_types > 1)
1376cd6a6acSopenharmony_ci			break;
1386cd6a6acSopenharmony_ci	}
1396cd6a6acSopenharmony_ci
1406cd6a6acSopenharmony_ci	if (num_types <= 1) {
1416cd6a6acSopenharmony_ci		for (i = ebitmap_startbit(&set->negset);
1426cd6a6acSopenharmony_ci		     i < ebitmap_length(&set->negset); i++) {
1436cd6a6acSopenharmony_ci			if (!ebitmap_get_bit(&set->negset, i))
1446cd6a6acSopenharmony_ci				continue;
1456cd6a6acSopenharmony_ci			num_types++;
1466cd6a6acSopenharmony_ci			if (num_types > 1)
1476cd6a6acSopenharmony_ci				break;
1486cd6a6acSopenharmony_ci		}
1496cd6a6acSopenharmony_ci	}
1506cd6a6acSopenharmony_ci
1516cd6a6acSopenharmony_ci	if (num_types > 1)
1526cd6a6acSopenharmony_ci		fprintf(fp, "{");
1536cd6a6acSopenharmony_ci
1546cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
1556cd6a6acSopenharmony_ci	     i++) {
1566cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(&set->types, i))
1576cd6a6acSopenharmony_ci			continue;
1586cd6a6acSopenharmony_ci		display_id(policy, fp, SYM_TYPES, i, "");
1596cd6a6acSopenharmony_ci	}
1606cd6a6acSopenharmony_ci
1616cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(&set->negset);
1626cd6a6acSopenharmony_ci	     i < ebitmap_length(&set->negset); i++) {
1636cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(&set->negset, i))
1646cd6a6acSopenharmony_ci			continue;
1656cd6a6acSopenharmony_ci		display_id(policy, fp, SYM_TYPES, i, "-");
1666cd6a6acSopenharmony_ci	}
1676cd6a6acSopenharmony_ci
1686cd6a6acSopenharmony_ci	if (flags & RULE_SELF) {
1696cd6a6acSopenharmony_ci		fprintf(fp, " self");
1706cd6a6acSopenharmony_ci	}
1716cd6a6acSopenharmony_ci
1726cd6a6acSopenharmony_ci	if (num_types > 1)
1736cd6a6acSopenharmony_ci		fprintf(fp, " }");
1746cd6a6acSopenharmony_ci
1756cd6a6acSopenharmony_ci	return 0;
1766cd6a6acSopenharmony_ci}
1776cd6a6acSopenharmony_ci
1786cd6a6acSopenharmony_cistatic int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
1796cd6a6acSopenharmony_ci{
1806cd6a6acSopenharmony_ci	unsigned int i, num = 0;
1816cd6a6acSopenharmony_ci
1826cd6a6acSopenharmony_ci	if (roles->flags & ROLE_STAR) {
1836cd6a6acSopenharmony_ci		fprintf(fp, " * ");
1846cd6a6acSopenharmony_ci		return 0;
1856cd6a6acSopenharmony_ci	} else if (roles->flags & ROLE_COMP) {
1866cd6a6acSopenharmony_ci		fprintf(fp, " ~");
1876cd6a6acSopenharmony_ci	}
1886cd6a6acSopenharmony_ci
1896cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(&roles->roles);
1906cd6a6acSopenharmony_ci	     i < ebitmap_length(&roles->roles); i++) {
1916cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(&roles->roles, i))
1926cd6a6acSopenharmony_ci			continue;
1936cd6a6acSopenharmony_ci		num++;
1946cd6a6acSopenharmony_ci		if (num > 1) {
1956cd6a6acSopenharmony_ci			fprintf(fp, "{");
1966cd6a6acSopenharmony_ci			break;
1976cd6a6acSopenharmony_ci		}
1986cd6a6acSopenharmony_ci	}
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(&roles->roles);
2016cd6a6acSopenharmony_ci	     i < ebitmap_length(&roles->roles); i++) {
2026cd6a6acSopenharmony_ci		if (ebitmap_get_bit(&roles->roles, i))
2036cd6a6acSopenharmony_ci			display_id(p, fp, SYM_ROLES, i, "");
2046cd6a6acSopenharmony_ci	}
2056cd6a6acSopenharmony_ci
2066cd6a6acSopenharmony_ci	if (num > 1)
2076cd6a6acSopenharmony_ci		fprintf(fp, " }");
2086cd6a6acSopenharmony_ci
2096cd6a6acSopenharmony_ci	return 0;
2106cd6a6acSopenharmony_ci
2116cd6a6acSopenharmony_ci}
2126cd6a6acSopenharmony_ci
2136cd6a6acSopenharmony_cistatic int display_avrule(avrule_t * avrule, policydb_t * policy,
2146cd6a6acSopenharmony_ci		   FILE * fp)
2156cd6a6acSopenharmony_ci{
2166cd6a6acSopenharmony_ci	class_perm_node_t *cur;
2176cd6a6acSopenharmony_ci	int num_classes;
2186cd6a6acSopenharmony_ci
2196cd6a6acSopenharmony_ci	if (avrule == NULL) {
2206cd6a6acSopenharmony_ci		fprintf(fp, "  <empty>\n");
2216cd6a6acSopenharmony_ci		return 0;
2226cd6a6acSopenharmony_ci	}
2236cd6a6acSopenharmony_ci	if (avrule->specified & AVRULE_AV) {
2246cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_ALLOWED) {
2256cd6a6acSopenharmony_ci			fprintf(fp, "  allow");
2266cd6a6acSopenharmony_ci		}
2276cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_AUDITALLOW) {
2286cd6a6acSopenharmony_ci			fprintf(fp, "  auditallow ");
2296cd6a6acSopenharmony_ci		}
2306cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_DONTAUDIT) {
2316cd6a6acSopenharmony_ci			fprintf(fp, "  dontaudit");
2326cd6a6acSopenharmony_ci		}
2336cd6a6acSopenharmony_ci	} else if (avrule->specified & AVRULE_TYPE) {
2346cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_TRANSITION) {
2356cd6a6acSopenharmony_ci			fprintf(fp, "  type_transition");
2366cd6a6acSopenharmony_ci		}
2376cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_MEMBER) {
2386cd6a6acSopenharmony_ci			fprintf(fp, "  type_member");
2396cd6a6acSopenharmony_ci		}
2406cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_CHANGE) {
2416cd6a6acSopenharmony_ci			fprintf(fp, "  type_change");
2426cd6a6acSopenharmony_ci		}
2436cd6a6acSopenharmony_ci	} else if (avrule->specified & AVRULE_NEVERALLOW) {
2446cd6a6acSopenharmony_ci		fprintf(fp, "  neverallow");
2456cd6a6acSopenharmony_ci	} else if (avrule->specified & AVRULE_XPERMS) {
2466cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_XPERMS_ALLOWED)
2476cd6a6acSopenharmony_ci			fprintf(fp, "allowxperm ");
2486cd6a6acSopenharmony_ci		else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW)
2496cd6a6acSopenharmony_ci			fprintf(fp, "auditallowxperm ");
2506cd6a6acSopenharmony_ci		else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT)
2516cd6a6acSopenharmony_ci			fprintf(fp, "dontauditxperm ");
2526cd6a6acSopenharmony_ci	} else {
2536cd6a6acSopenharmony_ci		fprintf(fp, "     ERROR: no valid rule type specified\n");
2546cd6a6acSopenharmony_ci		return -1;
2556cd6a6acSopenharmony_ci	}
2566cd6a6acSopenharmony_ci
2576cd6a6acSopenharmony_ci	if (display_type_set(&avrule->stypes, 0, policy, fp))
2586cd6a6acSopenharmony_ci		return -1;
2596cd6a6acSopenharmony_ci
2606cd6a6acSopenharmony_ci	if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
2616cd6a6acSopenharmony_ci		return -1;
2626cd6a6acSopenharmony_ci
2636cd6a6acSopenharmony_ci	fprintf(fp, " :");
2646cd6a6acSopenharmony_ci	cur = avrule->perms;
2656cd6a6acSopenharmony_ci	num_classes = 0;
2666cd6a6acSopenharmony_ci	while (cur) {
2676cd6a6acSopenharmony_ci		num_classes++;
2686cd6a6acSopenharmony_ci		if (num_classes > 1)
2696cd6a6acSopenharmony_ci			break;
2706cd6a6acSopenharmony_ci		cur = cur->next;
2716cd6a6acSopenharmony_ci	}
2726cd6a6acSopenharmony_ci
2736cd6a6acSopenharmony_ci	if (num_classes > 1)
2746cd6a6acSopenharmony_ci		fprintf(fp, " {");
2756cd6a6acSopenharmony_ci
2766cd6a6acSopenharmony_ci	cur = avrule->perms;
2776cd6a6acSopenharmony_ci	while (cur) {
2786cd6a6acSopenharmony_ci		display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
2796cd6a6acSopenharmony_ci		cur = cur->next;
2806cd6a6acSopenharmony_ci	}
2816cd6a6acSopenharmony_ci
2826cd6a6acSopenharmony_ci	if (num_classes > 1)
2836cd6a6acSopenharmony_ci		fprintf(fp, " }");
2846cd6a6acSopenharmony_ci	fprintf(fp, " ");
2856cd6a6acSopenharmony_ci
2866cd6a6acSopenharmony_ci	if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
2876cd6a6acSopenharmony_ci		render_access_mask(avrule->perms->data, avrule->perms->tclass,
2886cd6a6acSopenharmony_ci				   policy, fp);
2896cd6a6acSopenharmony_ci	} else if (avrule->specified & AVRULE_TYPE) {
2906cd6a6acSopenharmony_ci		display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
2916cd6a6acSopenharmony_ci	} else if (avrule->specified & AVRULE_XPERMS) {
2926cd6a6acSopenharmony_ci		avtab_extended_perms_t xperms;
2936cd6a6acSopenharmony_ci		int i;
2946cd6a6acSopenharmony_ci
2956cd6a6acSopenharmony_ci		if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION)
2966cd6a6acSopenharmony_ci			xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
2976cd6a6acSopenharmony_ci		else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER)
2986cd6a6acSopenharmony_ci			xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
2996cd6a6acSopenharmony_ci		else {
3006cd6a6acSopenharmony_ci			fprintf(fp, "     ERROR: no valid xperms specified\n");
3016cd6a6acSopenharmony_ci			return -1;
3026cd6a6acSopenharmony_ci		}
3036cd6a6acSopenharmony_ci
3046cd6a6acSopenharmony_ci		xperms.driver = avrule->xperms->driver;
3056cd6a6acSopenharmony_ci		for (i = 0; i < EXTENDED_PERMS_LEN; i++)
3066cd6a6acSopenharmony_ci			xperms.perms[i] = avrule->xperms->perms[i];
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_ci		fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms));
3096cd6a6acSopenharmony_ci	}
3106cd6a6acSopenharmony_ci
3116cd6a6acSopenharmony_ci	fprintf(fp, ";\n");
3126cd6a6acSopenharmony_ci
3136cd6a6acSopenharmony_ci	return 0;
3146cd6a6acSopenharmony_ci}
3156cd6a6acSopenharmony_ci
3166cd6a6acSopenharmony_cistatic int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
3176cd6a6acSopenharmony_ci{
3186cd6a6acSopenharmony_ci	type_datum_t *type;
3196cd6a6acSopenharmony_ci	FILE *fp;
3206cd6a6acSopenharmony_ci	unsigned int i, first_attrib = 1;
3216cd6a6acSopenharmony_ci
3226cd6a6acSopenharmony_ci	type = (type_datum_t *) datum;
3236cd6a6acSopenharmony_ci	fp = (FILE *) data;
3246cd6a6acSopenharmony_ci
3256cd6a6acSopenharmony_ci	if (type->primary) {
3266cd6a6acSopenharmony_ci		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
3276cd6a6acSopenharmony_ci		fprintf(fp, " [%d]: ", type->s.value);
3286cd6a6acSopenharmony_ci	} else {
3296cd6a6acSopenharmony_ci		/* as that aliases have no value of their own and that
3306cd6a6acSopenharmony_ci		 * they can never be required by a module, use this
3316cd6a6acSopenharmony_ci		 * alternative way of displaying a name */
3326cd6a6acSopenharmony_ci		fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
3336cd6a6acSopenharmony_ci	}
3346cd6a6acSopenharmony_ci	if (type->flavor == TYPE_ATTRIB) {
3356cd6a6acSopenharmony_ci		fprintf(fp, "attribute for types");
3366cd6a6acSopenharmony_ci		for (i = ebitmap_startbit(&type->types);
3376cd6a6acSopenharmony_ci		     i < ebitmap_length(&type->types); i++) {
3386cd6a6acSopenharmony_ci			if (!ebitmap_get_bit(&type->types, i))
3396cd6a6acSopenharmony_ci				continue;
3406cd6a6acSopenharmony_ci			if (first_attrib) {
3416cd6a6acSopenharmony_ci				first_attrib = 0;
3426cd6a6acSopenharmony_ci			} else {
3436cd6a6acSopenharmony_ci				fprintf(fp, ",");
3446cd6a6acSopenharmony_ci			}
3456cd6a6acSopenharmony_ci			display_id(&policydb, fp, SYM_TYPES, i, "");
3466cd6a6acSopenharmony_ci		}
3476cd6a6acSopenharmony_ci	} else if (type->primary) {
3486cd6a6acSopenharmony_ci		fprintf(fp, "type");
3496cd6a6acSopenharmony_ci	} else {
3506cd6a6acSopenharmony_ci		fprintf(fp, "alias for type");
3516cd6a6acSopenharmony_ci		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
3526cd6a6acSopenharmony_ci	}
3536cd6a6acSopenharmony_ci	fprintf(fp, " flags:%x\n", type->flags);
3546cd6a6acSopenharmony_ci
3556cd6a6acSopenharmony_ci	return 0;
3566cd6a6acSopenharmony_ci}
3576cd6a6acSopenharmony_ci
3586cd6a6acSopenharmony_cistatic int display_types(policydb_t * p, FILE * fp)
3596cd6a6acSopenharmony_ci{
3606cd6a6acSopenharmony_ci	if (hashtab_map(p->p_types.table, display_type_callback, fp))
3616cd6a6acSopenharmony_ci		return -1;
3626cd6a6acSopenharmony_ci	return 0;
3636cd6a6acSopenharmony_ci}
3646cd6a6acSopenharmony_ci
3656cd6a6acSopenharmony_cistatic int display_users(policydb_t * p, FILE * fp)
3666cd6a6acSopenharmony_ci{
3676cd6a6acSopenharmony_ci	unsigned int i, j;
3686cd6a6acSopenharmony_ci	ebitmap_t *bitmap;
3696cd6a6acSopenharmony_ci	for (i = 0; i < p->p_users.nprim; i++) {
3706cd6a6acSopenharmony_ci		display_id(p, fp, SYM_USERS, i, "");
3716cd6a6acSopenharmony_ci		fprintf(fp, ":");
3726cd6a6acSopenharmony_ci		bitmap = &(p->user_val_to_struct[i]->roles.roles);
3736cd6a6acSopenharmony_ci		for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
3746cd6a6acSopenharmony_ci		     j++) {
3756cd6a6acSopenharmony_ci			if (ebitmap_get_bit(bitmap, j)) {
3766cd6a6acSopenharmony_ci				display_id(p, fp, SYM_ROLES, j, "");
3776cd6a6acSopenharmony_ci			}
3786cd6a6acSopenharmony_ci		}
3796cd6a6acSopenharmony_ci		fprintf(fp, "\n");
3806cd6a6acSopenharmony_ci	}
3816cd6a6acSopenharmony_ci	return 0;
3826cd6a6acSopenharmony_ci}
3836cd6a6acSopenharmony_ci
3846cd6a6acSopenharmony_cistatic int display_bools(policydb_t * p, FILE * fp)
3856cd6a6acSopenharmony_ci{
3866cd6a6acSopenharmony_ci	unsigned int i;
3876cd6a6acSopenharmony_ci
3886cd6a6acSopenharmony_ci	for (i = 0; i < p->p_bools.nprim; i++) {
3896cd6a6acSopenharmony_ci		display_id(p, fp, SYM_BOOLS, i, "");
3906cd6a6acSopenharmony_ci		fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
3916cd6a6acSopenharmony_ci	}
3926cd6a6acSopenharmony_ci	return 0;
3936cd6a6acSopenharmony_ci}
3946cd6a6acSopenharmony_ci
3956cd6a6acSopenharmony_cistatic void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
3966cd6a6acSopenharmony_ci{
3976cd6a6acSopenharmony_ci
3986cd6a6acSopenharmony_ci	cond_expr_t *cur;
3996cd6a6acSopenharmony_ci	for (cur = exp; cur != NULL; cur = cur->next) {
4006cd6a6acSopenharmony_ci		switch (cur->expr_type) {
4016cd6a6acSopenharmony_ci		case COND_BOOL:
4026cd6a6acSopenharmony_ci			fprintf(fp, "%s ",
4036cd6a6acSopenharmony_ci				p->p_bool_val_to_name[cur->bool - 1]);
4046cd6a6acSopenharmony_ci			break;
4056cd6a6acSopenharmony_ci		case COND_NOT:
4066cd6a6acSopenharmony_ci			fprintf(fp, "! ");
4076cd6a6acSopenharmony_ci			break;
4086cd6a6acSopenharmony_ci		case COND_OR:
4096cd6a6acSopenharmony_ci			fprintf(fp, "|| ");
4106cd6a6acSopenharmony_ci			break;
4116cd6a6acSopenharmony_ci		case COND_AND:
4126cd6a6acSopenharmony_ci			fprintf(fp, "&& ");
4136cd6a6acSopenharmony_ci			break;
4146cd6a6acSopenharmony_ci		case COND_XOR:
4156cd6a6acSopenharmony_ci			fprintf(fp, "^ ");
4166cd6a6acSopenharmony_ci			break;
4176cd6a6acSopenharmony_ci		case COND_EQ:
4186cd6a6acSopenharmony_ci			fprintf(fp, "== ");
4196cd6a6acSopenharmony_ci			break;
4206cd6a6acSopenharmony_ci		case COND_NEQ:
4216cd6a6acSopenharmony_ci			fprintf(fp, "!= ");
4226cd6a6acSopenharmony_ci			break;
4236cd6a6acSopenharmony_ci		default:
4246cd6a6acSopenharmony_ci			fprintf(fp, "error!");
4256cd6a6acSopenharmony_ci			break;
4266cd6a6acSopenharmony_ci		}
4276cd6a6acSopenharmony_ci	}
4286cd6a6acSopenharmony_ci}
4296cd6a6acSopenharmony_ci
4306cd6a6acSopenharmony_cistatic void display_policycon(FILE * fp)
4316cd6a6acSopenharmony_ci{
4326cd6a6acSopenharmony_ci	/* There was an attempt to implement this at one time.  Look through
4336cd6a6acSopenharmony_ci	 * git history to find it. */
4346cd6a6acSopenharmony_ci	fprintf(fp, "Sorry, not implemented\n");
4356cd6a6acSopenharmony_ci}
4366cd6a6acSopenharmony_ci
4376cd6a6acSopenharmony_cistatic void display_initial_sids(policydb_t * p, FILE * fp)
4386cd6a6acSopenharmony_ci{
4396cd6a6acSopenharmony_ci	ocontext_t *cur;
4406cd6a6acSopenharmony_ci	char *user, *role, *type;
4416cd6a6acSopenharmony_ci
4426cd6a6acSopenharmony_ci	fprintf(fp, "Initial SIDs:\n");
4436cd6a6acSopenharmony_ci	for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
4446cd6a6acSopenharmony_ci		user = p->p_user_val_to_name[cur->context[0].user - 1];
4456cd6a6acSopenharmony_ci		role = p->p_role_val_to_name[cur->context[0].role - 1];
4466cd6a6acSopenharmony_ci		type = p->p_type_val_to_name[cur->context[0].type - 1];
4476cd6a6acSopenharmony_ci		fprintf(fp, "\tsid %d, context %s:%s:%s\n",
4486cd6a6acSopenharmony_ci			cur->sid[0], user, role, type);
4496cd6a6acSopenharmony_ci	}
4506cd6a6acSopenharmony_ci#if 0
4516cd6a6acSopenharmony_ci	fprintf(fp, "Policy Initial SIDs:\n");
4526cd6a6acSopenharmony_ci	for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
4536cd6a6acSopenharmony_ci		user = p->p_user_val_to_name[cur->context[0].user - 1];
4546cd6a6acSopenharmony_ci		role = p->p_role_val_to_name[cur->context[0].role - 1];
4556cd6a6acSopenharmony_ci		type = p->p_type_val_to_name[cur->context[0].type - 1];
4566cd6a6acSopenharmony_ci		fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
4576cd6a6acSopenharmony_ci			cur->u.name, cur->sid[0], user, role, type);
4586cd6a6acSopenharmony_ci	}
4596cd6a6acSopenharmony_ci#endif
4606cd6a6acSopenharmony_ci}
4616cd6a6acSopenharmony_ci
4626cd6a6acSopenharmony_cistatic void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
4636cd6a6acSopenharmony_ci{
4646cd6a6acSopenharmony_ci	unsigned int i, num = 0;
4656cd6a6acSopenharmony_ci
4666cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
4676cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(classes, i))
4686cd6a6acSopenharmony_ci			continue;
4696cd6a6acSopenharmony_ci		num++;
4706cd6a6acSopenharmony_ci		if (num > 1) {
4716cd6a6acSopenharmony_ci			fprintf(fp, "{");
4726cd6a6acSopenharmony_ci			break;
4736cd6a6acSopenharmony_ci		}
4746cd6a6acSopenharmony_ci	}
4756cd6a6acSopenharmony_ci
4766cd6a6acSopenharmony_ci	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
4776cd6a6acSopenharmony_ci		if (ebitmap_get_bit(classes, i))
4786cd6a6acSopenharmony_ci			display_id(p, fp, SYM_CLASSES, i, "");
4796cd6a6acSopenharmony_ci	}
4806cd6a6acSopenharmony_ci
4816cd6a6acSopenharmony_ci	if (num > 1)
4826cd6a6acSopenharmony_ci		fprintf(fp, " }");
4836cd6a6acSopenharmony_ci}
4846cd6a6acSopenharmony_ci
4856cd6a6acSopenharmony_cistatic void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
4866cd6a6acSopenharmony_ci{
4876cd6a6acSopenharmony_ci	for (; tr; tr = tr->next) {
4886cd6a6acSopenharmony_ci		fprintf(fp, "role transition ");
4896cd6a6acSopenharmony_ci		display_mod_role_set(&tr->roles, p, fp);
4906cd6a6acSopenharmony_ci		display_type_set(&tr->types, 0, p, fp);
4916cd6a6acSopenharmony_ci		fprintf(fp, " :");
4926cd6a6acSopenharmony_ci		display_class_set(&tr->classes, p, fp);
4936cd6a6acSopenharmony_ci		display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
4946cd6a6acSopenharmony_ci		fprintf(fp, "\n");
4956cd6a6acSopenharmony_ci	}
4966cd6a6acSopenharmony_ci}
4976cd6a6acSopenharmony_ci
4986cd6a6acSopenharmony_cistatic void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
4996cd6a6acSopenharmony_ci{
5006cd6a6acSopenharmony_ci	for (; ra; ra = ra->next) {
5016cd6a6acSopenharmony_ci		fprintf(fp, "role allow ");
5026cd6a6acSopenharmony_ci		display_mod_role_set(&ra->roles, p, fp);
5036cd6a6acSopenharmony_ci		display_mod_role_set(&ra->new_roles, p, fp);
5046cd6a6acSopenharmony_ci		fprintf(fp, "\n");
5056cd6a6acSopenharmony_ci	}
5066cd6a6acSopenharmony_ci}
5076cd6a6acSopenharmony_ci
5086cd6a6acSopenharmony_cistatic void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
5096cd6a6acSopenharmony_ci{
5106cd6a6acSopenharmony_ci	fprintf(fp, "filename transition");
5116cd6a6acSopenharmony_ci	for (; tr; tr = tr->next) {
5126cd6a6acSopenharmony_ci		display_type_set(&tr->stypes, 0, p, fp);
5136cd6a6acSopenharmony_ci		display_type_set(&tr->ttypes, 0, p, fp);
5146cd6a6acSopenharmony_ci		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
5156cd6a6acSopenharmony_ci		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
5166cd6a6acSopenharmony_ci		fprintf(fp, " %s\n", tr->name);
5176cd6a6acSopenharmony_ci	}
5186cd6a6acSopenharmony_ci}
5196cd6a6acSopenharmony_ci
5206cd6a6acSopenharmony_cistatic int role_display_callback(hashtab_key_t key __attribute__((unused)),
5216cd6a6acSopenharmony_ci			  hashtab_datum_t datum, void *data)
5226cd6a6acSopenharmony_ci{
5236cd6a6acSopenharmony_ci	role_datum_t *role;
5246cd6a6acSopenharmony_ci	FILE *fp;
5256cd6a6acSopenharmony_ci
5266cd6a6acSopenharmony_ci	role = (role_datum_t *) datum;
5276cd6a6acSopenharmony_ci	fp = (FILE *) data;
5286cd6a6acSopenharmony_ci
5296cd6a6acSopenharmony_ci	fprintf(fp, "role:");
5306cd6a6acSopenharmony_ci	display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
5316cd6a6acSopenharmony_ci	fprintf(fp, " types: ");
5326cd6a6acSopenharmony_ci	display_type_set(&role->types, 0, &policydb, fp);
5336cd6a6acSopenharmony_ci	fprintf(fp, "\n");
5346cd6a6acSopenharmony_ci
5356cd6a6acSopenharmony_ci	return 0;
5366cd6a6acSopenharmony_ci}
5376cd6a6acSopenharmony_ci
5386cd6a6acSopenharmony_cistatic int display_scope_index(scope_index_t * indices, policydb_t * p,
5396cd6a6acSopenharmony_ci			       FILE * out_fp)
5406cd6a6acSopenharmony_ci{
5416cd6a6acSopenharmony_ci	unsigned int i;
5426cd6a6acSopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
5436cd6a6acSopenharmony_ci		unsigned int any_found = 0, j;
5446cd6a6acSopenharmony_ci		fprintf(out_fp, "%s:", symbol_labels[i]);
5456cd6a6acSopenharmony_ci		for (j = ebitmap_startbit(&indices->scope[i]);
5466cd6a6acSopenharmony_ci		     j < ebitmap_length(&indices->scope[i]); j++) {
5476cd6a6acSopenharmony_ci			if (ebitmap_get_bit(&indices->scope[i], j)) {
5486cd6a6acSopenharmony_ci				any_found = 1;
5496cd6a6acSopenharmony_ci				fprintf(out_fp, " %s",
5506cd6a6acSopenharmony_ci					p->sym_val_to_name[i][j]);
5516cd6a6acSopenharmony_ci				if (i == SYM_CLASSES) {
5526cd6a6acSopenharmony_ci					if (j < indices->class_perms_len) {
5536cd6a6acSopenharmony_ci						render_access_bitmap(indices->
5546cd6a6acSopenharmony_ci								     class_perms_map
5556cd6a6acSopenharmony_ci								     + j, j + 1,
5566cd6a6acSopenharmony_ci								     p, out_fp);
5576cd6a6acSopenharmony_ci					} else {
5586cd6a6acSopenharmony_ci						fprintf(out_fp,
5596cd6a6acSopenharmony_ci							"<no perms known>");
5606cd6a6acSopenharmony_ci					}
5616cd6a6acSopenharmony_ci				}
5626cd6a6acSopenharmony_ci			}
5636cd6a6acSopenharmony_ci		}
5646cd6a6acSopenharmony_ci		if (!any_found) {
5656cd6a6acSopenharmony_ci			fprintf(out_fp, " <empty>");
5666cd6a6acSopenharmony_ci		}
5676cd6a6acSopenharmony_ci		fprintf(out_fp, "\n");
5686cd6a6acSopenharmony_ci	}
5696cd6a6acSopenharmony_ci	return 0;
5706cd6a6acSopenharmony_ci}
5716cd6a6acSopenharmony_ci
5726cd6a6acSopenharmony_ci#if 0
5736cd6a6acSopenharmony_ciint display_cond_expressions(policydb_t * p, FILE * fp)
5746cd6a6acSopenharmony_ci{
5756cd6a6acSopenharmony_ci	cond_node_t *cur;
5766cd6a6acSopenharmony_ci	cond_av_list_t *av_cur;
5776cd6a6acSopenharmony_ci	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
5786cd6a6acSopenharmony_ci		fprintf(fp, "expression: ");
5796cd6a6acSopenharmony_ci		display_expr(p, cur->expr, fp);
5806cd6a6acSopenharmony_ci		fprintf(fp, "current state: %d\n", cur->cur_state);
5816cd6a6acSopenharmony_ci		fprintf(fp, "True list:\n");
5826cd6a6acSopenharmony_ci		for (av_cur = cur->true_list; av_cur != NULL;
5836cd6a6acSopenharmony_ci		     av_cur = av_cur->next) {
5846cd6a6acSopenharmony_ci			fprintf(fp, "\t");
5856cd6a6acSopenharmony_ci			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
5866cd6a6acSopenharmony_ci				       RENDER_CONDITIONAL, p, fp);
5876cd6a6acSopenharmony_ci		}
5886cd6a6acSopenharmony_ci		fprintf(fp, "False list:\n");
5896cd6a6acSopenharmony_ci		for (av_cur = cur->false_list; av_cur != NULL;
5906cd6a6acSopenharmony_ci		     av_cur = av_cur->next) {
5916cd6a6acSopenharmony_ci			fprintf(fp, "\t");
5926cd6a6acSopenharmony_ci			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
5936cd6a6acSopenharmony_ci				       RENDER_CONDITIONAL, p, fp);
5946cd6a6acSopenharmony_ci		}
5956cd6a6acSopenharmony_ci	}
5966cd6a6acSopenharmony_ci	return 0;
5976cd6a6acSopenharmony_ci}
5986cd6a6acSopenharmony_ci
5996cd6a6acSopenharmony_ciint change_bool(char *name, int state, policydb_t * p, FILE * fp)
6006cd6a6acSopenharmony_ci{
6016cd6a6acSopenharmony_ci	cond_bool_datum_t *bool;
6026cd6a6acSopenharmony_ci
6036cd6a6acSopenharmony_ci	bool = hashtab_search(p->p_bools.table, name);
6046cd6a6acSopenharmony_ci	if (bool == NULL) {
6056cd6a6acSopenharmony_ci		fprintf(fp, "Could not find bool %s\n", name);
6066cd6a6acSopenharmony_ci		return -1;
6076cd6a6acSopenharmony_ci	}
6086cd6a6acSopenharmony_ci	bool->state = state;
6096cd6a6acSopenharmony_ci	evaluate_conds(p);
6106cd6a6acSopenharmony_ci	return 0;
6116cd6a6acSopenharmony_ci}
6126cd6a6acSopenharmony_ci#endif
6136cd6a6acSopenharmony_ci
6146cd6a6acSopenharmony_cistatic int display_avdecl(avrule_decl_t * decl, int field,
6156cd6a6acSopenharmony_ci		   policydb_t * policy, FILE * out_fp)
6166cd6a6acSopenharmony_ci{
6176cd6a6acSopenharmony_ci	fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
6186cd6a6acSopenharmony_ci		(decl->enabled ? " [enabled]" : ""));
6196cd6a6acSopenharmony_ci	switch (field) {
6206cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_COND_AVTAB:{
6216cd6a6acSopenharmony_ci			cond_list_t *cond = decl->cond_list;
6226cd6a6acSopenharmony_ci			avrule_t *avrule;
6236cd6a6acSopenharmony_ci			while (cond) {
6246cd6a6acSopenharmony_ci				fprintf(out_fp, "expression: ");
6256cd6a6acSopenharmony_ci				display_expr(&policydb, cond->expr, out_fp);
6266cd6a6acSopenharmony_ci				fprintf(out_fp, "current state: %d\n",
6276cd6a6acSopenharmony_ci					cond->cur_state);
6286cd6a6acSopenharmony_ci				fprintf(out_fp, "True list:\n");
6296cd6a6acSopenharmony_ci				avrule = cond->avtrue_list;
6306cd6a6acSopenharmony_ci				while (avrule) {
6316cd6a6acSopenharmony_ci					display_avrule(avrule,
6326cd6a6acSopenharmony_ci						       &policydb, out_fp);
6336cd6a6acSopenharmony_ci					avrule = avrule->next;
6346cd6a6acSopenharmony_ci				}
6356cd6a6acSopenharmony_ci				fprintf(out_fp, "False list:\n");
6366cd6a6acSopenharmony_ci				avrule = cond->avfalse_list;
6376cd6a6acSopenharmony_ci				while (avrule) {
6386cd6a6acSopenharmony_ci					display_avrule(avrule,
6396cd6a6acSopenharmony_ci						       &policydb, out_fp);
6406cd6a6acSopenharmony_ci					avrule = avrule->next;
6416cd6a6acSopenharmony_ci				}
6426cd6a6acSopenharmony_ci				cond = cond->next;
6436cd6a6acSopenharmony_ci			}
6446cd6a6acSopenharmony_ci			break;
6456cd6a6acSopenharmony_ci		}
6466cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
6476cd6a6acSopenharmony_ci			avrule_t *avrule = decl->avrules;
6486cd6a6acSopenharmony_ci			if (avrule == NULL) {
6496cd6a6acSopenharmony_ci				fprintf(out_fp, "  <empty>\n");
6506cd6a6acSopenharmony_ci			}
6516cd6a6acSopenharmony_ci			while (avrule != NULL) {
6526cd6a6acSopenharmony_ci				if (display_avrule(avrule, policy, out_fp))
6536cd6a6acSopenharmony_ci					return -1;
6546cd6a6acSopenharmony_ci				avrule = avrule->next;
6556cd6a6acSopenharmony_ci			}
6566cd6a6acSopenharmony_ci			break;
6576cd6a6acSopenharmony_ci		}
6586cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{	/* role_type_node */
6596cd6a6acSopenharmony_ci			break;
6606cd6a6acSopenharmony_ci		}
6616cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_ROLE_TRANS:{
6626cd6a6acSopenharmony_ci			display_role_trans(decl->role_tr_rules, policy, out_fp);
6636cd6a6acSopenharmony_ci			break;
6646cd6a6acSopenharmony_ci		}
6656cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_ROLE_ALLOW:{
6666cd6a6acSopenharmony_ci			display_role_allow(decl->role_allow_rules, policy,
6676cd6a6acSopenharmony_ci					   out_fp);
6686cd6a6acSopenharmony_ci			break;
6696cd6a6acSopenharmony_ci		}
6706cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_REQUIRES:{
6716cd6a6acSopenharmony_ci			if (display_scope_index
6726cd6a6acSopenharmony_ci			    (&decl->required, policy, out_fp)) {
6736cd6a6acSopenharmony_ci				return -1;
6746cd6a6acSopenharmony_ci			}
6756cd6a6acSopenharmony_ci			break;
6766cd6a6acSopenharmony_ci		}
6776cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_DECLARES:{
6786cd6a6acSopenharmony_ci			if (display_scope_index
6796cd6a6acSopenharmony_ci			    (&decl->declared, policy, out_fp)) {
6806cd6a6acSopenharmony_ci				return -1;
6816cd6a6acSopenharmony_ci			}
6826cd6a6acSopenharmony_ci			break;
6836cd6a6acSopenharmony_ci		}
6846cd6a6acSopenharmony_ci	case DISPLAY_AVBLOCK_FILENAME_TRANS:
6856cd6a6acSopenharmony_ci		display_filename_trans(decl->filename_trans_rules, policy,
6866cd6a6acSopenharmony_ci				       out_fp);
6876cd6a6acSopenharmony_ci		break;
6886cd6a6acSopenharmony_ci	default:{
6896cd6a6acSopenharmony_ci			assert(0);
6906cd6a6acSopenharmony_ci		}
6916cd6a6acSopenharmony_ci	}
6926cd6a6acSopenharmony_ci	return 0;		/* should never get here */
6936cd6a6acSopenharmony_ci}
6946cd6a6acSopenharmony_ci
6956cd6a6acSopenharmony_cistatic int display_avblock(int field, policydb_t * policy,
6966cd6a6acSopenharmony_ci		    FILE * out_fp)
6976cd6a6acSopenharmony_ci{
6986cd6a6acSopenharmony_ci	avrule_block_t *block = policydb.global;
6996cd6a6acSopenharmony_ci	while (block != NULL) {
7006cd6a6acSopenharmony_ci		avrule_decl_t *decl = block->branch_list;
7016cd6a6acSopenharmony_ci		fprintf(out_fp, "--- begin avrule block ---\n");
7026cd6a6acSopenharmony_ci		while (decl != NULL) {
7036cd6a6acSopenharmony_ci			if (display_avdecl(decl, field, policy, out_fp)) {
7046cd6a6acSopenharmony_ci				return -1;
7056cd6a6acSopenharmony_ci			}
7066cd6a6acSopenharmony_ci			decl = decl->next;
7076cd6a6acSopenharmony_ci		}
7086cd6a6acSopenharmony_ci		block = block->next;
7096cd6a6acSopenharmony_ci	}
7106cd6a6acSopenharmony_ci	return 0;
7116cd6a6acSopenharmony_ci}
7126cd6a6acSopenharmony_ci
7136cd6a6acSopenharmony_cistatic int display_handle_unknown(policydb_t * p, FILE * out_fp)
7146cd6a6acSopenharmony_ci{
7156cd6a6acSopenharmony_ci	if (p->handle_unknown == ALLOW_UNKNOWN)
7166cd6a6acSopenharmony_ci		fprintf(out_fp, "Allow unknown classes and perms\n");
7176cd6a6acSopenharmony_ci	else if (p->handle_unknown == DENY_UNKNOWN)
7186cd6a6acSopenharmony_ci		fprintf(out_fp, "Deny unknown classes and perms\n");
7196cd6a6acSopenharmony_ci	else if (p->handle_unknown == REJECT_UNKNOWN)
7206cd6a6acSopenharmony_ci		fprintf(out_fp, "Reject unknown classes and perms\n");
7216cd6a6acSopenharmony_ci	return 0;
7226cd6a6acSopenharmony_ci}
7236cd6a6acSopenharmony_ci
7246cd6a6acSopenharmony_cistatic int read_policy(char *filename, policydb_t * policy)
7256cd6a6acSopenharmony_ci{
7266cd6a6acSopenharmony_ci	FILE *in_fp;
7276cd6a6acSopenharmony_ci	struct policy_file f;
7286cd6a6acSopenharmony_ci	int retval;
7296cd6a6acSopenharmony_ci	uint32_t buf[1];
7306cd6a6acSopenharmony_ci
7316cd6a6acSopenharmony_ci	if ((in_fp = fopen(filename, "rb")) == NULL) {
7326cd6a6acSopenharmony_ci		fprintf(stderr, "Can't open '%s':  %s\n",
7336cd6a6acSopenharmony_ci			filename, strerror(errno));
7346cd6a6acSopenharmony_ci		exit(1);
7356cd6a6acSopenharmony_ci	}
7366cd6a6acSopenharmony_ci	policy_file_init(&f);
7376cd6a6acSopenharmony_ci	f.type = PF_USE_STDIO;
7386cd6a6acSopenharmony_ci	f.fp = in_fp;
7396cd6a6acSopenharmony_ci
7406cd6a6acSopenharmony_ci	/* peek at the first byte.  if they are indicative of a
7416cd6a6acSopenharmony_ci	   package use the package reader, otherwise use the normal
7426cd6a6acSopenharmony_ci	   policy reader */
7436cd6a6acSopenharmony_ci	if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
7446cd6a6acSopenharmony_ci		fprintf(stderr, "Could not read from policy.\n");
7456cd6a6acSopenharmony_ci		exit(1);
7466cd6a6acSopenharmony_ci	}
7476cd6a6acSopenharmony_ci	rewind(in_fp);
7486cd6a6acSopenharmony_ci	if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
7496cd6a6acSopenharmony_ci		sepol_module_package_t *package;
7506cd6a6acSopenharmony_ci		if (sepol_module_package_create(&package)) {
7516cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
7526cd6a6acSopenharmony_ci			exit(1);
7536cd6a6acSopenharmony_ci		}
7546cd6a6acSopenharmony_ci		sepol_policydb_free(package->policy);
7556cd6a6acSopenharmony_ci		package->policy = (sepol_policydb_t *) policy;
7566cd6a6acSopenharmony_ci		package->file_contexts = NULL;
7576cd6a6acSopenharmony_ci		retval =
7586cd6a6acSopenharmony_ci		    sepol_module_package_read(package,
7596cd6a6acSopenharmony_ci					      (sepol_policy_file_t *) & f, 1);
7606cd6a6acSopenharmony_ci		package->policy = NULL;
7616cd6a6acSopenharmony_ci		sepol_module_package_free(package);
7626cd6a6acSopenharmony_ci	} else {
7636cd6a6acSopenharmony_ci		if (policydb_init(policy)) {
7646cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
7656cd6a6acSopenharmony_ci			exit(1);
7666cd6a6acSopenharmony_ci		}
7676cd6a6acSopenharmony_ci		retval = policydb_read(policy, &f, 1);
7686cd6a6acSopenharmony_ci	}
7696cd6a6acSopenharmony_ci	fclose(in_fp);
7706cd6a6acSopenharmony_ci	return retval;
7716cd6a6acSopenharmony_ci}
7726cd6a6acSopenharmony_ci
7736cd6a6acSopenharmony_cistatic void link_module(policydb_t * base, FILE * out_fp)
7746cd6a6acSopenharmony_ci{
7756cd6a6acSopenharmony_ci	char module_name[80] = { 0 };
7766cd6a6acSopenharmony_ci	int ret;
7776cd6a6acSopenharmony_ci	policydb_t module, *mods = &module;
7786cd6a6acSopenharmony_ci
7796cd6a6acSopenharmony_ci	if (base->policy_type != POLICY_BASE) {
7806cd6a6acSopenharmony_ci		printf("Can only link if initial file was a base policy.\n");
7816cd6a6acSopenharmony_ci		return;
7826cd6a6acSopenharmony_ci	}
7836cd6a6acSopenharmony_ci	printf("\nModule filename: ");
7846cd6a6acSopenharmony_ci	if (fgets(module_name, sizeof(module_name), stdin) == NULL) {
7856cd6a6acSopenharmony_ci		fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
7866cd6a6acSopenharmony_ci				strerror(errno));
7876cd6a6acSopenharmony_ci		exit(1);
7886cd6a6acSopenharmony_ci	}
7896cd6a6acSopenharmony_ci
7906cd6a6acSopenharmony_ci	module_name[strlen(module_name) - 1] = '\0';	/* remove LF */
7916cd6a6acSopenharmony_ci	if (module_name[0] == '\0') {
7926cd6a6acSopenharmony_ci		return;
7936cd6a6acSopenharmony_ci	}
7946cd6a6acSopenharmony_ci
7956cd6a6acSopenharmony_ci	/* read the binary policy */
7966cd6a6acSopenharmony_ci	fprintf(out_fp, "Reading module...\n");
7976cd6a6acSopenharmony_ci	if (read_policy(module_name, mods)) {
7986cd6a6acSopenharmony_ci		fprintf(stderr,
7996cd6a6acSopenharmony_ci			"%s:  error(s) encountered while loading policy\n",
8006cd6a6acSopenharmony_ci			module_name);
8016cd6a6acSopenharmony_ci		exit(1);
8026cd6a6acSopenharmony_ci	}
8036cd6a6acSopenharmony_ci	if (module.policy_type != POLICY_MOD) {
8046cd6a6acSopenharmony_ci		fprintf(stderr, "This file is not a loadable policy module.\n");
8056cd6a6acSopenharmony_ci		exit(1);
8066cd6a6acSopenharmony_ci	}
8076cd6a6acSopenharmony_ci	if (policydb_index_classes(&module) ||
8086cd6a6acSopenharmony_ci	    policydb_index_others(NULL, &module, 0)) {
8096cd6a6acSopenharmony_ci		fprintf(stderr, "Could not index module.\n");
8106cd6a6acSopenharmony_ci		exit(1);
8116cd6a6acSopenharmony_ci	}
8126cd6a6acSopenharmony_ci	ret = link_modules(NULL, base, &mods, 1, 0);
8136cd6a6acSopenharmony_ci	if (ret != 0) {
8146cd6a6acSopenharmony_ci		printf("Link failed (error %d)\n", ret);
8156cd6a6acSopenharmony_ci		printf("(You will probably need to restart dismod.)\n");
8166cd6a6acSopenharmony_ci	}
8176cd6a6acSopenharmony_ci	policydb_destroy(&module);
8186cd6a6acSopenharmony_ci	return;
8196cd6a6acSopenharmony_ci}
8206cd6a6acSopenharmony_ci
8216cd6a6acSopenharmony_cistatic void display_policycaps(policydb_t * p, FILE * fp)
8226cd6a6acSopenharmony_ci{
8236cd6a6acSopenharmony_ci	ebitmap_node_t *node;
8246cd6a6acSopenharmony_ci	const char *capname;
8256cd6a6acSopenharmony_ci	char buf[64];
8266cd6a6acSopenharmony_ci	unsigned int i;
8276cd6a6acSopenharmony_ci
8286cd6a6acSopenharmony_ci	fprintf(fp, "policy capabilities:\n");
8296cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
8306cd6a6acSopenharmony_ci		capname = sepol_polcap_getname(i);
8316cd6a6acSopenharmony_ci		if (capname == NULL) {
8326cd6a6acSopenharmony_ci			snprintf(buf, sizeof(buf), "unknown (%u)", i);
8336cd6a6acSopenharmony_ci			capname = buf;
8346cd6a6acSopenharmony_ci		}
8356cd6a6acSopenharmony_ci		fprintf(fp, "\t%s\n", capname);
8366cd6a6acSopenharmony_ci	}
8376cd6a6acSopenharmony_ci}
8386cd6a6acSopenharmony_ci
8396cd6a6acSopenharmony_cistatic int menu(void)
8406cd6a6acSopenharmony_ci{
8416cd6a6acSopenharmony_ci	printf("\nSelect a command:\n");
8426cd6a6acSopenharmony_ci	printf("1)  display unconditional AVTAB\n");
8436cd6a6acSopenharmony_ci	printf("2)  display conditional AVTAB\n");
8446cd6a6acSopenharmony_ci	printf("3)  display users\n");
8456cd6a6acSopenharmony_ci	printf("4)  display bools\n");
8466cd6a6acSopenharmony_ci	printf("5)  display roles\n");
8476cd6a6acSopenharmony_ci	printf("6)  display types, attributes, and aliases\n");
8486cd6a6acSopenharmony_ci	printf("7)  display role transitions\n");
8496cd6a6acSopenharmony_ci	printf("8)  display role allows\n");
8506cd6a6acSopenharmony_ci	printf("9)  Display policycon\n");
8516cd6a6acSopenharmony_ci	printf("0)  Display initial SIDs\n");
8526cd6a6acSopenharmony_ci	printf("\n");
8536cd6a6acSopenharmony_ci	printf("a)  Display avrule requirements\n");
8546cd6a6acSopenharmony_ci	printf("b)  Display avrule declarations\n");
8556cd6a6acSopenharmony_ci	printf("c)  Display policy capabilities\n");
8566cd6a6acSopenharmony_ci	printf("l)  Link in a module\n");
8576cd6a6acSopenharmony_ci	printf("u)  Display the unknown handling setting\n");
8586cd6a6acSopenharmony_ci	printf("F)  Display filename_trans rules\n");
8596cd6a6acSopenharmony_ci	printf("\n");
8606cd6a6acSopenharmony_ci	printf("f)  set output file\n");
8616cd6a6acSopenharmony_ci	printf("m)  display menu\n");
8626cd6a6acSopenharmony_ci	printf("q)  quit\n");
8636cd6a6acSopenharmony_ci	return 0;
8646cd6a6acSopenharmony_ci}
8656cd6a6acSopenharmony_ci
8666cd6a6acSopenharmony_ciint main(int argc, char **argv)
8676cd6a6acSopenharmony_ci{
8686cd6a6acSopenharmony_ci	FILE *out_fp = stdout;
8696cd6a6acSopenharmony_ci	char ans[81], OutfileName[121];
8706cd6a6acSopenharmony_ci
8716cd6a6acSopenharmony_ci	if (argc != 2)
8726cd6a6acSopenharmony_ci		usage(argv[0]);
8736cd6a6acSopenharmony_ci
8746cd6a6acSopenharmony_ci	/* read the binary policy */
8756cd6a6acSopenharmony_ci	fprintf(out_fp, "Reading policy...\n");
8766cd6a6acSopenharmony_ci	if (policydb_init(&policydb)) {
8776cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
8786cd6a6acSopenharmony_ci		exit(1);
8796cd6a6acSopenharmony_ci	}
8806cd6a6acSopenharmony_ci	if (read_policy(argv[1], &policydb)) {
8816cd6a6acSopenharmony_ci		fprintf(stderr,
8826cd6a6acSopenharmony_ci			"%s:  error(s) encountered while loading policy\n",
8836cd6a6acSopenharmony_ci			argv[0]);
8846cd6a6acSopenharmony_ci		exit(1);
8856cd6a6acSopenharmony_ci	}
8866cd6a6acSopenharmony_ci
8876cd6a6acSopenharmony_ci	if (policydb.policy_type != POLICY_BASE &&
8886cd6a6acSopenharmony_ci	    policydb.policy_type != POLICY_MOD) {
8896cd6a6acSopenharmony_ci		fprintf(stderr,
8906cd6a6acSopenharmony_ci			"This file is neither a base nor loadable policy module.\n");
8916cd6a6acSopenharmony_ci		exit(1);
8926cd6a6acSopenharmony_ci	}
8936cd6a6acSopenharmony_ci
8946cd6a6acSopenharmony_ci	if (policydb_index_classes(&policydb)) {
8956cd6a6acSopenharmony_ci		fprintf(stderr, "Error indexing classes\n");
8966cd6a6acSopenharmony_ci		exit(1);
8976cd6a6acSopenharmony_ci	}
8986cd6a6acSopenharmony_ci
8996cd6a6acSopenharmony_ci	if (policydb_index_others(NULL, &policydb, 1)) {
9006cd6a6acSopenharmony_ci		fprintf(stderr, "Error indexing others\n");
9016cd6a6acSopenharmony_ci		exit(1);
9026cd6a6acSopenharmony_ci	}
9036cd6a6acSopenharmony_ci
9046cd6a6acSopenharmony_ci	if (policydb.policy_type == POLICY_BASE) {
9056cd6a6acSopenharmony_ci		printf("Binary base policy file loaded.\n");
9066cd6a6acSopenharmony_ci	} else {
9076cd6a6acSopenharmony_ci		printf("Binary policy module file loaded.\n");
9086cd6a6acSopenharmony_ci		printf("Module name: %s\n", policydb.name);
9096cd6a6acSopenharmony_ci		printf("Module version: %s\n", policydb.version);
9106cd6a6acSopenharmony_ci	}
9116cd6a6acSopenharmony_ci
9126cd6a6acSopenharmony_ci	printf("Policy version: %d\n\n", policydb.policyvers);
9136cd6a6acSopenharmony_ci	menu();
9146cd6a6acSopenharmony_ci	for (;;) {
9156cd6a6acSopenharmony_ci		printf("\nCommand (\'m\' for menu):  ");
9166cd6a6acSopenharmony_ci		if (fgets(ans, sizeof(ans), stdin) == NULL) {
9176cd6a6acSopenharmony_ci			fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
9186cd6a6acSopenharmony_ci					strerror(errno));
9196cd6a6acSopenharmony_ci			continue;
9206cd6a6acSopenharmony_ci		}
9216cd6a6acSopenharmony_ci
9226cd6a6acSopenharmony_ci		switch (ans[0]) {
9236cd6a6acSopenharmony_ci
9246cd6a6acSopenharmony_ci		case '1':
9256cd6a6acSopenharmony_ci			fprintf(out_fp, "unconditional avtab:\n");
9266cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
9276cd6a6acSopenharmony_ci					&policydb, out_fp);
9286cd6a6acSopenharmony_ci			break;
9296cd6a6acSopenharmony_ci		case '2':
9306cd6a6acSopenharmony_ci			fprintf(out_fp, "conditional avtab:\n");
9316cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
9326cd6a6acSopenharmony_ci					&policydb, out_fp);
9336cd6a6acSopenharmony_ci			break;
9346cd6a6acSopenharmony_ci		case '3':
9356cd6a6acSopenharmony_ci			display_users(&policydb, out_fp);
9366cd6a6acSopenharmony_ci			break;
9376cd6a6acSopenharmony_ci		case '4':
9386cd6a6acSopenharmony_ci			display_bools(&policydb, out_fp);
9396cd6a6acSopenharmony_ci			break;
9406cd6a6acSopenharmony_ci		case '5':
9416cd6a6acSopenharmony_ci			if (hashtab_map
9426cd6a6acSopenharmony_ci			    (policydb.p_roles.table, role_display_callback,
9436cd6a6acSopenharmony_ci			     out_fp))
9446cd6a6acSopenharmony_ci				exit(1);
9456cd6a6acSopenharmony_ci			break;
9466cd6a6acSopenharmony_ci		case '6':
9476cd6a6acSopenharmony_ci			if (display_types(&policydb, out_fp)) {
9486cd6a6acSopenharmony_ci				fprintf(stderr, "Error displaying types\n");
9496cd6a6acSopenharmony_ci				exit(1);
9506cd6a6acSopenharmony_ci			}
9516cd6a6acSopenharmony_ci			break;
9526cd6a6acSopenharmony_ci		case '7':
9536cd6a6acSopenharmony_ci			fprintf(out_fp, "role transitions:\n");
9546cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
9556cd6a6acSopenharmony_ci					&policydb, out_fp);
9566cd6a6acSopenharmony_ci			break;
9576cd6a6acSopenharmony_ci		case '8':
9586cd6a6acSopenharmony_ci			fprintf(out_fp, "role allows:\n");
9596cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
9606cd6a6acSopenharmony_ci					&policydb, out_fp);
9616cd6a6acSopenharmony_ci			break;
9626cd6a6acSopenharmony_ci		case '9':
9636cd6a6acSopenharmony_ci			display_policycon(out_fp);
9646cd6a6acSopenharmony_ci			break;
9656cd6a6acSopenharmony_ci		case '0':
9666cd6a6acSopenharmony_ci			display_initial_sids(&policydb, out_fp);
9676cd6a6acSopenharmony_ci			break;
9686cd6a6acSopenharmony_ci		case 'a':
9696cd6a6acSopenharmony_ci			fprintf(out_fp, "avrule block requirements:\n");
9706cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_REQUIRES,
9716cd6a6acSopenharmony_ci					&policydb, out_fp);
9726cd6a6acSopenharmony_ci			break;
9736cd6a6acSopenharmony_ci		case 'b':
9746cd6a6acSopenharmony_ci			fprintf(out_fp, "avrule block declarations:\n");
9756cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_DECLARES,
9766cd6a6acSopenharmony_ci					&policydb, out_fp);
9776cd6a6acSopenharmony_ci			break;
9786cd6a6acSopenharmony_ci		case 'c':
9796cd6a6acSopenharmony_ci			display_policycaps(&policydb, out_fp);
9806cd6a6acSopenharmony_ci			break;
9816cd6a6acSopenharmony_ci		case 'u':
9826cd6a6acSopenharmony_ci		case 'U':
9836cd6a6acSopenharmony_ci			display_handle_unknown(&policydb, out_fp);
9846cd6a6acSopenharmony_ci			break;
9856cd6a6acSopenharmony_ci		case 'f':
9866cd6a6acSopenharmony_ci			printf
9876cd6a6acSopenharmony_ci			    ("\nFilename for output (<CR> for screen output): ");
9886cd6a6acSopenharmony_ci			if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
9896cd6a6acSopenharmony_ci				fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
9906cd6a6acSopenharmony_ci						strerror(errno));
9916cd6a6acSopenharmony_ci				break;
9926cd6a6acSopenharmony_ci			}
9936cd6a6acSopenharmony_ci			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
9946cd6a6acSopenharmony_ci			if (strlen(OutfileName) == 0)
9956cd6a6acSopenharmony_ci				out_fp = stdout;
9966cd6a6acSopenharmony_ci			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
9976cd6a6acSopenharmony_ci				fprintf(stderr, "Cannot open output file %s\n",
9986cd6a6acSopenharmony_ci					OutfileName);
9996cd6a6acSopenharmony_ci				out_fp = stdout;
10006cd6a6acSopenharmony_ci			}
10016cd6a6acSopenharmony_ci			if (out_fp != stdout)
10026cd6a6acSopenharmony_ci				printf("\nOutput to file: %s\n", OutfileName);
10036cd6a6acSopenharmony_ci			break;
10046cd6a6acSopenharmony_ci		case 'F':
10056cd6a6acSopenharmony_ci			fprintf(out_fp, "filename_trans rules:\n");
10066cd6a6acSopenharmony_ci			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
10076cd6a6acSopenharmony_ci					&policydb, out_fp);
10086cd6a6acSopenharmony_ci			break;
10096cd6a6acSopenharmony_ci		case 'l':
10106cd6a6acSopenharmony_ci			link_module(&policydb, out_fp);
10116cd6a6acSopenharmony_ci			break;
10126cd6a6acSopenharmony_ci		case 'q':
10136cd6a6acSopenharmony_ci			policydb_destroy(&policydb);
10146cd6a6acSopenharmony_ci			exit(0);
10156cd6a6acSopenharmony_ci			break;
10166cd6a6acSopenharmony_ci		case 'm':
10176cd6a6acSopenharmony_ci			menu();
10186cd6a6acSopenharmony_ci			break;
10196cd6a6acSopenharmony_ci		default:
10206cd6a6acSopenharmony_ci			printf("\nInvalid choice\n");
10216cd6a6acSopenharmony_ci			menu();
10226cd6a6acSopenharmony_ci			break;
10236cd6a6acSopenharmony_ci
10246cd6a6acSopenharmony_ci		}
10256cd6a6acSopenharmony_ci	}
10266cd6a6acSopenharmony_ci	exit(EXIT_SUCCESS);
10276cd6a6acSopenharmony_ci}
1028