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