xref: /aosp_15_r20/external/selinux/checkpolicy/policy_define.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * Author : Stephen Smalley, <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker  */
4*2d543d20SAndroid Build Coastguard Worker 
5*2d543d20SAndroid Build Coastguard Worker /*
6*2d543d20SAndroid Build Coastguard Worker  * Updated: Trusted Computer Solutions, Inc. <[email protected]>
7*2d543d20SAndroid Build Coastguard Worker  *
8*2d543d20SAndroid Build Coastguard Worker  *	Support for enhanced MLS infrastructure.
9*2d543d20SAndroid Build Coastguard Worker  *
10*2d543d20SAndroid Build Coastguard Worker  * Updated: David Caplan, <[email protected]>
11*2d543d20SAndroid Build Coastguard Worker  *
12*2d543d20SAndroid Build Coastguard Worker  * 	Added conditional policy language extensions
13*2d543d20SAndroid Build Coastguard Worker  *
14*2d543d20SAndroid Build Coastguard Worker  * Updated: Joshua Brindle <[email protected]>
15*2d543d20SAndroid Build Coastguard Worker  *	    Karl MacMillan <[email protected]>
16*2d543d20SAndroid Build Coastguard Worker  *          Jason Tang     <[email protected]>
17*2d543d20SAndroid Build Coastguard Worker  *
18*2d543d20SAndroid Build Coastguard Worker  *	Added support for binary policy modules
19*2d543d20SAndroid Build Coastguard Worker  *
20*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
21*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
22*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2007 Red Hat Inc.
23*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2017 Mellanox Techonologies Inc.
24*2d543d20SAndroid Build Coastguard Worker  *	This program is free software; you can redistribute it and/or modify
25*2d543d20SAndroid Build Coastguard Worker  *  	it under the terms of the GNU General Public License as published by
26*2d543d20SAndroid Build Coastguard Worker  *	the Free Software Foundation, version 2.
27*2d543d20SAndroid Build Coastguard Worker  */
28*2d543d20SAndroid Build Coastguard Worker 
29*2d543d20SAndroid Build Coastguard Worker /* FLASK */
30*2d543d20SAndroid Build Coastguard Worker 
31*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
32*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
33*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
34*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
35*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
36*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
37*2d543d20SAndroid Build Coastguard Worker #include <string.h>
38*2d543d20SAndroid Build Coastguard Worker #include <sys/socket.h>
39*2d543d20SAndroid Build Coastguard Worker #include <netinet/in.h>
40*2d543d20SAndroid Build Coastguard Worker #ifndef IPPROTO_DCCP
41*2d543d20SAndroid Build Coastguard Worker #define IPPROTO_DCCP 33
42*2d543d20SAndroid Build Coastguard Worker #endif
43*2d543d20SAndroid Build Coastguard Worker #ifndef IPPROTO_SCTP
44*2d543d20SAndroid Build Coastguard Worker #define IPPROTO_SCTP 132
45*2d543d20SAndroid Build Coastguard Worker #endif
46*2d543d20SAndroid Build Coastguard Worker #include <arpa/inet.h>
47*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
48*2d543d20SAndroid Build Coastguard Worker #include <inttypes.h>
49*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
50*2d543d20SAndroid Build Coastguard Worker 
51*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/expand.h>
52*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
53*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/services.h>
54*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
55*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/hierarchy.h>
56*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/polcaps.h>
57*2d543d20SAndroid Build Coastguard Worker #include "queue.h"
58*2d543d20SAndroid Build Coastguard Worker #include "module_compiler.h"
59*2d543d20SAndroid Build Coastguard Worker #include "policy_define.h"
60*2d543d20SAndroid Build Coastguard Worker 
61*2d543d20SAndroid Build Coastguard Worker extern void init_parser(int pass_number);
62*2d543d20SAndroid Build Coastguard Worker __attribute__ ((format(printf, 1, 2)))
63*2d543d20SAndroid Build Coastguard Worker extern void yyerror2(const char *fmt, ...);
64*2d543d20SAndroid Build Coastguard Worker 
65*2d543d20SAndroid Build Coastguard Worker policydb_t *policydbp;
66*2d543d20SAndroid Build Coastguard Worker queue_t id_queue = 0;
67*2d543d20SAndroid Build Coastguard Worker unsigned int pass;
68*2d543d20SAndroid Build Coastguard Worker int mlspol = 0;
69*2d543d20SAndroid Build Coastguard Worker 
70*2d543d20SAndroid Build Coastguard Worker extern unsigned long policydb_lineno;
71*2d543d20SAndroid Build Coastguard Worker extern unsigned long source_lineno;
72*2d543d20SAndroid Build Coastguard Worker extern unsigned int policydb_errors;
73*2d543d20SAndroid Build Coastguard Worker extern char source_file[PATH_MAX];
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker extern int yywarn(const char *msg);
76*2d543d20SAndroid Build Coastguard Worker extern int yyerror(const char *msg);
77*2d543d20SAndroid Build Coastguard Worker 
78*2d543d20SAndroid Build Coastguard Worker /* initialize all of the state variables for the scanner/parser */
init_parser(int pass_number)79*2d543d20SAndroid Build Coastguard Worker void init_parser(int pass_number)
80*2d543d20SAndroid Build Coastguard Worker {
81*2d543d20SAndroid Build Coastguard Worker 	policydb_lineno = 1;
82*2d543d20SAndroid Build Coastguard Worker 	source_lineno = 1;
83*2d543d20SAndroid Build Coastguard Worker 	policydb_errors = 0;
84*2d543d20SAndroid Build Coastguard Worker 	pass = pass_number;
85*2d543d20SAndroid Build Coastguard Worker }
86*2d543d20SAndroid Build Coastguard Worker 
yyerror2(const char * fmt,...)87*2d543d20SAndroid Build Coastguard Worker void yyerror2(const char *fmt, ...)
88*2d543d20SAndroid Build Coastguard Worker {
89*2d543d20SAndroid Build Coastguard Worker 	char errormsg[256];
90*2d543d20SAndroid Build Coastguard Worker 	va_list ap;
91*2d543d20SAndroid Build Coastguard Worker 	va_start(ap, fmt);
92*2d543d20SAndroid Build Coastguard Worker 	vsnprintf(errormsg, sizeof(errormsg), fmt, ap);
93*2d543d20SAndroid Build Coastguard Worker 	yyerror(errormsg);
94*2d543d20SAndroid Build Coastguard Worker 	va_end(ap);
95*2d543d20SAndroid Build Coastguard Worker }
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker __attribute__ ((format(printf, 1, 2)))
yywarn2(const char * fmt,...)98*2d543d20SAndroid Build Coastguard Worker static void yywarn2(const char *fmt, ...)
99*2d543d20SAndroid Build Coastguard Worker {
100*2d543d20SAndroid Build Coastguard Worker 	char warnmsg[256];
101*2d543d20SAndroid Build Coastguard Worker 	va_list ap;
102*2d543d20SAndroid Build Coastguard Worker 	va_start(ap, fmt);
103*2d543d20SAndroid Build Coastguard Worker 	vsnprintf(warnmsg, sizeof(warnmsg), fmt, ap);
104*2d543d20SAndroid Build Coastguard Worker 	yywarn(warnmsg);
105*2d543d20SAndroid Build Coastguard Worker 	va_end(ap);
106*2d543d20SAndroid Build Coastguard Worker }
107*2d543d20SAndroid Build Coastguard Worker 
insert_separator(int push)108*2d543d20SAndroid Build Coastguard Worker int insert_separator(int push)
109*2d543d20SAndroid Build Coastguard Worker {
110*2d543d20SAndroid Build Coastguard Worker 	int error;
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker 	if (push)
113*2d543d20SAndroid Build Coastguard Worker 		error = queue_push(id_queue, 0);
114*2d543d20SAndroid Build Coastguard Worker 	else
115*2d543d20SAndroid Build Coastguard Worker 		error = queue_insert(id_queue, 0);
116*2d543d20SAndroid Build Coastguard Worker 
117*2d543d20SAndroid Build Coastguard Worker 	if (error) {
118*2d543d20SAndroid Build Coastguard Worker 		yyerror("queue overflow");
119*2d543d20SAndroid Build Coastguard Worker 		return -1;
120*2d543d20SAndroid Build Coastguard Worker 	}
121*2d543d20SAndroid Build Coastguard Worker 	return 0;
122*2d543d20SAndroid Build Coastguard Worker }
123*2d543d20SAndroid Build Coastguard Worker 
insert_id(const char * id,int push)124*2d543d20SAndroid Build Coastguard Worker int insert_id(const char *id, int push)
125*2d543d20SAndroid Build Coastguard Worker {
126*2d543d20SAndroid Build Coastguard Worker 	char *newid = 0;
127*2d543d20SAndroid Build Coastguard Worker 	int error;
128*2d543d20SAndroid Build Coastguard Worker 
129*2d543d20SAndroid Build Coastguard Worker 	newid = strdup(id);
130*2d543d20SAndroid Build Coastguard Worker 	if (!newid) {
131*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
132*2d543d20SAndroid Build Coastguard Worker 		return -1;
133*2d543d20SAndroid Build Coastguard Worker 	}
134*2d543d20SAndroid Build Coastguard Worker 	if (push)
135*2d543d20SAndroid Build Coastguard Worker 		error = queue_push(id_queue, (queue_element_t) newid);
136*2d543d20SAndroid Build Coastguard Worker 	else
137*2d543d20SAndroid Build Coastguard Worker 		error = queue_insert(id_queue, (queue_element_t) newid);
138*2d543d20SAndroid Build Coastguard Worker 
139*2d543d20SAndroid Build Coastguard Worker 	if (error) {
140*2d543d20SAndroid Build Coastguard Worker 		yyerror("queue overflow");
141*2d543d20SAndroid Build Coastguard Worker 		free(newid);
142*2d543d20SAndroid Build Coastguard Worker 		return -1;
143*2d543d20SAndroid Build Coastguard Worker 	}
144*2d543d20SAndroid Build Coastguard Worker 	return 0;
145*2d543d20SAndroid Build Coastguard Worker }
146*2d543d20SAndroid Build Coastguard Worker 
147*2d543d20SAndroid Build Coastguard Worker /* If the identifier has a dot within it and that its first character
148*2d543d20SAndroid Build Coastguard Worker    is not a dot then return 1, else return 0. */
id_has_dot(const char * id)149*2d543d20SAndroid Build Coastguard Worker static int id_has_dot(const char *id)
150*2d543d20SAndroid Build Coastguard Worker {
151*2d543d20SAndroid Build Coastguard Worker 	if (strchr(id, '.') >= id + 1) {
152*2d543d20SAndroid Build Coastguard Worker 		return 1;
153*2d543d20SAndroid Build Coastguard Worker 	}
154*2d543d20SAndroid Build Coastguard Worker 	return 0;
155*2d543d20SAndroid Build Coastguard Worker }
156*2d543d20SAndroid Build Coastguard Worker 
define_class(void)157*2d543d20SAndroid Build Coastguard Worker int define_class(void)
158*2d543d20SAndroid Build Coastguard Worker {
159*2d543d20SAndroid Build Coastguard Worker 	char *id = 0;
160*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *datum = 0;
161*2d543d20SAndroid Build Coastguard Worker 	int ret;
162*2d543d20SAndroid Build Coastguard Worker 	uint32_t value;
163*2d543d20SAndroid Build Coastguard Worker 
164*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
165*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
166*2d543d20SAndroid Build Coastguard Worker 		free(id);
167*2d543d20SAndroid Build Coastguard Worker 		return 0;
168*2d543d20SAndroid Build Coastguard Worker 	}
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
171*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
172*2d543d20SAndroid Build Coastguard Worker 		yyerror("no class name for class definition?");
173*2d543d20SAndroid Build Coastguard Worker 		return -1;
174*2d543d20SAndroid Build Coastguard Worker 	}
175*2d543d20SAndroid Build Coastguard Worker 	datum = (class_datum_t *) malloc(sizeof(class_datum_t));
176*2d543d20SAndroid Build Coastguard Worker 	if (!datum) {
177*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
178*2d543d20SAndroid Build Coastguard Worker 		goto bad;
179*2d543d20SAndroid Build Coastguard Worker 	}
180*2d543d20SAndroid Build Coastguard Worker 	memset(datum, 0, sizeof(class_datum_t));
181*2d543d20SAndroid Build Coastguard Worker 	ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value);
182*2d543d20SAndroid Build Coastguard Worker 	switch (ret) {
183*2d543d20SAndroid Build Coastguard Worker 	case -3:{
184*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
185*2d543d20SAndroid Build Coastguard Worker 			goto bad;
186*2d543d20SAndroid Build Coastguard Worker 		}
187*2d543d20SAndroid Build Coastguard Worker 	case -2:{
188*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate declaration of class %s", id);
189*2d543d20SAndroid Build Coastguard Worker 			goto bad;
190*2d543d20SAndroid Build Coastguard Worker 		}
191*2d543d20SAndroid Build Coastguard Worker 	case -1:{
192*2d543d20SAndroid Build Coastguard Worker 			yyerror("could not declare class here");
193*2d543d20SAndroid Build Coastguard Worker 			goto bad;
194*2d543d20SAndroid Build Coastguard Worker 		}
195*2d543d20SAndroid Build Coastguard Worker 	case 0:
196*2d543d20SAndroid Build Coastguard Worker 	case 1:{
197*2d543d20SAndroid Build Coastguard Worker 			break;
198*2d543d20SAndroid Build Coastguard Worker 		}
199*2d543d20SAndroid Build Coastguard Worker 	default:{
200*2d543d20SAndroid Build Coastguard Worker 			assert(0);	/* should never get here */
201*2d543d20SAndroid Build Coastguard Worker 		}
202*2d543d20SAndroid Build Coastguard Worker 	}
203*2d543d20SAndroid Build Coastguard Worker 	datum->s.value = value;
204*2d543d20SAndroid Build Coastguard Worker 	return 0;
205*2d543d20SAndroid Build Coastguard Worker 
206*2d543d20SAndroid Build Coastguard Worker       bad:
207*2d543d20SAndroid Build Coastguard Worker 	if (id)
208*2d543d20SAndroid Build Coastguard Worker 		free(id);
209*2d543d20SAndroid Build Coastguard Worker 	if (datum)
210*2d543d20SAndroid Build Coastguard Worker 		free(datum);
211*2d543d20SAndroid Build Coastguard Worker 	return -1;
212*2d543d20SAndroid Build Coastguard Worker }
213*2d543d20SAndroid Build Coastguard Worker 
define_permissive(void)214*2d543d20SAndroid Build Coastguard Worker int define_permissive(void)
215*2d543d20SAndroid Build Coastguard Worker {
216*2d543d20SAndroid Build Coastguard Worker 	char *type = NULL;
217*2d543d20SAndroid Build Coastguard Worker 	struct type_datum *t;
218*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	type = queue_remove(id_queue);
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker 	if (!type) {
223*2d543d20SAndroid Build Coastguard Worker 		yyerror2("forgot to include type in permissive definition?");
224*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
225*2d543d20SAndroid Build Coastguard Worker 		goto out;
226*2d543d20SAndroid Build Coastguard Worker 	}
227*2d543d20SAndroid Build Coastguard Worker 
228*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1)
229*2d543d20SAndroid Build Coastguard Worker 		goto out;
230*2d543d20SAndroid Build Coastguard Worker 
231*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, type)) {
232*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", type);
233*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
234*2d543d20SAndroid Build Coastguard Worker 		goto out;
235*2d543d20SAndroid Build Coastguard Worker 	}
236*2d543d20SAndroid Build Coastguard Worker 
237*2d543d20SAndroid Build Coastguard Worker 	t = hashtab_search(policydbp->p_types.table, type);
238*2d543d20SAndroid Build Coastguard Worker 	if (!t) {
239*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type is not defined: %s", type);
240*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
241*2d543d20SAndroid Build Coastguard Worker 		goto out;
242*2d543d20SAndroid Build Coastguard Worker 	}
243*2d543d20SAndroid Build Coastguard Worker 
244*2d543d20SAndroid Build Coastguard Worker 	if (t->flavor == TYPE_ATTRIB) {
245*2d543d20SAndroid Build Coastguard Worker 		yyerror2("attributes may not be permissive: %s", type);
246*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
247*2d543d20SAndroid Build Coastguard Worker 		goto out;
248*2d543d20SAndroid Build Coastguard Worker 	}
249*2d543d20SAndroid Build Coastguard Worker 
250*2d543d20SAndroid Build Coastguard Worker 	t->flags |= TYPE_FLAGS_PERMISSIVE;
251*2d543d20SAndroid Build Coastguard Worker 
252*2d543d20SAndroid Build Coastguard Worker out:
253*2d543d20SAndroid Build Coastguard Worker 	free(type);
254*2d543d20SAndroid Build Coastguard Worker 	return rc;
255*2d543d20SAndroid Build Coastguard Worker }
256*2d543d20SAndroid Build Coastguard Worker 
define_polcap(void)257*2d543d20SAndroid Build Coastguard Worker int define_polcap(void)
258*2d543d20SAndroid Build Coastguard Worker {
259*2d543d20SAndroid Build Coastguard Worker 	char *id = 0;
260*2d543d20SAndroid Build Coastguard Worker 	int capnum;
261*2d543d20SAndroid Build Coastguard Worker 
262*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
263*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
264*2d543d20SAndroid Build Coastguard Worker 		free(id);
265*2d543d20SAndroid Build Coastguard Worker 		return 0;
266*2d543d20SAndroid Build Coastguard Worker 	}
267*2d543d20SAndroid Build Coastguard Worker 
268*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
269*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
270*2d543d20SAndroid Build Coastguard Worker 		yyerror("no capability name for policycap definition?");
271*2d543d20SAndroid Build Coastguard Worker 		goto bad;
272*2d543d20SAndroid Build Coastguard Worker 	}
273*2d543d20SAndroid Build Coastguard Worker 
274*2d543d20SAndroid Build Coastguard Worker 	/* Check for valid cap name -> number mapping */
275*2d543d20SAndroid Build Coastguard Worker 	capnum = sepol_polcap_getnum(id);
276*2d543d20SAndroid Build Coastguard Worker 	if (capnum < 0) {
277*2d543d20SAndroid Build Coastguard Worker 		yyerror2("invalid policy capability name %s", id);
278*2d543d20SAndroid Build Coastguard Worker 		goto bad;
279*2d543d20SAndroid Build Coastguard Worker 	}
280*2d543d20SAndroid Build Coastguard Worker 
281*2d543d20SAndroid Build Coastguard Worker 	/* Store it */
282*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_set_bit(&policydbp->policycaps, capnum, TRUE)) {
283*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
284*2d543d20SAndroid Build Coastguard Worker 		goto bad;
285*2d543d20SAndroid Build Coastguard Worker 	}
286*2d543d20SAndroid Build Coastguard Worker 
287*2d543d20SAndroid Build Coastguard Worker 	free(id);
288*2d543d20SAndroid Build Coastguard Worker 	return 0;
289*2d543d20SAndroid Build Coastguard Worker 
290*2d543d20SAndroid Build Coastguard Worker       bad:
291*2d543d20SAndroid Build Coastguard Worker 	free(id);
292*2d543d20SAndroid Build Coastguard Worker 	return -1;
293*2d543d20SAndroid Build Coastguard Worker }
294*2d543d20SAndroid Build Coastguard Worker 
define_initial_sid(void)295*2d543d20SAndroid Build Coastguard Worker int define_initial_sid(void)
296*2d543d20SAndroid Build Coastguard Worker {
297*2d543d20SAndroid Build Coastguard Worker 	char *id = 0;
298*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc = 0, *c, *head;
299*2d543d20SAndroid Build Coastguard Worker 
300*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
301*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
302*2d543d20SAndroid Build Coastguard Worker 		free(id);
303*2d543d20SAndroid Build Coastguard Worker 		return 0;
304*2d543d20SAndroid Build Coastguard Worker 	}
305*2d543d20SAndroid Build Coastguard Worker 
306*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
307*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
308*2d543d20SAndroid Build Coastguard Worker 		yyerror("no sid name for SID definition?");
309*2d543d20SAndroid Build Coastguard Worker 		return -1;
310*2d543d20SAndroid Build Coastguard Worker 	}
311*2d543d20SAndroid Build Coastguard Worker 	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
312*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
313*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
314*2d543d20SAndroid Build Coastguard Worker 		goto bad;
315*2d543d20SAndroid Build Coastguard Worker 	}
316*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
317*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = id;
318*2d543d20SAndroid Build Coastguard Worker 	context_init(&newc->context[0]);
319*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_ISID];
320*2d543d20SAndroid Build Coastguard Worker 
321*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
322*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(newc->u.name, c->u.name)) {
323*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate initial SID %s", id);
324*2d543d20SAndroid Build Coastguard Worker 			goto bad;
325*2d543d20SAndroid Build Coastguard Worker 		}
326*2d543d20SAndroid Build Coastguard Worker 	}
327*2d543d20SAndroid Build Coastguard Worker 
328*2d543d20SAndroid Build Coastguard Worker 	if (head) {
329*2d543d20SAndroid Build Coastguard Worker 		newc->sid[0] = head->sid[0] + 1;
330*2d543d20SAndroid Build Coastguard Worker 	} else {
331*2d543d20SAndroid Build Coastguard Worker 		newc->sid[0] = 1;
332*2d543d20SAndroid Build Coastguard Worker 	}
333*2d543d20SAndroid Build Coastguard Worker 	newc->next = head;
334*2d543d20SAndroid Build Coastguard Worker 	policydbp->ocontexts[OCON_ISID] = newc;
335*2d543d20SAndroid Build Coastguard Worker 
336*2d543d20SAndroid Build Coastguard Worker 	return 0;
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker       bad:
339*2d543d20SAndroid Build Coastguard Worker 	if (id)
340*2d543d20SAndroid Build Coastguard Worker 		free(id);
341*2d543d20SAndroid Build Coastguard Worker 	if (newc)
342*2d543d20SAndroid Build Coastguard Worker 		free(newc);
343*2d543d20SAndroid Build Coastguard Worker 	return -1;
344*2d543d20SAndroid Build Coastguard Worker }
345*2d543d20SAndroid Build Coastguard Worker 
read_classes(ebitmap_t * e_classes)346*2d543d20SAndroid Build Coastguard Worker static int read_classes(ebitmap_t *e_classes)
347*2d543d20SAndroid Build Coastguard Worker {
348*2d543d20SAndroid Build Coastguard Worker 	char *id;
349*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
350*2d543d20SAndroid Build Coastguard Worker 
351*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
352*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
353*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
354*2d543d20SAndroid Build Coastguard Worker 			free(id);
355*2d543d20SAndroid Build Coastguard Worker 			return -1;
356*2d543d20SAndroid Build Coastguard Worker 		}
357*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table, id);
358*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
359*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown class %s", id);
360*2d543d20SAndroid Build Coastguard Worker 			free(id);
361*2d543d20SAndroid Build Coastguard Worker 			return -1;
362*2d543d20SAndroid Build Coastguard Worker 		}
363*2d543d20SAndroid Build Coastguard Worker 		free(id);
364*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) {
365*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory");
366*2d543d20SAndroid Build Coastguard Worker 			return -1;
367*2d543d20SAndroid Build Coastguard Worker 		}
368*2d543d20SAndroid Build Coastguard Worker 	}
369*2d543d20SAndroid Build Coastguard Worker 	return 0;
370*2d543d20SAndroid Build Coastguard Worker }
371*2d543d20SAndroid Build Coastguard Worker 
define_default_user(int which)372*2d543d20SAndroid Build Coastguard Worker int define_default_user(int which)
373*2d543d20SAndroid Build Coastguard Worker {
374*2d543d20SAndroid Build Coastguard Worker 	char *id;
375*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
376*2d543d20SAndroid Build Coastguard Worker 
377*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
378*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
379*2d543d20SAndroid Build Coastguard Worker 			free(id);
380*2d543d20SAndroid Build Coastguard Worker 		return 0;
381*2d543d20SAndroid Build Coastguard Worker 	}
382*2d543d20SAndroid Build Coastguard Worker 
383*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
384*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
385*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
386*2d543d20SAndroid Build Coastguard Worker 			free(id);
387*2d543d20SAndroid Build Coastguard Worker 			return -1;
388*2d543d20SAndroid Build Coastguard Worker 		}
389*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table, id);
390*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
391*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown class %s", id);
392*2d543d20SAndroid Build Coastguard Worker 			free(id);
393*2d543d20SAndroid Build Coastguard Worker 			return -1;
394*2d543d20SAndroid Build Coastguard Worker 		}
395*2d543d20SAndroid Build Coastguard Worker 		if (cladatum->default_user && cladatum->default_user != which) {
396*2d543d20SAndroid Build Coastguard Worker 			yyerror2("conflicting default user information for class %s", id);
397*2d543d20SAndroid Build Coastguard Worker 			free(id);
398*2d543d20SAndroid Build Coastguard Worker 			return -1;
399*2d543d20SAndroid Build Coastguard Worker 		}
400*2d543d20SAndroid Build Coastguard Worker 		cladatum->default_user = which;
401*2d543d20SAndroid Build Coastguard Worker 		free(id);
402*2d543d20SAndroid Build Coastguard Worker 	}
403*2d543d20SAndroid Build Coastguard Worker 
404*2d543d20SAndroid Build Coastguard Worker 	return 0;
405*2d543d20SAndroid Build Coastguard Worker }
406*2d543d20SAndroid Build Coastguard Worker 
define_default_role(int which)407*2d543d20SAndroid Build Coastguard Worker int define_default_role(int which)
408*2d543d20SAndroid Build Coastguard Worker {
409*2d543d20SAndroid Build Coastguard Worker 	char *id;
410*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
411*2d543d20SAndroid Build Coastguard Worker 
412*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
413*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
414*2d543d20SAndroid Build Coastguard Worker 			free(id);
415*2d543d20SAndroid Build Coastguard Worker 		return 0;
416*2d543d20SAndroid Build Coastguard Worker 	}
417*2d543d20SAndroid Build Coastguard Worker 
418*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
419*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
420*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
421*2d543d20SAndroid Build Coastguard Worker 			free(id);
422*2d543d20SAndroid Build Coastguard Worker 			return -1;
423*2d543d20SAndroid Build Coastguard Worker 		}
424*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table, id);
425*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
426*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown class %s", id);
427*2d543d20SAndroid Build Coastguard Worker 			free(id);
428*2d543d20SAndroid Build Coastguard Worker 			return -1;
429*2d543d20SAndroid Build Coastguard Worker 		}
430*2d543d20SAndroid Build Coastguard Worker 		if (cladatum->default_role && cladatum->default_role != which) {
431*2d543d20SAndroid Build Coastguard Worker 			yyerror2("conflicting default role information for class %s", id);
432*2d543d20SAndroid Build Coastguard Worker 			free(id);
433*2d543d20SAndroid Build Coastguard Worker 			return -1;
434*2d543d20SAndroid Build Coastguard Worker 		}
435*2d543d20SAndroid Build Coastguard Worker 		cladatum->default_role = which;
436*2d543d20SAndroid Build Coastguard Worker 		free(id);
437*2d543d20SAndroid Build Coastguard Worker 	}
438*2d543d20SAndroid Build Coastguard Worker 
439*2d543d20SAndroid Build Coastguard Worker 	return 0;
440*2d543d20SAndroid Build Coastguard Worker }
441*2d543d20SAndroid Build Coastguard Worker 
define_default_type(int which)442*2d543d20SAndroid Build Coastguard Worker int define_default_type(int which)
443*2d543d20SAndroid Build Coastguard Worker {
444*2d543d20SAndroid Build Coastguard Worker 	char *id;
445*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
446*2d543d20SAndroid Build Coastguard Worker 
447*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
448*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
449*2d543d20SAndroid Build Coastguard Worker 			free(id);
450*2d543d20SAndroid Build Coastguard Worker 		return 0;
451*2d543d20SAndroid Build Coastguard Worker 	}
452*2d543d20SAndroid Build Coastguard Worker 
453*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
454*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
455*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
456*2d543d20SAndroid Build Coastguard Worker 			free(id);
457*2d543d20SAndroid Build Coastguard Worker 			return -1;
458*2d543d20SAndroid Build Coastguard Worker 		}
459*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table, id);
460*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
461*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown class %s", id);
462*2d543d20SAndroid Build Coastguard Worker 			free(id);
463*2d543d20SAndroid Build Coastguard Worker 			return -1;
464*2d543d20SAndroid Build Coastguard Worker 		}
465*2d543d20SAndroid Build Coastguard Worker 		if (cladatum->default_type && cladatum->default_type != which) {
466*2d543d20SAndroid Build Coastguard Worker 			yyerror2("conflicting default type information for class %s", id);
467*2d543d20SAndroid Build Coastguard Worker 			free(id);
468*2d543d20SAndroid Build Coastguard Worker 			return -1;
469*2d543d20SAndroid Build Coastguard Worker 		}
470*2d543d20SAndroid Build Coastguard Worker 		cladatum->default_type = which;
471*2d543d20SAndroid Build Coastguard Worker 		free(id);
472*2d543d20SAndroid Build Coastguard Worker 	}
473*2d543d20SAndroid Build Coastguard Worker 
474*2d543d20SAndroid Build Coastguard Worker 	return 0;
475*2d543d20SAndroid Build Coastguard Worker }
476*2d543d20SAndroid Build Coastguard Worker 
define_default_range(int which)477*2d543d20SAndroid Build Coastguard Worker int define_default_range(int which)
478*2d543d20SAndroid Build Coastguard Worker {
479*2d543d20SAndroid Build Coastguard Worker 	char *id;
480*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
481*2d543d20SAndroid Build Coastguard Worker 
482*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
483*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
484*2d543d20SAndroid Build Coastguard Worker 			free(id);
485*2d543d20SAndroid Build Coastguard Worker 		return 0;
486*2d543d20SAndroid Build Coastguard Worker 	}
487*2d543d20SAndroid Build Coastguard Worker 
488*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
489*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
490*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
491*2d543d20SAndroid Build Coastguard Worker 			free(id);
492*2d543d20SAndroid Build Coastguard Worker 			return -1;
493*2d543d20SAndroid Build Coastguard Worker 		}
494*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table, id);
495*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
496*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown class %s", id);
497*2d543d20SAndroid Build Coastguard Worker 			free(id);
498*2d543d20SAndroid Build Coastguard Worker 			return -1;
499*2d543d20SAndroid Build Coastguard Worker 		}
500*2d543d20SAndroid Build Coastguard Worker 		if (cladatum->default_range && cladatum->default_range != which) {
501*2d543d20SAndroid Build Coastguard Worker 			yyerror2("conflicting default range information for class %s", id);
502*2d543d20SAndroid Build Coastguard Worker 			free(id);
503*2d543d20SAndroid Build Coastguard Worker 			return -1;
504*2d543d20SAndroid Build Coastguard Worker 		}
505*2d543d20SAndroid Build Coastguard Worker 		cladatum->default_range = which;
506*2d543d20SAndroid Build Coastguard Worker 		free(id);
507*2d543d20SAndroid Build Coastguard Worker 	}
508*2d543d20SAndroid Build Coastguard Worker 
509*2d543d20SAndroid Build Coastguard Worker 	return 0;
510*2d543d20SAndroid Build Coastguard Worker }
511*2d543d20SAndroid Build Coastguard Worker 
define_common_perms(void)512*2d543d20SAndroid Build Coastguard Worker int define_common_perms(void)
513*2d543d20SAndroid Build Coastguard Worker {
514*2d543d20SAndroid Build Coastguard Worker 	char *id = 0, *perm = 0;
515*2d543d20SAndroid Build Coastguard Worker 	common_datum_t *comdatum = 0;
516*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum = 0;
517*2d543d20SAndroid Build Coastguard Worker 	int ret;
518*2d543d20SAndroid Build Coastguard Worker 
519*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
520*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
521*2d543d20SAndroid Build Coastguard Worker 			free(id);
522*2d543d20SAndroid Build Coastguard Worker 		return 0;
523*2d543d20SAndroid Build Coastguard Worker 	}
524*2d543d20SAndroid Build Coastguard Worker 
525*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
526*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
527*2d543d20SAndroid Build Coastguard Worker 		yyerror("no common name for common perm definition?");
528*2d543d20SAndroid Build Coastguard Worker 		return -1;
529*2d543d20SAndroid Build Coastguard Worker 	}
530*2d543d20SAndroid Build Coastguard Worker 	comdatum = hashtab_search(policydbp->p_commons.table, id);
531*2d543d20SAndroid Build Coastguard Worker 	if (comdatum) {
532*2d543d20SAndroid Build Coastguard Worker 		yyerror2("duplicate declaration for common %s", id);
533*2d543d20SAndroid Build Coastguard Worker 		free(id);
534*2d543d20SAndroid Build Coastguard Worker 		return -1;
535*2d543d20SAndroid Build Coastguard Worker 	}
536*2d543d20SAndroid Build Coastguard Worker 	comdatum = (common_datum_t *) malloc(sizeof(common_datum_t));
537*2d543d20SAndroid Build Coastguard Worker 	if (!comdatum) {
538*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
539*2d543d20SAndroid Build Coastguard Worker 		goto bad;
540*2d543d20SAndroid Build Coastguard Worker 	}
541*2d543d20SAndroid Build Coastguard Worker 	memset(comdatum, 0, sizeof(common_datum_t));
542*2d543d20SAndroid Build Coastguard Worker 	ret = hashtab_insert(policydbp->p_commons.table,
543*2d543d20SAndroid Build Coastguard Worker 			     (hashtab_key_t) id, (hashtab_datum_t) comdatum);
544*2d543d20SAndroid Build Coastguard Worker 
545*2d543d20SAndroid Build Coastguard Worker 	if (ret == SEPOL_EEXIST) {
546*2d543d20SAndroid Build Coastguard Worker 		yyerror("duplicate common definition");
547*2d543d20SAndroid Build Coastguard Worker 		goto bad;
548*2d543d20SAndroid Build Coastguard Worker 	}
549*2d543d20SAndroid Build Coastguard Worker 	if (ret == SEPOL_ENOMEM) {
550*2d543d20SAndroid Build Coastguard Worker 		yyerror("hash table overflow");
551*2d543d20SAndroid Build Coastguard Worker 		goto bad;
552*2d543d20SAndroid Build Coastguard Worker 	}
553*2d543d20SAndroid Build Coastguard Worker 	comdatum->s.value = policydbp->p_commons.nprim + 1;
554*2d543d20SAndroid Build Coastguard Worker 	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) {
555*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
556*2d543d20SAndroid Build Coastguard Worker 		goto bad;
557*2d543d20SAndroid Build Coastguard Worker 	}
558*2d543d20SAndroid Build Coastguard Worker 	policydbp->p_commons.nprim++;
559*2d543d20SAndroid Build Coastguard Worker 	while ((perm = queue_remove(id_queue))) {
560*2d543d20SAndroid Build Coastguard Worker 		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
561*2d543d20SAndroid Build Coastguard Worker 		if (!perdatum) {
562*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
563*2d543d20SAndroid Build Coastguard Worker 			goto bad_perm;
564*2d543d20SAndroid Build Coastguard Worker 		}
565*2d543d20SAndroid Build Coastguard Worker 		memset(perdatum, 0, sizeof(perm_datum_t));
566*2d543d20SAndroid Build Coastguard Worker 		perdatum->s.value = comdatum->permissions.nprim + 1;
567*2d543d20SAndroid Build Coastguard Worker 
568*2d543d20SAndroid Build Coastguard Worker 		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
569*2d543d20SAndroid Build Coastguard Worker 			yyerror2
570*2d543d20SAndroid Build Coastguard Worker 			    ("too many permissions (%d) to fit in an access vector", perdatum->s.value);
571*2d543d20SAndroid Build Coastguard Worker 			goto bad_perm;
572*2d543d20SAndroid Build Coastguard Worker 		}
573*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(comdatum->permissions.table,
574*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) perm,
575*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) perdatum);
576*2d543d20SAndroid Build Coastguard Worker 
577*2d543d20SAndroid Build Coastguard Worker 		if (ret == SEPOL_EEXIST) {
578*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate permission %s in common %s", perm,
579*2d543d20SAndroid Build Coastguard Worker 				 id);
580*2d543d20SAndroid Build Coastguard Worker 			goto bad_perm;
581*2d543d20SAndroid Build Coastguard Worker 		}
582*2d543d20SAndroid Build Coastguard Worker 		if (ret == SEPOL_ENOMEM) {
583*2d543d20SAndroid Build Coastguard Worker 			yyerror("hash table overflow");
584*2d543d20SAndroid Build Coastguard Worker 			goto bad_perm;
585*2d543d20SAndroid Build Coastguard Worker 		}
586*2d543d20SAndroid Build Coastguard Worker 		comdatum->permissions.nprim++;
587*2d543d20SAndroid Build Coastguard Worker 	}
588*2d543d20SAndroid Build Coastguard Worker 
589*2d543d20SAndroid Build Coastguard Worker 	return 0;
590*2d543d20SAndroid Build Coastguard Worker 
591*2d543d20SAndroid Build Coastguard Worker       bad:
592*2d543d20SAndroid Build Coastguard Worker 	if (id)
593*2d543d20SAndroid Build Coastguard Worker 		free(id);
594*2d543d20SAndroid Build Coastguard Worker 	if (comdatum)
595*2d543d20SAndroid Build Coastguard Worker 		free(comdatum);
596*2d543d20SAndroid Build Coastguard Worker 	return -1;
597*2d543d20SAndroid Build Coastguard Worker 
598*2d543d20SAndroid Build Coastguard Worker       bad_perm:
599*2d543d20SAndroid Build Coastguard Worker 	if (perm)
600*2d543d20SAndroid Build Coastguard Worker 		free(perm);
601*2d543d20SAndroid Build Coastguard Worker 	if (perdatum)
602*2d543d20SAndroid Build Coastguard Worker 		free(perdatum);
603*2d543d20SAndroid Build Coastguard Worker 	return -1;
604*2d543d20SAndroid Build Coastguard Worker }
605*2d543d20SAndroid Build Coastguard Worker 
define_av_perms(int inherits)606*2d543d20SAndroid Build Coastguard Worker int define_av_perms(int inherits)
607*2d543d20SAndroid Build Coastguard Worker {
608*2d543d20SAndroid Build Coastguard Worker 	char *id;
609*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
610*2d543d20SAndroid Build Coastguard Worker 	common_datum_t *comdatum;
611*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum = 0, *perdatum2 = 0;
612*2d543d20SAndroid Build Coastguard Worker 	int ret;
613*2d543d20SAndroid Build Coastguard Worker 
614*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
615*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
616*2d543d20SAndroid Build Coastguard Worker 			free(id);
617*2d543d20SAndroid Build Coastguard Worker 		return 0;
618*2d543d20SAndroid Build Coastguard Worker 	}
619*2d543d20SAndroid Build Coastguard Worker 
620*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
621*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
622*2d543d20SAndroid Build Coastguard Worker 		yyerror("no tclass name for av perm definition?");
623*2d543d20SAndroid Build Coastguard Worker 		return -1;
624*2d543d20SAndroid Build Coastguard Worker 	}
625*2d543d20SAndroid Build Coastguard Worker 	cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
626*2d543d20SAndroid Build Coastguard Worker 						    (hashtab_key_t) id);
627*2d543d20SAndroid Build Coastguard Worker 	if (!cladatum) {
628*2d543d20SAndroid Build Coastguard Worker 		yyerror2("class %s is not defined", id);
629*2d543d20SAndroid Build Coastguard Worker 		goto bad;
630*2d543d20SAndroid Build Coastguard Worker 	}
631*2d543d20SAndroid Build Coastguard Worker 
632*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->comdatum || cladatum->permissions.nprim) {
633*2d543d20SAndroid Build Coastguard Worker 		yyerror2("duplicate access vector definition for class %s", id);
634*2d543d20SAndroid Build Coastguard Worker 		goto bad;
635*2d543d20SAndroid Build Coastguard Worker 	}
636*2d543d20SAndroid Build Coastguard Worker 
637*2d543d20SAndroid Build Coastguard Worker 	free(id);
638*2d543d20SAndroid Build Coastguard Worker 	id = NULL;
639*2d543d20SAndroid Build Coastguard Worker 
640*2d543d20SAndroid Build Coastguard Worker 	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) {
641*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
642*2d543d20SAndroid Build Coastguard Worker 		return -1;
643*2d543d20SAndroid Build Coastguard Worker 	}
644*2d543d20SAndroid Build Coastguard Worker 	if (inherits) {
645*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
646*2d543d20SAndroid Build Coastguard Worker 		if (!id) {
647*2d543d20SAndroid Build Coastguard Worker 			yyerror
648*2d543d20SAndroid Build Coastguard Worker 			    ("no inherits name for access vector definition?");
649*2d543d20SAndroid Build Coastguard Worker 			return -1;
650*2d543d20SAndroid Build Coastguard Worker 		}
651*2d543d20SAndroid Build Coastguard Worker 		comdatum =
652*2d543d20SAndroid Build Coastguard Worker 		    (common_datum_t *) hashtab_search(policydbp->p_commons.
653*2d543d20SAndroid Build Coastguard Worker 						      table,
654*2d543d20SAndroid Build Coastguard Worker 						      (hashtab_key_t) id);
655*2d543d20SAndroid Build Coastguard Worker 
656*2d543d20SAndroid Build Coastguard Worker 		if (!comdatum) {
657*2d543d20SAndroid Build Coastguard Worker 			yyerror2("common %s is not defined", id);
658*2d543d20SAndroid Build Coastguard Worker 			goto bad;
659*2d543d20SAndroid Build Coastguard Worker 		}
660*2d543d20SAndroid Build Coastguard Worker 		cladatum->comkey = id;
661*2d543d20SAndroid Build Coastguard Worker 		cladatum->comdatum = comdatum;
662*2d543d20SAndroid Build Coastguard Worker 
663*2d543d20SAndroid Build Coastguard Worker 		/*
664*2d543d20SAndroid Build Coastguard Worker 		 * Class-specific permissions start with values
665*2d543d20SAndroid Build Coastguard Worker 		 * after the last common permission.
666*2d543d20SAndroid Build Coastguard Worker 		 */
667*2d543d20SAndroid Build Coastguard Worker 		cladatum->permissions.nprim += comdatum->permissions.nprim;
668*2d543d20SAndroid Build Coastguard Worker 	}
669*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
670*2d543d20SAndroid Build Coastguard Worker 		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
671*2d543d20SAndroid Build Coastguard Worker 		if (!perdatum) {
672*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
673*2d543d20SAndroid Build Coastguard Worker 			goto bad;
674*2d543d20SAndroid Build Coastguard Worker 		}
675*2d543d20SAndroid Build Coastguard Worker 		memset(perdatum, 0, sizeof(perm_datum_t));
676*2d543d20SAndroid Build Coastguard Worker 		perdatum->s.value = ++cladatum->permissions.nprim;
677*2d543d20SAndroid Build Coastguard Worker 
678*2d543d20SAndroid Build Coastguard Worker 		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
679*2d543d20SAndroid Build Coastguard Worker 			yyerror2
680*2d543d20SAndroid Build Coastguard Worker 			    ("too many permissions (%d) to fit in an access vector", perdatum->s.value);
681*2d543d20SAndroid Build Coastguard Worker 			goto bad;
682*2d543d20SAndroid Build Coastguard Worker 		}
683*2d543d20SAndroid Build Coastguard Worker 		if (inherits) {
684*2d543d20SAndroid Build Coastguard Worker 			/*
685*2d543d20SAndroid Build Coastguard Worker 			 * Class-specific permissions and
686*2d543d20SAndroid Build Coastguard Worker 			 * common permissions exist in the same
687*2d543d20SAndroid Build Coastguard Worker 			 * name space.
688*2d543d20SAndroid Build Coastguard Worker 			 */
689*2d543d20SAndroid Build Coastguard Worker 			perdatum2 =
690*2d543d20SAndroid Build Coastguard Worker 			    (perm_datum_t *) hashtab_search(cladatum->comdatum->
691*2d543d20SAndroid Build Coastguard Worker 							    permissions.table,
692*2d543d20SAndroid Build Coastguard Worker 							    (hashtab_key_t) id);
693*2d543d20SAndroid Build Coastguard Worker 			if (perdatum2) {
694*2d543d20SAndroid Build Coastguard Worker 				yyerror2("permission %s conflicts with an "
695*2d543d20SAndroid Build Coastguard Worker 					 "inherited permission", id);
696*2d543d20SAndroid Build Coastguard Worker 				goto bad;
697*2d543d20SAndroid Build Coastguard Worker 			}
698*2d543d20SAndroid Build Coastguard Worker 		}
699*2d543d20SAndroid Build Coastguard Worker 		ret = hashtab_insert(cladatum->permissions.table,
700*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_key_t) id,
701*2d543d20SAndroid Build Coastguard Worker 				     (hashtab_datum_t) perdatum);
702*2d543d20SAndroid Build Coastguard Worker 
703*2d543d20SAndroid Build Coastguard Worker 		if (ret == SEPOL_EEXIST) {
704*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate permission %s", id);
705*2d543d20SAndroid Build Coastguard Worker 			goto bad;
706*2d543d20SAndroid Build Coastguard Worker 		}
707*2d543d20SAndroid Build Coastguard Worker 		if (ret == SEPOL_ENOMEM) {
708*2d543d20SAndroid Build Coastguard Worker 			yyerror("hash table overflow");
709*2d543d20SAndroid Build Coastguard Worker 			goto bad;
710*2d543d20SAndroid Build Coastguard Worker 		}
711*2d543d20SAndroid Build Coastguard Worker 		if (add_perm_to_class(perdatum->s.value, cladatum->s.value)) {
712*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
713*2d543d20SAndroid Build Coastguard Worker 			goto bad;
714*2d543d20SAndroid Build Coastguard Worker 		}
715*2d543d20SAndroid Build Coastguard Worker 	}
716*2d543d20SAndroid Build Coastguard Worker 
717*2d543d20SAndroid Build Coastguard Worker 	return 0;
718*2d543d20SAndroid Build Coastguard Worker 
719*2d543d20SAndroid Build Coastguard Worker       bad:
720*2d543d20SAndroid Build Coastguard Worker 	if (id)
721*2d543d20SAndroid Build Coastguard Worker 		free(id);
722*2d543d20SAndroid Build Coastguard Worker 	if (perdatum)
723*2d543d20SAndroid Build Coastguard Worker 		free(perdatum);
724*2d543d20SAndroid Build Coastguard Worker 	return -1;
725*2d543d20SAndroid Build Coastguard Worker }
726*2d543d20SAndroid Build Coastguard Worker 
define_sens(void)727*2d543d20SAndroid Build Coastguard Worker int define_sens(void)
728*2d543d20SAndroid Build Coastguard Worker {
729*2d543d20SAndroid Build Coastguard Worker 	char *id;
730*2d543d20SAndroid Build Coastguard Worker 	mls_level_t *level = 0;
731*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *datum = 0, *aliasdatum = 0;
732*2d543d20SAndroid Build Coastguard Worker 	int ret;
733*2d543d20SAndroid Build Coastguard Worker 	uint32_t value;		/* dummy variable -- its value is never used */
734*2d543d20SAndroid Build Coastguard Worker 
735*2d543d20SAndroid Build Coastguard Worker 	if (!mlspol) {
736*2d543d20SAndroid Build Coastguard Worker 		yyerror("sensitivity definition in non-MLS configuration");
737*2d543d20SAndroid Build Coastguard Worker 		return -1;
738*2d543d20SAndroid Build Coastguard Worker 	}
739*2d543d20SAndroid Build Coastguard Worker 
740*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
741*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
742*2d543d20SAndroid Build Coastguard Worker 			free(id);
743*2d543d20SAndroid Build Coastguard Worker 		return 0;
744*2d543d20SAndroid Build Coastguard Worker 	}
745*2d543d20SAndroid Build Coastguard Worker 
746*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
747*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
748*2d543d20SAndroid Build Coastguard Worker 		yyerror("no sensitivity name for sensitivity definition?");
749*2d543d20SAndroid Build Coastguard Worker 		return -1;
750*2d543d20SAndroid Build Coastguard Worker 	}
751*2d543d20SAndroid Build Coastguard Worker 	if (id_has_dot(id)) {
752*2d543d20SAndroid Build Coastguard Worker 		yyerror2("sensitivity identifier %s may not contain periods", id);
753*2d543d20SAndroid Build Coastguard Worker 		goto bad;
754*2d543d20SAndroid Build Coastguard Worker 	}
755*2d543d20SAndroid Build Coastguard Worker 	level = (mls_level_t *) malloc(sizeof(mls_level_t));
756*2d543d20SAndroid Build Coastguard Worker 	if (!level) {
757*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
758*2d543d20SAndroid Build Coastguard Worker 		goto bad;
759*2d543d20SAndroid Build Coastguard Worker 	}
760*2d543d20SAndroid Build Coastguard Worker 	mls_level_init(level);
761*2d543d20SAndroid Build Coastguard Worker 	level->sens = 0;	/* actual value set in define_dominance */
762*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&level->cat);	/* actual value set in define_level */
763*2d543d20SAndroid Build Coastguard Worker 
764*2d543d20SAndroid Build Coastguard Worker 	datum = (level_datum_t *) malloc(sizeof(level_datum_t));
765*2d543d20SAndroid Build Coastguard Worker 	if (!datum) {
766*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
767*2d543d20SAndroid Build Coastguard Worker 		goto bad;
768*2d543d20SAndroid Build Coastguard Worker 	}
769*2d543d20SAndroid Build Coastguard Worker 	level_datum_init(datum);
770*2d543d20SAndroid Build Coastguard Worker 	datum->isalias = FALSE;
771*2d543d20SAndroid Build Coastguard Worker 	datum->level = level;
772*2d543d20SAndroid Build Coastguard Worker 	datum->notdefined = TRUE;
773*2d543d20SAndroid Build Coastguard Worker 
774*2d543d20SAndroid Build Coastguard Worker 	ret = declare_symbol(SYM_LEVELS, id, datum, &value, &value);
775*2d543d20SAndroid Build Coastguard Worker 	switch (ret) {
776*2d543d20SAndroid Build Coastguard Worker 	case -3:{
777*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
778*2d543d20SAndroid Build Coastguard Worker 			goto bad;
779*2d543d20SAndroid Build Coastguard Worker 		}
780*2d543d20SAndroid Build Coastguard Worker 	case -2:{
781*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate declaration of sensitivity level %s", id);
782*2d543d20SAndroid Build Coastguard Worker 			goto bad;
783*2d543d20SAndroid Build Coastguard Worker 		}
784*2d543d20SAndroid Build Coastguard Worker 	case -1:{
785*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not declare sensitivity level %s here", id);
786*2d543d20SAndroid Build Coastguard Worker 			goto bad;
787*2d543d20SAndroid Build Coastguard Worker 		}
788*2d543d20SAndroid Build Coastguard Worker 	case 0:
789*2d543d20SAndroid Build Coastguard Worker 	case 1:{
790*2d543d20SAndroid Build Coastguard Worker 			break;
791*2d543d20SAndroid Build Coastguard Worker 		}
792*2d543d20SAndroid Build Coastguard Worker 	default:{
793*2d543d20SAndroid Build Coastguard Worker 			assert(0);	/* should never get here */
794*2d543d20SAndroid Build Coastguard Worker 		}
795*2d543d20SAndroid Build Coastguard Worker 	}
796*2d543d20SAndroid Build Coastguard Worker 
797*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
798*2d543d20SAndroid Build Coastguard Worker 		if (id_has_dot(id)) {
799*2d543d20SAndroid Build Coastguard Worker 			yyerror2("sensitivity alias %s may not contain periods", id);
800*2d543d20SAndroid Build Coastguard Worker 			free(id);
801*2d543d20SAndroid Build Coastguard Worker 			return -1;
802*2d543d20SAndroid Build Coastguard Worker 		}
803*2d543d20SAndroid Build Coastguard Worker 		aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t));
804*2d543d20SAndroid Build Coastguard Worker 		if (!aliasdatum) {
805*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
806*2d543d20SAndroid Build Coastguard Worker 			free(id);
807*2d543d20SAndroid Build Coastguard Worker 			return -1;
808*2d543d20SAndroid Build Coastguard Worker 		}
809*2d543d20SAndroid Build Coastguard Worker 		level_datum_init(aliasdatum);
810*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->isalias = TRUE;
811*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->level = level;
812*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->notdefined = TRUE;
813*2d543d20SAndroid Build Coastguard Worker 
814*2d543d20SAndroid Build Coastguard Worker 		ret = declare_symbol(SYM_LEVELS, id, aliasdatum, NULL, &value);
815*2d543d20SAndroid Build Coastguard Worker 		switch (ret) {
816*2d543d20SAndroid Build Coastguard Worker 		case -3:{
817*2d543d20SAndroid Build Coastguard Worker 				yyerror("Out of memory!");
818*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
819*2d543d20SAndroid Build Coastguard Worker 			}
820*2d543d20SAndroid Build Coastguard Worker 		case -2:{
821*2d543d20SAndroid Build Coastguard Worker 				yyerror2
822*2d543d20SAndroid Build Coastguard Worker 				    ("duplicate declaration of sensitivity alias %s", id);
823*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
824*2d543d20SAndroid Build Coastguard Worker 			}
825*2d543d20SAndroid Build Coastguard Worker 		case -1:{
826*2d543d20SAndroid Build Coastguard Worker 				yyerror2
827*2d543d20SAndroid Build Coastguard Worker 				    ("could not declare sensitivity alias %s here", id);
828*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
829*2d543d20SAndroid Build Coastguard Worker 			}
830*2d543d20SAndroid Build Coastguard Worker 		case 0:
831*2d543d20SAndroid Build Coastguard Worker 		case 1:{
832*2d543d20SAndroid Build Coastguard Worker 				break;
833*2d543d20SAndroid Build Coastguard Worker 			}
834*2d543d20SAndroid Build Coastguard Worker 		default:{
835*2d543d20SAndroid Build Coastguard Worker 				assert(0);	/* should never get here */
836*2d543d20SAndroid Build Coastguard Worker 			}
837*2d543d20SAndroid Build Coastguard Worker 		}
838*2d543d20SAndroid Build Coastguard Worker 	}
839*2d543d20SAndroid Build Coastguard Worker 
840*2d543d20SAndroid Build Coastguard Worker 	return 0;
841*2d543d20SAndroid Build Coastguard Worker 
842*2d543d20SAndroid Build Coastguard Worker       bad:
843*2d543d20SAndroid Build Coastguard Worker 	if (id)
844*2d543d20SAndroid Build Coastguard Worker 		free(id);
845*2d543d20SAndroid Build Coastguard Worker 	if (level)
846*2d543d20SAndroid Build Coastguard Worker 		free(level);
847*2d543d20SAndroid Build Coastguard Worker 	if (datum) {
848*2d543d20SAndroid Build Coastguard Worker 		level_datum_destroy(datum);
849*2d543d20SAndroid Build Coastguard Worker 		free(datum);
850*2d543d20SAndroid Build Coastguard Worker 	}
851*2d543d20SAndroid Build Coastguard Worker 	return -1;
852*2d543d20SAndroid Build Coastguard Worker 
853*2d543d20SAndroid Build Coastguard Worker       bad_alias:
854*2d543d20SAndroid Build Coastguard Worker 	if (id)
855*2d543d20SAndroid Build Coastguard Worker 		free(id);
856*2d543d20SAndroid Build Coastguard Worker 	if (aliasdatum) {
857*2d543d20SAndroid Build Coastguard Worker 		level_datum_destroy(aliasdatum);
858*2d543d20SAndroid Build Coastguard Worker 		free(aliasdatum);
859*2d543d20SAndroid Build Coastguard Worker 	}
860*2d543d20SAndroid Build Coastguard Worker 	return -1;
861*2d543d20SAndroid Build Coastguard Worker }
862*2d543d20SAndroid Build Coastguard Worker 
define_dominance(void)863*2d543d20SAndroid Build Coastguard Worker int define_dominance(void)
864*2d543d20SAndroid Build Coastguard Worker {
865*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *datum;
866*2d543d20SAndroid Build Coastguard Worker 	uint32_t order;
867*2d543d20SAndroid Build Coastguard Worker 	char *id;
868*2d543d20SAndroid Build Coastguard Worker 
869*2d543d20SAndroid Build Coastguard Worker 	if (!mlspol) {
870*2d543d20SAndroid Build Coastguard Worker 		yyerror("dominance definition in non-MLS configuration");
871*2d543d20SAndroid Build Coastguard Worker 		return -1;
872*2d543d20SAndroid Build Coastguard Worker 	}
873*2d543d20SAndroid Build Coastguard Worker 
874*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
875*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
876*2d543d20SAndroid Build Coastguard Worker 			free(id);
877*2d543d20SAndroid Build Coastguard Worker 		return 0;
878*2d543d20SAndroid Build Coastguard Worker 	}
879*2d543d20SAndroid Build Coastguard Worker 
880*2d543d20SAndroid Build Coastguard Worker 	order = 0;
881*2d543d20SAndroid Build Coastguard Worker 	while ((id = (char *)queue_remove(id_queue))) {
882*2d543d20SAndroid Build Coastguard Worker 		datum =
883*2d543d20SAndroid Build Coastguard Worker 		    (level_datum_t *) hashtab_search(policydbp->p_levels.table,
884*2d543d20SAndroid Build Coastguard Worker 						     (hashtab_key_t) id);
885*2d543d20SAndroid Build Coastguard Worker 		if (!datum) {
886*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown sensitivity %s used in dominance "
887*2d543d20SAndroid Build Coastguard Worker 				 "definition", id);
888*2d543d20SAndroid Build Coastguard Worker 			free(id);
889*2d543d20SAndroid Build Coastguard Worker 			return -1;
890*2d543d20SAndroid Build Coastguard Worker 		}
891*2d543d20SAndroid Build Coastguard Worker 		if (datum->level->sens != 0) {
892*2d543d20SAndroid Build Coastguard Worker 			yyerror2("sensitivity %s occurs multiply in dominance "
893*2d543d20SAndroid Build Coastguard Worker 				 "definition", id);
894*2d543d20SAndroid Build Coastguard Worker 			free(id);
895*2d543d20SAndroid Build Coastguard Worker 			return -1;
896*2d543d20SAndroid Build Coastguard Worker 		}
897*2d543d20SAndroid Build Coastguard Worker 		datum->level->sens = ++order;
898*2d543d20SAndroid Build Coastguard Worker 
899*2d543d20SAndroid Build Coastguard Worker 		/* no need to keep sensitivity name */
900*2d543d20SAndroid Build Coastguard Worker 		free(id);
901*2d543d20SAndroid Build Coastguard Worker 	}
902*2d543d20SAndroid Build Coastguard Worker 
903*2d543d20SAndroid Build Coastguard Worker 	if (order != policydbp->p_levels.nprim) {
904*2d543d20SAndroid Build Coastguard Worker 		yyerror
905*2d543d20SAndroid Build Coastguard Worker 		    ("all sensitivities must be specified in dominance definition");
906*2d543d20SAndroid Build Coastguard Worker 		return -1;
907*2d543d20SAndroid Build Coastguard Worker 	}
908*2d543d20SAndroid Build Coastguard Worker 	return 0;
909*2d543d20SAndroid Build Coastguard Worker }
910*2d543d20SAndroid Build Coastguard Worker 
define_category(void)911*2d543d20SAndroid Build Coastguard Worker int define_category(void)
912*2d543d20SAndroid Build Coastguard Worker {
913*2d543d20SAndroid Build Coastguard Worker 	char *id;
914*2d543d20SAndroid Build Coastguard Worker 	cat_datum_t *datum = 0, *aliasdatum = 0;
915*2d543d20SAndroid Build Coastguard Worker 	int ret;
916*2d543d20SAndroid Build Coastguard Worker 	uint32_t value;
917*2d543d20SAndroid Build Coastguard Worker 
918*2d543d20SAndroid Build Coastguard Worker 	if (!mlspol) {
919*2d543d20SAndroid Build Coastguard Worker 		yyerror("category definition in non-MLS configuration");
920*2d543d20SAndroid Build Coastguard Worker 		return -1;
921*2d543d20SAndroid Build Coastguard Worker 	}
922*2d543d20SAndroid Build Coastguard Worker 
923*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
924*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
925*2d543d20SAndroid Build Coastguard Worker 			free(id);
926*2d543d20SAndroid Build Coastguard Worker 		return 0;
927*2d543d20SAndroid Build Coastguard Worker 	}
928*2d543d20SAndroid Build Coastguard Worker 
929*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
930*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
931*2d543d20SAndroid Build Coastguard Worker 		yyerror("no category name for category definition?");
932*2d543d20SAndroid Build Coastguard Worker 		return -1;
933*2d543d20SAndroid Build Coastguard Worker 	}
934*2d543d20SAndroid Build Coastguard Worker 	if (id_has_dot(id)) {
935*2d543d20SAndroid Build Coastguard Worker 		yyerror2("category identifier %s may not contain periods", id);
936*2d543d20SAndroid Build Coastguard Worker 		goto bad;
937*2d543d20SAndroid Build Coastguard Worker 	}
938*2d543d20SAndroid Build Coastguard Worker 	datum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
939*2d543d20SAndroid Build Coastguard Worker 	if (!datum) {
940*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
941*2d543d20SAndroid Build Coastguard Worker 		goto bad;
942*2d543d20SAndroid Build Coastguard Worker 	}
943*2d543d20SAndroid Build Coastguard Worker 	cat_datum_init(datum);
944*2d543d20SAndroid Build Coastguard Worker 	datum->isalias = FALSE;
945*2d543d20SAndroid Build Coastguard Worker 
946*2d543d20SAndroid Build Coastguard Worker 	ret = declare_symbol(SYM_CATS, id, datum, &value, &value);
947*2d543d20SAndroid Build Coastguard Worker 	switch (ret) {
948*2d543d20SAndroid Build Coastguard Worker 	case -3:{
949*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
950*2d543d20SAndroid Build Coastguard Worker 			goto bad;
951*2d543d20SAndroid Build Coastguard Worker 		}
952*2d543d20SAndroid Build Coastguard Worker 	case -2:{
953*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate declaration of category %s", id);
954*2d543d20SAndroid Build Coastguard Worker 			goto bad;
955*2d543d20SAndroid Build Coastguard Worker 		}
956*2d543d20SAndroid Build Coastguard Worker 	case -1:{
957*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not declare category %s here", id);
958*2d543d20SAndroid Build Coastguard Worker 			goto bad;
959*2d543d20SAndroid Build Coastguard Worker 		}
960*2d543d20SAndroid Build Coastguard Worker 	case 0:
961*2d543d20SAndroid Build Coastguard Worker 	case 1:{
962*2d543d20SAndroid Build Coastguard Worker 			break;
963*2d543d20SAndroid Build Coastguard Worker 		}
964*2d543d20SAndroid Build Coastguard Worker 	default:{
965*2d543d20SAndroid Build Coastguard Worker 			assert(0);	/* should never get here */
966*2d543d20SAndroid Build Coastguard Worker 		}
967*2d543d20SAndroid Build Coastguard Worker 	}
968*2d543d20SAndroid Build Coastguard Worker 	datum->s.value = value;
969*2d543d20SAndroid Build Coastguard Worker 
970*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
971*2d543d20SAndroid Build Coastguard Worker 		if (id_has_dot(id)) {
972*2d543d20SAndroid Build Coastguard Worker 			yyerror2("category alias %s may not contain periods", id);
973*2d543d20SAndroid Build Coastguard Worker 			free(id);
974*2d543d20SAndroid Build Coastguard Worker 			return -1;
975*2d543d20SAndroid Build Coastguard Worker 		}
976*2d543d20SAndroid Build Coastguard Worker 		aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
977*2d543d20SAndroid Build Coastguard Worker 		if (!aliasdatum) {
978*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
979*2d543d20SAndroid Build Coastguard Worker 			free(id);
980*2d543d20SAndroid Build Coastguard Worker 			return -1;
981*2d543d20SAndroid Build Coastguard Worker 		}
982*2d543d20SAndroid Build Coastguard Worker 		cat_datum_init(aliasdatum);
983*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->isalias = TRUE;
984*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->s.value = datum->s.value;
985*2d543d20SAndroid Build Coastguard Worker 
986*2d543d20SAndroid Build Coastguard Worker 		ret =
987*2d543d20SAndroid Build Coastguard Worker 		    declare_symbol(SYM_CATS, id, aliasdatum, NULL,
988*2d543d20SAndroid Build Coastguard Worker 				   &datum->s.value);
989*2d543d20SAndroid Build Coastguard Worker 		switch (ret) {
990*2d543d20SAndroid Build Coastguard Worker 		case -3:{
991*2d543d20SAndroid Build Coastguard Worker 				yyerror("Out of memory!");
992*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
993*2d543d20SAndroid Build Coastguard Worker 			}
994*2d543d20SAndroid Build Coastguard Worker 		case -2:{
995*2d543d20SAndroid Build Coastguard Worker 				yyerror2
996*2d543d20SAndroid Build Coastguard Worker 				    ("duplicate declaration of category alias %s", id);
997*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
998*2d543d20SAndroid Build Coastguard Worker 			}
999*2d543d20SAndroid Build Coastguard Worker 		case -1:{
1000*2d543d20SAndroid Build Coastguard Worker 				yyerror2
1001*2d543d20SAndroid Build Coastguard Worker 				    ("could not declare category alias %s here", id);
1002*2d543d20SAndroid Build Coastguard Worker 				goto bad_alias;
1003*2d543d20SAndroid Build Coastguard Worker 			}
1004*2d543d20SAndroid Build Coastguard Worker 		case 0:
1005*2d543d20SAndroid Build Coastguard Worker 		case 1:{
1006*2d543d20SAndroid Build Coastguard Worker 				break;
1007*2d543d20SAndroid Build Coastguard Worker 			}
1008*2d543d20SAndroid Build Coastguard Worker 		default:{
1009*2d543d20SAndroid Build Coastguard Worker 				assert(0);	/* should never get here */
1010*2d543d20SAndroid Build Coastguard Worker 			}
1011*2d543d20SAndroid Build Coastguard Worker 		}
1012*2d543d20SAndroid Build Coastguard Worker 	}
1013*2d543d20SAndroid Build Coastguard Worker 
1014*2d543d20SAndroid Build Coastguard Worker 	return 0;
1015*2d543d20SAndroid Build Coastguard Worker 
1016*2d543d20SAndroid Build Coastguard Worker       bad:
1017*2d543d20SAndroid Build Coastguard Worker 	if (id)
1018*2d543d20SAndroid Build Coastguard Worker 		free(id);
1019*2d543d20SAndroid Build Coastguard Worker 	if (datum) {
1020*2d543d20SAndroid Build Coastguard Worker 		cat_datum_destroy(datum);
1021*2d543d20SAndroid Build Coastguard Worker 		free(datum);
1022*2d543d20SAndroid Build Coastguard Worker 	}
1023*2d543d20SAndroid Build Coastguard Worker 	return -1;
1024*2d543d20SAndroid Build Coastguard Worker 
1025*2d543d20SAndroid Build Coastguard Worker       bad_alias:
1026*2d543d20SAndroid Build Coastguard Worker 	if (id)
1027*2d543d20SAndroid Build Coastguard Worker 		free(id);
1028*2d543d20SAndroid Build Coastguard Worker 	if (aliasdatum) {
1029*2d543d20SAndroid Build Coastguard Worker 		cat_datum_destroy(aliasdatum);
1030*2d543d20SAndroid Build Coastguard Worker 		free(aliasdatum);
1031*2d543d20SAndroid Build Coastguard Worker 	}
1032*2d543d20SAndroid Build Coastguard Worker 	return -1;
1033*2d543d20SAndroid Build Coastguard Worker }
1034*2d543d20SAndroid Build Coastguard Worker 
clone_level(hashtab_key_t key,hashtab_datum_t datum,void * arg)1035*2d543d20SAndroid Build Coastguard Worker static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg)
1036*2d543d20SAndroid Build Coastguard Worker {
1037*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum = (level_datum_t *) datum;
1038*2d543d20SAndroid Build Coastguard Worker 	mls_level_t *level = (mls_level_t *) arg, *newlevel;
1039*2d543d20SAndroid Build Coastguard Worker 
1040*2d543d20SAndroid Build Coastguard Worker 	if (levdatum->notdefined && levdatum->level == level) {
1041*2d543d20SAndroid Build Coastguard Worker 		if (!levdatum->isalias) {
1042*2d543d20SAndroid Build Coastguard Worker 			levdatum->notdefined = FALSE;
1043*2d543d20SAndroid Build Coastguard Worker 			return 0;
1044*2d543d20SAndroid Build Coastguard Worker 		}
1045*2d543d20SAndroid Build Coastguard Worker 		newlevel = (mls_level_t *) malloc(sizeof(mls_level_t));
1046*2d543d20SAndroid Build Coastguard Worker 		if (!newlevel)
1047*2d543d20SAndroid Build Coastguard Worker 			return -1;
1048*2d543d20SAndroid Build Coastguard Worker 		if (mls_level_cpy(newlevel, level)) {
1049*2d543d20SAndroid Build Coastguard Worker 			free(newlevel);
1050*2d543d20SAndroid Build Coastguard Worker 			return -1;
1051*2d543d20SAndroid Build Coastguard Worker 		}
1052*2d543d20SAndroid Build Coastguard Worker 		levdatum->level = newlevel;
1053*2d543d20SAndroid Build Coastguard Worker 		levdatum->notdefined = FALSE;
1054*2d543d20SAndroid Build Coastguard Worker 	}
1055*2d543d20SAndroid Build Coastguard Worker 	return 0;
1056*2d543d20SAndroid Build Coastguard Worker }
1057*2d543d20SAndroid Build Coastguard Worker 
define_level(void)1058*2d543d20SAndroid Build Coastguard Worker int define_level(void)
1059*2d543d20SAndroid Build Coastguard Worker {
1060*2d543d20SAndroid Build Coastguard Worker 	char *id;
1061*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum;
1062*2d543d20SAndroid Build Coastguard Worker 
1063*2d543d20SAndroid Build Coastguard Worker 	if (!mlspol) {
1064*2d543d20SAndroid Build Coastguard Worker 		yyerror("level definition in non-MLS configuration");
1065*2d543d20SAndroid Build Coastguard Worker 		return -1;
1066*2d543d20SAndroid Build Coastguard Worker 	}
1067*2d543d20SAndroid Build Coastguard Worker 
1068*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1069*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1070*2d543d20SAndroid Build Coastguard Worker 			free(id);
1071*2d543d20SAndroid Build Coastguard Worker 		return 0;
1072*2d543d20SAndroid Build Coastguard Worker 	}
1073*2d543d20SAndroid Build Coastguard Worker 
1074*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
1075*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1076*2d543d20SAndroid Build Coastguard Worker 		yyerror("no level name for level definition?");
1077*2d543d20SAndroid Build Coastguard Worker 		return -1;
1078*2d543d20SAndroid Build Coastguard Worker 	}
1079*2d543d20SAndroid Build Coastguard Worker 	levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
1080*2d543d20SAndroid Build Coastguard Worker 						    (hashtab_key_t) id);
1081*2d543d20SAndroid Build Coastguard Worker 	if (!levdatum) {
1082*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown sensitivity %s used in level definition", id);
1083*2d543d20SAndroid Build Coastguard Worker 		free(id);
1084*2d543d20SAndroid Build Coastguard Worker 		return -1;
1085*2d543d20SAndroid Build Coastguard Worker 	}
1086*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_length(&levdatum->level->cat)) {
1087*2d543d20SAndroid Build Coastguard Worker 		yyerror2("sensitivity %s used in multiple level definitions",
1088*2d543d20SAndroid Build Coastguard Worker 			 id);
1089*2d543d20SAndroid Build Coastguard Worker 		free(id);
1090*2d543d20SAndroid Build Coastguard Worker 		return -1;
1091*2d543d20SAndroid Build Coastguard Worker 	}
1092*2d543d20SAndroid Build Coastguard Worker 	free(id);
1093*2d543d20SAndroid Build Coastguard Worker 
1094*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1095*2d543d20SAndroid Build Coastguard Worker 		cat_datum_t *cdatum;
1096*2d543d20SAndroid Build Coastguard Worker 		uint32_t range_start, range_end, i;
1097*2d543d20SAndroid Build Coastguard Worker 
1098*2d543d20SAndroid Build Coastguard Worker 		if (id_has_dot(id)) {
1099*2d543d20SAndroid Build Coastguard Worker 			char *id_start = id;
1100*2d543d20SAndroid Build Coastguard Worker 			char *id_end = strchr(id, '.');
1101*2d543d20SAndroid Build Coastguard Worker 
1102*2d543d20SAndroid Build Coastguard Worker 			*(id_end++) = '\0';
1103*2d543d20SAndroid Build Coastguard Worker 
1104*2d543d20SAndroid Build Coastguard Worker 			cdatum =
1105*2d543d20SAndroid Build Coastguard Worker 			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1106*2d543d20SAndroid Build Coastguard Worker 							   table,
1107*2d543d20SAndroid Build Coastguard Worker 							   (hashtab_key_t)
1108*2d543d20SAndroid Build Coastguard Worker 							   id_start);
1109*2d543d20SAndroid Build Coastguard Worker 			if (!cdatum) {
1110*2d543d20SAndroid Build Coastguard Worker 				yyerror2("unknown category %s", id_start);
1111*2d543d20SAndroid Build Coastguard Worker 				free(id);
1112*2d543d20SAndroid Build Coastguard Worker 				return -1;
1113*2d543d20SAndroid Build Coastguard Worker 			}
1114*2d543d20SAndroid Build Coastguard Worker 			range_start = cdatum->s.value - 1;
1115*2d543d20SAndroid Build Coastguard Worker 			cdatum =
1116*2d543d20SAndroid Build Coastguard Worker 			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1117*2d543d20SAndroid Build Coastguard Worker 							   table,
1118*2d543d20SAndroid Build Coastguard Worker 							   (hashtab_key_t)
1119*2d543d20SAndroid Build Coastguard Worker 							   id_end);
1120*2d543d20SAndroid Build Coastguard Worker 			if (!cdatum) {
1121*2d543d20SAndroid Build Coastguard Worker 				yyerror2("unknown category %s", id_end);
1122*2d543d20SAndroid Build Coastguard Worker 				free(id);
1123*2d543d20SAndroid Build Coastguard Worker 				return -1;
1124*2d543d20SAndroid Build Coastguard Worker 			}
1125*2d543d20SAndroid Build Coastguard Worker 			range_end = cdatum->s.value - 1;
1126*2d543d20SAndroid Build Coastguard Worker 
1127*2d543d20SAndroid Build Coastguard Worker 			if (range_end < range_start) {
1128*2d543d20SAndroid Build Coastguard Worker 				yyerror2("category range %d-%d is invalid", range_start, range_end);
1129*2d543d20SAndroid Build Coastguard Worker 				free(id);
1130*2d543d20SAndroid Build Coastguard Worker 				return -1;
1131*2d543d20SAndroid Build Coastguard Worker 			}
1132*2d543d20SAndroid Build Coastguard Worker 		} else {
1133*2d543d20SAndroid Build Coastguard Worker 			cdatum =
1134*2d543d20SAndroid Build Coastguard Worker 			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1135*2d543d20SAndroid Build Coastguard Worker 							   table,
1136*2d543d20SAndroid Build Coastguard Worker 							   (hashtab_key_t) id);
1137*2d543d20SAndroid Build Coastguard Worker 			if (!cdatum) {
1138*2d543d20SAndroid Build Coastguard Worker 				yyerror2("unknown category %s", id);
1139*2d543d20SAndroid Build Coastguard Worker 				free(id);
1140*2d543d20SAndroid Build Coastguard Worker 				return -1;
1141*2d543d20SAndroid Build Coastguard Worker 			}
1142*2d543d20SAndroid Build Coastguard Worker 			range_start = range_end = cdatum->s.value - 1;
1143*2d543d20SAndroid Build Coastguard Worker 		}
1144*2d543d20SAndroid Build Coastguard Worker 
1145*2d543d20SAndroid Build Coastguard Worker 		for (i = range_start; i <= range_end; i++) {
1146*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_set_bit(&levdatum->level->cat, i, TRUE)) {
1147*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
1148*2d543d20SAndroid Build Coastguard Worker 				free(id);
1149*2d543d20SAndroid Build Coastguard Worker 				return -1;
1150*2d543d20SAndroid Build Coastguard Worker 			}
1151*2d543d20SAndroid Build Coastguard Worker 		}
1152*2d543d20SAndroid Build Coastguard Worker 
1153*2d543d20SAndroid Build Coastguard Worker 		free(id);
1154*2d543d20SAndroid Build Coastguard Worker 	}
1155*2d543d20SAndroid Build Coastguard Worker 
1156*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map
1157*2d543d20SAndroid Build Coastguard Worker 	    (policydbp->p_levels.table, clone_level, levdatum->level)) {
1158*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
1159*2d543d20SAndroid Build Coastguard Worker 		return -1;
1160*2d543d20SAndroid Build Coastguard Worker 	}
1161*2d543d20SAndroid Build Coastguard Worker 
1162*2d543d20SAndroid Build Coastguard Worker 	return 0;
1163*2d543d20SAndroid Build Coastguard Worker }
1164*2d543d20SAndroid Build Coastguard Worker 
define_attrib(void)1165*2d543d20SAndroid Build Coastguard Worker int define_attrib(void)
1166*2d543d20SAndroid Build Coastguard Worker {
1167*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1168*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
1169*2d543d20SAndroid Build Coastguard Worker 		return 0;
1170*2d543d20SAndroid Build Coastguard Worker 	}
1171*2d543d20SAndroid Build Coastguard Worker 
1172*2d543d20SAndroid Build Coastguard Worker 	if (declare_type(TRUE, TRUE) == NULL) {
1173*2d543d20SAndroid Build Coastguard Worker 		return -1;
1174*2d543d20SAndroid Build Coastguard Worker 	}
1175*2d543d20SAndroid Build Coastguard Worker 	return 0;
1176*2d543d20SAndroid Build Coastguard Worker }
1177*2d543d20SAndroid Build Coastguard Worker 
expand_attrib(void)1178*2d543d20SAndroid Build Coastguard Worker int expand_attrib(void)
1179*2d543d20SAndroid Build Coastguard Worker {
1180*2d543d20SAndroid Build Coastguard Worker 	char *id;
1181*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t attrs;
1182*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *attr;
1183*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
1184*2d543d20SAndroid Build Coastguard Worker 	const char *name;
1185*2d543d20SAndroid Build Coastguard Worker 	uint32_t i;
1186*2d543d20SAndroid Build Coastguard Worker 	int rc = -1;
1187*2d543d20SAndroid Build Coastguard Worker 	int flags = 0;
1188*2d543d20SAndroid Build Coastguard Worker 
1189*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
1190*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < 2; i++) {
1191*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue))) {
1192*2d543d20SAndroid Build Coastguard Worker 				free(id);
1193*2d543d20SAndroid Build Coastguard Worker 			}
1194*2d543d20SAndroid Build Coastguard Worker 		}
1195*2d543d20SAndroid Build Coastguard Worker 		return 0;
1196*2d543d20SAndroid Build Coastguard Worker 	}
1197*2d543d20SAndroid Build Coastguard Worker 
1198*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&attrs);
1199*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1200*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_TYPES, id)) {
1201*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not within scope", id);
1202*2d543d20SAndroid Build Coastguard Worker 			goto exit;
1203*2d543d20SAndroid Build Coastguard Worker 		}
1204*2d543d20SAndroid Build Coastguard Worker 
1205*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_types.table, id);
1206*2d543d20SAndroid Build Coastguard Worker 		if (!attr) {
1207*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not declared", id);
1208*2d543d20SAndroid Build Coastguard Worker 			goto exit;
1209*2d543d20SAndroid Build Coastguard Worker 		}
1210*2d543d20SAndroid Build Coastguard Worker 
1211*2d543d20SAndroid Build Coastguard Worker 		if (attr->flavor != TYPE_ATTRIB) {
1212*2d543d20SAndroid Build Coastguard Worker 			yyerror2("%s is a type, not an attribute", id);
1213*2d543d20SAndroid Build Coastguard Worker 			goto exit;
1214*2d543d20SAndroid Build Coastguard Worker 		}
1215*2d543d20SAndroid Build Coastguard Worker 
1216*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&attrs, attr->s.value - 1, TRUE)) {
1217*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
1218*2d543d20SAndroid Build Coastguard Worker 			goto exit;
1219*2d543d20SAndroid Build Coastguard Worker 		}
1220*2d543d20SAndroid Build Coastguard Worker 
1221*2d543d20SAndroid Build Coastguard Worker 		free(id);
1222*2d543d20SAndroid Build Coastguard Worker 	}
1223*2d543d20SAndroid Build Coastguard Worker 
1224*2d543d20SAndroid Build Coastguard Worker 	id = (char *) queue_remove(id_queue);
1225*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1226*2d543d20SAndroid Build Coastguard Worker 		yyerror("No option specified for attribute expansion.");
1227*2d543d20SAndroid Build Coastguard Worker 		goto exit;
1228*2d543d20SAndroid Build Coastguard Worker 	}
1229*2d543d20SAndroid Build Coastguard Worker 
1230*2d543d20SAndroid Build Coastguard Worker 	if (!strcmp(id, "T")) {
1231*2d543d20SAndroid Build Coastguard Worker 		flags = TYPE_FLAGS_EXPAND_ATTR_TRUE;
1232*2d543d20SAndroid Build Coastguard Worker 	} else {
1233*2d543d20SAndroid Build Coastguard Worker 		flags = TYPE_FLAGS_EXPAND_ATTR_FALSE;
1234*2d543d20SAndroid Build Coastguard Worker 	}
1235*2d543d20SAndroid Build Coastguard Worker 
1236*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&attrs, node, i) {
1237*2d543d20SAndroid Build Coastguard Worker 		name = policydbp->sym_val_to_name[SYM_TYPES][i];
1238*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_types.table, name);
1239*2d543d20SAndroid Build Coastguard Worker 		attr->flags |= flags;
1240*2d543d20SAndroid Build Coastguard Worker 		if ((attr->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) &&
1241*2d543d20SAndroid Build Coastguard Worker 				(attr->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE)) {
1242*2d543d20SAndroid Build Coastguard Worker 			yywarn2("Expandattribute option of attribute %s was set to both true and false; "
1243*2d543d20SAndroid Build Coastguard Worker 				"Resolving to false.", name);
1244*2d543d20SAndroid Build Coastguard Worker 			attr->flags &= ~TYPE_FLAGS_EXPAND_ATTR_TRUE;
1245*2d543d20SAndroid Build Coastguard Worker 		}
1246*2d543d20SAndroid Build Coastguard Worker 	}
1247*2d543d20SAndroid Build Coastguard Worker 
1248*2d543d20SAndroid Build Coastguard Worker 	rc = 0;
1249*2d543d20SAndroid Build Coastguard Worker exit:
1250*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&attrs);
1251*2d543d20SAndroid Build Coastguard Worker 	free(id);
1252*2d543d20SAndroid Build Coastguard Worker 	return rc;
1253*2d543d20SAndroid Build Coastguard Worker }
1254*2d543d20SAndroid Build Coastguard Worker 
add_aliases_to_type(type_datum_t * type)1255*2d543d20SAndroid Build Coastguard Worker static int add_aliases_to_type(type_datum_t * type)
1256*2d543d20SAndroid Build Coastguard Worker {
1257*2d543d20SAndroid Build Coastguard Worker 	char *id;
1258*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *aliasdatum = NULL;
1259*2d543d20SAndroid Build Coastguard Worker 	int ret;
1260*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1261*2d543d20SAndroid Build Coastguard Worker 		if (id_has_dot(id)) {
1262*2d543d20SAndroid Build Coastguard Worker 			yyerror2
1263*2d543d20SAndroid Build Coastguard Worker 			    ("type alias identifier %s may not contain periods", id);
1264*2d543d20SAndroid Build Coastguard Worker 			free(id);
1265*2d543d20SAndroid Build Coastguard Worker 			return -1;
1266*2d543d20SAndroid Build Coastguard Worker 		}
1267*2d543d20SAndroid Build Coastguard Worker 		aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
1268*2d543d20SAndroid Build Coastguard Worker 		if (!aliasdatum) {
1269*2d543d20SAndroid Build Coastguard Worker 			free(id);
1270*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
1271*2d543d20SAndroid Build Coastguard Worker 			return -1;
1272*2d543d20SAndroid Build Coastguard Worker 		}
1273*2d543d20SAndroid Build Coastguard Worker 		memset(aliasdatum, 0, sizeof(type_datum_t));
1274*2d543d20SAndroid Build Coastguard Worker 		aliasdatum->s.value = type->s.value;
1275*2d543d20SAndroid Build Coastguard Worker 
1276*2d543d20SAndroid Build Coastguard Worker 		ret = declare_symbol(SYM_TYPES, id, aliasdatum,
1277*2d543d20SAndroid Build Coastguard Worker 				     NULL, &aliasdatum->s.value);
1278*2d543d20SAndroid Build Coastguard Worker 		switch (ret) {
1279*2d543d20SAndroid Build Coastguard Worker 		case -3:{
1280*2d543d20SAndroid Build Coastguard Worker 				yyerror("Out of memory!");
1281*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1282*2d543d20SAndroid Build Coastguard Worker 			}
1283*2d543d20SAndroid Build Coastguard Worker 		case -2:{
1284*2d543d20SAndroid Build Coastguard Worker 				yyerror2("duplicate declaration of alias %s",
1285*2d543d20SAndroid Build Coastguard Worker 					 id);
1286*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1287*2d543d20SAndroid Build Coastguard Worker 			}
1288*2d543d20SAndroid Build Coastguard Worker 		case -1:{
1289*2d543d20SAndroid Build Coastguard Worker 				yyerror2("could not declare alias %s here", id);
1290*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1291*2d543d20SAndroid Build Coastguard Worker 			}
1292*2d543d20SAndroid Build Coastguard Worker 		case 0:	 	break;
1293*2d543d20SAndroid Build Coastguard Worker 		case 1:{
1294*2d543d20SAndroid Build Coastguard Worker 				/* ret == 1 means the alias was required and therefore already
1295*2d543d20SAndroid Build Coastguard Worker 				 * has a value. Set it up as an alias with a different primary. */
1296*2d543d20SAndroid Build Coastguard Worker 				type_datum_destroy(aliasdatum);
1297*2d543d20SAndroid Build Coastguard Worker 				free(aliasdatum);
1298*2d543d20SAndroid Build Coastguard Worker 
1299*2d543d20SAndroid Build Coastguard Worker 				aliasdatum = hashtab_search(policydbp->symtab[SYM_TYPES].table, id);
1300*2d543d20SAndroid Build Coastguard Worker 				assert(aliasdatum);
1301*2d543d20SAndroid Build Coastguard Worker 
1302*2d543d20SAndroid Build Coastguard Worker 				aliasdatum->primary = type->s.value;
1303*2d543d20SAndroid Build Coastguard Worker 				aliasdatum->flavor = TYPE_ALIAS;
1304*2d543d20SAndroid Build Coastguard Worker 
1305*2d543d20SAndroid Build Coastguard Worker 				break;
1306*2d543d20SAndroid Build Coastguard Worker 			}
1307*2d543d20SAndroid Build Coastguard Worker 		default:{
1308*2d543d20SAndroid Build Coastguard Worker 				assert(0);	/* should never get here */
1309*2d543d20SAndroid Build Coastguard Worker 			}
1310*2d543d20SAndroid Build Coastguard Worker 		}
1311*2d543d20SAndroid Build Coastguard Worker 	}
1312*2d543d20SAndroid Build Coastguard Worker 	return 0;
1313*2d543d20SAndroid Build Coastguard Worker       cleanup:
1314*2d543d20SAndroid Build Coastguard Worker 	free(id);
1315*2d543d20SAndroid Build Coastguard Worker 	type_datum_destroy(aliasdatum);
1316*2d543d20SAndroid Build Coastguard Worker 	free(aliasdatum);
1317*2d543d20SAndroid Build Coastguard Worker 	return -1;
1318*2d543d20SAndroid Build Coastguard Worker }
1319*2d543d20SAndroid Build Coastguard Worker 
define_typealias(void)1320*2d543d20SAndroid Build Coastguard Worker int define_typealias(void)
1321*2d543d20SAndroid Build Coastguard Worker {
1322*2d543d20SAndroid Build Coastguard Worker 	char *id;
1323*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *t;
1324*2d543d20SAndroid Build Coastguard Worker 
1325*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1326*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1327*2d543d20SAndroid Build Coastguard Worker 			free(id);
1328*2d543d20SAndroid Build Coastguard Worker 		return 0;
1329*2d543d20SAndroid Build Coastguard Worker 	}
1330*2d543d20SAndroid Build Coastguard Worker 
1331*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
1332*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1333*2d543d20SAndroid Build Coastguard Worker 		yyerror("no type name for typealias definition?");
1334*2d543d20SAndroid Build Coastguard Worker 		return -1;
1335*2d543d20SAndroid Build Coastguard Worker 	}
1336*2d543d20SAndroid Build Coastguard Worker 
1337*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
1338*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
1339*2d543d20SAndroid Build Coastguard Worker 		free(id);
1340*2d543d20SAndroid Build Coastguard Worker 		return -1;
1341*2d543d20SAndroid Build Coastguard Worker 	}
1342*2d543d20SAndroid Build Coastguard Worker 	t = hashtab_search(policydbp->p_types.table, id);
1343*2d543d20SAndroid Build Coastguard Worker 	if (!t || t->flavor == TYPE_ATTRIB) {
1344*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown type %s, or it was already declared as an "
1345*2d543d20SAndroid Build Coastguard Worker 			 "attribute", id);
1346*2d543d20SAndroid Build Coastguard Worker 		free(id);
1347*2d543d20SAndroid Build Coastguard Worker 		return -1;
1348*2d543d20SAndroid Build Coastguard Worker 	}
1349*2d543d20SAndroid Build Coastguard Worker 	free(id);
1350*2d543d20SAndroid Build Coastguard Worker 	return add_aliases_to_type(t);
1351*2d543d20SAndroid Build Coastguard Worker }
1352*2d543d20SAndroid Build Coastguard Worker 
define_typeattribute(void)1353*2d543d20SAndroid Build Coastguard Worker int define_typeattribute(void)
1354*2d543d20SAndroid Build Coastguard Worker {
1355*2d543d20SAndroid Build Coastguard Worker 	char *id;
1356*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *t, *attr;
1357*2d543d20SAndroid Build Coastguard Worker 
1358*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1359*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1360*2d543d20SAndroid Build Coastguard Worker 			free(id);
1361*2d543d20SAndroid Build Coastguard Worker 		return 0;
1362*2d543d20SAndroid Build Coastguard Worker 	}
1363*2d543d20SAndroid Build Coastguard Worker 
1364*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
1365*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1366*2d543d20SAndroid Build Coastguard Worker 		yyerror("no type name for typeattribute definition?");
1367*2d543d20SAndroid Build Coastguard Worker 		return -1;
1368*2d543d20SAndroid Build Coastguard Worker 	}
1369*2d543d20SAndroid Build Coastguard Worker 
1370*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
1371*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
1372*2d543d20SAndroid Build Coastguard Worker 		free(id);
1373*2d543d20SAndroid Build Coastguard Worker 		return -1;
1374*2d543d20SAndroid Build Coastguard Worker 	}
1375*2d543d20SAndroid Build Coastguard Worker 	t = hashtab_search(policydbp->p_types.table, id);
1376*2d543d20SAndroid Build Coastguard Worker 	if (!t || t->flavor == TYPE_ATTRIB) {
1377*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown type %s", id);
1378*2d543d20SAndroid Build Coastguard Worker 		free(id);
1379*2d543d20SAndroid Build Coastguard Worker 		return -1;
1380*2d543d20SAndroid Build Coastguard Worker 	}
1381*2d543d20SAndroid Build Coastguard Worker 	free(id);
1382*2d543d20SAndroid Build Coastguard Worker 
1383*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1384*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_TYPES, id)) {
1385*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not within scope", id);
1386*2d543d20SAndroid Build Coastguard Worker 			free(id);
1387*2d543d20SAndroid Build Coastguard Worker 			return -1;
1388*2d543d20SAndroid Build Coastguard Worker 		}
1389*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_types.table, id);
1390*2d543d20SAndroid Build Coastguard Worker 		if (!attr) {
1391*2d543d20SAndroid Build Coastguard Worker 			/* treat it as a fatal error */
1392*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not declared", id);
1393*2d543d20SAndroid Build Coastguard Worker 			free(id);
1394*2d543d20SAndroid Build Coastguard Worker 			return -1;
1395*2d543d20SAndroid Build Coastguard Worker 		}
1396*2d543d20SAndroid Build Coastguard Worker 
1397*2d543d20SAndroid Build Coastguard Worker 		if (attr->flavor != TYPE_ATTRIB) {
1398*2d543d20SAndroid Build Coastguard Worker 			yyerror2("%s is a type, not an attribute", id);
1399*2d543d20SAndroid Build Coastguard Worker 			free(id);
1400*2d543d20SAndroid Build Coastguard Worker 			return -1;
1401*2d543d20SAndroid Build Coastguard Worker 		}
1402*2d543d20SAndroid Build Coastguard Worker 
1403*2d543d20SAndroid Build Coastguard Worker 		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
1404*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
1405*2d543d20SAndroid Build Coastguard Worker 			return -1;
1406*2d543d20SAndroid Build Coastguard Worker 		}
1407*2d543d20SAndroid Build Coastguard Worker 
1408*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&attr->types, (t->s.value - 1), TRUE)) {
1409*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
1410*2d543d20SAndroid Build Coastguard Worker 			return -1;
1411*2d543d20SAndroid Build Coastguard Worker 		}
1412*2d543d20SAndroid Build Coastguard Worker 	}
1413*2d543d20SAndroid Build Coastguard Worker 
1414*2d543d20SAndroid Build Coastguard Worker 	return 0;
1415*2d543d20SAndroid Build Coastguard Worker }
1416*2d543d20SAndroid Build Coastguard Worker 
define_typebounds_helper(const char * bounds_id,const char * type_id)1417*2d543d20SAndroid Build Coastguard Worker static int define_typebounds_helper(const char *bounds_id, const char *type_id)
1418*2d543d20SAndroid Build Coastguard Worker {
1419*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *bounds, *type;
1420*2d543d20SAndroid Build Coastguard Worker 
1421*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, bounds_id)) {
1422*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", bounds_id);
1423*2d543d20SAndroid Build Coastguard Worker 		return -1;
1424*2d543d20SAndroid Build Coastguard Worker 	}
1425*2d543d20SAndroid Build Coastguard Worker 
1426*2d543d20SAndroid Build Coastguard Worker 	bounds = hashtab_search(policydbp->p_types.table, bounds_id);
1427*2d543d20SAndroid Build Coastguard Worker 	if (!bounds || bounds->flavor == TYPE_ATTRIB) {
1428*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not declared", bounds_id);
1429*2d543d20SAndroid Build Coastguard Worker 		return -1;
1430*2d543d20SAndroid Build Coastguard Worker 	}
1431*2d543d20SAndroid Build Coastguard Worker 
1432*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, type_id)) {
1433*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", type_id);
1434*2d543d20SAndroid Build Coastguard Worker 		return -1;
1435*2d543d20SAndroid Build Coastguard Worker 	}
1436*2d543d20SAndroid Build Coastguard Worker 
1437*2d543d20SAndroid Build Coastguard Worker 	type = hashtab_search(policydbp->p_types.table, type_id);
1438*2d543d20SAndroid Build Coastguard Worker 	if (!type || type->flavor == TYPE_ATTRIB) {
1439*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not declared", type_id);
1440*2d543d20SAndroid Build Coastguard Worker 		return -1;
1441*2d543d20SAndroid Build Coastguard Worker 	}
1442*2d543d20SAndroid Build Coastguard Worker 
1443*2d543d20SAndroid Build Coastguard Worker 	if (type->flavor == TYPE_TYPE && !type->primary) {
1444*2d543d20SAndroid Build Coastguard Worker 		type = policydbp->type_val_to_struct[type->s.value - 1];
1445*2d543d20SAndroid Build Coastguard Worker 	} else if (type->flavor == TYPE_ALIAS) {
1446*2d543d20SAndroid Build Coastguard Worker 		type = policydbp->type_val_to_struct[type->primary - 1];
1447*2d543d20SAndroid Build Coastguard Worker 	}
1448*2d543d20SAndroid Build Coastguard Worker 
1449*2d543d20SAndroid Build Coastguard Worker 	if (!type->bounds)
1450*2d543d20SAndroid Build Coastguard Worker 		type->bounds = bounds->s.value;
1451*2d543d20SAndroid Build Coastguard Worker 	else if (type->bounds != bounds->s.value) {
1452*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s has inconsistent bounds %s/%s",
1453*2d543d20SAndroid Build Coastguard Worker 			 type_id,
1454*2d543d20SAndroid Build Coastguard Worker 			 policydbp->p_type_val_to_name[type->bounds - 1],
1455*2d543d20SAndroid Build Coastguard Worker 			 policydbp->p_type_val_to_name[bounds->s.value - 1]);
1456*2d543d20SAndroid Build Coastguard Worker 		return -1;
1457*2d543d20SAndroid Build Coastguard Worker 	}
1458*2d543d20SAndroid Build Coastguard Worker 
1459*2d543d20SAndroid Build Coastguard Worker 	return 0;
1460*2d543d20SAndroid Build Coastguard Worker }
1461*2d543d20SAndroid Build Coastguard Worker 
define_typebounds(void)1462*2d543d20SAndroid Build Coastguard Worker int define_typebounds(void)
1463*2d543d20SAndroid Build Coastguard Worker {
1464*2d543d20SAndroid Build Coastguard Worker 	char *bounds, *id;
1465*2d543d20SAndroid Build Coastguard Worker 
1466*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
1467*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1468*2d543d20SAndroid Build Coastguard Worker 			free(id);
1469*2d543d20SAndroid Build Coastguard Worker 		return 0;
1470*2d543d20SAndroid Build Coastguard Worker 	}
1471*2d543d20SAndroid Build Coastguard Worker 
1472*2d543d20SAndroid Build Coastguard Worker 	bounds = (char *) queue_remove(id_queue);
1473*2d543d20SAndroid Build Coastguard Worker 	if (!bounds) {
1474*2d543d20SAndroid Build Coastguard Worker 		yyerror("no type name for typebounds definition?");
1475*2d543d20SAndroid Build Coastguard Worker 		return -1;
1476*2d543d20SAndroid Build Coastguard Worker 	}
1477*2d543d20SAndroid Build Coastguard Worker 
1478*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1479*2d543d20SAndroid Build Coastguard Worker 		if (define_typebounds_helper(bounds, id)) {
1480*2d543d20SAndroid Build Coastguard Worker 			free(bounds);
1481*2d543d20SAndroid Build Coastguard Worker 			free(id);
1482*2d543d20SAndroid Build Coastguard Worker 			return -1;
1483*2d543d20SAndroid Build Coastguard Worker 		}
1484*2d543d20SAndroid Build Coastguard Worker 
1485*2d543d20SAndroid Build Coastguard Worker 		free(id);
1486*2d543d20SAndroid Build Coastguard Worker 	}
1487*2d543d20SAndroid Build Coastguard Worker 	free(bounds);
1488*2d543d20SAndroid Build Coastguard Worker 
1489*2d543d20SAndroid Build Coastguard Worker 	return 0;
1490*2d543d20SAndroid Build Coastguard Worker }
1491*2d543d20SAndroid Build Coastguard Worker 
define_type(int alias)1492*2d543d20SAndroid Build Coastguard Worker int define_type(int alias)
1493*2d543d20SAndroid Build Coastguard Worker {
1494*2d543d20SAndroid Build Coastguard Worker 	char *id;
1495*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *datum, *attr;
1496*2d543d20SAndroid Build Coastguard Worker 
1497*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1498*2d543d20SAndroid Build Coastguard Worker 		/*
1499*2d543d20SAndroid Build Coastguard Worker 		 * If type name contains ".", we have to define boundary
1500*2d543d20SAndroid Build Coastguard Worker 		 * relationship implicitly to keep compatibility with
1501*2d543d20SAndroid Build Coastguard Worker 		 * old name based hierarchy.
1502*2d543d20SAndroid Build Coastguard Worker 		 */
1503*2d543d20SAndroid Build Coastguard Worker 		if ((id = queue_remove(id_queue))) {
1504*2d543d20SAndroid Build Coastguard Worker 			const char *delim;
1505*2d543d20SAndroid Build Coastguard Worker 
1506*2d543d20SAndroid Build Coastguard Worker 			if ((delim = strrchr(id, '.'))) {
1507*2d543d20SAndroid Build Coastguard Worker 				int ret;
1508*2d543d20SAndroid Build Coastguard Worker 				char *bounds = strdup(id);
1509*2d543d20SAndroid Build Coastguard Worker 				if (!bounds) {
1510*2d543d20SAndroid Build Coastguard Worker 					yyerror("out of memory");
1511*2d543d20SAndroid Build Coastguard Worker 					free(id);
1512*2d543d20SAndroid Build Coastguard Worker 					return -1;
1513*2d543d20SAndroid Build Coastguard Worker 				}
1514*2d543d20SAndroid Build Coastguard Worker 
1515*2d543d20SAndroid Build Coastguard Worker 				bounds[(size_t)(delim - id)] = '\0';
1516*2d543d20SAndroid Build Coastguard Worker 
1517*2d543d20SAndroid Build Coastguard Worker 				ret = define_typebounds_helper(bounds, id);
1518*2d543d20SAndroid Build Coastguard Worker 				free(bounds);
1519*2d543d20SAndroid Build Coastguard Worker 				if (ret) {
1520*2d543d20SAndroid Build Coastguard Worker 					free(id);
1521*2d543d20SAndroid Build Coastguard Worker 					return -1;
1522*2d543d20SAndroid Build Coastguard Worker 				}
1523*2d543d20SAndroid Build Coastguard Worker 
1524*2d543d20SAndroid Build Coastguard Worker 			}
1525*2d543d20SAndroid Build Coastguard Worker 			free(id);
1526*2d543d20SAndroid Build Coastguard Worker 		}
1527*2d543d20SAndroid Build Coastguard Worker 
1528*2d543d20SAndroid Build Coastguard Worker 		if (alias) {
1529*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
1530*2d543d20SAndroid Build Coastguard Worker 				free(id);
1531*2d543d20SAndroid Build Coastguard Worker 		}
1532*2d543d20SAndroid Build Coastguard Worker 
1533*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1534*2d543d20SAndroid Build Coastguard Worker 			free(id);
1535*2d543d20SAndroid Build Coastguard Worker 		return 0;
1536*2d543d20SAndroid Build Coastguard Worker 	}
1537*2d543d20SAndroid Build Coastguard Worker 
1538*2d543d20SAndroid Build Coastguard Worker 	if ((datum = declare_type(TRUE, FALSE)) == NULL) {
1539*2d543d20SAndroid Build Coastguard Worker 		return -1;
1540*2d543d20SAndroid Build Coastguard Worker 	}
1541*2d543d20SAndroid Build Coastguard Worker 
1542*2d543d20SAndroid Build Coastguard Worker 	if (alias) {
1543*2d543d20SAndroid Build Coastguard Worker 		if (add_aliases_to_type(datum) == -1) {
1544*2d543d20SAndroid Build Coastguard Worker 			return -1;
1545*2d543d20SAndroid Build Coastguard Worker 		}
1546*2d543d20SAndroid Build Coastguard Worker 	}
1547*2d543d20SAndroid Build Coastguard Worker 
1548*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1549*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_TYPES, id)) {
1550*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not within scope", id);
1551*2d543d20SAndroid Build Coastguard Worker 			free(id);
1552*2d543d20SAndroid Build Coastguard Worker 			return -1;
1553*2d543d20SAndroid Build Coastguard Worker 		}
1554*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_types.table, id);
1555*2d543d20SAndroid Build Coastguard Worker 		if (!attr) {
1556*2d543d20SAndroid Build Coastguard Worker 			/* treat it as a fatal error */
1557*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not declared", id);
1558*2d543d20SAndroid Build Coastguard Worker 			free(id);
1559*2d543d20SAndroid Build Coastguard Worker 			return -1;
1560*2d543d20SAndroid Build Coastguard Worker 		}
1561*2d543d20SAndroid Build Coastguard Worker 
1562*2d543d20SAndroid Build Coastguard Worker 		if (attr->flavor != TYPE_ATTRIB) {
1563*2d543d20SAndroid Build Coastguard Worker 			yyerror2("%s is a type, not an attribute", id);
1564*2d543d20SAndroid Build Coastguard Worker 			free(id);
1565*2d543d20SAndroid Build Coastguard Worker 			return -1;
1566*2d543d20SAndroid Build Coastguard Worker 		}
1567*2d543d20SAndroid Build Coastguard Worker 
1568*2d543d20SAndroid Build Coastguard Worker 		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
1569*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
1570*2d543d20SAndroid Build Coastguard Worker 			return -1;
1571*2d543d20SAndroid Build Coastguard Worker 		}
1572*2d543d20SAndroid Build Coastguard Worker 
1573*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&attr->types, datum->s.value - 1, TRUE)) {
1574*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory");
1575*2d543d20SAndroid Build Coastguard Worker 			return -1;
1576*2d543d20SAndroid Build Coastguard Worker 		}
1577*2d543d20SAndroid Build Coastguard Worker 	}
1578*2d543d20SAndroid Build Coastguard Worker 
1579*2d543d20SAndroid Build Coastguard Worker 	return 0;
1580*2d543d20SAndroid Build Coastguard Worker }
1581*2d543d20SAndroid Build Coastguard Worker 
1582*2d543d20SAndroid Build Coastguard Worker struct val_to_name {
1583*2d543d20SAndroid Build Coastguard Worker 	unsigned int val;
1584*2d543d20SAndroid Build Coastguard Worker 	char *name;
1585*2d543d20SAndroid Build Coastguard Worker };
1586*2d543d20SAndroid Build Coastguard Worker 
1587*2d543d20SAndroid Build Coastguard Worker /* Adds a type, given by its textual name, to a typeset.  If *add is
1588*2d543d20SAndroid Build Coastguard Worker    0, then add the type to the negative set; otherwise if *add is 1
1589*2d543d20SAndroid Build Coastguard Worker    then add it to the positive side. */
set_types(type_set_t * set,char * id,int * add,char starallowed)1590*2d543d20SAndroid Build Coastguard Worker static int set_types(type_set_t * set, char *id, int *add, char starallowed)
1591*2d543d20SAndroid Build Coastguard Worker {
1592*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *t;
1593*2d543d20SAndroid Build Coastguard Worker 
1594*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "*") == 0) {
1595*2d543d20SAndroid Build Coastguard Worker 		free(id);
1596*2d543d20SAndroid Build Coastguard Worker 		if (!starallowed) {
1597*2d543d20SAndroid Build Coastguard Worker 			yyerror("* not allowed in this type of rule");
1598*2d543d20SAndroid Build Coastguard Worker 			return -1;
1599*2d543d20SAndroid Build Coastguard Worker 		}
1600*2d543d20SAndroid Build Coastguard Worker 		/* set TYPE_STAR flag */
1601*2d543d20SAndroid Build Coastguard Worker 		set->flags = TYPE_STAR;
1602*2d543d20SAndroid Build Coastguard Worker 		*add = 1;
1603*2d543d20SAndroid Build Coastguard Worker 		return 0;
1604*2d543d20SAndroid Build Coastguard Worker 	}
1605*2d543d20SAndroid Build Coastguard Worker 
1606*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "~") == 0) {
1607*2d543d20SAndroid Build Coastguard Worker 		free(id);
1608*2d543d20SAndroid Build Coastguard Worker 		if (!starallowed) {
1609*2d543d20SAndroid Build Coastguard Worker 			yyerror("~ not allowed in this type of rule");
1610*2d543d20SAndroid Build Coastguard Worker 			return -1;
1611*2d543d20SAndroid Build Coastguard Worker 		}
1612*2d543d20SAndroid Build Coastguard Worker 		/* complement the set */
1613*2d543d20SAndroid Build Coastguard Worker 		set->flags = TYPE_COMP;
1614*2d543d20SAndroid Build Coastguard Worker 		*add = 1;
1615*2d543d20SAndroid Build Coastguard Worker 		return 0;
1616*2d543d20SAndroid Build Coastguard Worker 	}
1617*2d543d20SAndroid Build Coastguard Worker 
1618*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "-") == 0) {
1619*2d543d20SAndroid Build Coastguard Worker 		*add = 0;
1620*2d543d20SAndroid Build Coastguard Worker 		free(id);
1621*2d543d20SAndroid Build Coastguard Worker 		return 0;
1622*2d543d20SAndroid Build Coastguard Worker 	}
1623*2d543d20SAndroid Build Coastguard Worker 
1624*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
1625*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
1626*2d543d20SAndroid Build Coastguard Worker 		free(id);
1627*2d543d20SAndroid Build Coastguard Worker 		return -1;
1628*2d543d20SAndroid Build Coastguard Worker 	}
1629*2d543d20SAndroid Build Coastguard Worker 	t = hashtab_search(policydbp->p_types.table, id);
1630*2d543d20SAndroid Build Coastguard Worker 	if (!t) {
1631*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown type %s", id);
1632*2d543d20SAndroid Build Coastguard Worker 		free(id);
1633*2d543d20SAndroid Build Coastguard Worker 		return -1;
1634*2d543d20SAndroid Build Coastguard Worker 	}
1635*2d543d20SAndroid Build Coastguard Worker 
1636*2d543d20SAndroid Build Coastguard Worker 	if (*add == 0) {
1637*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&set->negset, t->s.value - 1, TRUE))
1638*2d543d20SAndroid Build Coastguard Worker 			goto oom;
1639*2d543d20SAndroid Build Coastguard Worker 	} else {
1640*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&set->types, t->s.value - 1, TRUE))
1641*2d543d20SAndroid Build Coastguard Worker 			goto oom;
1642*2d543d20SAndroid Build Coastguard Worker 	}
1643*2d543d20SAndroid Build Coastguard Worker 	free(id);
1644*2d543d20SAndroid Build Coastguard Worker 	*add = 1;
1645*2d543d20SAndroid Build Coastguard Worker 	return 0;
1646*2d543d20SAndroid Build Coastguard Worker       oom:
1647*2d543d20SAndroid Build Coastguard Worker 	yyerror("Out of memory");
1648*2d543d20SAndroid Build Coastguard Worker 	free(id);
1649*2d543d20SAndroid Build Coastguard Worker 	return -1;
1650*2d543d20SAndroid Build Coastguard Worker }
1651*2d543d20SAndroid Build Coastguard Worker 
define_compute_type_helper(int which,avrule_t ** rule)1652*2d543d20SAndroid Build Coastguard Worker static int define_compute_type_helper(int which, avrule_t ** rule)
1653*2d543d20SAndroid Build Coastguard Worker {
1654*2d543d20SAndroid Build Coastguard Worker 	char *id;
1655*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *datum;
1656*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tclasses;
1657*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
1658*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
1659*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *perm;
1660*2d543d20SAndroid Build Coastguard Worker 	uint32_t i;
1661*2d543d20SAndroid Build Coastguard Worker 	int add = 1;
1662*2d543d20SAndroid Build Coastguard Worker 
1663*2d543d20SAndroid Build Coastguard Worker 	avrule = malloc(sizeof(avrule_t));
1664*2d543d20SAndroid Build Coastguard Worker 	if (!avrule) {
1665*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
1666*2d543d20SAndroid Build Coastguard Worker 		return -1;
1667*2d543d20SAndroid Build Coastguard Worker 	}
1668*2d543d20SAndroid Build Coastguard Worker 	avrule_init(avrule);
1669*2d543d20SAndroid Build Coastguard Worker 	avrule->specified = which;
1670*2d543d20SAndroid Build Coastguard Worker 	avrule->line = policydb_lineno;
1671*2d543d20SAndroid Build Coastguard Worker 	avrule->source_line = source_lineno;
1672*2d543d20SAndroid Build Coastguard Worker 	avrule->source_filename = strdup(source_file);
1673*2d543d20SAndroid Build Coastguard Worker 	if (!avrule->source_filename) {
1674*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
1675*2d543d20SAndroid Build Coastguard Worker 		return -1;
1676*2d543d20SAndroid Build Coastguard Worker 	}
1677*2d543d20SAndroid Build Coastguard Worker 
1678*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1679*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&avrule->stypes, id, &add, 0))
1680*2d543d20SAndroid Build Coastguard Worker 			goto bad;
1681*2d543d20SAndroid Build Coastguard Worker 	}
1682*2d543d20SAndroid Build Coastguard Worker 	add = 1;
1683*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1684*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(id, "self") == 0) {
1685*2d543d20SAndroid Build Coastguard Worker 			free(id);
1686*2d543d20SAndroid Build Coastguard Worker 			if (add == 0) {
1687*2d543d20SAndroid Build Coastguard Worker 				yyerror("-self is not supported");
1688*2d543d20SAndroid Build Coastguard Worker 				goto bad;
1689*2d543d20SAndroid Build Coastguard Worker 			}
1690*2d543d20SAndroid Build Coastguard Worker 			avrule->flags |= RULE_SELF;
1691*2d543d20SAndroid Build Coastguard Worker 			continue;
1692*2d543d20SAndroid Build Coastguard Worker 		}
1693*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&avrule->ttypes, id, &add, 0))
1694*2d543d20SAndroid Build Coastguard Worker 			goto bad;
1695*2d543d20SAndroid Build Coastguard Worker 	}
1696*2d543d20SAndroid Build Coastguard Worker 
1697*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&tclasses);
1698*2d543d20SAndroid Build Coastguard Worker 	if (read_classes(&tclasses))
1699*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1700*2d543d20SAndroid Build Coastguard Worker 
1701*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
1702*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1703*2d543d20SAndroid Build Coastguard Worker 		yyerror("no newtype?");
1704*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1705*2d543d20SAndroid Build Coastguard Worker 	}
1706*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
1707*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
1708*2d543d20SAndroid Build Coastguard Worker 		free(id);
1709*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1710*2d543d20SAndroid Build Coastguard Worker 	}
1711*2d543d20SAndroid Build Coastguard Worker 	datum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
1712*2d543d20SAndroid Build Coastguard Worker 						(hashtab_key_t) id);
1713*2d543d20SAndroid Build Coastguard Worker 	if (!datum || datum->flavor == TYPE_ATTRIB) {
1714*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown type %s", id);
1715*2d543d20SAndroid Build Coastguard Worker 		free(id);
1716*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1717*2d543d20SAndroid Build Coastguard Worker 	}
1718*2d543d20SAndroid Build Coastguard Worker 	free(id);
1719*2d543d20SAndroid Build Coastguard Worker 
1720*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&tclasses, node, i) {
1721*2d543d20SAndroid Build Coastguard Worker 		perm = malloc(sizeof(class_perm_node_t));
1722*2d543d20SAndroid Build Coastguard Worker 		if (!perm) {
1723*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
1724*2d543d20SAndroid Build Coastguard Worker 			goto bad;
1725*2d543d20SAndroid Build Coastguard Worker 		}
1726*2d543d20SAndroid Build Coastguard Worker 		class_perm_node_init(perm);
1727*2d543d20SAndroid Build Coastguard Worker 		perm->tclass = i + 1;
1728*2d543d20SAndroid Build Coastguard Worker 		perm->data = datum->s.value;
1729*2d543d20SAndroid Build Coastguard Worker 		perm->next = avrule->perms;
1730*2d543d20SAndroid Build Coastguard Worker 		avrule->perms = perm;
1731*2d543d20SAndroid Build Coastguard Worker 	}
1732*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tclasses);
1733*2d543d20SAndroid Build Coastguard Worker 
1734*2d543d20SAndroid Build Coastguard Worker 	*rule = avrule;
1735*2d543d20SAndroid Build Coastguard Worker 	return 0;
1736*2d543d20SAndroid Build Coastguard Worker 
1737*2d543d20SAndroid Build Coastguard Worker       bad:
1738*2d543d20SAndroid Build Coastguard Worker 	avrule_destroy(avrule);
1739*2d543d20SAndroid Build Coastguard Worker 	free(avrule);
1740*2d543d20SAndroid Build Coastguard Worker 	return -1;
1741*2d543d20SAndroid Build Coastguard Worker }
1742*2d543d20SAndroid Build Coastguard Worker 
define_compute_type(int which)1743*2d543d20SAndroid Build Coastguard Worker int define_compute_type(int which)
1744*2d543d20SAndroid Build Coastguard Worker {
1745*2d543d20SAndroid Build Coastguard Worker 	char *id;
1746*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
1747*2d543d20SAndroid Build Coastguard Worker 
1748*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
1749*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1750*2d543d20SAndroid Build Coastguard Worker 			free(id);
1751*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1752*2d543d20SAndroid Build Coastguard Worker 			free(id);
1753*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1754*2d543d20SAndroid Build Coastguard Worker 			free(id);
1755*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
1756*2d543d20SAndroid Build Coastguard Worker 		free(id);
1757*2d543d20SAndroid Build Coastguard Worker 		return 0;
1758*2d543d20SAndroid Build Coastguard Worker 	}
1759*2d543d20SAndroid Build Coastguard Worker 
1760*2d543d20SAndroid Build Coastguard Worker 	if (define_compute_type_helper(which, &avrule))
1761*2d543d20SAndroid Build Coastguard Worker 		return -1;
1762*2d543d20SAndroid Build Coastguard Worker 
1763*2d543d20SAndroid Build Coastguard Worker 	append_avrule(avrule);
1764*2d543d20SAndroid Build Coastguard Worker 	return 0;
1765*2d543d20SAndroid Build Coastguard Worker }
1766*2d543d20SAndroid Build Coastguard Worker 
define_cond_compute_type(int which)1767*2d543d20SAndroid Build Coastguard Worker avrule_t *define_cond_compute_type(int which)
1768*2d543d20SAndroid Build Coastguard Worker {
1769*2d543d20SAndroid Build Coastguard Worker 	char *id;
1770*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
1771*2d543d20SAndroid Build Coastguard Worker 
1772*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
1773*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1774*2d543d20SAndroid Build Coastguard Worker 			free(id);
1775*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1776*2d543d20SAndroid Build Coastguard Worker 			free(id);
1777*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1778*2d543d20SAndroid Build Coastguard Worker 			free(id);
1779*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
1780*2d543d20SAndroid Build Coastguard Worker 		free(id);
1781*2d543d20SAndroid Build Coastguard Worker 		return (avrule_t *) 1;
1782*2d543d20SAndroid Build Coastguard Worker 	}
1783*2d543d20SAndroid Build Coastguard Worker 
1784*2d543d20SAndroid Build Coastguard Worker 	if (define_compute_type_helper(which, &avrule))
1785*2d543d20SAndroid Build Coastguard Worker 		return COND_ERR;
1786*2d543d20SAndroid Build Coastguard Worker 
1787*2d543d20SAndroid Build Coastguard Worker 	return avrule;
1788*2d543d20SAndroid Build Coastguard Worker }
1789*2d543d20SAndroid Build Coastguard Worker 
define_bool_tunable(int is_tunable)1790*2d543d20SAndroid Build Coastguard Worker int define_bool_tunable(int is_tunable)
1791*2d543d20SAndroid Build Coastguard Worker {
1792*2d543d20SAndroid Build Coastguard Worker 	char *id, *bool_value;
1793*2d543d20SAndroid Build Coastguard Worker 	cond_bool_datum_t *datum;
1794*2d543d20SAndroid Build Coastguard Worker 	int ret;
1795*2d543d20SAndroid Build Coastguard Worker 	uint32_t value;
1796*2d543d20SAndroid Build Coastguard Worker 
1797*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
1798*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
1799*2d543d20SAndroid Build Coastguard Worker 			free(id);
1800*2d543d20SAndroid Build Coastguard Worker 		return 0;
1801*2d543d20SAndroid Build Coastguard Worker 	}
1802*2d543d20SAndroid Build Coastguard Worker 
1803*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
1804*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
1805*2d543d20SAndroid Build Coastguard Worker 		yyerror("no identifier for bool definition?");
1806*2d543d20SAndroid Build Coastguard Worker 		return -1;
1807*2d543d20SAndroid Build Coastguard Worker 	}
1808*2d543d20SAndroid Build Coastguard Worker 	if (id_has_dot(id)) {
1809*2d543d20SAndroid Build Coastguard Worker 		yyerror2("boolean identifier %s may not contain periods", id);
1810*2d543d20SAndroid Build Coastguard Worker 		free(id);
1811*2d543d20SAndroid Build Coastguard Worker 		return -1;
1812*2d543d20SAndroid Build Coastguard Worker 	}
1813*2d543d20SAndroid Build Coastguard Worker 	datum = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
1814*2d543d20SAndroid Build Coastguard Worker 	if (!datum) {
1815*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
1816*2d543d20SAndroid Build Coastguard Worker 		free(id);
1817*2d543d20SAndroid Build Coastguard Worker 		return -1;
1818*2d543d20SAndroid Build Coastguard Worker 	}
1819*2d543d20SAndroid Build Coastguard Worker 	memset(datum, 0, sizeof(cond_bool_datum_t));
1820*2d543d20SAndroid Build Coastguard Worker 	if (is_tunable)
1821*2d543d20SAndroid Build Coastguard Worker 		datum->flags |= COND_BOOL_FLAGS_TUNABLE;
1822*2d543d20SAndroid Build Coastguard Worker 	ret = declare_symbol(SYM_BOOLS, id, datum, &value, &value);
1823*2d543d20SAndroid Build Coastguard Worker 	switch (ret) {
1824*2d543d20SAndroid Build Coastguard Worker 	case -3:{
1825*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
1826*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1827*2d543d20SAndroid Build Coastguard Worker 		}
1828*2d543d20SAndroid Build Coastguard Worker 	case -2:{
1829*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate declaration of boolean %s", id);
1830*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1831*2d543d20SAndroid Build Coastguard Worker 		}
1832*2d543d20SAndroid Build Coastguard Worker 	case -1:{
1833*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not declare boolean %s here", id);
1834*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1835*2d543d20SAndroid Build Coastguard Worker 		}
1836*2d543d20SAndroid Build Coastguard Worker 	case 0:
1837*2d543d20SAndroid Build Coastguard Worker 	case 1:{
1838*2d543d20SAndroid Build Coastguard Worker 			break;
1839*2d543d20SAndroid Build Coastguard Worker 		}
1840*2d543d20SAndroid Build Coastguard Worker 	default:{
1841*2d543d20SAndroid Build Coastguard Worker 			assert(0);	/* should never get here */
1842*2d543d20SAndroid Build Coastguard Worker 		}
1843*2d543d20SAndroid Build Coastguard Worker 	}
1844*2d543d20SAndroid Build Coastguard Worker 	datum->s.value = value;
1845*2d543d20SAndroid Build Coastguard Worker 
1846*2d543d20SAndroid Build Coastguard Worker 	bool_value = (char *)queue_remove(id_queue);
1847*2d543d20SAndroid Build Coastguard Worker 	if (!bool_value) {
1848*2d543d20SAndroid Build Coastguard Worker 		yyerror("no default value for bool definition?");
1849*2d543d20SAndroid Build Coastguard Worker 		return -1;
1850*2d543d20SAndroid Build Coastguard Worker 	}
1851*2d543d20SAndroid Build Coastguard Worker 
1852*2d543d20SAndroid Build Coastguard Worker 	datum->state = (bool_value[0] == 'T') ? 1 : 0;
1853*2d543d20SAndroid Build Coastguard Worker 	free(bool_value);
1854*2d543d20SAndroid Build Coastguard Worker 	return 0;
1855*2d543d20SAndroid Build Coastguard Worker       cleanup:
1856*2d543d20SAndroid Build Coastguard Worker 	cond_destroy_bool(id, datum, NULL);
1857*2d543d20SAndroid Build Coastguard Worker 	return -1;
1858*2d543d20SAndroid Build Coastguard Worker }
1859*2d543d20SAndroid Build Coastguard Worker 
define_cond_pol_list(avrule_t * avlist,avrule_t * sl)1860*2d543d20SAndroid Build Coastguard Worker avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
1861*2d543d20SAndroid Build Coastguard Worker {
1862*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
1863*2d543d20SAndroid Build Coastguard Worker 		/* return something so we get through pass 1 */
1864*2d543d20SAndroid Build Coastguard Worker 		return (avrule_t *) 1;
1865*2d543d20SAndroid Build Coastguard Worker 	}
1866*2d543d20SAndroid Build Coastguard Worker 
1867*2d543d20SAndroid Build Coastguard Worker 	if (sl == NULL) {
1868*2d543d20SAndroid Build Coastguard Worker 		/* This is a require block, return previous list */
1869*2d543d20SAndroid Build Coastguard Worker 		return avlist;
1870*2d543d20SAndroid Build Coastguard Worker 	}
1871*2d543d20SAndroid Build Coastguard Worker 
1872*2d543d20SAndroid Build Coastguard Worker 	/* prepend the new avlist to the pre-existing one */
1873*2d543d20SAndroid Build Coastguard Worker 	sl->next = avlist;
1874*2d543d20SAndroid Build Coastguard Worker 	return sl;
1875*2d543d20SAndroid Build Coastguard Worker }
1876*2d543d20SAndroid Build Coastguard Worker 
1877*2d543d20SAndroid Build Coastguard Worker typedef struct av_xperm_range {
1878*2d543d20SAndroid Build Coastguard Worker 	uint16_t low;
1879*2d543d20SAndroid Build Coastguard Worker 	uint16_t high;
1880*2d543d20SAndroid Build Coastguard Worker } av_xperm_range_t;
1881*2d543d20SAndroid Build Coastguard Worker 
1882*2d543d20SAndroid Build Coastguard Worker struct av_xperm_range_list {
1883*2d543d20SAndroid Build Coastguard Worker 	uint8_t omit;
1884*2d543d20SAndroid Build Coastguard Worker 	av_xperm_range_t range;
1885*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *next;
1886*2d543d20SAndroid Build Coastguard Worker };
1887*2d543d20SAndroid Build Coastguard Worker 
avrule_sort_xperms(struct av_xperm_range_list ** rangehead)1888*2d543d20SAndroid Build Coastguard Worker static int avrule_sort_xperms(struct av_xperm_range_list **rangehead)
1889*2d543d20SAndroid Build Coastguard Worker {
1890*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *r, *r2, *sorted, *sortedhead = NULL;
1891*2d543d20SAndroid Build Coastguard Worker 
1892*2d543d20SAndroid Build Coastguard Worker 	/* order list by range.low */
1893*2d543d20SAndroid Build Coastguard Worker 	for (r = *rangehead; r != NULL; r = r->next) {
1894*2d543d20SAndroid Build Coastguard Worker 		sorted = malloc(sizeof(struct av_xperm_range_list));
1895*2d543d20SAndroid Build Coastguard Worker 		if (sorted == NULL)
1896*2d543d20SAndroid Build Coastguard Worker 			goto error;
1897*2d543d20SAndroid Build Coastguard Worker 		memcpy(sorted, r, sizeof(struct av_xperm_range_list));
1898*2d543d20SAndroid Build Coastguard Worker 		sorted->next = NULL;
1899*2d543d20SAndroid Build Coastguard Worker 		if (sortedhead == NULL) {
1900*2d543d20SAndroid Build Coastguard Worker 			sortedhead = sorted;
1901*2d543d20SAndroid Build Coastguard Worker 			continue;
1902*2d543d20SAndroid Build Coastguard Worker 		}
1903*2d543d20SAndroid Build Coastguard Worker 	        for (r2 = sortedhead; r2 != NULL; r2 = r2->next) {
1904*2d543d20SAndroid Build Coastguard Worker 			if (sorted->range.low < r2->range.low) {
1905*2d543d20SAndroid Build Coastguard Worker 				/* range is the new head */
1906*2d543d20SAndroid Build Coastguard Worker 				sorted->next = r2;
1907*2d543d20SAndroid Build Coastguard Worker 				sortedhead = sorted;
1908*2d543d20SAndroid Build Coastguard Worker 				break;
1909*2d543d20SAndroid Build Coastguard Worker 			} else if ((r2 ->next != NULL) &&
1910*2d543d20SAndroid Build Coastguard Worker 					(r->range.low < r2->next->range.low)) {
1911*2d543d20SAndroid Build Coastguard Worker 				/* insert range between elements */
1912*2d543d20SAndroid Build Coastguard Worker 				sorted->next = r2->next;
1913*2d543d20SAndroid Build Coastguard Worker 				r2->next = sorted;
1914*2d543d20SAndroid Build Coastguard Worker 				break;
1915*2d543d20SAndroid Build Coastguard Worker 			} else if (r2->next == NULL) {
1916*2d543d20SAndroid Build Coastguard Worker 				/* range is the new tail*/
1917*2d543d20SAndroid Build Coastguard Worker 				r2->next = sorted;
1918*2d543d20SAndroid Build Coastguard Worker 				break;
1919*2d543d20SAndroid Build Coastguard Worker 			}
1920*2d543d20SAndroid Build Coastguard Worker 		}
1921*2d543d20SAndroid Build Coastguard Worker 	}
1922*2d543d20SAndroid Build Coastguard Worker 
1923*2d543d20SAndroid Build Coastguard Worker 	r = *rangehead;
1924*2d543d20SAndroid Build Coastguard Worker 	while (r != NULL) {
1925*2d543d20SAndroid Build Coastguard Worker 		r2 = r;
1926*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
1927*2d543d20SAndroid Build Coastguard Worker 		free(r2);
1928*2d543d20SAndroid Build Coastguard Worker 	}
1929*2d543d20SAndroid Build Coastguard Worker 	*rangehead = sortedhead;
1930*2d543d20SAndroid Build Coastguard Worker 	return 0;
1931*2d543d20SAndroid Build Coastguard Worker error:
1932*2d543d20SAndroid Build Coastguard Worker 	yyerror("out of memory");
1933*2d543d20SAndroid Build Coastguard Worker 	return -1;
1934*2d543d20SAndroid Build Coastguard Worker }
1935*2d543d20SAndroid Build Coastguard Worker 
avrule_merge_xperms(struct av_xperm_range_list ** rangehead)1936*2d543d20SAndroid Build Coastguard Worker static void avrule_merge_xperms(struct av_xperm_range_list **rangehead)
1937*2d543d20SAndroid Build Coastguard Worker {
1938*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *r, *tmp;
1939*2d543d20SAndroid Build Coastguard Worker 	r = *rangehead;
1940*2d543d20SAndroid Build Coastguard Worker 	while (r != NULL && r->next != NULL) {
1941*2d543d20SAndroid Build Coastguard Worker 		/* merge */
1942*2d543d20SAndroid Build Coastguard Worker 		if ((r->range.high + 1) >= r->next->range.low) {
1943*2d543d20SAndroid Build Coastguard Worker 			/* keep the higher of the two */
1944*2d543d20SAndroid Build Coastguard Worker 			if (r->range.high < r->next->range.high)
1945*2d543d20SAndroid Build Coastguard Worker 				r->range.high = r->next->range.high;
1946*2d543d20SAndroid Build Coastguard Worker 			tmp = r->next;
1947*2d543d20SAndroid Build Coastguard Worker 			r->next = r->next->next;
1948*2d543d20SAndroid Build Coastguard Worker 			free(tmp);
1949*2d543d20SAndroid Build Coastguard Worker 			continue;
1950*2d543d20SAndroid Build Coastguard Worker 		}
1951*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
1952*2d543d20SAndroid Build Coastguard Worker 	}
1953*2d543d20SAndroid Build Coastguard Worker }
1954*2d543d20SAndroid Build Coastguard Worker 
avrule_read_xperm_ranges(struct av_xperm_range_list ** rangehead)1955*2d543d20SAndroid Build Coastguard Worker static int avrule_read_xperm_ranges(struct av_xperm_range_list **rangehead)
1956*2d543d20SAndroid Build Coastguard Worker {
1957*2d543d20SAndroid Build Coastguard Worker 	char *id;
1958*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *rnew, *r = NULL;
1959*2d543d20SAndroid Build Coastguard Worker 	uint8_t omit = 0;
1960*2d543d20SAndroid Build Coastguard Worker 
1961*2d543d20SAndroid Build Coastguard Worker 	*rangehead = NULL;
1962*2d543d20SAndroid Build Coastguard Worker 
1963*2d543d20SAndroid Build Coastguard Worker 	/* read in all the ioctl/netlink commands */
1964*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
1965*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(id,"~") == 0) {
1966*2d543d20SAndroid Build Coastguard Worker 			/* these are values to be omitted */
1967*2d543d20SAndroid Build Coastguard Worker 			free(id);
1968*2d543d20SAndroid Build Coastguard Worker 			omit = 1;
1969*2d543d20SAndroid Build Coastguard Worker 		} else if (strcmp(id,"-") == 0) {
1970*2d543d20SAndroid Build Coastguard Worker 			/* high value of range */
1971*2d543d20SAndroid Build Coastguard Worker 			free(id);
1972*2d543d20SAndroid Build Coastguard Worker 			id = queue_remove(id_queue);
1973*2d543d20SAndroid Build Coastguard Worker 			r->range.high = (uint16_t) strtoul(id,NULL,0);
1974*2d543d20SAndroid Build Coastguard Worker 			if (r->range.high < r->range.low) {
1975*2d543d20SAndroid Build Coastguard Worker 				yyerror2("Ioctl range %d-%d must be in ascending order.",
1976*2d543d20SAndroid Build Coastguard Worker 					 r->range.low, r->range.high);
1977*2d543d20SAndroid Build Coastguard Worker 				return -1;
1978*2d543d20SAndroid Build Coastguard Worker 			}
1979*2d543d20SAndroid Build Coastguard Worker 			free(id);
1980*2d543d20SAndroid Build Coastguard Worker 		} else {
1981*2d543d20SAndroid Build Coastguard Worker 			/* read in new low value */
1982*2d543d20SAndroid Build Coastguard Worker 			rnew = malloc(sizeof(struct av_xperm_range_list));
1983*2d543d20SAndroid Build Coastguard Worker 			if (rnew == NULL)
1984*2d543d20SAndroid Build Coastguard Worker 				goto error;
1985*2d543d20SAndroid Build Coastguard Worker 			rnew->next = NULL;
1986*2d543d20SAndroid Build Coastguard Worker 			if (*rangehead == NULL) {
1987*2d543d20SAndroid Build Coastguard Worker 				*rangehead = rnew;
1988*2d543d20SAndroid Build Coastguard Worker 				r = *rangehead;
1989*2d543d20SAndroid Build Coastguard Worker 			} else {
1990*2d543d20SAndroid Build Coastguard Worker 				r->next = rnew;
1991*2d543d20SAndroid Build Coastguard Worker 				r = r->next;
1992*2d543d20SAndroid Build Coastguard Worker 			}
1993*2d543d20SAndroid Build Coastguard Worker 			rnew->range.low = (uint16_t) strtoul(id,NULL,0);
1994*2d543d20SAndroid Build Coastguard Worker 			rnew->range.high = rnew->range.low;
1995*2d543d20SAndroid Build Coastguard Worker 			free(id);
1996*2d543d20SAndroid Build Coastguard Worker 		}
1997*2d543d20SAndroid Build Coastguard Worker 	}
1998*2d543d20SAndroid Build Coastguard Worker 	r = *rangehead;
1999*2d543d20SAndroid Build Coastguard Worker 	if (r) {
2000*2d543d20SAndroid Build Coastguard Worker 		r->omit = omit;
2001*2d543d20SAndroid Build Coastguard Worker 	}
2002*2d543d20SAndroid Build Coastguard Worker 	return 0;
2003*2d543d20SAndroid Build Coastguard Worker error:
2004*2d543d20SAndroid Build Coastguard Worker 	yyerror("out of memory");
2005*2d543d20SAndroid Build Coastguard Worker 	return -1;
2006*2d543d20SAndroid Build Coastguard Worker }
2007*2d543d20SAndroid Build Coastguard Worker 
2008*2d543d20SAndroid Build Coastguard Worker /* flip to included ranges */
avrule_omit_xperms(struct av_xperm_range_list ** rangehead)2009*2d543d20SAndroid Build Coastguard Worker static int avrule_omit_xperms(struct av_xperm_range_list **rangehead)
2010*2d543d20SAndroid Build Coastguard Worker {
2011*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *rnew, *r, *newhead, *r2;
2012*2d543d20SAndroid Build Coastguard Worker 
2013*2d543d20SAndroid Build Coastguard Worker 	rnew = calloc(1, sizeof(struct av_xperm_range_list));
2014*2d543d20SAndroid Build Coastguard Worker 	if (!rnew)
2015*2d543d20SAndroid Build Coastguard Worker 		goto error;
2016*2d543d20SAndroid Build Coastguard Worker 
2017*2d543d20SAndroid Build Coastguard Worker 	newhead = rnew;
2018*2d543d20SAndroid Build Coastguard Worker 
2019*2d543d20SAndroid Build Coastguard Worker 	r = *rangehead;
2020*2d543d20SAndroid Build Coastguard Worker 	r2 = newhead;
2021*2d543d20SAndroid Build Coastguard Worker 
2022*2d543d20SAndroid Build Coastguard Worker 	if (r->range.low == 0) {
2023*2d543d20SAndroid Build Coastguard Worker 		r2->range.low = r->range.high + 1;
2024*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2025*2d543d20SAndroid Build Coastguard Worker 	} else {
2026*2d543d20SAndroid Build Coastguard Worker 		r2->range.low = 0;
2027*2d543d20SAndroid Build Coastguard Worker 	}
2028*2d543d20SAndroid Build Coastguard Worker 
2029*2d543d20SAndroid Build Coastguard Worker 	while (r) {
2030*2d543d20SAndroid Build Coastguard Worker 		r2->range.high = r->range.low - 1;
2031*2d543d20SAndroid Build Coastguard Worker 		rnew = calloc(1, sizeof(struct av_xperm_range_list));
2032*2d543d20SAndroid Build Coastguard Worker 		if (!rnew)
2033*2d543d20SAndroid Build Coastguard Worker 			goto error;
2034*2d543d20SAndroid Build Coastguard Worker 		r2->next = rnew;
2035*2d543d20SAndroid Build Coastguard Worker 		r2 = r2->next;
2036*2d543d20SAndroid Build Coastguard Worker 
2037*2d543d20SAndroid Build Coastguard Worker 		r2->range.low = r->range.high + 1;
2038*2d543d20SAndroid Build Coastguard Worker 		if (!r->next)
2039*2d543d20SAndroid Build Coastguard Worker 			r2->range.high = 0xffff;
2040*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2041*2d543d20SAndroid Build Coastguard Worker 	}
2042*2d543d20SAndroid Build Coastguard Worker 
2043*2d543d20SAndroid Build Coastguard Worker 	r = *rangehead;
2044*2d543d20SAndroid Build Coastguard Worker 	while (r != NULL) {
2045*2d543d20SAndroid Build Coastguard Worker 		r2 = r;
2046*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2047*2d543d20SAndroid Build Coastguard Worker 		free(r2);
2048*2d543d20SAndroid Build Coastguard Worker 	}
2049*2d543d20SAndroid Build Coastguard Worker 	*rangehead = newhead;
2050*2d543d20SAndroid Build Coastguard Worker 	return 0;
2051*2d543d20SAndroid Build Coastguard Worker 
2052*2d543d20SAndroid Build Coastguard Worker error:
2053*2d543d20SAndroid Build Coastguard Worker 	yyerror("out of memory");
2054*2d543d20SAndroid Build Coastguard Worker 	return -1;
2055*2d543d20SAndroid Build Coastguard Worker }
2056*2d543d20SAndroid Build Coastguard Worker 
avrule_xperm_ranges(struct av_xperm_range_list ** rangelist)2057*2d543d20SAndroid Build Coastguard Worker static int avrule_xperm_ranges(struct av_xperm_range_list **rangelist)
2058*2d543d20SAndroid Build Coastguard Worker {
2059*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *rangehead;
2060*2d543d20SAndroid Build Coastguard Worker 	uint8_t omit;
2061*2d543d20SAndroid Build Coastguard Worker 
2062*2d543d20SAndroid Build Coastguard Worker 	/* read in ranges to include and omit */
2063*2d543d20SAndroid Build Coastguard Worker 	if (avrule_read_xperm_ranges(&rangehead))
2064*2d543d20SAndroid Build Coastguard Worker 		return -1;
2065*2d543d20SAndroid Build Coastguard Worker 	if (rangehead == NULL) {
2066*2d543d20SAndroid Build Coastguard Worker 		yyerror("error processing ioctl/netlink commands");
2067*2d543d20SAndroid Build Coastguard Worker 		return -1;
2068*2d543d20SAndroid Build Coastguard Worker 	}
2069*2d543d20SAndroid Build Coastguard Worker 	omit = rangehead->omit;
2070*2d543d20SAndroid Build Coastguard Worker 	/* sort and merge the input ranges */
2071*2d543d20SAndroid Build Coastguard Worker 	if (avrule_sort_xperms(&rangehead))
2072*2d543d20SAndroid Build Coastguard Worker 		return -1;
2073*2d543d20SAndroid Build Coastguard Worker 	avrule_merge_xperms(&rangehead);
2074*2d543d20SAndroid Build Coastguard Worker 	/* flip ranges if these are omitted */
2075*2d543d20SAndroid Build Coastguard Worker 	if (omit) {
2076*2d543d20SAndroid Build Coastguard Worker 		if (avrule_omit_xperms(&rangehead))
2077*2d543d20SAndroid Build Coastguard Worker 			return -1;
2078*2d543d20SAndroid Build Coastguard Worker 	}
2079*2d543d20SAndroid Build Coastguard Worker 
2080*2d543d20SAndroid Build Coastguard Worker 	*rangelist = rangehead;
2081*2d543d20SAndroid Build Coastguard Worker 	return 0;
2082*2d543d20SAndroid Build Coastguard Worker }
2083*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab_xperms_helper(int which,avrule_t ** rule)2084*2d543d20SAndroid Build Coastguard Worker static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
2085*2d543d20SAndroid Build Coastguard Worker {
2086*2d543d20SAndroid Build Coastguard Worker 	char *id;
2087*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
2088*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
2089*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum = NULL;
2090*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tclasses;
2091*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
2092*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2093*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2094*2d543d20SAndroid Build Coastguard Worker 	int add = 1, ret = 0;
2095*2d543d20SAndroid Build Coastguard Worker 
2096*2d543d20SAndroid Build Coastguard Worker 	avrule = (avrule_t *) malloc(sizeof(avrule_t));
2097*2d543d20SAndroid Build Coastguard Worker 	if (!avrule) {
2098*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2099*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
2100*2d543d20SAndroid Build Coastguard Worker 		goto out;
2101*2d543d20SAndroid Build Coastguard Worker 	}
2102*2d543d20SAndroid Build Coastguard Worker 	avrule_init(avrule);
2103*2d543d20SAndroid Build Coastguard Worker 	avrule->specified = which;
2104*2d543d20SAndroid Build Coastguard Worker 	avrule->line = policydb_lineno;
2105*2d543d20SAndroid Build Coastguard Worker 	avrule->source_line = source_lineno;
2106*2d543d20SAndroid Build Coastguard Worker 	avrule->source_filename = strdup(source_file);
2107*2d543d20SAndroid Build Coastguard Worker 	avrule->xperms = NULL;
2108*2d543d20SAndroid Build Coastguard Worker 	if (!avrule->source_filename) {
2109*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2110*2d543d20SAndroid Build Coastguard Worker 		return -1;
2111*2d543d20SAndroid Build Coastguard Worker 	}
2112*2d543d20SAndroid Build Coastguard Worker 
2113*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2114*2d543d20SAndroid Build Coastguard Worker 		if (set_types
2115*2d543d20SAndroid Build Coastguard Worker 		    (&avrule->stypes, id, &add,
2116*2d543d20SAndroid Build Coastguard Worker 		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
2117*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2118*2d543d20SAndroid Build Coastguard Worker 			goto out;
2119*2d543d20SAndroid Build Coastguard Worker 		}
2120*2d543d20SAndroid Build Coastguard Worker 	}
2121*2d543d20SAndroid Build Coastguard Worker 	add = 1;
2122*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2123*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(id, "self") == 0) {
2124*2d543d20SAndroid Build Coastguard Worker 			free(id);
2125*2d543d20SAndroid Build Coastguard Worker 			if (add == 0 && which != AVRULE_XPERMS_NEVERALLOW) {
2126*2d543d20SAndroid Build Coastguard Worker 				yyerror("-self is only supported in neverallow and neverallowxperm rules");
2127*2d543d20SAndroid Build Coastguard Worker 				ret = -1;
2128*2d543d20SAndroid Build Coastguard Worker 				goto out;
2129*2d543d20SAndroid Build Coastguard Worker 			}
2130*2d543d20SAndroid Build Coastguard Worker 			avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
2131*2d543d20SAndroid Build Coastguard Worker 			if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
2132*2d543d20SAndroid Build Coastguard Worker 				yyerror("self and -self are mutual exclusive");
2133*2d543d20SAndroid Build Coastguard Worker 				ret = -1;
2134*2d543d20SAndroid Build Coastguard Worker 				goto out;
2135*2d543d20SAndroid Build Coastguard Worker 			}
2136*2d543d20SAndroid Build Coastguard Worker 			continue;
2137*2d543d20SAndroid Build Coastguard Worker 		}
2138*2d543d20SAndroid Build Coastguard Worker 		if (set_types
2139*2d543d20SAndroid Build Coastguard Worker 		    (&avrule->ttypes, id, &add,
2140*2d543d20SAndroid Build Coastguard Worker 		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
2141*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2142*2d543d20SAndroid Build Coastguard Worker 			goto out;
2143*2d543d20SAndroid Build Coastguard Worker 		}
2144*2d543d20SAndroid Build Coastguard Worker 	}
2145*2d543d20SAndroid Build Coastguard Worker 
2146*2d543d20SAndroid Build Coastguard Worker 	if ((avrule->ttypes.flags & TYPE_COMP)) {
2147*2d543d20SAndroid Build Coastguard Worker 		if (avrule->flags & RULE_NOTSELF) {
2148*2d543d20SAndroid Build Coastguard Worker 			yyerror("-self is not supported in complements");
2149*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2150*2d543d20SAndroid Build Coastguard Worker 			goto out;
2151*2d543d20SAndroid Build Coastguard Worker 		}
2152*2d543d20SAndroid Build Coastguard Worker 		if (avrule->flags & RULE_SELF) {
2153*2d543d20SAndroid Build Coastguard Worker 			avrule->flags &= ~RULE_SELF;
2154*2d543d20SAndroid Build Coastguard Worker 			avrule->flags |= RULE_NOTSELF;
2155*2d543d20SAndroid Build Coastguard Worker 		}
2156*2d543d20SAndroid Build Coastguard Worker 	}
2157*2d543d20SAndroid Build Coastguard Worker 
2158*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&tclasses);
2159*2d543d20SAndroid Build Coastguard Worker 	ret = read_classes(&tclasses);
2160*2d543d20SAndroid Build Coastguard Worker 	if (ret)
2161*2d543d20SAndroid Build Coastguard Worker 		goto out;
2162*2d543d20SAndroid Build Coastguard Worker 
2163*2d543d20SAndroid Build Coastguard Worker 	perms = NULL;
2164*2d543d20SAndroid Build Coastguard Worker 	id = queue_head(id_queue);
2165*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&tclasses, node, i) {
2166*2d543d20SAndroid Build Coastguard Worker 		cur_perms =
2167*2d543d20SAndroid Build Coastguard Worker 		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2168*2d543d20SAndroid Build Coastguard Worker 		if (!cur_perms) {
2169*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
2170*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2171*2d543d20SAndroid Build Coastguard Worker 			goto out;
2172*2d543d20SAndroid Build Coastguard Worker 		}
2173*2d543d20SAndroid Build Coastguard Worker 		class_perm_node_init(cur_perms);
2174*2d543d20SAndroid Build Coastguard Worker 		cur_perms->tclass = i + 1;
2175*2d543d20SAndroid Build Coastguard Worker 		if (!perms)
2176*2d543d20SAndroid Build Coastguard Worker 			perms = cur_perms;
2177*2d543d20SAndroid Build Coastguard Worker 		if (tail)
2178*2d543d20SAndroid Build Coastguard Worker 			tail->next = cur_perms;
2179*2d543d20SAndroid Build Coastguard Worker 		tail = cur_perms;
2180*2d543d20SAndroid Build Coastguard Worker 
2181*2d543d20SAndroid Build Coastguard Worker 		cladatum = policydbp->class_val_to_struct[i];
2182*2d543d20SAndroid Build Coastguard Worker 		perdatum = hashtab_search(cladatum->permissions.table, id);
2183*2d543d20SAndroid Build Coastguard Worker 		if (!perdatum) {
2184*2d543d20SAndroid Build Coastguard Worker 			if (cladatum->comdatum) {
2185*2d543d20SAndroid Build Coastguard Worker 				perdatum = hashtab_search(cladatum->comdatum->
2186*2d543d20SAndroid Build Coastguard Worker 							permissions.table,
2187*2d543d20SAndroid Build Coastguard Worker 							id);
2188*2d543d20SAndroid Build Coastguard Worker 			}
2189*2d543d20SAndroid Build Coastguard Worker 		}
2190*2d543d20SAndroid Build Coastguard Worker 		if (!perdatum) {
2191*2d543d20SAndroid Build Coastguard Worker 			yyerror2("permission %s is not defined"
2192*2d543d20SAndroid Build Coastguard Worker 				     " for class %s", id,
2193*2d543d20SAndroid Build Coastguard Worker 				     policydbp->p_class_val_to_name[i]);
2194*2d543d20SAndroid Build Coastguard Worker 			continue;
2195*2d543d20SAndroid Build Coastguard Worker 		} else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) {
2196*2d543d20SAndroid Build Coastguard Worker 			yyerror2("permission %s of class %s is"
2197*2d543d20SAndroid Build Coastguard Worker 			     " not within scope", id,
2198*2d543d20SAndroid Build Coastguard Worker 			     policydbp->p_class_val_to_name[i]);
2199*2d543d20SAndroid Build Coastguard Worker 			continue;
2200*2d543d20SAndroid Build Coastguard Worker 		} else {
2201*2d543d20SAndroid Build Coastguard Worker 			cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
2202*2d543d20SAndroid Build Coastguard Worker 		}
2203*2d543d20SAndroid Build Coastguard Worker 	}
2204*2d543d20SAndroid Build Coastguard Worker 
2205*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tclasses);
2206*2d543d20SAndroid Build Coastguard Worker 
2207*2d543d20SAndroid Build Coastguard Worker 	avrule->perms = perms;
2208*2d543d20SAndroid Build Coastguard Worker 	*rule = avrule;
2209*2d543d20SAndroid Build Coastguard Worker 
2210*2d543d20SAndroid Build Coastguard Worker out:
2211*2d543d20SAndroid Build Coastguard Worker 	return ret;
2212*2d543d20SAndroid Build Coastguard Worker }
2213*2d543d20SAndroid Build Coastguard Worker 
2214*2d543d20SAndroid Build Coastguard Worker /* index of the u32 containing the permission */
2215*2d543d20SAndroid Build Coastguard Worker #define XPERM_IDX(x) ((x) >> 5)
2216*2d543d20SAndroid Build Coastguard Worker /* set bits 0 through x-1 within the u32 */
2217*2d543d20SAndroid Build Coastguard Worker #define XPERM_SETBITS(x) ((UINT32_C(1) << ((x) & 0x1f)) - 1)
2218*2d543d20SAndroid Build Coastguard Worker /* low value for this u32 */
2219*2d543d20SAndroid Build Coastguard Worker #define XPERM_LOW(x) ((x) << 5)
2220*2d543d20SAndroid Build Coastguard Worker /* high value for this u32 */
2221*2d543d20SAndroid Build Coastguard Worker #define XPERM_HIGH(x) ((((x) + 1) << 5) - 1)
avrule_xperm_setrangebits(uint16_t low,uint16_t high,av_extended_perms_t * xperms)2222*2d543d20SAndroid Build Coastguard Worker static void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
2223*2d543d20SAndroid Build Coastguard Worker 				av_extended_perms_t *xperms)
2224*2d543d20SAndroid Build Coastguard Worker {
2225*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2226*2d543d20SAndroid Build Coastguard Worker 	uint16_t h = high + 1;
2227*2d543d20SAndroid Build Coastguard Worker 	/* for each u32 that this low-high range touches, set driver permissions */
2228*2d543d20SAndroid Build Coastguard Worker 	for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) {
2229*2d543d20SAndroid Build Coastguard Worker 		/* set all bits in u32 */
2230*2d543d20SAndroid Build Coastguard Worker 		if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
2231*2d543d20SAndroid Build Coastguard Worker 			xperms->perms[i] |= ~0U;
2232*2d543d20SAndroid Build Coastguard Worker 		/* set low bits */
2233*2d543d20SAndroid Build Coastguard Worker 		else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i)))
2234*2d543d20SAndroid Build Coastguard Worker 			xperms->perms[i] |= XPERM_SETBITS(h);
2235*2d543d20SAndroid Build Coastguard Worker 		/* set high bits */
2236*2d543d20SAndroid Build Coastguard Worker 		else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
2237*2d543d20SAndroid Build Coastguard Worker 			xperms->perms[i] |= ~0U - XPERM_SETBITS(low);
2238*2d543d20SAndroid Build Coastguard Worker 		/* set middle bits */
2239*2d543d20SAndroid Build Coastguard Worker 		else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i)))
2240*2d543d20SAndroid Build Coastguard Worker 			xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
2241*2d543d20SAndroid Build Coastguard Worker 	}
2242*2d543d20SAndroid Build Coastguard Worker }
2243*2d543d20SAndroid Build Coastguard Worker 
avrule_xperms_used(const av_extended_perms_t * xperms)2244*2d543d20SAndroid Build Coastguard Worker static int avrule_xperms_used(const av_extended_perms_t *xperms)
2245*2d543d20SAndroid Build Coastguard Worker {
2246*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2247*2d543d20SAndroid Build Coastguard Worker 
2248*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) {
2249*2d543d20SAndroid Build Coastguard Worker 		if (xperms->perms[i])
2250*2d543d20SAndroid Build Coastguard Worker 			return 1;
2251*2d543d20SAndroid Build Coastguard Worker 	}
2252*2d543d20SAndroid Build Coastguard Worker 	return 0;
2253*2d543d20SAndroid Build Coastguard Worker }
2254*2d543d20SAndroid Build Coastguard Worker 
2255*2d543d20SAndroid Build Coastguard Worker /*
2256*2d543d20SAndroid Build Coastguard Worker  * using definitions found in kernel document ioctl-number.txt
2257*2d543d20SAndroid Build Coastguard Worker  * The kernel components of an ioctl command are:
2258*2d543d20SAndroid Build Coastguard Worker  * dir, size, driver, and function. Only the driver and function fields
2259*2d543d20SAndroid Build Coastguard Worker  * are considered here
2260*2d543d20SAndroid Build Coastguard Worker  */
2261*2d543d20SAndroid Build Coastguard Worker #define IOC_DRIV(x) ((x) >> 8)
2262*2d543d20SAndroid Build Coastguard Worker #define IOC_FUNC(x) ((x) & 0xff)
2263*2d543d20SAndroid Build Coastguard Worker #define IOC_CMD(driver, func) (((driver) << 8) + (func))
avrule_xperm_partialdriver(struct av_xperm_range_list * rangelist,av_extended_perms_t * complete_driver,av_extended_perms_t ** extended_perms)2264*2d543d20SAndroid Build Coastguard Worker static int avrule_xperm_partialdriver(struct av_xperm_range_list *rangelist,
2265*2d543d20SAndroid Build Coastguard Worker 				av_extended_perms_t *complete_driver,
2266*2d543d20SAndroid Build Coastguard Worker 				av_extended_perms_t **extended_perms)
2267*2d543d20SAndroid Build Coastguard Worker {
2268*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *r;
2269*2d543d20SAndroid Build Coastguard Worker 	av_extended_perms_t *xperms;
2270*2d543d20SAndroid Build Coastguard Worker 	uint8_t low, high;
2271*2d543d20SAndroid Build Coastguard Worker 
2272*2d543d20SAndroid Build Coastguard Worker 	xperms = calloc(1, sizeof(av_extended_perms_t));
2273*2d543d20SAndroid Build Coastguard Worker 	if (!xperms) {
2274*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2275*2d543d20SAndroid Build Coastguard Worker 		return -1;
2276*2d543d20SAndroid Build Coastguard Worker 	}
2277*2d543d20SAndroid Build Coastguard Worker 
2278*2d543d20SAndroid Build Coastguard Worker 	r = rangelist;
2279*2d543d20SAndroid Build Coastguard Worker 	while(r) {
2280*2d543d20SAndroid Build Coastguard Worker 		low = IOC_DRIV(r->range.low);
2281*2d543d20SAndroid Build Coastguard Worker 		high = IOC_DRIV(r->range.high);
2282*2d543d20SAndroid Build Coastguard Worker 		if (complete_driver) {
2283*2d543d20SAndroid Build Coastguard Worker 			if (!xperm_test(low, complete_driver->perms))
2284*2d543d20SAndroid Build Coastguard Worker 				xperm_set(low, xperms->perms);
2285*2d543d20SAndroid Build Coastguard Worker 			if (!xperm_test(high, complete_driver->perms))
2286*2d543d20SAndroid Build Coastguard Worker 				xperm_set(high, xperms->perms);
2287*2d543d20SAndroid Build Coastguard Worker 		} else {
2288*2d543d20SAndroid Build Coastguard Worker 			xperm_set(low, xperms->perms);
2289*2d543d20SAndroid Build Coastguard Worker 			xperm_set(high, xperms->perms);
2290*2d543d20SAndroid Build Coastguard Worker 		}
2291*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2292*2d543d20SAndroid Build Coastguard Worker 	}
2293*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperms_used(xperms)) {
2294*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = xperms;
2295*2d543d20SAndroid Build Coastguard Worker 	} else {
2296*2d543d20SAndroid Build Coastguard Worker 		free(xperms);
2297*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = NULL;
2298*2d543d20SAndroid Build Coastguard Worker 	}
2299*2d543d20SAndroid Build Coastguard Worker 	return 0;
2300*2d543d20SAndroid Build Coastguard Worker 
2301*2d543d20SAndroid Build Coastguard Worker }
2302*2d543d20SAndroid Build Coastguard Worker 
avrule_ioctl_completedriver(struct av_xperm_range_list * rangelist,av_extended_perms_t ** extended_perms)2303*2d543d20SAndroid Build Coastguard Worker static int avrule_ioctl_completedriver(struct av_xperm_range_list *rangelist,
2304*2d543d20SAndroid Build Coastguard Worker 			av_extended_perms_t **extended_perms)
2305*2d543d20SAndroid Build Coastguard Worker {
2306*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *r;
2307*2d543d20SAndroid Build Coastguard Worker 	av_extended_perms_t *xperms;
2308*2d543d20SAndroid Build Coastguard Worker 	uint16_t low, high;
2309*2d543d20SAndroid Build Coastguard Worker 	xperms = calloc(1, sizeof(av_extended_perms_t));
2310*2d543d20SAndroid Build Coastguard Worker 	if (!xperms) {
2311*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2312*2d543d20SAndroid Build Coastguard Worker 		return -1;
2313*2d543d20SAndroid Build Coastguard Worker 	}
2314*2d543d20SAndroid Build Coastguard Worker 
2315*2d543d20SAndroid Build Coastguard Worker 	r = rangelist;
2316*2d543d20SAndroid Build Coastguard Worker 	while(r) {
2317*2d543d20SAndroid Build Coastguard Worker 		/*
2318*2d543d20SAndroid Build Coastguard Worker 		 * Any driver code that has sequence 0x00 - 0xff is a complete code,
2319*2d543d20SAndroid Build Coastguard Worker 		 *
2320*2d543d20SAndroid Build Coastguard Worker 		 * if command number = 0xff, then round high up to next code,
2321*2d543d20SAndroid Build Coastguard Worker 		 * else 0x00 - 0xfe keep current code
2322*2d543d20SAndroid Build Coastguard Worker 		 * of this range. temporarily u32 for the + 1
2323*2d543d20SAndroid Build Coastguard Worker 		 * to account for possible rollover before right shift
2324*2d543d20SAndroid Build Coastguard Worker 		 */
2325*2d543d20SAndroid Build Coastguard Worker 		high = IOC_DRIV((uint32_t) (r->range.high + 1));
2326*2d543d20SAndroid Build Coastguard Worker 		/* if 0x00 keep current driver code else 0x01 - 0xff round up to next code*/
2327*2d543d20SAndroid Build Coastguard Worker 		low = IOC_DRIV(r->range.low);
2328*2d543d20SAndroid Build Coastguard Worker 		if (IOC_FUNC(r->range.low))
2329*2d543d20SAndroid Build Coastguard Worker 			low++;
2330*2d543d20SAndroid Build Coastguard Worker 		if (high > low)
2331*2d543d20SAndroid Build Coastguard Worker 			avrule_xperm_setrangebits(low, high - 1, xperms);
2332*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2333*2d543d20SAndroid Build Coastguard Worker 	}
2334*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperms_used(xperms)) {
2335*2d543d20SAndroid Build Coastguard Worker 		xperms->driver = 0x00;
2336*2d543d20SAndroid Build Coastguard Worker 		xperms->specified = AVRULE_XPERMS_IOCTLDRIVER;
2337*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = xperms;
2338*2d543d20SAndroid Build Coastguard Worker 	} else {
2339*2d543d20SAndroid Build Coastguard Worker 		free(xperms);
2340*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = NULL;
2341*2d543d20SAndroid Build Coastguard Worker 	}
2342*2d543d20SAndroid Build Coastguard Worker 	return 0;
2343*2d543d20SAndroid Build Coastguard Worker }
2344*2d543d20SAndroid Build Coastguard Worker 
avrule_xperm_func(struct av_xperm_range_list * rangelist,av_extended_perms_t ** extended_perms,unsigned int driver,uint8_t specified)2345*2d543d20SAndroid Build Coastguard Worker static int avrule_xperm_func(struct av_xperm_range_list *rangelist,
2346*2d543d20SAndroid Build Coastguard Worker 		av_extended_perms_t **extended_perms, unsigned int driver, uint8_t specified)
2347*2d543d20SAndroid Build Coastguard Worker {
2348*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *r;
2349*2d543d20SAndroid Build Coastguard Worker 	av_extended_perms_t *xperms;
2350*2d543d20SAndroid Build Coastguard Worker 	uint16_t low, high;
2351*2d543d20SAndroid Build Coastguard Worker 
2352*2d543d20SAndroid Build Coastguard Worker 	*extended_perms = NULL;
2353*2d543d20SAndroid Build Coastguard Worker 	xperms = calloc(1, sizeof(av_extended_perms_t));
2354*2d543d20SAndroid Build Coastguard Worker 	if (!xperms) {
2355*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2356*2d543d20SAndroid Build Coastguard Worker 		return -1;
2357*2d543d20SAndroid Build Coastguard Worker 	}
2358*2d543d20SAndroid Build Coastguard Worker 
2359*2d543d20SAndroid Build Coastguard Worker 	r = rangelist;
2360*2d543d20SAndroid Build Coastguard Worker 	/* for the passed in driver code, find the ranges that apply */
2361*2d543d20SAndroid Build Coastguard Worker 	while (r) {
2362*2d543d20SAndroid Build Coastguard Worker 		low = r->range.low;
2363*2d543d20SAndroid Build Coastguard Worker 		high = r->range.high;
2364*2d543d20SAndroid Build Coastguard Worker 		if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) {
2365*2d543d20SAndroid Build Coastguard Worker 			r = r->next;
2366*2d543d20SAndroid Build Coastguard Worker 			continue;
2367*2d543d20SAndroid Build Coastguard Worker 		}
2368*2d543d20SAndroid Build Coastguard Worker 
2369*2d543d20SAndroid Build Coastguard Worker 		if (driver == IOC_DRIV(low)) {
2370*2d543d20SAndroid Build Coastguard Worker 			if (high > IOC_CMD(driver, 0xff))
2371*2d543d20SAndroid Build Coastguard Worker 				high = IOC_CMD(driver, 0xff);
2372*2d543d20SAndroid Build Coastguard Worker 
2373*2d543d20SAndroid Build Coastguard Worker 		} else {
2374*2d543d20SAndroid Build Coastguard Worker 			if (low < IOC_CMD(driver, 0))
2375*2d543d20SAndroid Build Coastguard Worker 				low = IOC_CMD(driver, 0);
2376*2d543d20SAndroid Build Coastguard Worker 		}
2377*2d543d20SAndroid Build Coastguard Worker 
2378*2d543d20SAndroid Build Coastguard Worker 		low = IOC_FUNC(low);
2379*2d543d20SAndroid Build Coastguard Worker 		high = IOC_FUNC(high);
2380*2d543d20SAndroid Build Coastguard Worker 		avrule_xperm_setrangebits(low, high, xperms);
2381*2d543d20SAndroid Build Coastguard Worker 		xperms->driver = driver;
2382*2d543d20SAndroid Build Coastguard Worker 		xperms->specified = specified;
2383*2d543d20SAndroid Build Coastguard Worker 		r = r->next;
2384*2d543d20SAndroid Build Coastguard Worker 	}
2385*2d543d20SAndroid Build Coastguard Worker 
2386*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperms_used(xperms)) {
2387*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = xperms;
2388*2d543d20SAndroid Build Coastguard Worker 	} else {
2389*2d543d20SAndroid Build Coastguard Worker 		free(xperms);
2390*2d543d20SAndroid Build Coastguard Worker 		*extended_perms = NULL;
2391*2d543d20SAndroid Build Coastguard Worker 	}
2392*2d543d20SAndroid Build Coastguard Worker 	return 0;
2393*2d543d20SAndroid Build Coastguard Worker }
2394*2d543d20SAndroid Build Coastguard Worker 
xperms_for_each_bit(unsigned int * bit,av_extended_perms_t * xperms)2395*2d543d20SAndroid Build Coastguard Worker static unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
2396*2d543d20SAndroid Build Coastguard Worker {
2397*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2398*2d543d20SAndroid Build Coastguard Worker 	for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
2399*2d543d20SAndroid Build Coastguard Worker 		if (xperm_test(i,xperms->perms)) {
2400*2d543d20SAndroid Build Coastguard Worker 			xperm_clear(i, xperms->perms);
2401*2d543d20SAndroid Build Coastguard Worker 			*bit = i;
2402*2d543d20SAndroid Build Coastguard Worker 			return 1;
2403*2d543d20SAndroid Build Coastguard Worker 		}
2404*2d543d20SAndroid Build Coastguard Worker 	}
2405*2d543d20SAndroid Build Coastguard Worker 	return 0;
2406*2d543d20SAndroid Build Coastguard Worker }
2407*2d543d20SAndroid Build Coastguard Worker 
avrule_cpy(avrule_t * dest,const avrule_t * src)2408*2d543d20SAndroid Build Coastguard Worker static int avrule_cpy(avrule_t *dest, const avrule_t *src)
2409*2d543d20SAndroid Build Coastguard Worker {
2410*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *src_perms;
2411*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *dest_perms, *dest_tail;
2412*2d543d20SAndroid Build Coastguard Worker 	dest_tail = NULL;
2413*2d543d20SAndroid Build Coastguard Worker 
2414*2d543d20SAndroid Build Coastguard Worker 	avrule_init(dest);
2415*2d543d20SAndroid Build Coastguard Worker 	dest->specified = src->specified;
2416*2d543d20SAndroid Build Coastguard Worker 	dest->flags = src->flags;
2417*2d543d20SAndroid Build Coastguard Worker 	if (type_set_cpy(&dest->stypes, &src->stypes)) {
2418*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2419*2d543d20SAndroid Build Coastguard Worker 		return -1;
2420*2d543d20SAndroid Build Coastguard Worker 	}
2421*2d543d20SAndroid Build Coastguard Worker 	if (type_set_cpy(&dest->ttypes, &src->ttypes)) {
2422*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2423*2d543d20SAndroid Build Coastguard Worker 		return -1;
2424*2d543d20SAndroid Build Coastguard Worker 	}
2425*2d543d20SAndroid Build Coastguard Worker 	dest->line = src->line;
2426*2d543d20SAndroid Build Coastguard Worker 	dest->source_filename = strdup(source_file);
2427*2d543d20SAndroid Build Coastguard Worker 	if (!dest->source_filename) {
2428*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2429*2d543d20SAndroid Build Coastguard Worker 		return -1;
2430*2d543d20SAndroid Build Coastguard Worker 	}
2431*2d543d20SAndroid Build Coastguard Worker 	dest->source_line = src->source_line;
2432*2d543d20SAndroid Build Coastguard Worker 
2433*2d543d20SAndroid Build Coastguard Worker 	/* increment through the class perms and copy over */
2434*2d543d20SAndroid Build Coastguard Worker 	src_perms = src->perms;
2435*2d543d20SAndroid Build Coastguard Worker 	while (src_perms) {
2436*2d543d20SAndroid Build Coastguard Worker 		dest_perms = (class_perm_node_t *) calloc(1, sizeof(class_perm_node_t));
2437*2d543d20SAndroid Build Coastguard Worker 		if (!dest_perms) {
2438*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
2439*2d543d20SAndroid Build Coastguard Worker 			return -1;
2440*2d543d20SAndroid Build Coastguard Worker 		}
2441*2d543d20SAndroid Build Coastguard Worker 		class_perm_node_init(dest_perms);
2442*2d543d20SAndroid Build Coastguard Worker 
2443*2d543d20SAndroid Build Coastguard Worker 		if (!dest->perms)
2444*2d543d20SAndroid Build Coastguard Worker 			dest->perms = dest_perms;
2445*2d543d20SAndroid Build Coastguard Worker 		else
2446*2d543d20SAndroid Build Coastguard Worker 			dest_tail->next = dest_perms;
2447*2d543d20SAndroid Build Coastguard Worker 
2448*2d543d20SAndroid Build Coastguard Worker 		dest_perms->tclass = src_perms->tclass;
2449*2d543d20SAndroid Build Coastguard Worker 		dest_perms->data = src_perms->data;
2450*2d543d20SAndroid Build Coastguard Worker 		dest_perms->next = NULL;
2451*2d543d20SAndroid Build Coastguard Worker 		dest_tail = dest_perms;
2452*2d543d20SAndroid Build Coastguard Worker 		src_perms = src_perms->next;
2453*2d543d20SAndroid Build Coastguard Worker 	}
2454*2d543d20SAndroid Build Coastguard Worker 	return 0;
2455*2d543d20SAndroid Build Coastguard Worker }
2456*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab_ioctl(const avrule_t * avrule_template)2457*2d543d20SAndroid Build Coastguard Worker static int define_te_avtab_ioctl(const avrule_t *avrule_template)
2458*2d543d20SAndroid Build Coastguard Worker {
2459*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2460*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *rangelist, *r;
2461*2d543d20SAndroid Build Coastguard Worker 	av_extended_perms_t *complete_driver, *partial_driver, *xperms;
2462*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2463*2d543d20SAndroid Build Coastguard Worker 
2464*2d543d20SAndroid Build Coastguard Worker 
2465*2d543d20SAndroid Build Coastguard Worker 	/* organize ioctl ranges */
2466*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperm_ranges(&rangelist))
2467*2d543d20SAndroid Build Coastguard Worker 		return -1;
2468*2d543d20SAndroid Build Coastguard Worker 
2469*2d543d20SAndroid Build Coastguard Worker 	/* create rule for ioctl driver types that are entirely enabled */
2470*2d543d20SAndroid Build Coastguard Worker 	if (avrule_ioctl_completedriver(rangelist, &complete_driver))
2471*2d543d20SAndroid Build Coastguard Worker 		return -1;
2472*2d543d20SAndroid Build Coastguard Worker 	if (complete_driver) {
2473*2d543d20SAndroid Build Coastguard Worker 		avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
2474*2d543d20SAndroid Build Coastguard Worker 		if (!avrule) {
2475*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
2476*2d543d20SAndroid Build Coastguard Worker 			return -1;
2477*2d543d20SAndroid Build Coastguard Worker 		}
2478*2d543d20SAndroid Build Coastguard Worker 		if (avrule_cpy(avrule, avrule_template))
2479*2d543d20SAndroid Build Coastguard Worker 			return -1;
2480*2d543d20SAndroid Build Coastguard Worker 		avrule->xperms = complete_driver;
2481*2d543d20SAndroid Build Coastguard Worker 		append_avrule(avrule);
2482*2d543d20SAndroid Build Coastguard Worker 	}
2483*2d543d20SAndroid Build Coastguard Worker 
2484*2d543d20SAndroid Build Coastguard Worker 	/* flag ioctl driver codes that are partially enabled */
2485*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperm_partialdriver(rangelist, complete_driver, &partial_driver))
2486*2d543d20SAndroid Build Coastguard Worker 		return -1;
2487*2d543d20SAndroid Build Coastguard Worker 
2488*2d543d20SAndroid Build Coastguard Worker 	if (!partial_driver || !avrule_xperms_used(partial_driver))
2489*2d543d20SAndroid Build Coastguard Worker 		goto done;
2490*2d543d20SAndroid Build Coastguard Worker 
2491*2d543d20SAndroid Build Coastguard Worker 	/*
2492*2d543d20SAndroid Build Coastguard Worker 	 * create rule for each partially used driver codes
2493*2d543d20SAndroid Build Coastguard Worker 	 * "partially used" meaning that the code number e.g. socket 0x89
2494*2d543d20SAndroid Build Coastguard Worker 	 * has some permission bits set and others not set.
2495*2d543d20SAndroid Build Coastguard Worker 	 */
2496*2d543d20SAndroid Build Coastguard Worker 	i = 0;
2497*2d543d20SAndroid Build Coastguard Worker 	while (xperms_for_each_bit(&i, partial_driver)) {
2498*2d543d20SAndroid Build Coastguard Worker 		if (avrule_xperm_func(rangelist, &xperms, i, AVRULE_XPERMS_IOCTLFUNCTION))
2499*2d543d20SAndroid Build Coastguard Worker 			return -1;
2500*2d543d20SAndroid Build Coastguard Worker 
2501*2d543d20SAndroid Build Coastguard Worker 		if (xperms) {
2502*2d543d20SAndroid Build Coastguard Worker 			avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
2503*2d543d20SAndroid Build Coastguard Worker 			if (!avrule) {
2504*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
2505*2d543d20SAndroid Build Coastguard Worker 				return -1;
2506*2d543d20SAndroid Build Coastguard Worker 			}
2507*2d543d20SAndroid Build Coastguard Worker 			if (avrule_cpy(avrule, avrule_template))
2508*2d543d20SAndroid Build Coastguard Worker 				return -1;
2509*2d543d20SAndroid Build Coastguard Worker 			avrule->xperms = xperms;
2510*2d543d20SAndroid Build Coastguard Worker 			append_avrule(avrule);
2511*2d543d20SAndroid Build Coastguard Worker 		}
2512*2d543d20SAndroid Build Coastguard Worker 	}
2513*2d543d20SAndroid Build Coastguard Worker 
2514*2d543d20SAndroid Build Coastguard Worker done:
2515*2d543d20SAndroid Build Coastguard Worker 	if (partial_driver)
2516*2d543d20SAndroid Build Coastguard Worker 		free(partial_driver);
2517*2d543d20SAndroid Build Coastguard Worker 
2518*2d543d20SAndroid Build Coastguard Worker 	while (rangelist != NULL) {
2519*2d543d20SAndroid Build Coastguard Worker 		r = rangelist;
2520*2d543d20SAndroid Build Coastguard Worker 		rangelist = rangelist->next;
2521*2d543d20SAndroid Build Coastguard Worker 		free(r);
2522*2d543d20SAndroid Build Coastguard Worker 	}
2523*2d543d20SAndroid Build Coastguard Worker 
2524*2d543d20SAndroid Build Coastguard Worker 	return 0;
2525*2d543d20SAndroid Build Coastguard Worker }
2526*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab_netlink(const avrule_t * avrule_template)2527*2d543d20SAndroid Build Coastguard Worker static int define_te_avtab_netlink(const avrule_t *avrule_template)
2528*2d543d20SAndroid Build Coastguard Worker {
2529*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2530*2d543d20SAndroid Build Coastguard Worker 	struct av_xperm_range_list *rangelist, *r;
2531*2d543d20SAndroid Build Coastguard Worker 	av_extended_perms_t *partial_driver, *xperms;
2532*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2533*2d543d20SAndroid Build Coastguard Worker 
2534*2d543d20SAndroid Build Coastguard Worker 	/* organize ranges */
2535*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperm_ranges(&rangelist))
2536*2d543d20SAndroid Build Coastguard Worker 		return -1;
2537*2d543d20SAndroid Build Coastguard Worker 
2538*2d543d20SAndroid Build Coastguard Worker 	/* flag driver codes that are partially enabled */
2539*2d543d20SAndroid Build Coastguard Worker 	if (avrule_xperm_partialdriver(rangelist, NULL, &partial_driver))
2540*2d543d20SAndroid Build Coastguard Worker 		return -1;
2541*2d543d20SAndroid Build Coastguard Worker 
2542*2d543d20SAndroid Build Coastguard Worker 	if (!partial_driver || !avrule_xperms_used(partial_driver))
2543*2d543d20SAndroid Build Coastguard Worker 		goto done;
2544*2d543d20SAndroid Build Coastguard Worker 
2545*2d543d20SAndroid Build Coastguard Worker 	/*
2546*2d543d20SAndroid Build Coastguard Worker 	 * create rule for each partially used driver codes
2547*2d543d20SAndroid Build Coastguard Worker 	 * "partially used" meaning that the code number e.g. socket 0x89
2548*2d543d20SAndroid Build Coastguard Worker 	 * has some permission bits set and others not set.
2549*2d543d20SAndroid Build Coastguard Worker 	 */
2550*2d543d20SAndroid Build Coastguard Worker 	i = 0;
2551*2d543d20SAndroid Build Coastguard Worker 	while (xperms_for_each_bit(&i, partial_driver)) {
2552*2d543d20SAndroid Build Coastguard Worker 		if (avrule_xperm_func(rangelist, &xperms, i, AVRULE_XPERMS_NLMSG))
2553*2d543d20SAndroid Build Coastguard Worker 			return -1;
2554*2d543d20SAndroid Build Coastguard Worker 
2555*2d543d20SAndroid Build Coastguard Worker 		if (xperms) {
2556*2d543d20SAndroid Build Coastguard Worker 			avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
2557*2d543d20SAndroid Build Coastguard Worker 			if (!avrule) {
2558*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
2559*2d543d20SAndroid Build Coastguard Worker 				return -1;
2560*2d543d20SAndroid Build Coastguard Worker 			}
2561*2d543d20SAndroid Build Coastguard Worker 			if (avrule_cpy(avrule, avrule_template))
2562*2d543d20SAndroid Build Coastguard Worker 				return -1;
2563*2d543d20SAndroid Build Coastguard Worker 			avrule->xperms = xperms;
2564*2d543d20SAndroid Build Coastguard Worker 			append_avrule(avrule);
2565*2d543d20SAndroid Build Coastguard Worker 		}
2566*2d543d20SAndroid Build Coastguard Worker 	}
2567*2d543d20SAndroid Build Coastguard Worker 
2568*2d543d20SAndroid Build Coastguard Worker done:
2569*2d543d20SAndroid Build Coastguard Worker 	if (partial_driver)
2570*2d543d20SAndroid Build Coastguard Worker 		free(partial_driver);
2571*2d543d20SAndroid Build Coastguard Worker 
2572*2d543d20SAndroid Build Coastguard Worker 	while (rangelist != NULL) {
2573*2d543d20SAndroid Build Coastguard Worker 		r = rangelist;
2574*2d543d20SAndroid Build Coastguard Worker 		rangelist = rangelist->next;
2575*2d543d20SAndroid Build Coastguard Worker 		free(r);
2576*2d543d20SAndroid Build Coastguard Worker 	}
2577*2d543d20SAndroid Build Coastguard Worker 
2578*2d543d20SAndroid Build Coastguard Worker 	return 0;
2579*2d543d20SAndroid Build Coastguard Worker }
2580*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab_extended_perms(int which)2581*2d543d20SAndroid Build Coastguard Worker int define_te_avtab_extended_perms(int which)
2582*2d543d20SAndroid Build Coastguard Worker {
2583*2d543d20SAndroid Build Coastguard Worker 	char *id;
2584*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2585*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule_template;
2586*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2587*2d543d20SAndroid Build Coastguard Worker 
2588*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
2589*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < 4; i++) {
2590*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
2591*2d543d20SAndroid Build Coastguard Worker 				free(id);
2592*2d543d20SAndroid Build Coastguard Worker 		}
2593*2d543d20SAndroid Build Coastguard Worker 		return 0;
2594*2d543d20SAndroid Build Coastguard Worker 	}
2595*2d543d20SAndroid Build Coastguard Worker 
2596*2d543d20SAndroid Build Coastguard Worker 	/* populate avrule template with source/target/tclass */
2597*2d543d20SAndroid Build Coastguard Worker 	if (define_te_avtab_xperms_helper(which, &avrule_template))
2598*2d543d20SAndroid Build Coastguard Worker 		return -1;
2599*2d543d20SAndroid Build Coastguard Worker 
2600*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
2601*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id,"ioctl") == 0) {
2602*2d543d20SAndroid Build Coastguard Worker 		rc = define_te_avtab_ioctl(avrule_template);
2603*2d543d20SAndroid Build Coastguard Worker 	} else if (strcmp(id,"nlmsg") == 0) {
2604*2d543d20SAndroid Build Coastguard Worker 		rc = define_te_avtab_netlink(avrule_template);
2605*2d543d20SAndroid Build Coastguard Worker 	} else {
2606*2d543d20SAndroid Build Coastguard Worker 		yyerror2("only ioctl extended permissions are supported, found %s", id);
2607*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
2608*2d543d20SAndroid Build Coastguard Worker 	}
2609*2d543d20SAndroid Build Coastguard Worker 
2610*2d543d20SAndroid Build Coastguard Worker 	free(id);
2611*2d543d20SAndroid Build Coastguard Worker 	avrule_destroy(avrule_template);
2612*2d543d20SAndroid Build Coastguard Worker 	free(avrule_template);
2613*2d543d20SAndroid Build Coastguard Worker 
2614*2d543d20SAndroid Build Coastguard Worker 	return rc;
2615*2d543d20SAndroid Build Coastguard Worker }
2616*2d543d20SAndroid Build Coastguard Worker 
2617*2d543d20SAndroid Build Coastguard Worker #define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1))
2618*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab_helper(int which,avrule_t ** rule)2619*2d543d20SAndroid Build Coastguard Worker static int define_te_avtab_helper(int which, avrule_t ** rule)
2620*2d543d20SAndroid Build Coastguard Worker {
2621*2d543d20SAndroid Build Coastguard Worker 	char *id;
2622*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
2623*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum = NULL;
2624*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
2625*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t tclasses;
2626*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
2627*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2628*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2629*2d543d20SAndroid Build Coastguard Worker 	int add = 1, ret = 0;
2630*2d543d20SAndroid Build Coastguard Worker 	int suppress = 0;
2631*2d543d20SAndroid Build Coastguard Worker 
2632*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&tclasses);
2633*2d543d20SAndroid Build Coastguard Worker 
2634*2d543d20SAndroid Build Coastguard Worker 	avrule = (avrule_t *) malloc(sizeof(avrule_t));
2635*2d543d20SAndroid Build Coastguard Worker 	if (!avrule) {
2636*2d543d20SAndroid Build Coastguard Worker 		yyerror("memory error");
2637*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
2638*2d543d20SAndroid Build Coastguard Worker 		goto out;
2639*2d543d20SAndroid Build Coastguard Worker 	}
2640*2d543d20SAndroid Build Coastguard Worker 	avrule_init(avrule);
2641*2d543d20SAndroid Build Coastguard Worker 	avrule->specified = which;
2642*2d543d20SAndroid Build Coastguard Worker 	avrule->line = policydb_lineno;
2643*2d543d20SAndroid Build Coastguard Worker 	avrule->source_line = source_lineno;
2644*2d543d20SAndroid Build Coastguard Worker 	avrule->source_filename = strdup(source_file);
2645*2d543d20SAndroid Build Coastguard Worker 	avrule->xperms = NULL;
2646*2d543d20SAndroid Build Coastguard Worker 	if (!avrule->source_filename) {
2647*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
2648*2d543d20SAndroid Build Coastguard Worker 		return -1;
2649*2d543d20SAndroid Build Coastguard Worker 	}
2650*2d543d20SAndroid Build Coastguard Worker 
2651*2d543d20SAndroid Build Coastguard Worker 
2652*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2653*2d543d20SAndroid Build Coastguard Worker 		if (set_types
2654*2d543d20SAndroid Build Coastguard Worker 		    (&avrule->stypes, id, &add,
2655*2d543d20SAndroid Build Coastguard Worker 		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
2656*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2657*2d543d20SAndroid Build Coastguard Worker 			goto out;
2658*2d543d20SAndroid Build Coastguard Worker 		}
2659*2d543d20SAndroid Build Coastguard Worker 	}
2660*2d543d20SAndroid Build Coastguard Worker 	add = 1;
2661*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2662*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(id, "self") == 0) {
2663*2d543d20SAndroid Build Coastguard Worker 			free(id);
2664*2d543d20SAndroid Build Coastguard Worker 			if (add == 0 && which != AVRULE_NEVERALLOW) {
2665*2d543d20SAndroid Build Coastguard Worker 				yyerror("-self is only supported in neverallow and neverallowxperm rules");
2666*2d543d20SAndroid Build Coastguard Worker 				ret = -1;
2667*2d543d20SAndroid Build Coastguard Worker 				goto out;
2668*2d543d20SAndroid Build Coastguard Worker 			}
2669*2d543d20SAndroid Build Coastguard Worker 			avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
2670*2d543d20SAndroid Build Coastguard Worker 			if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
2671*2d543d20SAndroid Build Coastguard Worker 				yyerror("self and -self are mutual exclusive");
2672*2d543d20SAndroid Build Coastguard Worker 				ret = -1;
2673*2d543d20SAndroid Build Coastguard Worker 				goto out;
2674*2d543d20SAndroid Build Coastguard Worker 			}
2675*2d543d20SAndroid Build Coastguard Worker 			continue;
2676*2d543d20SAndroid Build Coastguard Worker 		}
2677*2d543d20SAndroid Build Coastguard Worker 		if (set_types
2678*2d543d20SAndroid Build Coastguard Worker 		    (&avrule->ttypes, id, &add,
2679*2d543d20SAndroid Build Coastguard Worker 		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
2680*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2681*2d543d20SAndroid Build Coastguard Worker 			goto out;
2682*2d543d20SAndroid Build Coastguard Worker 		}
2683*2d543d20SAndroid Build Coastguard Worker 	}
2684*2d543d20SAndroid Build Coastguard Worker 
2685*2d543d20SAndroid Build Coastguard Worker 	if ((avrule->ttypes.flags & TYPE_COMP)) {
2686*2d543d20SAndroid Build Coastguard Worker 		if (avrule->flags & RULE_NOTSELF) {
2687*2d543d20SAndroid Build Coastguard Worker 			yyerror("-self is not supported in complements");
2688*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2689*2d543d20SAndroid Build Coastguard Worker 			goto out;
2690*2d543d20SAndroid Build Coastguard Worker 		}
2691*2d543d20SAndroid Build Coastguard Worker 		if (avrule->flags & RULE_SELF) {
2692*2d543d20SAndroid Build Coastguard Worker 			avrule->flags &= ~RULE_SELF;
2693*2d543d20SAndroid Build Coastguard Worker 			avrule->flags |= RULE_NOTSELF;
2694*2d543d20SAndroid Build Coastguard Worker 		}
2695*2d543d20SAndroid Build Coastguard Worker 	}
2696*2d543d20SAndroid Build Coastguard Worker 
2697*2d543d20SAndroid Build Coastguard Worker 	ret = read_classes(&tclasses);
2698*2d543d20SAndroid Build Coastguard Worker 	if (ret)
2699*2d543d20SAndroid Build Coastguard Worker 		goto out;
2700*2d543d20SAndroid Build Coastguard Worker 
2701*2d543d20SAndroid Build Coastguard Worker 	perms = NULL;
2702*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&tclasses, node, i) {
2703*2d543d20SAndroid Build Coastguard Worker 		cur_perms =
2704*2d543d20SAndroid Build Coastguard Worker 		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2705*2d543d20SAndroid Build Coastguard Worker 		if (!cur_perms) {
2706*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
2707*2d543d20SAndroid Build Coastguard Worker 			ret = -1;
2708*2d543d20SAndroid Build Coastguard Worker 			goto out;
2709*2d543d20SAndroid Build Coastguard Worker 		}
2710*2d543d20SAndroid Build Coastguard Worker 		class_perm_node_init(cur_perms);
2711*2d543d20SAndroid Build Coastguard Worker 		cur_perms->tclass = i + 1;
2712*2d543d20SAndroid Build Coastguard Worker 		if (!perms)
2713*2d543d20SAndroid Build Coastguard Worker 			perms = cur_perms;
2714*2d543d20SAndroid Build Coastguard Worker 		if (tail)
2715*2d543d20SAndroid Build Coastguard Worker 			tail->next = cur_perms;
2716*2d543d20SAndroid Build Coastguard Worker 		tail = cur_perms;
2717*2d543d20SAndroid Build Coastguard Worker 	}
2718*2d543d20SAndroid Build Coastguard Worker 
2719*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2720*2d543d20SAndroid Build Coastguard Worker 		cur_perms = perms;
2721*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&tclasses, node, i) {
2722*2d543d20SAndroid Build Coastguard Worker 			cladatum = policydbp->class_val_to_struct[i];
2723*2d543d20SAndroid Build Coastguard Worker 
2724*2d543d20SAndroid Build Coastguard Worker 			if (strcmp(id, "*") == 0) {
2725*2d543d20SAndroid Build Coastguard Worker 				/* set all declared permissions in the class */
2726*2d543d20SAndroid Build Coastguard Worker 				cur_perms->data = PERMISSION_MASK(cladatum->permissions.nprim);
2727*2d543d20SAndroid Build Coastguard Worker 				goto next;
2728*2d543d20SAndroid Build Coastguard Worker 			}
2729*2d543d20SAndroid Build Coastguard Worker 
2730*2d543d20SAndroid Build Coastguard Worker 			if (strcmp(id, "~") == 0) {
2731*2d543d20SAndroid Build Coastguard Worker 				/* complement the set */
2732*2d543d20SAndroid Build Coastguard Worker 				if (which == AVRULE_DONTAUDIT)
2733*2d543d20SAndroid Build Coastguard Worker 					yywarn("dontaudit rule with a ~?");
2734*2d543d20SAndroid Build Coastguard Worker 				cur_perms->data = ~cur_perms->data & PERMISSION_MASK(cladatum->permissions.nprim);
2735*2d543d20SAndroid Build Coastguard Worker 				if (cur_perms->data == 0) {
2736*2d543d20SAndroid Build Coastguard Worker 					class_perm_node_t *tmp = cur_perms;
2737*2d543d20SAndroid Build Coastguard Worker 					yywarn("omitting avrule with no permission set");
2738*2d543d20SAndroid Build Coastguard Worker 					if (perms == cur_perms)
2739*2d543d20SAndroid Build Coastguard Worker 						perms = cur_perms->next;
2740*2d543d20SAndroid Build Coastguard Worker 					cur_perms = cur_perms->next;
2741*2d543d20SAndroid Build Coastguard Worker 					free(tmp);
2742*2d543d20SAndroid Build Coastguard Worker 					continue;
2743*2d543d20SAndroid Build Coastguard Worker 				}
2744*2d543d20SAndroid Build Coastguard Worker 				goto next;
2745*2d543d20SAndroid Build Coastguard Worker 			}
2746*2d543d20SAndroid Build Coastguard Worker 
2747*2d543d20SAndroid Build Coastguard Worker 			perdatum =
2748*2d543d20SAndroid Build Coastguard Worker 			    hashtab_search(cladatum->permissions.table, id);
2749*2d543d20SAndroid Build Coastguard Worker 			if (!perdatum) {
2750*2d543d20SAndroid Build Coastguard Worker 				if (cladatum->comdatum) {
2751*2d543d20SAndroid Build Coastguard Worker 					perdatum =
2752*2d543d20SAndroid Build Coastguard Worker 					    hashtab_search(cladatum->comdatum->
2753*2d543d20SAndroid Build Coastguard Worker 							   permissions.table,
2754*2d543d20SAndroid Build Coastguard Worker 							   id);
2755*2d543d20SAndroid Build Coastguard Worker 				}
2756*2d543d20SAndroid Build Coastguard Worker 			}
2757*2d543d20SAndroid Build Coastguard Worker 			if (!perdatum) {
2758*2d543d20SAndroid Build Coastguard Worker 				if (!suppress)
2759*2d543d20SAndroid Build Coastguard Worker 					yyerror2("permission %s is not defined"
2760*2d543d20SAndroid Build Coastguard Worker 					     " for class %s", id,
2761*2d543d20SAndroid Build Coastguard Worker 					     policydbp->p_class_val_to_name[i]);
2762*2d543d20SAndroid Build Coastguard Worker 				continue;
2763*2d543d20SAndroid Build Coastguard Worker 			} else
2764*2d543d20SAndroid Build Coastguard Worker 			    if (!is_perm_in_scope
2765*2d543d20SAndroid Build Coastguard Worker 				(id, policydbp->p_class_val_to_name[i])) {
2766*2d543d20SAndroid Build Coastguard Worker 				if (!suppress) {
2767*2d543d20SAndroid Build Coastguard Worker 					yyerror2("permission %s of class %s is"
2768*2d543d20SAndroid Build Coastguard Worker 					     " not within scope", id,
2769*2d543d20SAndroid Build Coastguard Worker 					     policydbp->p_class_val_to_name[i]);
2770*2d543d20SAndroid Build Coastguard Worker 				}
2771*2d543d20SAndroid Build Coastguard Worker 				continue;
2772*2d543d20SAndroid Build Coastguard Worker 			} else {
2773*2d543d20SAndroid Build Coastguard Worker 				cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
2774*2d543d20SAndroid Build Coastguard Worker 			}
2775*2d543d20SAndroid Build Coastguard Worker 		      next:
2776*2d543d20SAndroid Build Coastguard Worker 			cur_perms = cur_perms->next;
2777*2d543d20SAndroid Build Coastguard Worker 		}
2778*2d543d20SAndroid Build Coastguard Worker 
2779*2d543d20SAndroid Build Coastguard Worker 		free(id);
2780*2d543d20SAndroid Build Coastguard Worker 	}
2781*2d543d20SAndroid Build Coastguard Worker 
2782*2d543d20SAndroid Build Coastguard Worker 	avrule->perms = perms;
2783*2d543d20SAndroid Build Coastguard Worker 	*rule = avrule;
2784*2d543d20SAndroid Build Coastguard Worker 
2785*2d543d20SAndroid Build Coastguard Worker       out:
2786*2d543d20SAndroid Build Coastguard Worker 	if (ret) {
2787*2d543d20SAndroid Build Coastguard Worker 		avrule_destroy(avrule);
2788*2d543d20SAndroid Build Coastguard Worker 		free(avrule);
2789*2d543d20SAndroid Build Coastguard Worker 	}
2790*2d543d20SAndroid Build Coastguard Worker 
2791*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&tclasses);
2792*2d543d20SAndroid Build Coastguard Worker 
2793*2d543d20SAndroid Build Coastguard Worker 	return ret;
2794*2d543d20SAndroid Build Coastguard Worker 
2795*2d543d20SAndroid Build Coastguard Worker }
2796*2d543d20SAndroid Build Coastguard Worker 
define_cond_te_avtab(int which)2797*2d543d20SAndroid Build Coastguard Worker avrule_t *define_cond_te_avtab(int which)
2798*2d543d20SAndroid Build Coastguard Worker {
2799*2d543d20SAndroid Build Coastguard Worker 	char *id;
2800*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2801*2d543d20SAndroid Build Coastguard Worker 	int i;
2802*2d543d20SAndroid Build Coastguard Worker 
2803*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
2804*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < 4; i++) {
2805*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
2806*2d543d20SAndroid Build Coastguard Worker 				free(id);
2807*2d543d20SAndroid Build Coastguard Worker 		}
2808*2d543d20SAndroid Build Coastguard Worker 		return (avrule_t *) 1;	/* any non-NULL value */
2809*2d543d20SAndroid Build Coastguard Worker 	}
2810*2d543d20SAndroid Build Coastguard Worker 
2811*2d543d20SAndroid Build Coastguard Worker 	if (define_te_avtab_helper(which, &avrule))
2812*2d543d20SAndroid Build Coastguard Worker 		return COND_ERR;
2813*2d543d20SAndroid Build Coastguard Worker 
2814*2d543d20SAndroid Build Coastguard Worker 	return avrule;
2815*2d543d20SAndroid Build Coastguard Worker }
2816*2d543d20SAndroid Build Coastguard Worker 
define_te_avtab(int which)2817*2d543d20SAndroid Build Coastguard Worker int define_te_avtab(int which)
2818*2d543d20SAndroid Build Coastguard Worker {
2819*2d543d20SAndroid Build Coastguard Worker 	char *id;
2820*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
2821*2d543d20SAndroid Build Coastguard Worker 	int i;
2822*2d543d20SAndroid Build Coastguard Worker 
2823*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
2824*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < 4; i++) {
2825*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
2826*2d543d20SAndroid Build Coastguard Worker 				free(id);
2827*2d543d20SAndroid Build Coastguard Worker 		}
2828*2d543d20SAndroid Build Coastguard Worker 		return 0;
2829*2d543d20SAndroid Build Coastguard Worker 	}
2830*2d543d20SAndroid Build Coastguard Worker 
2831*2d543d20SAndroid Build Coastguard Worker 	if (define_te_avtab_helper(which, &avrule))
2832*2d543d20SAndroid Build Coastguard Worker 		return -1;
2833*2d543d20SAndroid Build Coastguard Worker 
2834*2d543d20SAndroid Build Coastguard Worker 	/* append this avrule to the end of the current rules list */
2835*2d543d20SAndroid Build Coastguard Worker 	append_avrule(avrule);
2836*2d543d20SAndroid Build Coastguard Worker 	return 0;
2837*2d543d20SAndroid Build Coastguard Worker }
2838*2d543d20SAndroid Build Coastguard Worker 
2839*2d543d20SAndroid Build Coastguard Worker /* The role-types rule is no longer used to declare regular role or
2840*2d543d20SAndroid Build Coastguard Worker  * role attribute, but solely aimed for declaring role-types associations.
2841*2d543d20SAndroid Build Coastguard Worker  */
define_role_types(void)2842*2d543d20SAndroid Build Coastguard Worker int define_role_types(void)
2843*2d543d20SAndroid Build Coastguard Worker {
2844*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
2845*2d543d20SAndroid Build Coastguard Worker 	char *id;
2846*2d543d20SAndroid Build Coastguard Worker 	int add = 1;
2847*2d543d20SAndroid Build Coastguard Worker 
2848*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
2849*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
2850*2d543d20SAndroid Build Coastguard Worker 			free(id);
2851*2d543d20SAndroid Build Coastguard Worker 		return 0;
2852*2d543d20SAndroid Build Coastguard Worker 	}
2853*2d543d20SAndroid Build Coastguard Worker 
2854*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
2855*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
2856*2d543d20SAndroid Build Coastguard Worker 		yyerror("no role name for role-types rule?");
2857*2d543d20SAndroid Build Coastguard Worker 		return -1;
2858*2d543d20SAndroid Build Coastguard Worker 	}
2859*2d543d20SAndroid Build Coastguard Worker 
2860*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
2861*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
2862*2d543d20SAndroid Build Coastguard Worker 		free(id);
2863*2d543d20SAndroid Build Coastguard Worker 		return -1;
2864*2d543d20SAndroid Build Coastguard Worker 	}
2865*2d543d20SAndroid Build Coastguard Worker 
2866*2d543d20SAndroid Build Coastguard Worker 	role = hashtab_search(policydbp->p_roles.table, id);
2867*2d543d20SAndroid Build Coastguard Worker 	if (!role) {
2868*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown role %s", id);
2869*2d543d20SAndroid Build Coastguard Worker 		free(id);
2870*2d543d20SAndroid Build Coastguard Worker 		return -1;
2871*2d543d20SAndroid Build Coastguard Worker 	}
2872*2d543d20SAndroid Build Coastguard Worker 	role = get_local_role(id, role->s.value, (role->flavor == ROLE_ATTRIB));
2873*2d543d20SAndroid Build Coastguard Worker 
2874*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2875*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&role->types, id, &add, 0))
2876*2d543d20SAndroid Build Coastguard Worker 			return -1;
2877*2d543d20SAndroid Build Coastguard Worker 	}
2878*2d543d20SAndroid Build Coastguard Worker 
2879*2d543d20SAndroid Build Coastguard Worker 	return 0;
2880*2d543d20SAndroid Build Coastguard Worker }
2881*2d543d20SAndroid Build Coastguard Worker 
define_attrib_role(void)2882*2d543d20SAndroid Build Coastguard Worker int define_attrib_role(void)
2883*2d543d20SAndroid Build Coastguard Worker {
2884*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
2885*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
2886*2d543d20SAndroid Build Coastguard Worker 		return 0;
2887*2d543d20SAndroid Build Coastguard Worker 	}
2888*2d543d20SAndroid Build Coastguard Worker 
2889*2d543d20SAndroid Build Coastguard Worker 	/* Declare a role attribute */
2890*2d543d20SAndroid Build Coastguard Worker 	if (declare_role(TRUE) == NULL)
2891*2d543d20SAndroid Build Coastguard Worker 		return -1;
2892*2d543d20SAndroid Build Coastguard Worker 
2893*2d543d20SAndroid Build Coastguard Worker 	return 0;
2894*2d543d20SAndroid Build Coastguard Worker }
2895*2d543d20SAndroid Build Coastguard Worker 
define_role_attr(void)2896*2d543d20SAndroid Build Coastguard Worker int define_role_attr(void)
2897*2d543d20SAndroid Build Coastguard Worker {
2898*2d543d20SAndroid Build Coastguard Worker 	char *id;
2899*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *r, *attr;
2900*2d543d20SAndroid Build Coastguard Worker 
2901*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
2902*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
2903*2d543d20SAndroid Build Coastguard Worker 			free(id);
2904*2d543d20SAndroid Build Coastguard Worker 		return 0;
2905*2d543d20SAndroid Build Coastguard Worker 	}
2906*2d543d20SAndroid Build Coastguard Worker 
2907*2d543d20SAndroid Build Coastguard Worker 	/* Declare a regular role */
2908*2d543d20SAndroid Build Coastguard Worker 	if ((r = declare_role(FALSE)) == NULL)
2909*2d543d20SAndroid Build Coastguard Worker 		return -1;
2910*2d543d20SAndroid Build Coastguard Worker 
2911*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2912*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_ROLES, id)) {
2913*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not within scope", id);
2914*2d543d20SAndroid Build Coastguard Worker 			free(id);
2915*2d543d20SAndroid Build Coastguard Worker 			return -1;
2916*2d543d20SAndroid Build Coastguard Worker 		}
2917*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_roles.table, id);
2918*2d543d20SAndroid Build Coastguard Worker 		if (!attr) {
2919*2d543d20SAndroid Build Coastguard Worker 			/* treat it as a fatal error */
2920*2d543d20SAndroid Build Coastguard Worker 			yyerror2("role attribute %s is not declared", id);
2921*2d543d20SAndroid Build Coastguard Worker 			free(id);
2922*2d543d20SAndroid Build Coastguard Worker 			return -1;
2923*2d543d20SAndroid Build Coastguard Worker 		}
2924*2d543d20SAndroid Build Coastguard Worker 
2925*2d543d20SAndroid Build Coastguard Worker 		if (attr->flavor != ROLE_ATTRIB) {
2926*2d543d20SAndroid Build Coastguard Worker 			yyerror2("%s is a regular role, not an attribute", id);
2927*2d543d20SAndroid Build Coastguard Worker 			free(id);
2928*2d543d20SAndroid Build Coastguard Worker 			return -1;
2929*2d543d20SAndroid Build Coastguard Worker 		}
2930*2d543d20SAndroid Build Coastguard Worker 
2931*2d543d20SAndroid Build Coastguard Worker 		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
2932*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
2933*2d543d20SAndroid Build Coastguard Worker 			return -1;
2934*2d543d20SAndroid Build Coastguard Worker 		}
2935*2d543d20SAndroid Build Coastguard Worker 
2936*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
2937*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
2938*2d543d20SAndroid Build Coastguard Worker 			return -1;
2939*2d543d20SAndroid Build Coastguard Worker 		}
2940*2d543d20SAndroid Build Coastguard Worker 	}
2941*2d543d20SAndroid Build Coastguard Worker 
2942*2d543d20SAndroid Build Coastguard Worker 	return 0;
2943*2d543d20SAndroid Build Coastguard Worker }
2944*2d543d20SAndroid Build Coastguard Worker 
define_roleattribute(void)2945*2d543d20SAndroid Build Coastguard Worker int define_roleattribute(void)
2946*2d543d20SAndroid Build Coastguard Worker {
2947*2d543d20SAndroid Build Coastguard Worker 	char *id;
2948*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *r, *attr;
2949*2d543d20SAndroid Build Coastguard Worker 
2950*2d543d20SAndroid Build Coastguard Worker 	if (pass == 2) {
2951*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
2952*2d543d20SAndroid Build Coastguard Worker 			free(id);
2953*2d543d20SAndroid Build Coastguard Worker 		return 0;
2954*2d543d20SAndroid Build Coastguard Worker 	}
2955*2d543d20SAndroid Build Coastguard Worker 
2956*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
2957*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
2958*2d543d20SAndroid Build Coastguard Worker 		yyerror("no role name for roleattribute definition?");
2959*2d543d20SAndroid Build Coastguard Worker 		return -1;
2960*2d543d20SAndroid Build Coastguard Worker 	}
2961*2d543d20SAndroid Build Coastguard Worker 
2962*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
2963*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
2964*2d543d20SAndroid Build Coastguard Worker 		free(id);
2965*2d543d20SAndroid Build Coastguard Worker 		return -1;
2966*2d543d20SAndroid Build Coastguard Worker 	}
2967*2d543d20SAndroid Build Coastguard Worker 	r = hashtab_search(policydbp->p_roles.table, id);
2968*2d543d20SAndroid Build Coastguard Worker 	/* We support adding one role attribute into another */
2969*2d543d20SAndroid Build Coastguard Worker 	if (!r) {
2970*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown role %s", id);
2971*2d543d20SAndroid Build Coastguard Worker 		free(id);
2972*2d543d20SAndroid Build Coastguard Worker 		return -1;
2973*2d543d20SAndroid Build Coastguard Worker 	}
2974*2d543d20SAndroid Build Coastguard Worker 	free(id);
2975*2d543d20SAndroid Build Coastguard Worker 
2976*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
2977*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_ROLES, id)) {
2978*2d543d20SAndroid Build Coastguard Worker 			yyerror2("attribute %s is not within scope", id);
2979*2d543d20SAndroid Build Coastguard Worker 			free(id);
2980*2d543d20SAndroid Build Coastguard Worker 			return -1;
2981*2d543d20SAndroid Build Coastguard Worker 		}
2982*2d543d20SAndroid Build Coastguard Worker 		attr = hashtab_search(policydbp->p_roles.table, id);
2983*2d543d20SAndroid Build Coastguard Worker 		if (!attr) {
2984*2d543d20SAndroid Build Coastguard Worker 			/* treat it as a fatal error */
2985*2d543d20SAndroid Build Coastguard Worker 			yyerror2("role attribute %s is not declared", id);
2986*2d543d20SAndroid Build Coastguard Worker 			free(id);
2987*2d543d20SAndroid Build Coastguard Worker 			return -1;
2988*2d543d20SAndroid Build Coastguard Worker 		}
2989*2d543d20SAndroid Build Coastguard Worker 
2990*2d543d20SAndroid Build Coastguard Worker 		if (attr->flavor != ROLE_ATTRIB) {
2991*2d543d20SAndroid Build Coastguard Worker 			yyerror2("%s is a regular role, not an attribute", id);
2992*2d543d20SAndroid Build Coastguard Worker 			free(id);
2993*2d543d20SAndroid Build Coastguard Worker 			return -1;
2994*2d543d20SAndroid Build Coastguard Worker 		}
2995*2d543d20SAndroid Build Coastguard Worker 
2996*2d543d20SAndroid Build Coastguard Worker 		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
2997*2d543d20SAndroid Build Coastguard Worker 			yyerror("Out of memory!");
2998*2d543d20SAndroid Build Coastguard Worker 			return -1;
2999*2d543d20SAndroid Build Coastguard Worker 		}
3000*2d543d20SAndroid Build Coastguard Worker 
3001*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
3002*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3003*2d543d20SAndroid Build Coastguard Worker 			return -1;
3004*2d543d20SAndroid Build Coastguard Worker 		}
3005*2d543d20SAndroid Build Coastguard Worker 	}
3006*2d543d20SAndroid Build Coastguard Worker 
3007*2d543d20SAndroid Build Coastguard Worker 	return 0;
3008*2d543d20SAndroid Build Coastguard Worker }
3009*2d543d20SAndroid Build Coastguard Worker 
role_val_to_name_helper(hashtab_key_t key,hashtab_datum_t datum,void * p)3010*2d543d20SAndroid Build Coastguard Worker static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum,
3011*2d543d20SAndroid Build Coastguard Worker 				   void *p)
3012*2d543d20SAndroid Build Coastguard Worker {
3013*2d543d20SAndroid Build Coastguard Worker 	struct val_to_name *v = p;
3014*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *roldatum;
3015*2d543d20SAndroid Build Coastguard Worker 
3016*2d543d20SAndroid Build Coastguard Worker 	roldatum = (role_datum_t *) datum;
3017*2d543d20SAndroid Build Coastguard Worker 
3018*2d543d20SAndroid Build Coastguard Worker 	if (v->val == roldatum->s.value) {
3019*2d543d20SAndroid Build Coastguard Worker 		v->name = key;
3020*2d543d20SAndroid Build Coastguard Worker 		return 1;
3021*2d543d20SAndroid Build Coastguard Worker 	}
3022*2d543d20SAndroid Build Coastguard Worker 
3023*2d543d20SAndroid Build Coastguard Worker 	return 0;
3024*2d543d20SAndroid Build Coastguard Worker }
3025*2d543d20SAndroid Build Coastguard Worker 
role_val_to_name(unsigned int val)3026*2d543d20SAndroid Build Coastguard Worker static char *role_val_to_name(unsigned int val)
3027*2d543d20SAndroid Build Coastguard Worker {
3028*2d543d20SAndroid Build Coastguard Worker 	struct val_to_name v;
3029*2d543d20SAndroid Build Coastguard Worker 	int rc;
3030*2d543d20SAndroid Build Coastguard Worker 
3031*2d543d20SAndroid Build Coastguard Worker 	v.val = val;
3032*2d543d20SAndroid Build Coastguard Worker 	rc = hashtab_map(policydbp->p_roles.table, role_val_to_name_helper, &v);
3033*2d543d20SAndroid Build Coastguard Worker 	if (rc)
3034*2d543d20SAndroid Build Coastguard Worker 		return v.name;
3035*2d543d20SAndroid Build Coastguard Worker 	return NULL;
3036*2d543d20SAndroid Build Coastguard Worker }
3037*2d543d20SAndroid Build Coastguard Worker 
set_roles(role_set_t * set,char * id)3038*2d543d20SAndroid Build Coastguard Worker static int set_roles(role_set_t * set, char *id)
3039*2d543d20SAndroid Build Coastguard Worker {
3040*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *r;
3041*2d543d20SAndroid Build Coastguard Worker 
3042*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "*") == 0) {
3043*2d543d20SAndroid Build Coastguard Worker 		free(id);
3044*2d543d20SAndroid Build Coastguard Worker 		yyerror("* is not allowed for role sets");
3045*2d543d20SAndroid Build Coastguard Worker 		return -1;
3046*2d543d20SAndroid Build Coastguard Worker 	}
3047*2d543d20SAndroid Build Coastguard Worker 
3048*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "~") == 0) {
3049*2d543d20SAndroid Build Coastguard Worker 		free(id);
3050*2d543d20SAndroid Build Coastguard Worker 		yyerror("~ is not allowed for role sets");
3051*2d543d20SAndroid Build Coastguard Worker 		return -1;
3052*2d543d20SAndroid Build Coastguard Worker 	}
3053*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
3054*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
3055*2d543d20SAndroid Build Coastguard Worker 		free(id);
3056*2d543d20SAndroid Build Coastguard Worker 		return -1;
3057*2d543d20SAndroid Build Coastguard Worker 	}
3058*2d543d20SAndroid Build Coastguard Worker 	r = hashtab_search(policydbp->p_roles.table, id);
3059*2d543d20SAndroid Build Coastguard Worker 	if (!r) {
3060*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown role %s", id);
3061*2d543d20SAndroid Build Coastguard Worker 		free(id);
3062*2d543d20SAndroid Build Coastguard Worker 		return -1;
3063*2d543d20SAndroid Build Coastguard Worker 	}
3064*2d543d20SAndroid Build Coastguard Worker 
3065*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE)) {
3066*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
3067*2d543d20SAndroid Build Coastguard Worker 		free(id);
3068*2d543d20SAndroid Build Coastguard Worker 		return -1;
3069*2d543d20SAndroid Build Coastguard Worker 	}
3070*2d543d20SAndroid Build Coastguard Worker 	free(id);
3071*2d543d20SAndroid Build Coastguard Worker 	return 0;
3072*2d543d20SAndroid Build Coastguard Worker }
3073*2d543d20SAndroid Build Coastguard Worker 
define_role_trans(int class_specified)3074*2d543d20SAndroid Build Coastguard Worker int define_role_trans(int class_specified)
3075*2d543d20SAndroid Build Coastguard Worker {
3076*2d543d20SAndroid Build Coastguard Worker 	char *id;
3077*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
3078*2d543d20SAndroid Build Coastguard Worker 	role_set_t roles;
3079*2d543d20SAndroid Build Coastguard Worker 	type_set_t types;
3080*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
3081*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e_types, e_roles, e_classes;
3082*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *tnode, *rnode, *cnode;
3083*2d543d20SAndroid Build Coastguard Worker 	struct role_trans *tr = NULL;
3084*2d543d20SAndroid Build Coastguard Worker 	struct role_trans_rule *rule = NULL;
3085*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j, k;
3086*2d543d20SAndroid Build Coastguard Worker 	int add = 1;
3087*2d543d20SAndroid Build Coastguard Worker 
3088*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3089*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3090*2d543d20SAndroid Build Coastguard Worker 			free(id);
3091*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3092*2d543d20SAndroid Build Coastguard Worker 			free(id);
3093*2d543d20SAndroid Build Coastguard Worker 		if (class_specified)
3094*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
3095*2d543d20SAndroid Build Coastguard Worker 				free(id);
3096*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
3097*2d543d20SAndroid Build Coastguard Worker 		free(id);
3098*2d543d20SAndroid Build Coastguard Worker 		return 0;
3099*2d543d20SAndroid Build Coastguard Worker 	}
3100*2d543d20SAndroid Build Coastguard Worker 
3101*2d543d20SAndroid Build Coastguard Worker 	role_set_init(&roles);
3102*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_roles);
3103*2d543d20SAndroid Build Coastguard Worker 	type_set_init(&types);
3104*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_types);
3105*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_classes);
3106*2d543d20SAndroid Build Coastguard Worker 
3107*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3108*2d543d20SAndroid Build Coastguard Worker 		if (set_roles(&roles, id))
3109*2d543d20SAndroid Build Coastguard Worker 			return -1;
3110*2d543d20SAndroid Build Coastguard Worker 	}
3111*2d543d20SAndroid Build Coastguard Worker 	add = 1;
3112*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3113*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&types, id, &add, 0))
3114*2d543d20SAndroid Build Coastguard Worker 			return -1;
3115*2d543d20SAndroid Build Coastguard Worker 	}
3116*2d543d20SAndroid Build Coastguard Worker 
3117*2d543d20SAndroid Build Coastguard Worker 	if (class_specified) {
3118*2d543d20SAndroid Build Coastguard Worker 		if (read_classes(&e_classes))
3119*2d543d20SAndroid Build Coastguard Worker 			return -1;
3120*2d543d20SAndroid Build Coastguard Worker 	} else {
3121*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table,
3122*2d543d20SAndroid Build Coastguard Worker 					  "process");
3123*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
3124*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not find process class for "
3125*2d543d20SAndroid Build Coastguard Worker 				 "legacy role_transition statement");
3126*2d543d20SAndroid Build Coastguard Worker 			return -1;
3127*2d543d20SAndroid Build Coastguard Worker 		}
3128*2d543d20SAndroid Build Coastguard Worker 
3129*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&e_classes, cladatum->s.value - 1, TRUE)) {
3130*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3131*2d543d20SAndroid Build Coastguard Worker 			return -1;
3132*2d543d20SAndroid Build Coastguard Worker 		}
3133*2d543d20SAndroid Build Coastguard Worker 	}
3134*2d543d20SAndroid Build Coastguard Worker 
3135*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
3136*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
3137*2d543d20SAndroid Build Coastguard Worker 		yyerror("no new role in transition definition?");
3138*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3139*2d543d20SAndroid Build Coastguard Worker 	}
3140*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
3141*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
3142*2d543d20SAndroid Build Coastguard Worker 		free(id);
3143*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3144*2d543d20SAndroid Build Coastguard Worker 	}
3145*2d543d20SAndroid Build Coastguard Worker 	role = hashtab_search(policydbp->p_roles.table, id);
3146*2d543d20SAndroid Build Coastguard Worker 	if (!role) {
3147*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown role %s used in transition definition", id);
3148*2d543d20SAndroid Build Coastguard Worker 		free(id);
3149*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3150*2d543d20SAndroid Build Coastguard Worker 	}
3151*2d543d20SAndroid Build Coastguard Worker 
3152*2d543d20SAndroid Build Coastguard Worker 	if (role->flavor != ROLE_ROLE) {
3153*2d543d20SAndroid Build Coastguard Worker 		yyerror2("the new role %s must be a regular role", id);
3154*2d543d20SAndroid Build Coastguard Worker 		free(id);
3155*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3156*2d543d20SAndroid Build Coastguard Worker 	}
3157*2d543d20SAndroid Build Coastguard Worker 	free(id);
3158*2d543d20SAndroid Build Coastguard Worker 
3159*2d543d20SAndroid Build Coastguard Worker 	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
3160*2d543d20SAndroid Build Coastguard Worker 	if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
3161*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3162*2d543d20SAndroid Build Coastguard Worker 
3163*2d543d20SAndroid Build Coastguard Worker 	if (type_set_expand(&types, &e_types, policydbp, 1))
3164*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3165*2d543d20SAndroid Build Coastguard Worker 
3166*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&e_roles, rnode, i) {
3167*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&e_types, tnode, j) {
3168*2d543d20SAndroid Build Coastguard Worker 			ebitmap_for_each_positive_bit(&e_classes, cnode, k) {
3169*2d543d20SAndroid Build Coastguard Worker 				for (tr = policydbp->role_tr; tr;
3170*2d543d20SAndroid Build Coastguard Worker 				     tr = tr->next) {
3171*2d543d20SAndroid Build Coastguard Worker 					if (tr->role == (i + 1) &&
3172*2d543d20SAndroid Build Coastguard Worker 					    tr->type == (j + 1) &&
3173*2d543d20SAndroid Build Coastguard Worker 					    tr->tclass == (k + 1)) {
3174*2d543d20SAndroid Build Coastguard Worker 						yyerror2("duplicate role "
3175*2d543d20SAndroid Build Coastguard Worker 							 "transition for "
3176*2d543d20SAndroid Build Coastguard Worker 							 "(%s,%s,%s)",
3177*2d543d20SAndroid Build Coastguard Worker 							 role_val_to_name(i+1),
3178*2d543d20SAndroid Build Coastguard Worker 							 policydbp->p_type_val_to_name[j],
3179*2d543d20SAndroid Build Coastguard Worker 							 policydbp->p_class_val_to_name[k]);
3180*2d543d20SAndroid Build Coastguard Worker 						goto bad;
3181*2d543d20SAndroid Build Coastguard Worker 					}
3182*2d543d20SAndroid Build Coastguard Worker 				}
3183*2d543d20SAndroid Build Coastguard Worker 
3184*2d543d20SAndroid Build Coastguard Worker 				tr = malloc(sizeof(struct role_trans));
3185*2d543d20SAndroid Build Coastguard Worker 				if (!tr) {
3186*2d543d20SAndroid Build Coastguard Worker 					yyerror("out of memory");
3187*2d543d20SAndroid Build Coastguard Worker 					return -1;
3188*2d543d20SAndroid Build Coastguard Worker 				}
3189*2d543d20SAndroid Build Coastguard Worker 				memset(tr, 0, sizeof(struct role_trans));
3190*2d543d20SAndroid Build Coastguard Worker 				tr->role = i + 1;
3191*2d543d20SAndroid Build Coastguard Worker 				tr->type = j + 1;
3192*2d543d20SAndroid Build Coastguard Worker 				tr->tclass = k + 1;
3193*2d543d20SAndroid Build Coastguard Worker 				tr->new_role = role->s.value;
3194*2d543d20SAndroid Build Coastguard Worker 				tr->next = policydbp->role_tr;
3195*2d543d20SAndroid Build Coastguard Worker 				policydbp->role_tr = tr;
3196*2d543d20SAndroid Build Coastguard Worker 			}
3197*2d543d20SAndroid Build Coastguard Worker 		}
3198*2d543d20SAndroid Build Coastguard Worker 	}
3199*2d543d20SAndroid Build Coastguard Worker 	/* Now add the real rule */
3200*2d543d20SAndroid Build Coastguard Worker 	rule = malloc(sizeof(struct role_trans_rule));
3201*2d543d20SAndroid Build Coastguard Worker 	if (!rule) {
3202*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
3203*2d543d20SAndroid Build Coastguard Worker 		return -1;
3204*2d543d20SAndroid Build Coastguard Worker 	}
3205*2d543d20SAndroid Build Coastguard Worker 	memset(rule, 0, sizeof(struct role_trans_rule));
3206*2d543d20SAndroid Build Coastguard Worker 	rule->roles = roles;
3207*2d543d20SAndroid Build Coastguard Worker 	rule->types = types;
3208*2d543d20SAndroid Build Coastguard Worker 	rule->classes = e_classes;
3209*2d543d20SAndroid Build Coastguard Worker 	rule->new_role = role->s.value;
3210*2d543d20SAndroid Build Coastguard Worker 
3211*2d543d20SAndroid Build Coastguard Worker 	append_role_trans(rule);
3212*2d543d20SAndroid Build Coastguard Worker 
3213*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_roles);
3214*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_types);
3215*2d543d20SAndroid Build Coastguard Worker 
3216*2d543d20SAndroid Build Coastguard Worker 	return 0;
3217*2d543d20SAndroid Build Coastguard Worker 
3218*2d543d20SAndroid Build Coastguard Worker       bad:
3219*2d543d20SAndroid Build Coastguard Worker 	return -1;
3220*2d543d20SAndroid Build Coastguard Worker }
3221*2d543d20SAndroid Build Coastguard Worker 
define_role_allow(void)3222*2d543d20SAndroid Build Coastguard Worker int define_role_allow(void)
3223*2d543d20SAndroid Build Coastguard Worker {
3224*2d543d20SAndroid Build Coastguard Worker 	char *id;
3225*2d543d20SAndroid Build Coastguard Worker 	struct role_allow_rule *ra = 0;
3226*2d543d20SAndroid Build Coastguard Worker 
3227*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3228*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3229*2d543d20SAndroid Build Coastguard Worker 			free(id);
3230*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3231*2d543d20SAndroid Build Coastguard Worker 			free(id);
3232*2d543d20SAndroid Build Coastguard Worker 		return 0;
3233*2d543d20SAndroid Build Coastguard Worker 	}
3234*2d543d20SAndroid Build Coastguard Worker 
3235*2d543d20SAndroid Build Coastguard Worker 	ra = malloc(sizeof(role_allow_rule_t));
3236*2d543d20SAndroid Build Coastguard Worker 	if (!ra) {
3237*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
3238*2d543d20SAndroid Build Coastguard Worker 		return -1;
3239*2d543d20SAndroid Build Coastguard Worker 	}
3240*2d543d20SAndroid Build Coastguard Worker 	role_allow_rule_init(ra);
3241*2d543d20SAndroid Build Coastguard Worker 
3242*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3243*2d543d20SAndroid Build Coastguard Worker 		if (set_roles(&ra->roles, id)) {
3244*2d543d20SAndroid Build Coastguard Worker 			role_allow_rule_destroy(ra);
3245*2d543d20SAndroid Build Coastguard Worker 			free(ra);
3246*2d543d20SAndroid Build Coastguard Worker 			return -1;
3247*2d543d20SAndroid Build Coastguard Worker 		}
3248*2d543d20SAndroid Build Coastguard Worker 	}
3249*2d543d20SAndroid Build Coastguard Worker 
3250*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3251*2d543d20SAndroid Build Coastguard Worker 		if (set_roles(&ra->new_roles, id)) {
3252*2d543d20SAndroid Build Coastguard Worker 			role_allow_rule_destroy(ra);
3253*2d543d20SAndroid Build Coastguard Worker 			free(ra);
3254*2d543d20SAndroid Build Coastguard Worker 			return -1;
3255*2d543d20SAndroid Build Coastguard Worker 		}
3256*2d543d20SAndroid Build Coastguard Worker 	}
3257*2d543d20SAndroid Build Coastguard Worker 
3258*2d543d20SAndroid Build Coastguard Worker 	append_role_allow(ra);
3259*2d543d20SAndroid Build Coastguard Worker 	return 0;
3260*2d543d20SAndroid Build Coastguard Worker }
3261*2d543d20SAndroid Build Coastguard Worker 
define_cond_filename_trans(void)3262*2d543d20SAndroid Build Coastguard Worker avrule_t *define_cond_filename_trans(void)
3263*2d543d20SAndroid Build Coastguard Worker {
3264*2d543d20SAndroid Build Coastguard Worker 	yyerror("type transitions with a filename not allowed inside "
3265*2d543d20SAndroid Build Coastguard Worker 		"conditionals");
3266*2d543d20SAndroid Build Coastguard Worker 	return COND_ERR;
3267*2d543d20SAndroid Build Coastguard Worker }
3268*2d543d20SAndroid Build Coastguard Worker 
define_filename_trans(void)3269*2d543d20SAndroid Build Coastguard Worker int define_filename_trans(void)
3270*2d543d20SAndroid Build Coastguard Worker {
3271*2d543d20SAndroid Build Coastguard Worker 	char *id, *name = NULL;
3272*2d543d20SAndroid Build Coastguard Worker 	type_set_t stypes, ttypes;
3273*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e_stypes, e_ttypes;
3274*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t e_tclasses;
3275*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *snode, *tnode, *cnode;
3276*2d543d20SAndroid Build Coastguard Worker 	filename_trans_rule_t *ftr;
3277*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *typdatum;
3278*2d543d20SAndroid Build Coastguard Worker 	uint32_t otype;
3279*2d543d20SAndroid Build Coastguard Worker 	unsigned int c, s, t;
3280*2d543d20SAndroid Build Coastguard Worker 	int add, self, rc;
3281*2d543d20SAndroid Build Coastguard Worker 
3282*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3283*2d543d20SAndroid Build Coastguard Worker 		/* stype */
3284*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3285*2d543d20SAndroid Build Coastguard Worker 			free(id);
3286*2d543d20SAndroid Build Coastguard Worker 		/* ttype */
3287*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3288*2d543d20SAndroid Build Coastguard Worker 			free(id);
3289*2d543d20SAndroid Build Coastguard Worker 		/* tclass */
3290*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3291*2d543d20SAndroid Build Coastguard Worker 			free(id);
3292*2d543d20SAndroid Build Coastguard Worker 		/* otype */
3293*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
3294*2d543d20SAndroid Build Coastguard Worker 		free(id);
3295*2d543d20SAndroid Build Coastguard Worker 		/* name */
3296*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
3297*2d543d20SAndroid Build Coastguard Worker 		free(id);
3298*2d543d20SAndroid Build Coastguard Worker 		return 0;
3299*2d543d20SAndroid Build Coastguard Worker 	}
3300*2d543d20SAndroid Build Coastguard Worker 
3301*2d543d20SAndroid Build Coastguard Worker 	type_set_init(&stypes);
3302*2d543d20SAndroid Build Coastguard Worker 	type_set_init(&ttypes);
3303*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_stypes);
3304*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_ttypes);
3305*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&e_tclasses);
3306*2d543d20SAndroid Build Coastguard Worker 
3307*2d543d20SAndroid Build Coastguard Worker 	add = 1;
3308*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3309*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&stypes, id, &add, 0))
3310*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3311*2d543d20SAndroid Build Coastguard Worker 	}
3312*2d543d20SAndroid Build Coastguard Worker 
3313*2d543d20SAndroid Build Coastguard Worker 	self = 0;
3314*2d543d20SAndroid Build Coastguard Worker 	add = 1;
3315*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3316*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(id, "self") == 0) {
3317*2d543d20SAndroid Build Coastguard Worker 			free(id);
3318*2d543d20SAndroid Build Coastguard Worker 			if (add == 0) {
3319*2d543d20SAndroid Build Coastguard Worker 				yyerror("-self is not supported");
3320*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3321*2d543d20SAndroid Build Coastguard Worker 			}
3322*2d543d20SAndroid Build Coastguard Worker 			self = 1;
3323*2d543d20SAndroid Build Coastguard Worker 			continue;
3324*2d543d20SAndroid Build Coastguard Worker 		}
3325*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&ttypes, id, &add, 0))
3326*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3327*2d543d20SAndroid Build Coastguard Worker 	}
3328*2d543d20SAndroid Build Coastguard Worker 
3329*2d543d20SAndroid Build Coastguard Worker 	if (read_classes(&e_tclasses))
3330*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3331*2d543d20SAndroid Build Coastguard Worker 
3332*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
3333*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
3334*2d543d20SAndroid Build Coastguard Worker 		yyerror("no otype in transition definition?");
3335*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3336*2d543d20SAndroid Build Coastguard Worker 	}
3337*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
3338*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
3339*2d543d20SAndroid Build Coastguard Worker 		free(id);
3340*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3341*2d543d20SAndroid Build Coastguard Worker 	}
3342*2d543d20SAndroid Build Coastguard Worker 	typdatum = hashtab_search(policydbp->p_types.table, id);
3343*2d543d20SAndroid Build Coastguard Worker 	if (!typdatum) {
3344*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown type %s used in transition definition", id);
3345*2d543d20SAndroid Build Coastguard Worker 		free(id);
3346*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3347*2d543d20SAndroid Build Coastguard Worker 	}
3348*2d543d20SAndroid Build Coastguard Worker 	free(id);
3349*2d543d20SAndroid Build Coastguard Worker 	otype = typdatum->s.value;
3350*2d543d20SAndroid Build Coastguard Worker 
3351*2d543d20SAndroid Build Coastguard Worker 	name = queue_remove(id_queue);
3352*2d543d20SAndroid Build Coastguard Worker 	if (!name) {
3353*2d543d20SAndroid Build Coastguard Worker 		yyerror("no pathname specified in filename_trans definition?");
3354*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3355*2d543d20SAndroid Build Coastguard Worker 	}
3356*2d543d20SAndroid Build Coastguard Worker 
3357*2d543d20SAndroid Build Coastguard Worker 	/* We expand the class set into separate rules.  We expand the types
3358*2d543d20SAndroid Build Coastguard Worker 	 * just to make sure there are not duplicates.  They will get turned
3359*2d543d20SAndroid Build Coastguard Worker 	 * into separate rules later */
3360*2d543d20SAndroid Build Coastguard Worker 	if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
3361*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3362*2d543d20SAndroid Build Coastguard Worker 
3363*2d543d20SAndroid Build Coastguard Worker 	if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
3364*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3365*2d543d20SAndroid Build Coastguard Worker 
3366*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&e_tclasses, cnode, c) {
3367*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&e_stypes, snode, s) {
3368*2d543d20SAndroid Build Coastguard Worker 			ebitmap_for_each_positive_bit(&e_ttypes, tnode, t) {
3369*2d543d20SAndroid Build Coastguard Worker 				rc = policydb_filetrans_insert(
3370*2d543d20SAndroid Build Coastguard Worker 					policydbp, s+1, t+1, c+1, name,
3371*2d543d20SAndroid Build Coastguard Worker 					NULL, otype, NULL
3372*2d543d20SAndroid Build Coastguard Worker 				);
3373*2d543d20SAndroid Build Coastguard Worker 				if (rc != SEPOL_OK) {
3374*2d543d20SAndroid Build Coastguard Worker 					if (rc == SEPOL_EEXIST) {
3375*2d543d20SAndroid Build Coastguard Worker 						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
3376*2d543d20SAndroid Build Coastguard Worker 							name,
3377*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_type_val_to_name[s],
3378*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_type_val_to_name[t],
3379*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_class_val_to_name[c]);
3380*2d543d20SAndroid Build Coastguard Worker 						goto bad;
3381*2d543d20SAndroid Build Coastguard Worker 					}
3382*2d543d20SAndroid Build Coastguard Worker 					yyerror("out of memory");
3383*2d543d20SAndroid Build Coastguard Worker 					goto bad;
3384*2d543d20SAndroid Build Coastguard Worker 				}
3385*2d543d20SAndroid Build Coastguard Worker 			}
3386*2d543d20SAndroid Build Coastguard Worker 			if (self) {
3387*2d543d20SAndroid Build Coastguard Worker 				rc = policydb_filetrans_insert(
3388*2d543d20SAndroid Build Coastguard Worker 					policydbp, s+1, s+1, c+1, name,
3389*2d543d20SAndroid Build Coastguard Worker 					NULL, otype, NULL
3390*2d543d20SAndroid Build Coastguard Worker 				);
3391*2d543d20SAndroid Build Coastguard Worker 				if (rc != SEPOL_OK) {
3392*2d543d20SAndroid Build Coastguard Worker 					if (rc == SEPOL_EEXIST) {
3393*2d543d20SAndroid Build Coastguard Worker 						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
3394*2d543d20SAndroid Build Coastguard Worker 							name,
3395*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_type_val_to_name[s],
3396*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_type_val_to_name[s],
3397*2d543d20SAndroid Build Coastguard Worker 							policydbp->p_class_val_to_name[c]);
3398*2d543d20SAndroid Build Coastguard Worker 						goto bad;
3399*2d543d20SAndroid Build Coastguard Worker 					}
3400*2d543d20SAndroid Build Coastguard Worker 					yyerror("out of memory");
3401*2d543d20SAndroid Build Coastguard Worker 					goto bad;
3402*2d543d20SAndroid Build Coastguard Worker 				}
3403*2d543d20SAndroid Build Coastguard Worker 			}
3404*2d543d20SAndroid Build Coastguard Worker 		}
3405*2d543d20SAndroid Build Coastguard Worker 
3406*2d543d20SAndroid Build Coastguard Worker 		/* Now add the real rule since we didn't find any duplicates */
3407*2d543d20SAndroid Build Coastguard Worker 		ftr = malloc(sizeof(*ftr));
3408*2d543d20SAndroid Build Coastguard Worker 		if (!ftr) {
3409*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3410*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3411*2d543d20SAndroid Build Coastguard Worker 		}
3412*2d543d20SAndroid Build Coastguard Worker 		filename_trans_rule_init(ftr);
3413*2d543d20SAndroid Build Coastguard Worker 		append_filename_trans(ftr);
3414*2d543d20SAndroid Build Coastguard Worker 
3415*2d543d20SAndroid Build Coastguard Worker 		ftr->name = strdup(name);
3416*2d543d20SAndroid Build Coastguard Worker 		if (type_set_cpy(&ftr->stypes, &stypes)) {
3417*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3418*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3419*2d543d20SAndroid Build Coastguard Worker 		}
3420*2d543d20SAndroid Build Coastguard Worker 		if (type_set_cpy(&ftr->ttypes, &ttypes)) {
3421*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3422*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3423*2d543d20SAndroid Build Coastguard Worker 		}
3424*2d543d20SAndroid Build Coastguard Worker 		ftr->tclass = c + 1;
3425*2d543d20SAndroid Build Coastguard Worker 		ftr->otype = otype;
3426*2d543d20SAndroid Build Coastguard Worker 		ftr->flags = self ? RULE_SELF : 0;
3427*2d543d20SAndroid Build Coastguard Worker 	}
3428*2d543d20SAndroid Build Coastguard Worker 
3429*2d543d20SAndroid Build Coastguard Worker 	free(name);
3430*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_stypes);
3431*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_ttypes);
3432*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tclasses);
3433*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&stypes);
3434*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&ttypes);
3435*2d543d20SAndroid Build Coastguard Worker 
3436*2d543d20SAndroid Build Coastguard Worker 	return 0;
3437*2d543d20SAndroid Build Coastguard Worker 
3438*2d543d20SAndroid Build Coastguard Worker bad:
3439*2d543d20SAndroid Build Coastguard Worker 	free(name);
3440*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_stypes);
3441*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_ttypes);
3442*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&e_tclasses);
3443*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&stypes);
3444*2d543d20SAndroid Build Coastguard Worker 	type_set_destroy(&ttypes);
3445*2d543d20SAndroid Build Coastguard Worker 	return -1;
3446*2d543d20SAndroid Build Coastguard Worker }
3447*2d543d20SAndroid Build Coastguard Worker 
constraint_expr_clone(const constraint_expr_t * expr)3448*2d543d20SAndroid Build Coastguard Worker static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
3449*2d543d20SAndroid Build Coastguard Worker {
3450*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *h = NULL, *l = NULL, *newe;
3451*2d543d20SAndroid Build Coastguard Worker 	const constraint_expr_t *e;
3452*2d543d20SAndroid Build Coastguard Worker 	for (e = expr; e; e = e->next) {
3453*2d543d20SAndroid Build Coastguard Worker 		newe = malloc(sizeof(*newe));
3454*2d543d20SAndroid Build Coastguard Worker 		if (!newe)
3455*2d543d20SAndroid Build Coastguard Worker 			goto oom;
3456*2d543d20SAndroid Build Coastguard Worker 		if (constraint_expr_init(newe) == -1) {
3457*2d543d20SAndroid Build Coastguard Worker 			free(newe);
3458*2d543d20SAndroid Build Coastguard Worker 			goto oom;
3459*2d543d20SAndroid Build Coastguard Worker 		}
3460*2d543d20SAndroid Build Coastguard Worker 		if (l)
3461*2d543d20SAndroid Build Coastguard Worker 			l->next = newe;
3462*2d543d20SAndroid Build Coastguard Worker 		else
3463*2d543d20SAndroid Build Coastguard Worker 			h = newe;
3464*2d543d20SAndroid Build Coastguard Worker 		l = newe;
3465*2d543d20SAndroid Build Coastguard Worker 		newe->expr_type = e->expr_type;
3466*2d543d20SAndroid Build Coastguard Worker 		newe->attr = e->attr;
3467*2d543d20SAndroid Build Coastguard Worker 		newe->op = e->op;
3468*2d543d20SAndroid Build Coastguard Worker 		if (newe->expr_type == CEXPR_NAMES) {
3469*2d543d20SAndroid Build Coastguard Worker 			if (newe->attr & CEXPR_TYPE) {
3470*2d543d20SAndroid Build Coastguard Worker 				if (type_set_cpy
3471*2d543d20SAndroid Build Coastguard Worker 				    (newe->type_names, e->type_names))
3472*2d543d20SAndroid Build Coastguard Worker 					goto oom;
3473*2d543d20SAndroid Build Coastguard Worker 			} else {
3474*2d543d20SAndroid Build Coastguard Worker 				if (ebitmap_cpy(&newe->names, &e->names))
3475*2d543d20SAndroid Build Coastguard Worker 					goto oom;
3476*2d543d20SAndroid Build Coastguard Worker 			}
3477*2d543d20SAndroid Build Coastguard Worker 		}
3478*2d543d20SAndroid Build Coastguard Worker 	}
3479*2d543d20SAndroid Build Coastguard Worker 
3480*2d543d20SAndroid Build Coastguard Worker 	return h;
3481*2d543d20SAndroid Build Coastguard Worker       oom:
3482*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_destroy(h);
3483*2d543d20SAndroid Build Coastguard Worker 	return NULL;
3484*2d543d20SAndroid Build Coastguard Worker }
3485*2d543d20SAndroid Build Coastguard Worker 
define_constraint(constraint_expr_t * expr)3486*2d543d20SAndroid Build Coastguard Worker int define_constraint(constraint_expr_t * expr)
3487*2d543d20SAndroid Build Coastguard Worker {
3488*2d543d20SAndroid Build Coastguard Worker 	struct constraint_node *node;
3489*2d543d20SAndroid Build Coastguard Worker 	char *id;
3490*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
3491*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum;
3492*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t classmap;
3493*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *enode;
3494*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *e;
3495*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
3496*2d543d20SAndroid Build Coastguard Worker 	int depth;
3497*2d543d20SAndroid Build Coastguard Worker 	unsigned char useexpr = 1;
3498*2d543d20SAndroid Build Coastguard Worker 
3499*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3500*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3501*2d543d20SAndroid Build Coastguard Worker 			free(id);
3502*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3503*2d543d20SAndroid Build Coastguard Worker 			free(id);
3504*2d543d20SAndroid Build Coastguard Worker 		return 0;
3505*2d543d20SAndroid Build Coastguard Worker 	}
3506*2d543d20SAndroid Build Coastguard Worker 
3507*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&classmap);
3508*2d543d20SAndroid Build Coastguard Worker 
3509*2d543d20SAndroid Build Coastguard Worker 	depth = -1;
3510*2d543d20SAndroid Build Coastguard Worker 	for (e = expr; e; e = e->next) {
3511*2d543d20SAndroid Build Coastguard Worker 		switch (e->expr_type) {
3512*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NOT:
3513*2d543d20SAndroid Build Coastguard Worker 			if (depth < 0) {
3514*2d543d20SAndroid Build Coastguard Worker 				yyerror("illegal constraint expression");
3515*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3516*2d543d20SAndroid Build Coastguard Worker 			}
3517*2d543d20SAndroid Build Coastguard Worker 			break;
3518*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_AND:
3519*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_OR:
3520*2d543d20SAndroid Build Coastguard Worker 			if (depth < 1) {
3521*2d543d20SAndroid Build Coastguard Worker 				yyerror("illegal constraint expression");
3522*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3523*2d543d20SAndroid Build Coastguard Worker 			}
3524*2d543d20SAndroid Build Coastguard Worker 			depth--;
3525*2d543d20SAndroid Build Coastguard Worker 			break;
3526*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_ATTR:
3527*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NAMES:
3528*2d543d20SAndroid Build Coastguard Worker 			if (e->attr & CEXPR_XTARGET) {
3529*2d543d20SAndroid Build Coastguard Worker 				yyerror("illegal constraint expression");
3530*2d543d20SAndroid Build Coastguard Worker 				goto bad;	/* only for validatetrans rules */
3531*2d543d20SAndroid Build Coastguard Worker 			}
3532*2d543d20SAndroid Build Coastguard Worker 			if (depth == (CEXPR_MAXDEPTH - 1)) {
3533*2d543d20SAndroid Build Coastguard Worker 				yyerror("constraint expression is too deep");
3534*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3535*2d543d20SAndroid Build Coastguard Worker 			}
3536*2d543d20SAndroid Build Coastguard Worker 			depth++;
3537*2d543d20SAndroid Build Coastguard Worker 			break;
3538*2d543d20SAndroid Build Coastguard Worker 		default:
3539*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal constraint expression");
3540*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3541*2d543d20SAndroid Build Coastguard Worker 		}
3542*2d543d20SAndroid Build Coastguard Worker 	}
3543*2d543d20SAndroid Build Coastguard Worker 	if (depth != 0) {
3544*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal constraint expression");
3545*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3546*2d543d20SAndroid Build Coastguard Worker 	}
3547*2d543d20SAndroid Build Coastguard Worker 
3548*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3549*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
3550*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
3551*2d543d20SAndroid Build Coastguard Worker 			free(id);
3552*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3553*2d543d20SAndroid Build Coastguard Worker 		}
3554*2d543d20SAndroid Build Coastguard Worker 		cladatum =
3555*2d543d20SAndroid Build Coastguard Worker 		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
3556*2d543d20SAndroid Build Coastguard Worker 						     (hashtab_key_t) id);
3557*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
3558*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not defined", id);
3559*2d543d20SAndroid Build Coastguard Worker 			free(id);
3560*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3561*2d543d20SAndroid Build Coastguard Worker 		}
3562*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) {
3563*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3564*2d543d20SAndroid Build Coastguard Worker 			free(id);
3565*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3566*2d543d20SAndroid Build Coastguard Worker 		}
3567*2d543d20SAndroid Build Coastguard Worker 		node = malloc(sizeof(struct constraint_node));
3568*2d543d20SAndroid Build Coastguard Worker 		if (!node) {
3569*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3570*2d543d20SAndroid Build Coastguard Worker 			free(node);
3571*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3572*2d543d20SAndroid Build Coastguard Worker 		}
3573*2d543d20SAndroid Build Coastguard Worker 		memset(node, 0, sizeof(constraint_node_t));
3574*2d543d20SAndroid Build Coastguard Worker 		if (useexpr) {
3575*2d543d20SAndroid Build Coastguard Worker 			node->expr = expr;
3576*2d543d20SAndroid Build Coastguard Worker 			useexpr = 0;
3577*2d543d20SAndroid Build Coastguard Worker 		} else {
3578*2d543d20SAndroid Build Coastguard Worker 			node->expr = constraint_expr_clone(expr);
3579*2d543d20SAndroid Build Coastguard Worker 		}
3580*2d543d20SAndroid Build Coastguard Worker 		if (!node->expr) {
3581*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3582*2d543d20SAndroid Build Coastguard Worker 			free(node);
3583*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3584*2d543d20SAndroid Build Coastguard Worker 		}
3585*2d543d20SAndroid Build Coastguard Worker 		node->permissions = 0;
3586*2d543d20SAndroid Build Coastguard Worker 
3587*2d543d20SAndroid Build Coastguard Worker 		node->next = cladatum->constraints;
3588*2d543d20SAndroid Build Coastguard Worker 		cladatum->constraints = node;
3589*2d543d20SAndroid Build Coastguard Worker 
3590*2d543d20SAndroid Build Coastguard Worker 		free(id);
3591*2d543d20SAndroid Build Coastguard Worker 	}
3592*2d543d20SAndroid Build Coastguard Worker 
3593*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3594*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&classmap, enode, i) {
3595*2d543d20SAndroid Build Coastguard Worker 			cladatum = policydbp->class_val_to_struct[i];
3596*2d543d20SAndroid Build Coastguard Worker 			node = cladatum->constraints;
3597*2d543d20SAndroid Build Coastguard Worker 
3598*2d543d20SAndroid Build Coastguard Worker 			if (strcmp(id, "*") == 0) {
3599*2d543d20SAndroid Build Coastguard Worker 				node->permissions = PERMISSION_MASK(cladatum->permissions.nprim);
3600*2d543d20SAndroid Build Coastguard Worker 				continue;
3601*2d543d20SAndroid Build Coastguard Worker 			}
3602*2d543d20SAndroid Build Coastguard Worker 
3603*2d543d20SAndroid Build Coastguard Worker 			if (strcmp(id, "~") == 0) {
3604*2d543d20SAndroid Build Coastguard Worker 				node->permissions = ~node->permissions & PERMISSION_MASK(cladatum->permissions.nprim);
3605*2d543d20SAndroid Build Coastguard Worker 				if (node->permissions == 0) {
3606*2d543d20SAndroid Build Coastguard Worker 					yywarn("omitting constraint with no permission set");
3607*2d543d20SAndroid Build Coastguard Worker 					cladatum->constraints = node->next;
3608*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(node->expr);
3609*2d543d20SAndroid Build Coastguard Worker 					free(node);
3610*2d543d20SAndroid Build Coastguard Worker 				}
3611*2d543d20SAndroid Build Coastguard Worker 				continue;
3612*2d543d20SAndroid Build Coastguard Worker 			}
3613*2d543d20SAndroid Build Coastguard Worker 
3614*2d543d20SAndroid Build Coastguard Worker 			perdatum =
3615*2d543d20SAndroid Build Coastguard Worker 			    (perm_datum_t *) hashtab_search(cladatum->
3616*2d543d20SAndroid Build Coastguard Worker 							    permissions.
3617*2d543d20SAndroid Build Coastguard Worker 							    table,
3618*2d543d20SAndroid Build Coastguard Worker 							    (hashtab_key_t)
3619*2d543d20SAndroid Build Coastguard Worker 							    id);
3620*2d543d20SAndroid Build Coastguard Worker 			if (!perdatum) {
3621*2d543d20SAndroid Build Coastguard Worker 				if (cladatum->comdatum) {
3622*2d543d20SAndroid Build Coastguard Worker 					perdatum =
3623*2d543d20SAndroid Build Coastguard Worker 					    (perm_datum_t *)
3624*2d543d20SAndroid Build Coastguard Worker 					    hashtab_search(cladatum->
3625*2d543d20SAndroid Build Coastguard Worker 							   comdatum->
3626*2d543d20SAndroid Build Coastguard Worker 							   permissions.
3627*2d543d20SAndroid Build Coastguard Worker 							   table,
3628*2d543d20SAndroid Build Coastguard Worker 							   (hashtab_key_t)
3629*2d543d20SAndroid Build Coastguard Worker 							   id);
3630*2d543d20SAndroid Build Coastguard Worker 				}
3631*2d543d20SAndroid Build Coastguard Worker 				if (!perdatum) {
3632*2d543d20SAndroid Build Coastguard Worker 					yyerror2("permission %s is not"
3633*2d543d20SAndroid Build Coastguard Worker 						 " defined for class %s", id, policydbp->p_class_val_to_name[i]);
3634*2d543d20SAndroid Build Coastguard Worker 					free(id);
3635*2d543d20SAndroid Build Coastguard Worker 					goto bad;
3636*2d543d20SAndroid Build Coastguard Worker 				}
3637*2d543d20SAndroid Build Coastguard Worker 			}
3638*2d543d20SAndroid Build Coastguard Worker 			node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1));
3639*2d543d20SAndroid Build Coastguard Worker 		}
3640*2d543d20SAndroid Build Coastguard Worker 		free(id);
3641*2d543d20SAndroid Build Coastguard Worker 	}
3642*2d543d20SAndroid Build Coastguard Worker 
3643*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&classmap);
3644*2d543d20SAndroid Build Coastguard Worker 
3645*2d543d20SAndroid Build Coastguard Worker 	return 0;
3646*2d543d20SAndroid Build Coastguard Worker 
3647*2d543d20SAndroid Build Coastguard Worker bad:
3648*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&classmap);
3649*2d543d20SAndroid Build Coastguard Worker 	if (useexpr)
3650*2d543d20SAndroid Build Coastguard Worker 		constraint_expr_destroy(expr);
3651*2d543d20SAndroid Build Coastguard Worker 
3652*2d543d20SAndroid Build Coastguard Worker 	return -1;
3653*2d543d20SAndroid Build Coastguard Worker }
3654*2d543d20SAndroid Build Coastguard Worker 
define_validatetrans(constraint_expr_t * expr)3655*2d543d20SAndroid Build Coastguard Worker int define_validatetrans(constraint_expr_t * expr)
3656*2d543d20SAndroid Build Coastguard Worker {
3657*2d543d20SAndroid Build Coastguard Worker 	struct constraint_node *node;
3658*2d543d20SAndroid Build Coastguard Worker 	char *id;
3659*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
3660*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t classmap;
3661*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *e;
3662*2d543d20SAndroid Build Coastguard Worker 	int depth;
3663*2d543d20SAndroid Build Coastguard Worker 	unsigned char useexpr = 1;
3664*2d543d20SAndroid Build Coastguard Worker 
3665*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3666*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
3667*2d543d20SAndroid Build Coastguard Worker 			free(id);
3668*2d543d20SAndroid Build Coastguard Worker 		return 0;
3669*2d543d20SAndroid Build Coastguard Worker 	}
3670*2d543d20SAndroid Build Coastguard Worker 
3671*2d543d20SAndroid Build Coastguard Worker 	ebitmap_init(&classmap);
3672*2d543d20SAndroid Build Coastguard Worker 
3673*2d543d20SAndroid Build Coastguard Worker 	depth = -1;
3674*2d543d20SAndroid Build Coastguard Worker 	for (e = expr; e; e = e->next) {
3675*2d543d20SAndroid Build Coastguard Worker 		switch (e->expr_type) {
3676*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NOT:
3677*2d543d20SAndroid Build Coastguard Worker 			if (depth < 0) {
3678*2d543d20SAndroid Build Coastguard Worker 				yyerror("illegal validatetrans expression");
3679*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3680*2d543d20SAndroid Build Coastguard Worker 			}
3681*2d543d20SAndroid Build Coastguard Worker 			break;
3682*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_AND:
3683*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_OR:
3684*2d543d20SAndroid Build Coastguard Worker 			if (depth < 1) {
3685*2d543d20SAndroid Build Coastguard Worker 				yyerror("illegal validatetrans expression");
3686*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3687*2d543d20SAndroid Build Coastguard Worker 			}
3688*2d543d20SAndroid Build Coastguard Worker 			depth--;
3689*2d543d20SAndroid Build Coastguard Worker 			break;
3690*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_ATTR:
3691*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NAMES:
3692*2d543d20SAndroid Build Coastguard Worker 			if (depth == (CEXPR_MAXDEPTH - 1)) {
3693*2d543d20SAndroid Build Coastguard Worker 				yyerror("validatetrans expression is too deep");
3694*2d543d20SAndroid Build Coastguard Worker 				goto bad;
3695*2d543d20SAndroid Build Coastguard Worker 			}
3696*2d543d20SAndroid Build Coastguard Worker 			depth++;
3697*2d543d20SAndroid Build Coastguard Worker 			break;
3698*2d543d20SAndroid Build Coastguard Worker 		default:
3699*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal validatetrans expression");
3700*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3701*2d543d20SAndroid Build Coastguard Worker 		}
3702*2d543d20SAndroid Build Coastguard Worker 	}
3703*2d543d20SAndroid Build Coastguard Worker 	if (depth != 0) {
3704*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal validatetrans expression");
3705*2d543d20SAndroid Build Coastguard Worker 		goto bad;
3706*2d543d20SAndroid Build Coastguard Worker 	}
3707*2d543d20SAndroid Build Coastguard Worker 
3708*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
3709*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_CLASSES, id)) {
3710*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not within scope", id);
3711*2d543d20SAndroid Build Coastguard Worker 			free(id);
3712*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3713*2d543d20SAndroid Build Coastguard Worker 		}
3714*2d543d20SAndroid Build Coastguard Worker 		cladatum =
3715*2d543d20SAndroid Build Coastguard Worker 		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
3716*2d543d20SAndroid Build Coastguard Worker 						     (hashtab_key_t) id);
3717*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
3718*2d543d20SAndroid Build Coastguard Worker 			yyerror2("class %s is not defined", id);
3719*2d543d20SAndroid Build Coastguard Worker 			free(id);
3720*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3721*2d543d20SAndroid Build Coastguard Worker 		}
3722*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) {
3723*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3724*2d543d20SAndroid Build Coastguard Worker 			free(id);
3725*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3726*2d543d20SAndroid Build Coastguard Worker 		}
3727*2d543d20SAndroid Build Coastguard Worker 
3728*2d543d20SAndroid Build Coastguard Worker 		node = malloc(sizeof(struct constraint_node));
3729*2d543d20SAndroid Build Coastguard Worker 		if (!node) {
3730*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
3731*2d543d20SAndroid Build Coastguard Worker 			free(id);
3732*2d543d20SAndroid Build Coastguard Worker 			goto bad;
3733*2d543d20SAndroid Build Coastguard Worker 		}
3734*2d543d20SAndroid Build Coastguard Worker 		memset(node, 0, sizeof(constraint_node_t));
3735*2d543d20SAndroid Build Coastguard Worker 		if (useexpr) {
3736*2d543d20SAndroid Build Coastguard Worker 			node->expr = expr;
3737*2d543d20SAndroid Build Coastguard Worker 			useexpr = 0;
3738*2d543d20SAndroid Build Coastguard Worker 		} else {
3739*2d543d20SAndroid Build Coastguard Worker 			node->expr = constraint_expr_clone(expr);
3740*2d543d20SAndroid Build Coastguard Worker 		}
3741*2d543d20SAndroid Build Coastguard Worker 		node->permissions = 0;
3742*2d543d20SAndroid Build Coastguard Worker 
3743*2d543d20SAndroid Build Coastguard Worker 		node->next = cladatum->validatetrans;
3744*2d543d20SAndroid Build Coastguard Worker 		cladatum->validatetrans = node;
3745*2d543d20SAndroid Build Coastguard Worker 
3746*2d543d20SAndroid Build Coastguard Worker 		free(id);
3747*2d543d20SAndroid Build Coastguard Worker 	}
3748*2d543d20SAndroid Build Coastguard Worker 
3749*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&classmap);
3750*2d543d20SAndroid Build Coastguard Worker 
3751*2d543d20SAndroid Build Coastguard Worker 	return 0;
3752*2d543d20SAndroid Build Coastguard Worker 
3753*2d543d20SAndroid Build Coastguard Worker bad:
3754*2d543d20SAndroid Build Coastguard Worker 	ebitmap_destroy(&classmap);
3755*2d543d20SAndroid Build Coastguard Worker 	if (useexpr)
3756*2d543d20SAndroid Build Coastguard Worker 		constraint_expr_destroy(expr);
3757*2d543d20SAndroid Build Coastguard Worker 
3758*2d543d20SAndroid Build Coastguard Worker 	return -1;
3759*2d543d20SAndroid Build Coastguard Worker }
3760*2d543d20SAndroid Build Coastguard Worker 
define_cexpr(uint32_t expr_type,uintptr_t arg1,uintptr_t arg2)3761*2d543d20SAndroid Build Coastguard Worker uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2)
3762*2d543d20SAndroid Build Coastguard Worker {
3763*2d543d20SAndroid Build Coastguard Worker 	struct constraint_expr *expr, *e1 = NULL, *e2;
3764*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *user;
3765*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
3766*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t negset;
3767*2d543d20SAndroid Build Coastguard Worker 	char *id;
3768*2d543d20SAndroid Build Coastguard Worker 	uint32_t val;
3769*2d543d20SAndroid Build Coastguard Worker 	int add = 1;
3770*2d543d20SAndroid Build Coastguard Worker 
3771*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
3772*2d543d20SAndroid Build Coastguard Worker 		if (expr_type == CEXPR_NAMES) {
3773*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
3774*2d543d20SAndroid Build Coastguard Worker 				free(id);
3775*2d543d20SAndroid Build Coastguard Worker 		}
3776*2d543d20SAndroid Build Coastguard Worker 		return 1;	/* any non-NULL value */
3777*2d543d20SAndroid Build Coastguard Worker 	}
3778*2d543d20SAndroid Build Coastguard Worker 
3779*2d543d20SAndroid Build Coastguard Worker 	if ((expr = malloc(sizeof(*expr))) == NULL ||
3780*2d543d20SAndroid Build Coastguard Worker 	    constraint_expr_init(expr) == -1) {
3781*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
3782*2d543d20SAndroid Build Coastguard Worker 		free(expr);
3783*2d543d20SAndroid Build Coastguard Worker 		return 0;
3784*2d543d20SAndroid Build Coastguard Worker 	}
3785*2d543d20SAndroid Build Coastguard Worker 	expr->expr_type = expr_type;
3786*2d543d20SAndroid Build Coastguard Worker 
3787*2d543d20SAndroid Build Coastguard Worker 	switch (expr_type) {
3788*2d543d20SAndroid Build Coastguard Worker 	case CEXPR_NOT:
3789*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
3790*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct constraint_expr *)arg1;
3791*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
3792*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
3793*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
3794*2d543d20SAndroid Build Coastguard Worker 		}
3795*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
3796*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal constraint expression");
3797*2d543d20SAndroid Build Coastguard Worker 			constraint_expr_destroy(expr);
3798*2d543d20SAndroid Build Coastguard Worker 			return 0;
3799*2d543d20SAndroid Build Coastguard Worker 		}
3800*2d543d20SAndroid Build Coastguard Worker 		e1->next = expr;
3801*2d543d20SAndroid Build Coastguard Worker 		return arg1;
3802*2d543d20SAndroid Build Coastguard Worker 	case CEXPR_AND:
3803*2d543d20SAndroid Build Coastguard Worker 	case CEXPR_OR:
3804*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
3805*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct constraint_expr *)arg1;
3806*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
3807*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
3808*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
3809*2d543d20SAndroid Build Coastguard Worker 		}
3810*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
3811*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal constraint expression");
3812*2d543d20SAndroid Build Coastguard Worker 			constraint_expr_destroy(expr);
3813*2d543d20SAndroid Build Coastguard Worker 			return 0;
3814*2d543d20SAndroid Build Coastguard Worker 		}
3815*2d543d20SAndroid Build Coastguard Worker 		e1->next = (struct constraint_expr *)arg2;
3816*2d543d20SAndroid Build Coastguard Worker 
3817*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
3818*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct constraint_expr *)arg2;
3819*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
3820*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
3821*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
3822*2d543d20SAndroid Build Coastguard Worker 		}
3823*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
3824*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal constraint expression");
3825*2d543d20SAndroid Build Coastguard Worker 			constraint_expr_destroy(expr);
3826*2d543d20SAndroid Build Coastguard Worker 			return 0;
3827*2d543d20SAndroid Build Coastguard Worker 		}
3828*2d543d20SAndroid Build Coastguard Worker 		e1->next = expr;
3829*2d543d20SAndroid Build Coastguard Worker 		return arg1;
3830*2d543d20SAndroid Build Coastguard Worker 	case CEXPR_ATTR:
3831*2d543d20SAndroid Build Coastguard Worker 		expr->attr = arg1;
3832*2d543d20SAndroid Build Coastguard Worker 		expr->op = arg2;
3833*2d543d20SAndroid Build Coastguard Worker 		return (uintptr_t) expr;
3834*2d543d20SAndroid Build Coastguard Worker 	case CEXPR_NAMES:
3835*2d543d20SAndroid Build Coastguard Worker 		add = 1;
3836*2d543d20SAndroid Build Coastguard Worker 		expr->attr = arg1;
3837*2d543d20SAndroid Build Coastguard Worker 		expr->op = arg2;
3838*2d543d20SAndroid Build Coastguard Worker 		ebitmap_init(&negset);
3839*2d543d20SAndroid Build Coastguard Worker 		while ((id = (char *)queue_remove(id_queue))) {
3840*2d543d20SAndroid Build Coastguard Worker 			if (expr->attr & CEXPR_USER) {
3841*2d543d20SAndroid Build Coastguard Worker 				if (!is_id_in_scope(SYM_USERS, id)) {
3842*2d543d20SAndroid Build Coastguard Worker 					yyerror2("user %s is not within scope",
3843*2d543d20SAndroid Build Coastguard Worker 						 id);
3844*2d543d20SAndroid Build Coastguard Worker 					free(id);
3845*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(expr);
3846*2d543d20SAndroid Build Coastguard Worker 					return 0;
3847*2d543d20SAndroid Build Coastguard Worker 				}
3848*2d543d20SAndroid Build Coastguard Worker 				user =
3849*2d543d20SAndroid Build Coastguard Worker 				    (user_datum_t *) hashtab_search(policydbp->
3850*2d543d20SAndroid Build Coastguard Worker 								    p_users.
3851*2d543d20SAndroid Build Coastguard Worker 								    table,
3852*2d543d20SAndroid Build Coastguard Worker 								    (hashtab_key_t)
3853*2d543d20SAndroid Build Coastguard Worker 								    id);
3854*2d543d20SAndroid Build Coastguard Worker 				if (!user) {
3855*2d543d20SAndroid Build Coastguard Worker 					yyerror2("unknown user %s", id);
3856*2d543d20SAndroid Build Coastguard Worker 					free(id);
3857*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(expr);
3858*2d543d20SAndroid Build Coastguard Worker 					return 0;
3859*2d543d20SAndroid Build Coastguard Worker 				}
3860*2d543d20SAndroid Build Coastguard Worker 				val = user->s.value;
3861*2d543d20SAndroid Build Coastguard Worker 			} else if (expr->attr & CEXPR_ROLE) {
3862*2d543d20SAndroid Build Coastguard Worker 				if (!is_id_in_scope(SYM_ROLES, id)) {
3863*2d543d20SAndroid Build Coastguard Worker 					yyerror2("role %s is not within scope",
3864*2d543d20SAndroid Build Coastguard Worker 						 id);
3865*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(expr);
3866*2d543d20SAndroid Build Coastguard Worker 					free(id);
3867*2d543d20SAndroid Build Coastguard Worker 					return 0;
3868*2d543d20SAndroid Build Coastguard Worker 				}
3869*2d543d20SAndroid Build Coastguard Worker 				role =
3870*2d543d20SAndroid Build Coastguard Worker 				    (role_datum_t *) hashtab_search(policydbp->
3871*2d543d20SAndroid Build Coastguard Worker 								    p_roles.
3872*2d543d20SAndroid Build Coastguard Worker 								    table,
3873*2d543d20SAndroid Build Coastguard Worker 								    (hashtab_key_t)
3874*2d543d20SAndroid Build Coastguard Worker 								    id);
3875*2d543d20SAndroid Build Coastguard Worker 				if (!role) {
3876*2d543d20SAndroid Build Coastguard Worker 					yyerror2("unknown role %s", id);
3877*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(expr);
3878*2d543d20SAndroid Build Coastguard Worker 					free(id);
3879*2d543d20SAndroid Build Coastguard Worker 					return 0;
3880*2d543d20SAndroid Build Coastguard Worker 				}
3881*2d543d20SAndroid Build Coastguard Worker 				val = role->s.value;
3882*2d543d20SAndroid Build Coastguard Worker 			} else if (expr->attr & CEXPR_TYPE) {
3883*2d543d20SAndroid Build Coastguard Worker 				if (set_types(expr->type_names, id, &add, 0)) {
3884*2d543d20SAndroid Build Coastguard Worker 					constraint_expr_destroy(expr);
3885*2d543d20SAndroid Build Coastguard Worker 					return 0;
3886*2d543d20SAndroid Build Coastguard Worker 				}
3887*2d543d20SAndroid Build Coastguard Worker 				continue;
3888*2d543d20SAndroid Build Coastguard Worker 			} else {
3889*2d543d20SAndroid Build Coastguard Worker 				yyerror("invalid constraint expression");
3890*2d543d20SAndroid Build Coastguard Worker 				constraint_expr_destroy(expr);
3891*2d543d20SAndroid Build Coastguard Worker 				free(id);
3892*2d543d20SAndroid Build Coastguard Worker 				return 0;
3893*2d543d20SAndroid Build Coastguard Worker 			}
3894*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_set_bit(&expr->names, val - 1, TRUE)) {
3895*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
3896*2d543d20SAndroid Build Coastguard Worker 				ebitmap_destroy(&expr->names);
3897*2d543d20SAndroid Build Coastguard Worker 				free(id);
3898*2d543d20SAndroid Build Coastguard Worker 				constraint_expr_destroy(expr);
3899*2d543d20SAndroid Build Coastguard Worker 				return 0;
3900*2d543d20SAndroid Build Coastguard Worker 			}
3901*2d543d20SAndroid Build Coastguard Worker 			free(id);
3902*2d543d20SAndroid Build Coastguard Worker 		}
3903*2d543d20SAndroid Build Coastguard Worker 		ebitmap_destroy(&negset);
3904*2d543d20SAndroid Build Coastguard Worker 		return (uintptr_t) expr;
3905*2d543d20SAndroid Build Coastguard Worker 	default:
3906*2d543d20SAndroid Build Coastguard Worker 		break;
3907*2d543d20SAndroid Build Coastguard Worker 	}
3908*2d543d20SAndroid Build Coastguard Worker 
3909*2d543d20SAndroid Build Coastguard Worker 	yyerror("invalid constraint expression");
3910*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_destroy(expr);
3911*2d543d20SAndroid Build Coastguard Worker 	return 0;
3912*2d543d20SAndroid Build Coastguard Worker }
3913*2d543d20SAndroid Build Coastguard Worker 
define_conditional(cond_expr_t * expr,avrule_t * t_list,avrule_t * f_list)3914*2d543d20SAndroid Build Coastguard Worker int define_conditional(cond_expr_t * expr, avrule_t * t_list, avrule_t * f_list)
3915*2d543d20SAndroid Build Coastguard Worker {
3916*2d543d20SAndroid Build Coastguard Worker 	cond_expr_t *e;
3917*2d543d20SAndroid Build Coastguard Worker 	int depth, booleans, tunables;
3918*2d543d20SAndroid Build Coastguard Worker 	cond_node_t cn, *cn_old;
3919*2d543d20SAndroid Build Coastguard Worker 	const cond_bool_datum_t *bool_var;
3920*2d543d20SAndroid Build Coastguard Worker 
3921*2d543d20SAndroid Build Coastguard Worker 	/* expression cannot be NULL */
3922*2d543d20SAndroid Build Coastguard Worker 	if (!expr) {
3923*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal conditional expression");
3924*2d543d20SAndroid Build Coastguard Worker 		return -1;
3925*2d543d20SAndroid Build Coastguard Worker 	}
3926*2d543d20SAndroid Build Coastguard Worker 	if (!t_list) {
3927*2d543d20SAndroid Build Coastguard Worker 		if (!f_list) {
3928*2d543d20SAndroid Build Coastguard Worker 			/* empty is fine, destroy expression and return */
3929*2d543d20SAndroid Build Coastguard Worker 			cond_expr_destroy(expr);
3930*2d543d20SAndroid Build Coastguard Worker 			return 0;
3931*2d543d20SAndroid Build Coastguard Worker 		}
3932*2d543d20SAndroid Build Coastguard Worker 		/* Invert */
3933*2d543d20SAndroid Build Coastguard Worker 		t_list = f_list;
3934*2d543d20SAndroid Build Coastguard Worker 		f_list = NULL;
3935*2d543d20SAndroid Build Coastguard Worker 		expr = define_cond_expr(COND_NOT, expr, 0);
3936*2d543d20SAndroid Build Coastguard Worker 		if (!expr) {
3937*2d543d20SAndroid Build Coastguard Worker 			yyerror("unable to invert conditional expression");
3938*2d543d20SAndroid Build Coastguard Worker 			return -1;
3939*2d543d20SAndroid Build Coastguard Worker 		}
3940*2d543d20SAndroid Build Coastguard Worker 	}
3941*2d543d20SAndroid Build Coastguard Worker 
3942*2d543d20SAndroid Build Coastguard Worker 	/* verify expression */
3943*2d543d20SAndroid Build Coastguard Worker 	depth = -1;
3944*2d543d20SAndroid Build Coastguard Worker 	booleans = 0;
3945*2d543d20SAndroid Build Coastguard Worker 	tunables = 0;
3946*2d543d20SAndroid Build Coastguard Worker 	for (e = expr; e; e = e->next) {
3947*2d543d20SAndroid Build Coastguard Worker 		switch (e->expr_type) {
3948*2d543d20SAndroid Build Coastguard Worker 		case COND_NOT:
3949*2d543d20SAndroid Build Coastguard Worker 			if (depth < 0) {
3950*2d543d20SAndroid Build Coastguard Worker 				yyerror
3951*2d543d20SAndroid Build Coastguard Worker 				    ("illegal conditional expression; Bad NOT");
3952*2d543d20SAndroid Build Coastguard Worker 				return -1;
3953*2d543d20SAndroid Build Coastguard Worker 			}
3954*2d543d20SAndroid Build Coastguard Worker 			break;
3955*2d543d20SAndroid Build Coastguard Worker 		case COND_AND:
3956*2d543d20SAndroid Build Coastguard Worker 		case COND_OR:
3957*2d543d20SAndroid Build Coastguard Worker 		case COND_XOR:
3958*2d543d20SAndroid Build Coastguard Worker 		case COND_EQ:
3959*2d543d20SAndroid Build Coastguard Worker 		case COND_NEQ:
3960*2d543d20SAndroid Build Coastguard Worker 			if (depth < 1) {
3961*2d543d20SAndroid Build Coastguard Worker 				yyerror
3962*2d543d20SAndroid Build Coastguard Worker 				    ("illegal conditional expression; Bad binary op");
3963*2d543d20SAndroid Build Coastguard Worker 				return -1;
3964*2d543d20SAndroid Build Coastguard Worker 			}
3965*2d543d20SAndroid Build Coastguard Worker 			depth--;
3966*2d543d20SAndroid Build Coastguard Worker 			break;
3967*2d543d20SAndroid Build Coastguard Worker 		case COND_BOOL:
3968*2d543d20SAndroid Build Coastguard Worker 			if (depth == (COND_EXPR_MAXDEPTH - 1)) {
3969*2d543d20SAndroid Build Coastguard Worker 				yyerror
3970*2d543d20SAndroid Build Coastguard Worker 				    ("conditional expression is like totally too deep");
3971*2d543d20SAndroid Build Coastguard Worker 				return -1;
3972*2d543d20SAndroid Build Coastguard Worker 			}
3973*2d543d20SAndroid Build Coastguard Worker 			depth++;
3974*2d543d20SAndroid Build Coastguard Worker 
3975*2d543d20SAndroid Build Coastguard Worker 			bool_var = policydbp->bool_val_to_struct[e->boolean - 1];
3976*2d543d20SAndroid Build Coastguard Worker 			if (bool_var->flags & COND_BOOL_FLAGS_TUNABLE) {
3977*2d543d20SAndroid Build Coastguard Worker 				tunables = 1;
3978*2d543d20SAndroid Build Coastguard Worker 			} else {
3979*2d543d20SAndroid Build Coastguard Worker 				booleans = 1;
3980*2d543d20SAndroid Build Coastguard Worker 			}
3981*2d543d20SAndroid Build Coastguard Worker 
3982*2d543d20SAndroid Build Coastguard Worker 			break;
3983*2d543d20SAndroid Build Coastguard Worker 		default:
3984*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal conditional expression");
3985*2d543d20SAndroid Build Coastguard Worker 			return -1;
3986*2d543d20SAndroid Build Coastguard Worker 		}
3987*2d543d20SAndroid Build Coastguard Worker 	}
3988*2d543d20SAndroid Build Coastguard Worker 	if (depth != 0) {
3989*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal conditional expression");
3990*2d543d20SAndroid Build Coastguard Worker 		return -1;
3991*2d543d20SAndroid Build Coastguard Worker 	}
3992*2d543d20SAndroid Build Coastguard Worker 	if (booleans && tunables) {
3993*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal conditional expression; Contains boolean and tunable");
3994*2d543d20SAndroid Build Coastguard Worker 		return -1;
3995*2d543d20SAndroid Build Coastguard Worker 	}
3996*2d543d20SAndroid Build Coastguard Worker 
3997*2d543d20SAndroid Build Coastguard Worker 	/*  use tmp conditional node to partially build new node */
3998*2d543d20SAndroid Build Coastguard Worker 	memset(&cn, 0, sizeof(cn));
3999*2d543d20SAndroid Build Coastguard Worker 	cn.expr = expr;
4000*2d543d20SAndroid Build Coastguard Worker 	cn.avtrue_list = t_list;
4001*2d543d20SAndroid Build Coastguard Worker 	cn.avfalse_list = f_list;
4002*2d543d20SAndroid Build Coastguard Worker 
4003*2d543d20SAndroid Build Coastguard Worker 	/* normalize/precompute expression */
4004*2d543d20SAndroid Build Coastguard Worker 	if (cond_normalize_expr(policydbp, &cn) < 0) {
4005*2d543d20SAndroid Build Coastguard Worker 		yyerror("problem normalizing conditional expression");
4006*2d543d20SAndroid Build Coastguard Worker 		return -1;
4007*2d543d20SAndroid Build Coastguard Worker 	}
4008*2d543d20SAndroid Build Coastguard Worker 
4009*2d543d20SAndroid Build Coastguard Worker 	/* get the existing conditional node, or create a new one */
4010*2d543d20SAndroid Build Coastguard Worker 	cn_old = get_current_cond_list(&cn);
4011*2d543d20SAndroid Build Coastguard Worker 	if (!cn_old) {
4012*2d543d20SAndroid Build Coastguard Worker 		return -1;
4013*2d543d20SAndroid Build Coastguard Worker 	}
4014*2d543d20SAndroid Build Coastguard Worker 
4015*2d543d20SAndroid Build Coastguard Worker 	append_cond_list(&cn);
4016*2d543d20SAndroid Build Coastguard Worker 
4017*2d543d20SAndroid Build Coastguard Worker 	/* note that there is no check here for duplicate rules, nor
4018*2d543d20SAndroid Build Coastguard Worker 	 * check that rule already exists in base -- that will be
4019*2d543d20SAndroid Build Coastguard Worker 	 * handled during conditional expansion, in expand.c */
4020*2d543d20SAndroid Build Coastguard Worker 
4021*2d543d20SAndroid Build Coastguard Worker 	cn.avtrue_list = NULL;
4022*2d543d20SAndroid Build Coastguard Worker 	cn.avfalse_list = NULL;
4023*2d543d20SAndroid Build Coastguard Worker 	cond_node_destroy(&cn);
4024*2d543d20SAndroid Build Coastguard Worker 
4025*2d543d20SAndroid Build Coastguard Worker 	return 0;
4026*2d543d20SAndroid Build Coastguard Worker }
4027*2d543d20SAndroid Build Coastguard Worker 
define_cond_expr(uint32_t expr_type,void * arg1,void * arg2)4028*2d543d20SAndroid Build Coastguard Worker cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2)
4029*2d543d20SAndroid Build Coastguard Worker {
4030*2d543d20SAndroid Build Coastguard Worker 	struct cond_expr *expr, *e1 = NULL, *e2;
4031*2d543d20SAndroid Build Coastguard Worker 	cond_bool_datum_t *bool_var;
4032*2d543d20SAndroid Build Coastguard Worker 	char *id;
4033*2d543d20SAndroid Build Coastguard Worker 
4034*2d543d20SAndroid Build Coastguard Worker 	/* expressions are handled in the second pass */
4035*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4036*2d543d20SAndroid Build Coastguard Worker 		if (expr_type == COND_BOOL) {
4037*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue))) {
4038*2d543d20SAndroid Build Coastguard Worker 				free(id);
4039*2d543d20SAndroid Build Coastguard Worker 			}
4040*2d543d20SAndroid Build Coastguard Worker 		}
4041*2d543d20SAndroid Build Coastguard Worker 		return (cond_expr_t *) 1;	/* any non-NULL value */
4042*2d543d20SAndroid Build Coastguard Worker 	}
4043*2d543d20SAndroid Build Coastguard Worker 
4044*2d543d20SAndroid Build Coastguard Worker 	/* create a new expression struct */
4045*2d543d20SAndroid Build Coastguard Worker 	expr = malloc(sizeof(struct cond_expr));
4046*2d543d20SAndroid Build Coastguard Worker 	if (!expr) {
4047*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4048*2d543d20SAndroid Build Coastguard Worker 		return NULL;
4049*2d543d20SAndroid Build Coastguard Worker 	}
4050*2d543d20SAndroid Build Coastguard Worker 	memset(expr, 0, sizeof(cond_expr_t));
4051*2d543d20SAndroid Build Coastguard Worker 	expr->expr_type = expr_type;
4052*2d543d20SAndroid Build Coastguard Worker 
4053*2d543d20SAndroid Build Coastguard Worker 	/* create the type asked for */
4054*2d543d20SAndroid Build Coastguard Worker 	switch (expr_type) {
4055*2d543d20SAndroid Build Coastguard Worker 	case COND_NOT:
4056*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
4057*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct cond_expr *)arg1;
4058*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
4059*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
4060*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
4061*2d543d20SAndroid Build Coastguard Worker 		}
4062*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
4063*2d543d20SAndroid Build Coastguard Worker 			yyerror("illegal conditional NOT expression");
4064*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4065*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4066*2d543d20SAndroid Build Coastguard Worker 		}
4067*2d543d20SAndroid Build Coastguard Worker 		e1->next = expr;
4068*2d543d20SAndroid Build Coastguard Worker 		return (struct cond_expr *)arg1;
4069*2d543d20SAndroid Build Coastguard Worker 	case COND_AND:
4070*2d543d20SAndroid Build Coastguard Worker 	case COND_OR:
4071*2d543d20SAndroid Build Coastguard Worker 	case COND_XOR:
4072*2d543d20SAndroid Build Coastguard Worker 	case COND_EQ:
4073*2d543d20SAndroid Build Coastguard Worker 	case COND_NEQ:
4074*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
4075*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct cond_expr *)arg1;
4076*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
4077*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
4078*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
4079*2d543d20SAndroid Build Coastguard Worker 		}
4080*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
4081*2d543d20SAndroid Build Coastguard Worker 			yyerror
4082*2d543d20SAndroid Build Coastguard Worker 			    ("illegal left side of conditional binary op expression");
4083*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4084*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4085*2d543d20SAndroid Build Coastguard Worker 		}
4086*2d543d20SAndroid Build Coastguard Worker 		e1->next = (struct cond_expr *)arg2;
4087*2d543d20SAndroid Build Coastguard Worker 
4088*2d543d20SAndroid Build Coastguard Worker 		e1 = NULL;
4089*2d543d20SAndroid Build Coastguard Worker 		e2 = (struct cond_expr *)arg2;
4090*2d543d20SAndroid Build Coastguard Worker 		while (e2) {
4091*2d543d20SAndroid Build Coastguard Worker 			e1 = e2;
4092*2d543d20SAndroid Build Coastguard Worker 			e2 = e2->next;
4093*2d543d20SAndroid Build Coastguard Worker 		}
4094*2d543d20SAndroid Build Coastguard Worker 		if (!e1 || e1->next) {
4095*2d543d20SAndroid Build Coastguard Worker 			yyerror
4096*2d543d20SAndroid Build Coastguard Worker 			    ("illegal right side of conditional binary op expression");
4097*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4098*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4099*2d543d20SAndroid Build Coastguard Worker 		}
4100*2d543d20SAndroid Build Coastguard Worker 		e1->next = expr;
4101*2d543d20SAndroid Build Coastguard Worker 		return (struct cond_expr *)arg1;
4102*2d543d20SAndroid Build Coastguard Worker 	case COND_BOOL:
4103*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4104*2d543d20SAndroid Build Coastguard Worker 		if (!id) {
4105*2d543d20SAndroid Build Coastguard Worker 			yyerror("bad conditional; expected boolean id");
4106*2d543d20SAndroid Build Coastguard Worker 			free(id);
4107*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4108*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4109*2d543d20SAndroid Build Coastguard Worker 		}
4110*2d543d20SAndroid Build Coastguard Worker 		if (!is_id_in_scope(SYM_BOOLS, id)) {
4111*2d543d20SAndroid Build Coastguard Worker 			yyerror2("boolean %s is not within scope", id);
4112*2d543d20SAndroid Build Coastguard Worker 			free(id);
4113*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4114*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4115*2d543d20SAndroid Build Coastguard Worker 		}
4116*2d543d20SAndroid Build Coastguard Worker 		bool_var =
4117*2d543d20SAndroid Build Coastguard Worker 		    (cond_bool_datum_t *) hashtab_search(policydbp->p_bools.
4118*2d543d20SAndroid Build Coastguard Worker 							 table,
4119*2d543d20SAndroid Build Coastguard Worker 							 (hashtab_key_t) id);
4120*2d543d20SAndroid Build Coastguard Worker 		if (!bool_var) {
4121*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown boolean %s in conditional expression",
4122*2d543d20SAndroid Build Coastguard Worker 				 id);
4123*2d543d20SAndroid Build Coastguard Worker 			free(expr);
4124*2d543d20SAndroid Build Coastguard Worker 			free(id);
4125*2d543d20SAndroid Build Coastguard Worker 			return NULL;
4126*2d543d20SAndroid Build Coastguard Worker 		}
4127*2d543d20SAndroid Build Coastguard Worker 		expr->boolean = bool_var->s.value;
4128*2d543d20SAndroid Build Coastguard Worker 		free(id);
4129*2d543d20SAndroid Build Coastguard Worker 		return expr;
4130*2d543d20SAndroid Build Coastguard Worker 	default:
4131*2d543d20SAndroid Build Coastguard Worker 		yyerror("illegal conditional expression");
4132*2d543d20SAndroid Build Coastguard Worker 		free(expr);
4133*2d543d20SAndroid Build Coastguard Worker 		return NULL;
4134*2d543d20SAndroid Build Coastguard Worker 	}
4135*2d543d20SAndroid Build Coastguard Worker }
4136*2d543d20SAndroid Build Coastguard Worker 
set_user_roles(role_set_t * set,char * id)4137*2d543d20SAndroid Build Coastguard Worker static int set_user_roles(role_set_t * set, char *id)
4138*2d543d20SAndroid Build Coastguard Worker {
4139*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *r;
4140*2d543d20SAndroid Build Coastguard Worker 
4141*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "*") == 0) {
4142*2d543d20SAndroid Build Coastguard Worker 		free(id);
4143*2d543d20SAndroid Build Coastguard Worker 		yyerror("* is not allowed in user declarations");
4144*2d543d20SAndroid Build Coastguard Worker 		return -1;
4145*2d543d20SAndroid Build Coastguard Worker 	}
4146*2d543d20SAndroid Build Coastguard Worker 
4147*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(id, "~") == 0) {
4148*2d543d20SAndroid Build Coastguard Worker 		free(id);
4149*2d543d20SAndroid Build Coastguard Worker 		yyerror("~ is not allowed in user declarations");
4150*2d543d20SAndroid Build Coastguard Worker 		return -1;
4151*2d543d20SAndroid Build Coastguard Worker 	}
4152*2d543d20SAndroid Build Coastguard Worker 
4153*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
4154*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
4155*2d543d20SAndroid Build Coastguard Worker 		free(id);
4156*2d543d20SAndroid Build Coastguard Worker 		return -1;
4157*2d543d20SAndroid Build Coastguard Worker 	}
4158*2d543d20SAndroid Build Coastguard Worker 	r = hashtab_search(policydbp->p_roles.table, id);
4159*2d543d20SAndroid Build Coastguard Worker 	if (!r) {
4160*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unknown role %s", id);
4161*2d543d20SAndroid Build Coastguard Worker 		free(id);
4162*2d543d20SAndroid Build Coastguard Worker 		return -1;
4163*2d543d20SAndroid Build Coastguard Worker 	}
4164*2d543d20SAndroid Build Coastguard Worker 
4165*2d543d20SAndroid Build Coastguard Worker 	free(id);
4166*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE))
4167*2d543d20SAndroid Build Coastguard Worker 		goto oom;
4168*2d543d20SAndroid Build Coastguard Worker 	return 0;
4169*2d543d20SAndroid Build Coastguard Worker       oom:
4170*2d543d20SAndroid Build Coastguard Worker 	yyerror("out of memory");
4171*2d543d20SAndroid Build Coastguard Worker 	return -1;
4172*2d543d20SAndroid Build Coastguard Worker }
4173*2d543d20SAndroid Build Coastguard Worker 
parse_categories(char * id,level_datum_t * levdatum,ebitmap_t * cats)4174*2d543d20SAndroid Build Coastguard Worker static int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats)
4175*2d543d20SAndroid Build Coastguard Worker {
4176*2d543d20SAndroid Build Coastguard Worker 	cat_datum_t *cdatum;
4177*2d543d20SAndroid Build Coastguard Worker 	uint32_t range_start, range_end, i;
4178*2d543d20SAndroid Build Coastguard Worker 
4179*2d543d20SAndroid Build Coastguard Worker 	if (id_has_dot(id)) {
4180*2d543d20SAndroid Build Coastguard Worker 		char *id_start = id;
4181*2d543d20SAndroid Build Coastguard Worker 		char *id_end = strchr(id, '.');
4182*2d543d20SAndroid Build Coastguard Worker 
4183*2d543d20SAndroid Build Coastguard Worker 		*(id_end++) = '\0';
4184*2d543d20SAndroid Build Coastguard Worker 
4185*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4186*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t)
4187*2d543d20SAndroid Build Coastguard Worker 							id_start);
4188*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4189*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id_start);
4190*2d543d20SAndroid Build Coastguard Worker 			return -1;
4191*2d543d20SAndroid Build Coastguard Worker 		}
4192*2d543d20SAndroid Build Coastguard Worker 		range_start = cdatum->s.value - 1;
4193*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4194*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t) id_end);
4195*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4196*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id_end);
4197*2d543d20SAndroid Build Coastguard Worker 			return -1;
4198*2d543d20SAndroid Build Coastguard Worker 		}
4199*2d543d20SAndroid Build Coastguard Worker 		range_end = cdatum->s.value - 1;
4200*2d543d20SAndroid Build Coastguard Worker 
4201*2d543d20SAndroid Build Coastguard Worker 		if (range_end < range_start) {
4202*2d543d20SAndroid Build Coastguard Worker 			yyerror2("category range %d-%d is invalid", range_start, range_end);
4203*2d543d20SAndroid Build Coastguard Worker 			return -1;
4204*2d543d20SAndroid Build Coastguard Worker 		}
4205*2d543d20SAndroid Build Coastguard Worker 	} else {
4206*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4207*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t) id);
4208*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4209*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id);
4210*2d543d20SAndroid Build Coastguard Worker 			return -1;
4211*2d543d20SAndroid Build Coastguard Worker 		}
4212*2d543d20SAndroid Build Coastguard Worker 		range_start = range_end = cdatum->s.value - 1;
4213*2d543d20SAndroid Build Coastguard Worker 	}
4214*2d543d20SAndroid Build Coastguard Worker 
4215*2d543d20SAndroid Build Coastguard Worker 	for (i = range_start; i <= range_end; i++) {
4216*2d543d20SAndroid Build Coastguard Worker 		if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
4217*2d543d20SAndroid Build Coastguard Worker 			uint32_t level_value = levdatum->level->sens - 1;
4218*2d543d20SAndroid Build Coastguard Worker 			policydb_index_others(NULL, policydbp, 0);
4219*2d543d20SAndroid Build Coastguard Worker 			yyerror2("category %s can not be associated "
4220*2d543d20SAndroid Build Coastguard Worker 				 "with level %s",
4221*2d543d20SAndroid Build Coastguard Worker 				 policydbp->p_cat_val_to_name[i],
4222*2d543d20SAndroid Build Coastguard Worker 				 policydbp->p_sens_val_to_name[level_value]);
4223*2d543d20SAndroid Build Coastguard Worker 			return -1;
4224*2d543d20SAndroid Build Coastguard Worker 		}
4225*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(cats, i, TRUE)) {
4226*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
4227*2d543d20SAndroid Build Coastguard Worker 			return -1;
4228*2d543d20SAndroid Build Coastguard Worker 		}
4229*2d543d20SAndroid Build Coastguard Worker 	}
4230*2d543d20SAndroid Build Coastguard Worker 
4231*2d543d20SAndroid Build Coastguard Worker 	return 0;
4232*2d543d20SAndroid Build Coastguard Worker }
4233*2d543d20SAndroid Build Coastguard Worker 
parse_semantic_categories(char * id,level_datum_t * levdatum,mls_semantic_cat_t ** cats)4234*2d543d20SAndroid Build Coastguard Worker static int parse_semantic_categories(char *id, level_datum_t * levdatum __attribute__ ((unused)),
4235*2d543d20SAndroid Build Coastguard Worker 				     mls_semantic_cat_t ** cats)
4236*2d543d20SAndroid Build Coastguard Worker {
4237*2d543d20SAndroid Build Coastguard Worker 	cat_datum_t *cdatum;
4238*2d543d20SAndroid Build Coastguard Worker 	mls_semantic_cat_t *newcat;
4239*2d543d20SAndroid Build Coastguard Worker 	unsigned int range_start, range_end;
4240*2d543d20SAndroid Build Coastguard Worker 
4241*2d543d20SAndroid Build Coastguard Worker 	if (id_has_dot(id)) {
4242*2d543d20SAndroid Build Coastguard Worker 		char *id_start = id;
4243*2d543d20SAndroid Build Coastguard Worker 		char *id_end = strchr(id, '.');
4244*2d543d20SAndroid Build Coastguard Worker 
4245*2d543d20SAndroid Build Coastguard Worker 		*(id_end++) = '\0';
4246*2d543d20SAndroid Build Coastguard Worker 
4247*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4248*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t)
4249*2d543d20SAndroid Build Coastguard Worker 							id_start);
4250*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4251*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id_start);
4252*2d543d20SAndroid Build Coastguard Worker 			return -1;
4253*2d543d20SAndroid Build Coastguard Worker 		}
4254*2d543d20SAndroid Build Coastguard Worker 		range_start = cdatum->s.value;
4255*2d543d20SAndroid Build Coastguard Worker 
4256*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4257*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t) id_end);
4258*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4259*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id_end);
4260*2d543d20SAndroid Build Coastguard Worker 			return -1;
4261*2d543d20SAndroid Build Coastguard Worker 		}
4262*2d543d20SAndroid Build Coastguard Worker 		range_end = cdatum->s.value;
4263*2d543d20SAndroid Build Coastguard Worker 	} else {
4264*2d543d20SAndroid Build Coastguard Worker 		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4265*2d543d20SAndroid Build Coastguard Worker 							(hashtab_key_t) id);
4266*2d543d20SAndroid Build Coastguard Worker 		if (!cdatum) {
4267*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown category %s", id);
4268*2d543d20SAndroid Build Coastguard Worker 			return -1;
4269*2d543d20SAndroid Build Coastguard Worker 		}
4270*2d543d20SAndroid Build Coastguard Worker 		range_start = range_end = cdatum->s.value;
4271*2d543d20SAndroid Build Coastguard Worker 	}
4272*2d543d20SAndroid Build Coastguard Worker 
4273*2d543d20SAndroid Build Coastguard Worker 	newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
4274*2d543d20SAndroid Build Coastguard Worker 	if (!newcat) {
4275*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4276*2d543d20SAndroid Build Coastguard Worker 		return -1;
4277*2d543d20SAndroid Build Coastguard Worker 	}
4278*2d543d20SAndroid Build Coastguard Worker 
4279*2d543d20SAndroid Build Coastguard Worker 	mls_semantic_cat_init(newcat);
4280*2d543d20SAndroid Build Coastguard Worker 	newcat->next = *cats;
4281*2d543d20SAndroid Build Coastguard Worker 	newcat->low = range_start;
4282*2d543d20SAndroid Build Coastguard Worker 	newcat->high = range_end;
4283*2d543d20SAndroid Build Coastguard Worker 
4284*2d543d20SAndroid Build Coastguard Worker 	*cats = newcat;
4285*2d543d20SAndroid Build Coastguard Worker 
4286*2d543d20SAndroid Build Coastguard Worker 	return 0;
4287*2d543d20SAndroid Build Coastguard Worker }
4288*2d543d20SAndroid Build Coastguard Worker 
define_user(void)4289*2d543d20SAndroid Build Coastguard Worker int define_user(void)
4290*2d543d20SAndroid Build Coastguard Worker {
4291*2d543d20SAndroid Build Coastguard Worker 	char *id;
4292*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *usrdatum;
4293*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum;
4294*2d543d20SAndroid Build Coastguard Worker 	int l;
4295*2d543d20SAndroid Build Coastguard Worker 
4296*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4297*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
4298*2d543d20SAndroid Build Coastguard Worker 			free(id);
4299*2d543d20SAndroid Build Coastguard Worker 		if (mlspol) {
4300*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
4301*2d543d20SAndroid Build Coastguard Worker 				free(id);
4302*2d543d20SAndroid Build Coastguard Worker 			id = queue_remove(id_queue);
4303*2d543d20SAndroid Build Coastguard Worker 			free(id);
4304*2d543d20SAndroid Build Coastguard Worker 			for (l = 0; l < 2; l++) {
4305*2d543d20SAndroid Build Coastguard Worker 				while ((id = queue_remove(id_queue))) {
4306*2d543d20SAndroid Build Coastguard Worker 					free(id);
4307*2d543d20SAndroid Build Coastguard Worker 				}
4308*2d543d20SAndroid Build Coastguard Worker 				id = queue_remove(id_queue);
4309*2d543d20SAndroid Build Coastguard Worker 				if (!id)
4310*2d543d20SAndroid Build Coastguard Worker 					break;
4311*2d543d20SAndroid Build Coastguard Worker 				free(id);
4312*2d543d20SAndroid Build Coastguard Worker 			}
4313*2d543d20SAndroid Build Coastguard Worker 		}
4314*2d543d20SAndroid Build Coastguard Worker 		return 0;
4315*2d543d20SAndroid Build Coastguard Worker 	}
4316*2d543d20SAndroid Build Coastguard Worker 
4317*2d543d20SAndroid Build Coastguard Worker 	if ((usrdatum = declare_user()) == NULL) {
4318*2d543d20SAndroid Build Coastguard Worker 		return -1;
4319*2d543d20SAndroid Build Coastguard Worker 	}
4320*2d543d20SAndroid Build Coastguard Worker 
4321*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
4322*2d543d20SAndroid Build Coastguard Worker 		if (set_user_roles(&usrdatum->roles, id))
4323*2d543d20SAndroid Build Coastguard Worker 			return -1;
4324*2d543d20SAndroid Build Coastguard Worker 	}
4325*2d543d20SAndroid Build Coastguard Worker 
4326*2d543d20SAndroid Build Coastguard Worker 	if (mlspol) {
4327*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
4328*2d543d20SAndroid Build Coastguard Worker 		if (!id) {
4329*2d543d20SAndroid Build Coastguard Worker 			yyerror("no default level specified for user");
4330*2d543d20SAndroid Build Coastguard Worker 			return -1;
4331*2d543d20SAndroid Build Coastguard Worker 		}
4332*2d543d20SAndroid Build Coastguard Worker 
4333*2d543d20SAndroid Build Coastguard Worker 		levdatum = (level_datum_t *)
4334*2d543d20SAndroid Build Coastguard Worker 		    hashtab_search(policydbp->p_levels.table,
4335*2d543d20SAndroid Build Coastguard Worker 				   (hashtab_key_t) id);
4336*2d543d20SAndroid Build Coastguard Worker 		if (!levdatum) {
4337*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown sensitivity %s used in user"
4338*2d543d20SAndroid Build Coastguard Worker 				 " level definition", id);
4339*2d543d20SAndroid Build Coastguard Worker 			free(id);
4340*2d543d20SAndroid Build Coastguard Worker 			return -1;
4341*2d543d20SAndroid Build Coastguard Worker 		}
4342*2d543d20SAndroid Build Coastguard Worker 		free(id);
4343*2d543d20SAndroid Build Coastguard Worker 
4344*2d543d20SAndroid Build Coastguard Worker 		usrdatum->dfltlevel.sens = levdatum->level->sens;
4345*2d543d20SAndroid Build Coastguard Worker 
4346*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue))) {
4347*2d543d20SAndroid Build Coastguard Worker 			if (parse_semantic_categories(id, levdatum,
4348*2d543d20SAndroid Build Coastguard Worker 			                            &usrdatum->dfltlevel.cat)) {
4349*2d543d20SAndroid Build Coastguard Worker 				free(id);
4350*2d543d20SAndroid Build Coastguard Worker 				return -1;
4351*2d543d20SAndroid Build Coastguard Worker 			}
4352*2d543d20SAndroid Build Coastguard Worker 			free(id);
4353*2d543d20SAndroid Build Coastguard Worker 		}
4354*2d543d20SAndroid Build Coastguard Worker 
4355*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
4356*2d543d20SAndroid Build Coastguard Worker 
4357*2d543d20SAndroid Build Coastguard Worker 		for (l = 0; l < 2; l++) {
4358*2d543d20SAndroid Build Coastguard Worker 			levdatum = (level_datum_t *)
4359*2d543d20SAndroid Build Coastguard Worker 			    hashtab_search(policydbp->p_levels.table,
4360*2d543d20SAndroid Build Coastguard Worker 					   (hashtab_key_t) id);
4361*2d543d20SAndroid Build Coastguard Worker 			if (!levdatum) {
4362*2d543d20SAndroid Build Coastguard Worker 				yyerror2("unknown sensitivity %s used in user"
4363*2d543d20SAndroid Build Coastguard Worker 					 " range definition", id);
4364*2d543d20SAndroid Build Coastguard Worker 				free(id);
4365*2d543d20SAndroid Build Coastguard Worker 				return -1;
4366*2d543d20SAndroid Build Coastguard Worker 			}
4367*2d543d20SAndroid Build Coastguard Worker 			free(id);
4368*2d543d20SAndroid Build Coastguard Worker 
4369*2d543d20SAndroid Build Coastguard Worker 			usrdatum->range.level[l].sens = levdatum->level->sens;
4370*2d543d20SAndroid Build Coastguard Worker 
4371*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue))) {
4372*2d543d20SAndroid Build Coastguard Worker 				if (parse_semantic_categories(id, levdatum,
4373*2d543d20SAndroid Build Coastguard Worker 				               &usrdatum->range.level[l].cat)) {
4374*2d543d20SAndroid Build Coastguard Worker 					free(id);
4375*2d543d20SAndroid Build Coastguard Worker 					return -1;
4376*2d543d20SAndroid Build Coastguard Worker 				}
4377*2d543d20SAndroid Build Coastguard Worker 				free(id);
4378*2d543d20SAndroid Build Coastguard Worker 			}
4379*2d543d20SAndroid Build Coastguard Worker 
4380*2d543d20SAndroid Build Coastguard Worker 			id = queue_remove(id_queue);
4381*2d543d20SAndroid Build Coastguard Worker 			if (!id)
4382*2d543d20SAndroid Build Coastguard Worker 				break;
4383*2d543d20SAndroid Build Coastguard Worker 		}
4384*2d543d20SAndroid Build Coastguard Worker 
4385*2d543d20SAndroid Build Coastguard Worker 		if (l == 0) {
4386*2d543d20SAndroid Build Coastguard Worker 			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
4387*2d543d20SAndroid Build Coastguard Worker 			                           &usrdatum->range.level[0])) {
4388*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
4389*2d543d20SAndroid Build Coastguard Worker 				return -1;
4390*2d543d20SAndroid Build Coastguard Worker 			}
4391*2d543d20SAndroid Build Coastguard Worker 		}
4392*2d543d20SAndroid Build Coastguard Worker 	}
4393*2d543d20SAndroid Build Coastguard Worker 	return 0;
4394*2d543d20SAndroid Build Coastguard Worker }
4395*2d543d20SAndroid Build Coastguard Worker 
parse_security_context(context_struct_t * c)4396*2d543d20SAndroid Build Coastguard Worker static int parse_security_context(context_struct_t * c)
4397*2d543d20SAndroid Build Coastguard Worker {
4398*2d543d20SAndroid Build Coastguard Worker 	char *id;
4399*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
4400*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *typdatum;
4401*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *usrdatum;
4402*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum;
4403*2d543d20SAndroid Build Coastguard Worker 	int l;
4404*2d543d20SAndroid Build Coastguard Worker 
4405*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4406*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
4407*2d543d20SAndroid Build Coastguard Worker 		free(id);	/* user  */
4408*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
4409*2d543d20SAndroid Build Coastguard Worker 		free(id);	/* role  */
4410*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
4411*2d543d20SAndroid Build Coastguard Worker 		free(id);	/* type  */
4412*2d543d20SAndroid Build Coastguard Worker 		if (mlspol) {
4413*2d543d20SAndroid Build Coastguard Worker 			id = queue_remove(id_queue);
4414*2d543d20SAndroid Build Coastguard Worker 			free(id);
4415*2d543d20SAndroid Build Coastguard Worker 			for (l = 0; l < 2; l++) {
4416*2d543d20SAndroid Build Coastguard Worker 				while ((id = queue_remove(id_queue))) {
4417*2d543d20SAndroid Build Coastguard Worker 					free(id);
4418*2d543d20SAndroid Build Coastguard Worker 				}
4419*2d543d20SAndroid Build Coastguard Worker 				id = queue_remove(id_queue);
4420*2d543d20SAndroid Build Coastguard Worker 				if (!id)
4421*2d543d20SAndroid Build Coastguard Worker 					break;
4422*2d543d20SAndroid Build Coastguard Worker 				free(id);
4423*2d543d20SAndroid Build Coastguard Worker 			}
4424*2d543d20SAndroid Build Coastguard Worker 		}
4425*2d543d20SAndroid Build Coastguard Worker 		return 0;
4426*2d543d20SAndroid Build Coastguard Worker 	}
4427*2d543d20SAndroid Build Coastguard Worker 
4428*2d543d20SAndroid Build Coastguard Worker 	/* check context c to make sure ok to dereference c later */
4429*2d543d20SAndroid Build Coastguard Worker 	if (c == NULL) {
4430*2d543d20SAndroid Build Coastguard Worker 		yyerror("null context pointer!");
4431*2d543d20SAndroid Build Coastguard Worker 		return -1;
4432*2d543d20SAndroid Build Coastguard Worker 	}
4433*2d543d20SAndroid Build Coastguard Worker 
4434*2d543d20SAndroid Build Coastguard Worker 	context_init(c);
4435*2d543d20SAndroid Build Coastguard Worker 
4436*2d543d20SAndroid Build Coastguard Worker 	/* extract the user */
4437*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
4438*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
4439*2d543d20SAndroid Build Coastguard Worker 		yyerror("no effective user?");
4440*2d543d20SAndroid Build Coastguard Worker 		goto bad;
4441*2d543d20SAndroid Build Coastguard Worker 	}
4442*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_USERS, id)) {
4443*2d543d20SAndroid Build Coastguard Worker 		yyerror2("user %s is not within scope", id);
4444*2d543d20SAndroid Build Coastguard Worker 		free(id);
4445*2d543d20SAndroid Build Coastguard Worker 		goto bad;
4446*2d543d20SAndroid Build Coastguard Worker 	}
4447*2d543d20SAndroid Build Coastguard Worker 	usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table,
4448*2d543d20SAndroid Build Coastguard Worker 						   (hashtab_key_t) id);
4449*2d543d20SAndroid Build Coastguard Worker 	if (!usrdatum) {
4450*2d543d20SAndroid Build Coastguard Worker 		yyerror2("user %s is not defined", id);
4451*2d543d20SAndroid Build Coastguard Worker 		free(id);
4452*2d543d20SAndroid Build Coastguard Worker 		goto bad;
4453*2d543d20SAndroid Build Coastguard Worker 	}
4454*2d543d20SAndroid Build Coastguard Worker 	c->user = usrdatum->s.value;
4455*2d543d20SAndroid Build Coastguard Worker 
4456*2d543d20SAndroid Build Coastguard Worker 	/* no need to keep the user name */
4457*2d543d20SAndroid Build Coastguard Worker 	free(id);
4458*2d543d20SAndroid Build Coastguard Worker 
4459*2d543d20SAndroid Build Coastguard Worker 	/* extract the role */
4460*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
4461*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
4462*2d543d20SAndroid Build Coastguard Worker 		yyerror("no role name for sid context definition?");
4463*2d543d20SAndroid Build Coastguard Worker 		return -1;
4464*2d543d20SAndroid Build Coastguard Worker 	}
4465*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_ROLES, id)) {
4466*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not within scope", id);
4467*2d543d20SAndroid Build Coastguard Worker 		free(id);
4468*2d543d20SAndroid Build Coastguard Worker 		return -1;
4469*2d543d20SAndroid Build Coastguard Worker 	}
4470*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
4471*2d543d20SAndroid Build Coastguard Worker 					       (hashtab_key_t) id);
4472*2d543d20SAndroid Build Coastguard Worker 	if (!role) {
4473*2d543d20SAndroid Build Coastguard Worker 		yyerror2("role %s is not defined", id);
4474*2d543d20SAndroid Build Coastguard Worker 		free(id);
4475*2d543d20SAndroid Build Coastguard Worker 		return -1;
4476*2d543d20SAndroid Build Coastguard Worker 	}
4477*2d543d20SAndroid Build Coastguard Worker 	c->role = role->s.value;
4478*2d543d20SAndroid Build Coastguard Worker 
4479*2d543d20SAndroid Build Coastguard Worker 	/* no need to keep the role name */
4480*2d543d20SAndroid Build Coastguard Worker 	free(id);
4481*2d543d20SAndroid Build Coastguard Worker 
4482*2d543d20SAndroid Build Coastguard Worker 	/* extract the type */
4483*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
4484*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
4485*2d543d20SAndroid Build Coastguard Worker 		yyerror("no type name for sid context definition?");
4486*2d543d20SAndroid Build Coastguard Worker 		return -1;
4487*2d543d20SAndroid Build Coastguard Worker 	}
4488*2d543d20SAndroid Build Coastguard Worker 	if (!is_id_in_scope(SYM_TYPES, id)) {
4489*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not within scope", id);
4490*2d543d20SAndroid Build Coastguard Worker 		free(id);
4491*2d543d20SAndroid Build Coastguard Worker 		return -1;
4492*2d543d20SAndroid Build Coastguard Worker 	}
4493*2d543d20SAndroid Build Coastguard Worker 	typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
4494*2d543d20SAndroid Build Coastguard Worker 						   (hashtab_key_t) id);
4495*2d543d20SAndroid Build Coastguard Worker 	if (!typdatum || typdatum->flavor == TYPE_ATTRIB) {
4496*2d543d20SAndroid Build Coastguard Worker 		yyerror2("type %s is not defined or is an attribute", id);
4497*2d543d20SAndroid Build Coastguard Worker 		free(id);
4498*2d543d20SAndroid Build Coastguard Worker 		return -1;
4499*2d543d20SAndroid Build Coastguard Worker 	}
4500*2d543d20SAndroid Build Coastguard Worker 	c->type = typdatum->s.value;
4501*2d543d20SAndroid Build Coastguard Worker 
4502*2d543d20SAndroid Build Coastguard Worker 	/* no need to keep the type name */
4503*2d543d20SAndroid Build Coastguard Worker 	free(id);
4504*2d543d20SAndroid Build Coastguard Worker 
4505*2d543d20SAndroid Build Coastguard Worker 	if (mlspol) {
4506*2d543d20SAndroid Build Coastguard Worker 		/* extract the low sensitivity */
4507*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_head(id_queue);
4508*2d543d20SAndroid Build Coastguard Worker 		if (!id) {
4509*2d543d20SAndroid Build Coastguard Worker 			yyerror("no sensitivity name for sid context"
4510*2d543d20SAndroid Build Coastguard Worker 				" definition?");
4511*2d543d20SAndroid Build Coastguard Worker 			return -1;
4512*2d543d20SAndroid Build Coastguard Worker 		}
4513*2d543d20SAndroid Build Coastguard Worker 
4514*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4515*2d543d20SAndroid Build Coastguard Worker 		for (l = 0; l < 2; l++) {
4516*2d543d20SAndroid Build Coastguard Worker 			levdatum = (level_datum_t *)
4517*2d543d20SAndroid Build Coastguard Worker 			    hashtab_search(policydbp->p_levels.table,
4518*2d543d20SAndroid Build Coastguard Worker 					   (hashtab_key_t) id);
4519*2d543d20SAndroid Build Coastguard Worker 			if (!levdatum) {
4520*2d543d20SAndroid Build Coastguard Worker 				yyerror2("Sensitivity %s is not defined", id);
4521*2d543d20SAndroid Build Coastguard Worker 				free(id);
4522*2d543d20SAndroid Build Coastguard Worker 				return -1;
4523*2d543d20SAndroid Build Coastguard Worker 			}
4524*2d543d20SAndroid Build Coastguard Worker 			free(id);
4525*2d543d20SAndroid Build Coastguard Worker 			c->range.level[l].sens = levdatum->level->sens;
4526*2d543d20SAndroid Build Coastguard Worker 
4527*2d543d20SAndroid Build Coastguard Worker 			/* extract low category set */
4528*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue))) {
4529*2d543d20SAndroid Build Coastguard Worker 				if (parse_categories(id, levdatum,
4530*2d543d20SAndroid Build Coastguard Worker 						     &c->range.level[l].cat)) {
4531*2d543d20SAndroid Build Coastguard Worker 					free(id);
4532*2d543d20SAndroid Build Coastguard Worker 					return -1;
4533*2d543d20SAndroid Build Coastguard Worker 				}
4534*2d543d20SAndroid Build Coastguard Worker 				free(id);
4535*2d543d20SAndroid Build Coastguard Worker 			}
4536*2d543d20SAndroid Build Coastguard Worker 
4537*2d543d20SAndroid Build Coastguard Worker 			/* extract high sensitivity */
4538*2d543d20SAndroid Build Coastguard Worker 			id = (char *)queue_remove(id_queue);
4539*2d543d20SAndroid Build Coastguard Worker 			if (!id)
4540*2d543d20SAndroid Build Coastguard Worker 				break;
4541*2d543d20SAndroid Build Coastguard Worker 		}
4542*2d543d20SAndroid Build Coastguard Worker 
4543*2d543d20SAndroid Build Coastguard Worker 		if (l == 0) {
4544*2d543d20SAndroid Build Coastguard Worker 			c->range.level[1].sens = c->range.level[0].sens;
4545*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_cpy(&c->range.level[1].cat,
4546*2d543d20SAndroid Build Coastguard Worker 					&c->range.level[0].cat)) {
4547*2d543d20SAndroid Build Coastguard Worker 
4548*2d543d20SAndroid Build Coastguard Worker 				yyerror("out of memory");
4549*2d543d20SAndroid Build Coastguard Worker 				goto bad;
4550*2d543d20SAndroid Build Coastguard Worker 			}
4551*2d543d20SAndroid Build Coastguard Worker 		}
4552*2d543d20SAndroid Build Coastguard Worker 	}
4553*2d543d20SAndroid Build Coastguard Worker 
4554*2d543d20SAndroid Build Coastguard Worker 	if (!policydb_context_isvalid(policydbp, c)) {
4555*2d543d20SAndroid Build Coastguard Worker 		yyerror("invalid security context");
4556*2d543d20SAndroid Build Coastguard Worker 		goto bad;
4557*2d543d20SAndroid Build Coastguard Worker 	}
4558*2d543d20SAndroid Build Coastguard Worker 	return 0;
4559*2d543d20SAndroid Build Coastguard Worker 
4560*2d543d20SAndroid Build Coastguard Worker       bad:
4561*2d543d20SAndroid Build Coastguard Worker 	context_destroy(c);
4562*2d543d20SAndroid Build Coastguard Worker 
4563*2d543d20SAndroid Build Coastguard Worker 	return -1;
4564*2d543d20SAndroid Build Coastguard Worker }
4565*2d543d20SAndroid Build Coastguard Worker 
define_initial_sid_context(void)4566*2d543d20SAndroid Build Coastguard Worker int define_initial_sid_context(void)
4567*2d543d20SAndroid Build Coastguard Worker {
4568*2d543d20SAndroid Build Coastguard Worker 	char *id;
4569*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
4570*2d543d20SAndroid Build Coastguard Worker 
4571*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4572*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4573*2d543d20SAndroid Build Coastguard Worker 		free(id);
4574*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4575*2d543d20SAndroid Build Coastguard Worker 		return 0;
4576*2d543d20SAndroid Build Coastguard Worker 	}
4577*2d543d20SAndroid Build Coastguard Worker 
4578*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
4579*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
4580*2d543d20SAndroid Build Coastguard Worker 		yyerror("no sid name for SID context definition?");
4581*2d543d20SAndroid Build Coastguard Worker 		return -1;
4582*2d543d20SAndroid Build Coastguard Worker 	}
4583*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_ISID];
4584*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
4585*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(id, c->u.name))
4586*2d543d20SAndroid Build Coastguard Worker 			break;
4587*2d543d20SAndroid Build Coastguard Worker 	}
4588*2d543d20SAndroid Build Coastguard Worker 
4589*2d543d20SAndroid Build Coastguard Worker 	if (!c) {
4590*2d543d20SAndroid Build Coastguard Worker 		yyerror2("SID %s is not defined", id);
4591*2d543d20SAndroid Build Coastguard Worker 		free(id);
4592*2d543d20SAndroid Build Coastguard Worker 		return -1;
4593*2d543d20SAndroid Build Coastguard Worker 	}
4594*2d543d20SAndroid Build Coastguard Worker 	if (c->context[0].user) {
4595*2d543d20SAndroid Build Coastguard Worker 		yyerror2("The context for SID %s is multiply defined", id);
4596*2d543d20SAndroid Build Coastguard Worker 		free(id);
4597*2d543d20SAndroid Build Coastguard Worker 		return -1;
4598*2d543d20SAndroid Build Coastguard Worker 	}
4599*2d543d20SAndroid Build Coastguard Worker 	/* no need to keep the sid name */
4600*2d543d20SAndroid Build Coastguard Worker 	free(id);
4601*2d543d20SAndroid Build Coastguard Worker 
4602*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&c->context[0]))
4603*2d543d20SAndroid Build Coastguard Worker 		return -1;
4604*2d543d20SAndroid Build Coastguard Worker 
4605*2d543d20SAndroid Build Coastguard Worker 	return 0;
4606*2d543d20SAndroid Build Coastguard Worker }
4607*2d543d20SAndroid Build Coastguard Worker 
define_fs_context(unsigned int major,unsigned int minor)4608*2d543d20SAndroid Build Coastguard Worker int define_fs_context(unsigned int major, unsigned int minor)
4609*2d543d20SAndroid Build Coastguard Worker {
4610*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *head;
4611*2d543d20SAndroid Build Coastguard Worker 
4612*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
4613*2d543d20SAndroid Build Coastguard Worker 		yyerror("fscon not supported for target");
4614*2d543d20SAndroid Build Coastguard Worker 		return -1;
4615*2d543d20SAndroid Build Coastguard Worker 	}
4616*2d543d20SAndroid Build Coastguard Worker 
4617*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4618*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4619*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4620*2d543d20SAndroid Build Coastguard Worker 		return 0;
4621*2d543d20SAndroid Build Coastguard Worker 	}
4622*2d543d20SAndroid Build Coastguard Worker 
4623*2d543d20SAndroid Build Coastguard Worker 	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
4624*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4625*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4626*2d543d20SAndroid Build Coastguard Worker 		return -1;
4627*2d543d20SAndroid Build Coastguard Worker 	}
4628*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4629*2d543d20SAndroid Build Coastguard Worker 
4630*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = (char *)malloc(6);
4631*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.name) {
4632*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4633*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4634*2d543d20SAndroid Build Coastguard Worker 		return -1;
4635*2d543d20SAndroid Build Coastguard Worker 	}
4636*2d543d20SAndroid Build Coastguard Worker 	sprintf(newc->u.name, "%02x:%02x", major, minor);
4637*2d543d20SAndroid Build Coastguard Worker 
4638*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4639*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
4640*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4641*2d543d20SAndroid Build Coastguard Worker 		return -1;
4642*2d543d20SAndroid Build Coastguard Worker 	}
4643*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[1])) {
4644*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&newc->context[0]);
4645*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
4646*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4647*2d543d20SAndroid Build Coastguard Worker 		return -1;
4648*2d543d20SAndroid Build Coastguard Worker 	}
4649*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_FS];
4650*2d543d20SAndroid Build Coastguard Worker 
4651*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
4652*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(newc->u.name, c->u.name)) {
4653*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate entry for file system %s",
4654*2d543d20SAndroid Build Coastguard Worker 				 newc->u.name);
4655*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[0]);
4656*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[1]);
4657*2d543d20SAndroid Build Coastguard Worker 			free(newc->u.name);
4658*2d543d20SAndroid Build Coastguard Worker 			free(newc);
4659*2d543d20SAndroid Build Coastguard Worker 			return -1;
4660*2d543d20SAndroid Build Coastguard Worker 		}
4661*2d543d20SAndroid Build Coastguard Worker 	}
4662*2d543d20SAndroid Build Coastguard Worker 
4663*2d543d20SAndroid Build Coastguard Worker 	newc->next = head;
4664*2d543d20SAndroid Build Coastguard Worker 	policydbp->ocontexts[OCON_FS] = newc;
4665*2d543d20SAndroid Build Coastguard Worker 
4666*2d543d20SAndroid Build Coastguard Worker 	return 0;
4667*2d543d20SAndroid Build Coastguard Worker }
4668*2d543d20SAndroid Build Coastguard Worker 
define_pirq_context(unsigned int pirq)4669*2d543d20SAndroid Build Coastguard Worker int define_pirq_context(unsigned int pirq)
4670*2d543d20SAndroid Build Coastguard Worker {
4671*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4672*2d543d20SAndroid Build Coastguard Worker 	char *id;
4673*2d543d20SAndroid Build Coastguard Worker 
4674*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4675*2d543d20SAndroid Build Coastguard Worker 		yyerror("pirqcon not supported for target");
4676*2d543d20SAndroid Build Coastguard Worker 		return -1;
4677*2d543d20SAndroid Build Coastguard Worker 	}
4678*2d543d20SAndroid Build Coastguard Worker 
4679*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4680*2d543d20SAndroid Build Coastguard Worker 		id = (char *) queue_remove(id_queue);
4681*2d543d20SAndroid Build Coastguard Worker 		free(id);
4682*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4683*2d543d20SAndroid Build Coastguard Worker 		return 0;
4684*2d543d20SAndroid Build Coastguard Worker 	}
4685*2d543d20SAndroid Build Coastguard Worker 
4686*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4687*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4688*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4689*2d543d20SAndroid Build Coastguard Worker 		return -1;
4690*2d543d20SAndroid Build Coastguard Worker 	}
4691*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4692*2d543d20SAndroid Build Coastguard Worker 
4693*2d543d20SAndroid Build Coastguard Worker 	newc->u.pirq = pirq;
4694*2d543d20SAndroid Build Coastguard Worker 
4695*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4696*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4697*2d543d20SAndroid Build Coastguard Worker 		return -1;
4698*2d543d20SAndroid Build Coastguard Worker 	}
4699*2d543d20SAndroid Build Coastguard Worker 
4700*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_XEN_PIRQ];
4701*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
4702*2d543d20SAndroid Build Coastguard Worker 		unsigned int pirq2;
4703*2d543d20SAndroid Build Coastguard Worker 
4704*2d543d20SAndroid Build Coastguard Worker 		pirq2 = c->u.pirq;
4705*2d543d20SAndroid Build Coastguard Worker 		if (pirq == pirq2) {
4706*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate pirqcon entry for %d ", pirq);
4707*2d543d20SAndroid Build Coastguard Worker 			goto bad;
4708*2d543d20SAndroid Build Coastguard Worker 		}
4709*2d543d20SAndroid Build Coastguard Worker 	}
4710*2d543d20SAndroid Build Coastguard Worker 
4711*2d543d20SAndroid Build Coastguard Worker 	if (l)
4712*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
4713*2d543d20SAndroid Build Coastguard Worker 	else
4714*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_XEN_PIRQ] = newc;
4715*2d543d20SAndroid Build Coastguard Worker 
4716*2d543d20SAndroid Build Coastguard Worker 	return 0;
4717*2d543d20SAndroid Build Coastguard Worker 
4718*2d543d20SAndroid Build Coastguard Worker bad:
4719*2d543d20SAndroid Build Coastguard Worker 	free(newc);
4720*2d543d20SAndroid Build Coastguard Worker 	return -1;
4721*2d543d20SAndroid Build Coastguard Worker }
4722*2d543d20SAndroid Build Coastguard Worker 
define_iomem_context(uint64_t low,uint64_t high)4723*2d543d20SAndroid Build Coastguard Worker int define_iomem_context(uint64_t low, uint64_t high)
4724*2d543d20SAndroid Build Coastguard Worker {
4725*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4726*2d543d20SAndroid Build Coastguard Worker 	char *id;
4727*2d543d20SAndroid Build Coastguard Worker 
4728*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4729*2d543d20SAndroid Build Coastguard Worker 		yyerror("iomemcon not supported for target");
4730*2d543d20SAndroid Build Coastguard Worker 		return -1;
4731*2d543d20SAndroid Build Coastguard Worker 	}
4732*2d543d20SAndroid Build Coastguard Worker 
4733*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4734*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4735*2d543d20SAndroid Build Coastguard Worker 		free(id);
4736*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4737*2d543d20SAndroid Build Coastguard Worker 		return 0;
4738*2d543d20SAndroid Build Coastguard Worker 	}
4739*2d543d20SAndroid Build Coastguard Worker 
4740*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4741*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4742*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4743*2d543d20SAndroid Build Coastguard Worker 		return -1;
4744*2d543d20SAndroid Build Coastguard Worker 	}
4745*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4746*2d543d20SAndroid Build Coastguard Worker 
4747*2d543d20SAndroid Build Coastguard Worker 	newc->u.iomem.low_iomem  = low;
4748*2d543d20SAndroid Build Coastguard Worker 	newc->u.iomem.high_iomem = high;
4749*2d543d20SAndroid Build Coastguard Worker 
4750*2d543d20SAndroid Build Coastguard Worker 	if (low > high) {
4751*2d543d20SAndroid Build Coastguard Worker 		yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high);
4752*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4753*2d543d20SAndroid Build Coastguard Worker 		return -1;
4754*2d543d20SAndroid Build Coastguard Worker 	}
4755*2d543d20SAndroid Build Coastguard Worker 
4756*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4757*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4758*2d543d20SAndroid Build Coastguard Worker 		return -1;
4759*2d543d20SAndroid Build Coastguard Worker 	}
4760*2d543d20SAndroid Build Coastguard Worker 
4761*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_XEN_IOMEM];
4762*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
4763*2d543d20SAndroid Build Coastguard Worker 		uint64_t low2, high2;
4764*2d543d20SAndroid Build Coastguard Worker 
4765*2d543d20SAndroid Build Coastguard Worker 		low2 = c->u.iomem.low_iomem;
4766*2d543d20SAndroid Build Coastguard Worker 		high2 = c->u.iomem.high_iomem;
4767*2d543d20SAndroid Build Coastguard Worker 		if (low <= high2 && low2 <= high) {
4768*2d543d20SAndroid Build Coastguard Worker 			yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with "
4769*2d543d20SAndroid Build Coastguard Worker 				"earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high,
4770*2d543d20SAndroid Build Coastguard Worker 				low2, high2);
4771*2d543d20SAndroid Build Coastguard Worker 			goto bad;
4772*2d543d20SAndroid Build Coastguard Worker 		}
4773*2d543d20SAndroid Build Coastguard Worker 	}
4774*2d543d20SAndroid Build Coastguard Worker 
4775*2d543d20SAndroid Build Coastguard Worker 	if (l)
4776*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
4777*2d543d20SAndroid Build Coastguard Worker 	else
4778*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_XEN_IOMEM] = newc;
4779*2d543d20SAndroid Build Coastguard Worker 
4780*2d543d20SAndroid Build Coastguard Worker 	return 0;
4781*2d543d20SAndroid Build Coastguard Worker 
4782*2d543d20SAndroid Build Coastguard Worker bad:
4783*2d543d20SAndroid Build Coastguard Worker 	free(newc);
4784*2d543d20SAndroid Build Coastguard Worker 	return -1;
4785*2d543d20SAndroid Build Coastguard Worker }
4786*2d543d20SAndroid Build Coastguard Worker 
define_ioport_context(unsigned long low,unsigned long high)4787*2d543d20SAndroid Build Coastguard Worker int define_ioport_context(unsigned long low, unsigned long high)
4788*2d543d20SAndroid Build Coastguard Worker {
4789*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4790*2d543d20SAndroid Build Coastguard Worker 	char *id;
4791*2d543d20SAndroid Build Coastguard Worker 
4792*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4793*2d543d20SAndroid Build Coastguard Worker 		yyerror("ioportcon not supported for target");
4794*2d543d20SAndroid Build Coastguard Worker 		return -1;
4795*2d543d20SAndroid Build Coastguard Worker 	}
4796*2d543d20SAndroid Build Coastguard Worker 
4797*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4798*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4799*2d543d20SAndroid Build Coastguard Worker 		free(id);
4800*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4801*2d543d20SAndroid Build Coastguard Worker 		return 0;
4802*2d543d20SAndroid Build Coastguard Worker 	}
4803*2d543d20SAndroid Build Coastguard Worker 
4804*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4805*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4806*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4807*2d543d20SAndroid Build Coastguard Worker 		return -1;
4808*2d543d20SAndroid Build Coastguard Worker 	}
4809*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4810*2d543d20SAndroid Build Coastguard Worker 
4811*2d543d20SAndroid Build Coastguard Worker 	newc->u.ioport.low_ioport  = low;
4812*2d543d20SAndroid Build Coastguard Worker 	newc->u.ioport.high_ioport = high;
4813*2d543d20SAndroid Build Coastguard Worker 
4814*2d543d20SAndroid Build Coastguard Worker 	if (low > high) {
4815*2d543d20SAndroid Build Coastguard Worker 		yyerror2("low ioport 0x%lx exceeds high ioport 0x%lx", low, high);
4816*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4817*2d543d20SAndroid Build Coastguard Worker 		return -1;
4818*2d543d20SAndroid Build Coastguard Worker 	}
4819*2d543d20SAndroid Build Coastguard Worker 
4820*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4821*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4822*2d543d20SAndroid Build Coastguard Worker 		return -1;
4823*2d543d20SAndroid Build Coastguard Worker 	}
4824*2d543d20SAndroid Build Coastguard Worker 
4825*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_XEN_IOPORT];
4826*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
4827*2d543d20SAndroid Build Coastguard Worker 		uint32_t low2, high2;
4828*2d543d20SAndroid Build Coastguard Worker 
4829*2d543d20SAndroid Build Coastguard Worker 		low2 = c->u.ioport.low_ioport;
4830*2d543d20SAndroid Build Coastguard Worker 		high2 = c->u.ioport.high_ioport;
4831*2d543d20SAndroid Build Coastguard Worker 		if (low <= high2 && low2 <= high) {
4832*2d543d20SAndroid Build Coastguard Worker 			yyerror2("ioportcon entry for 0x%lx-0x%lx overlaps with"
4833*2d543d20SAndroid Build Coastguard Worker 				"earlier entry 0x%x-0x%x", low, high,
4834*2d543d20SAndroid Build Coastguard Worker 				low2, high2);
4835*2d543d20SAndroid Build Coastguard Worker 			goto bad;
4836*2d543d20SAndroid Build Coastguard Worker 		}
4837*2d543d20SAndroid Build Coastguard Worker 	}
4838*2d543d20SAndroid Build Coastguard Worker 
4839*2d543d20SAndroid Build Coastguard Worker 	if (l)
4840*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
4841*2d543d20SAndroid Build Coastguard Worker 	else
4842*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_XEN_IOPORT] = newc;
4843*2d543d20SAndroid Build Coastguard Worker 
4844*2d543d20SAndroid Build Coastguard Worker 	return 0;
4845*2d543d20SAndroid Build Coastguard Worker 
4846*2d543d20SAndroid Build Coastguard Worker bad:
4847*2d543d20SAndroid Build Coastguard Worker 	free(newc);
4848*2d543d20SAndroid Build Coastguard Worker 	return -1;
4849*2d543d20SAndroid Build Coastguard Worker }
4850*2d543d20SAndroid Build Coastguard Worker 
define_pcidevice_context(unsigned long device)4851*2d543d20SAndroid Build Coastguard Worker int define_pcidevice_context(unsigned long device)
4852*2d543d20SAndroid Build Coastguard Worker {
4853*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4854*2d543d20SAndroid Build Coastguard Worker 	char *id;
4855*2d543d20SAndroid Build Coastguard Worker 
4856*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4857*2d543d20SAndroid Build Coastguard Worker 		yyerror("pcidevicecon not supported for target");
4858*2d543d20SAndroid Build Coastguard Worker 		return -1;
4859*2d543d20SAndroid Build Coastguard Worker 	}
4860*2d543d20SAndroid Build Coastguard Worker 
4861*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4862*2d543d20SAndroid Build Coastguard Worker 		id = (char *) queue_remove(id_queue);
4863*2d543d20SAndroid Build Coastguard Worker 		free(id);
4864*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4865*2d543d20SAndroid Build Coastguard Worker 		return 0;
4866*2d543d20SAndroid Build Coastguard Worker 	}
4867*2d543d20SAndroid Build Coastguard Worker 
4868*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4869*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4870*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4871*2d543d20SAndroid Build Coastguard Worker 		return -1;
4872*2d543d20SAndroid Build Coastguard Worker 	}
4873*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4874*2d543d20SAndroid Build Coastguard Worker 
4875*2d543d20SAndroid Build Coastguard Worker 	newc->u.device = device;
4876*2d543d20SAndroid Build Coastguard Worker 
4877*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4878*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4879*2d543d20SAndroid Build Coastguard Worker 		return -1;
4880*2d543d20SAndroid Build Coastguard Worker 	}
4881*2d543d20SAndroid Build Coastguard Worker 
4882*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_XEN_PCIDEVICE];
4883*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
4884*2d543d20SAndroid Build Coastguard Worker 		unsigned int device2;
4885*2d543d20SAndroid Build Coastguard Worker 
4886*2d543d20SAndroid Build Coastguard Worker 		device2 = c->u.device;
4887*2d543d20SAndroid Build Coastguard Worker 		if (device == device2) {
4888*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate pcidevicecon entry for 0x%lx",
4889*2d543d20SAndroid Build Coastguard Worker 				 device);
4890*2d543d20SAndroid Build Coastguard Worker 			goto bad;
4891*2d543d20SAndroid Build Coastguard Worker 		}
4892*2d543d20SAndroid Build Coastguard Worker 	}
4893*2d543d20SAndroid Build Coastguard Worker 
4894*2d543d20SAndroid Build Coastguard Worker 	if (l)
4895*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
4896*2d543d20SAndroid Build Coastguard Worker 	else
4897*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_XEN_PCIDEVICE] = newc;
4898*2d543d20SAndroid Build Coastguard Worker 
4899*2d543d20SAndroid Build Coastguard Worker 	return 0;
4900*2d543d20SAndroid Build Coastguard Worker 
4901*2d543d20SAndroid Build Coastguard Worker bad:
4902*2d543d20SAndroid Build Coastguard Worker 	free(newc);
4903*2d543d20SAndroid Build Coastguard Worker 	return -1;
4904*2d543d20SAndroid Build Coastguard Worker }
4905*2d543d20SAndroid Build Coastguard Worker 
define_devicetree_context(void)4906*2d543d20SAndroid Build Coastguard Worker int define_devicetree_context(void)
4907*2d543d20SAndroid Build Coastguard Worker {
4908*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4909*2d543d20SAndroid Build Coastguard Worker 
4910*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4911*2d543d20SAndroid Build Coastguard Worker 		yyerror("devicetreecon not supported for target");
4912*2d543d20SAndroid Build Coastguard Worker 		return -1;
4913*2d543d20SAndroid Build Coastguard Worker 	}
4914*2d543d20SAndroid Build Coastguard Worker 
4915*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4916*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
4917*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4918*2d543d20SAndroid Build Coastguard Worker 		return 0;
4919*2d543d20SAndroid Build Coastguard Worker 	}
4920*2d543d20SAndroid Build Coastguard Worker 
4921*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4922*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4923*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4924*2d543d20SAndroid Build Coastguard Worker 		return -1;
4925*2d543d20SAndroid Build Coastguard Worker 	}
4926*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4927*2d543d20SAndroid Build Coastguard Worker 
4928*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = (char *)queue_remove(id_queue);
4929*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.name) {
4930*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4931*2d543d20SAndroid Build Coastguard Worker 		return -1;
4932*2d543d20SAndroid Build Coastguard Worker 	}
4933*2d543d20SAndroid Build Coastguard Worker 
4934*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
4935*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
4936*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4937*2d543d20SAndroid Build Coastguard Worker 		return -1;
4938*2d543d20SAndroid Build Coastguard Worker 	}
4939*2d543d20SAndroid Build Coastguard Worker 
4940*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_XEN_DEVICETREE];
4941*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
4942*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(newc->u.name, c->u.name) == 0) {
4943*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate devicetree entry for '%s'", newc->u.name);
4944*2d543d20SAndroid Build Coastguard Worker 			goto bad;
4945*2d543d20SAndroid Build Coastguard Worker 		}
4946*2d543d20SAndroid Build Coastguard Worker 	}
4947*2d543d20SAndroid Build Coastguard Worker 
4948*2d543d20SAndroid Build Coastguard Worker 	if (l)
4949*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
4950*2d543d20SAndroid Build Coastguard Worker 	else
4951*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_XEN_DEVICETREE] = newc;
4952*2d543d20SAndroid Build Coastguard Worker 
4953*2d543d20SAndroid Build Coastguard Worker 	return 0;
4954*2d543d20SAndroid Build Coastguard Worker 
4955*2d543d20SAndroid Build Coastguard Worker bad:
4956*2d543d20SAndroid Build Coastguard Worker 	free(newc->u.name);
4957*2d543d20SAndroid Build Coastguard Worker 	free(newc);
4958*2d543d20SAndroid Build Coastguard Worker 	return -1;
4959*2d543d20SAndroid Build Coastguard Worker }
4960*2d543d20SAndroid Build Coastguard Worker 
define_port_context(unsigned int low,unsigned int high)4961*2d543d20SAndroid Build Coastguard Worker int define_port_context(unsigned int low, unsigned int high)
4962*2d543d20SAndroid Build Coastguard Worker {
4963*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
4964*2d543d20SAndroid Build Coastguard Worker 	unsigned int protocol;
4965*2d543d20SAndroid Build Coastguard Worker 	char *id;
4966*2d543d20SAndroid Build Coastguard Worker 
4967*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
4968*2d543d20SAndroid Build Coastguard Worker 		yyerror("portcon not supported for target");
4969*2d543d20SAndroid Build Coastguard Worker 		return -1;
4970*2d543d20SAndroid Build Coastguard Worker 	}
4971*2d543d20SAndroid Build Coastguard Worker 
4972*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
4973*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
4974*2d543d20SAndroid Build Coastguard Worker 		free(id);
4975*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
4976*2d543d20SAndroid Build Coastguard Worker 		return 0;
4977*2d543d20SAndroid Build Coastguard Worker 	}
4978*2d543d20SAndroid Build Coastguard Worker 
4979*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
4980*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
4981*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
4982*2d543d20SAndroid Build Coastguard Worker 		return -1;
4983*2d543d20SAndroid Build Coastguard Worker 	}
4984*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
4985*2d543d20SAndroid Build Coastguard Worker 
4986*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
4987*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
4988*2d543d20SAndroid Build Coastguard Worker 		free(newc);
4989*2d543d20SAndroid Build Coastguard Worker 		return -1;
4990*2d543d20SAndroid Build Coastguard Worker 	}
4991*2d543d20SAndroid Build Coastguard Worker 	if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) {
4992*2d543d20SAndroid Build Coastguard Worker 		protocol = IPPROTO_TCP;
4993*2d543d20SAndroid Build Coastguard Worker 	} else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) {
4994*2d543d20SAndroid Build Coastguard Worker 		protocol = IPPROTO_UDP;
4995*2d543d20SAndroid Build Coastguard Worker 	} else if ((strcmp(id, "dccp") == 0) || (strcmp(id, "DCCP") == 0)) {
4996*2d543d20SAndroid Build Coastguard Worker 		protocol = IPPROTO_DCCP;
4997*2d543d20SAndroid Build Coastguard Worker 	} else if ((strcmp(id, "sctp") == 0) || (strcmp(id, "SCTP") == 0)) {
4998*2d543d20SAndroid Build Coastguard Worker 		protocol = IPPROTO_SCTP;
4999*2d543d20SAndroid Build Coastguard Worker 	} else {
5000*2d543d20SAndroid Build Coastguard Worker 		yyerror2("unrecognized protocol %s", id);
5001*2d543d20SAndroid Build Coastguard Worker 		goto bad;
5002*2d543d20SAndroid Build Coastguard Worker 	}
5003*2d543d20SAndroid Build Coastguard Worker 
5004*2d543d20SAndroid Build Coastguard Worker 	newc->u.port.protocol = protocol;
5005*2d543d20SAndroid Build Coastguard Worker 	newc->u.port.low_port = low;
5006*2d543d20SAndroid Build Coastguard Worker 	newc->u.port.high_port = high;
5007*2d543d20SAndroid Build Coastguard Worker 
5008*2d543d20SAndroid Build Coastguard Worker 	if (low > high) {
5009*2d543d20SAndroid Build Coastguard Worker 		yyerror2("low port %d exceeds high port %d", low, high);
5010*2d543d20SAndroid Build Coastguard Worker 		goto bad;
5011*2d543d20SAndroid Build Coastguard Worker 	}
5012*2d543d20SAndroid Build Coastguard Worker 
5013*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5014*2d543d20SAndroid Build Coastguard Worker 		goto bad;
5015*2d543d20SAndroid Build Coastguard Worker 	}
5016*2d543d20SAndroid Build Coastguard Worker 
5017*2d543d20SAndroid Build Coastguard Worker 	/* Preserve the matching order specified in the configuration. */
5018*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_PORT];
5019*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
5020*2d543d20SAndroid Build Coastguard Worker 		unsigned int prot2, low2, high2;
5021*2d543d20SAndroid Build Coastguard Worker 
5022*2d543d20SAndroid Build Coastguard Worker 		prot2 = c->u.port.protocol;
5023*2d543d20SAndroid Build Coastguard Worker 		low2 = c->u.port.low_port;
5024*2d543d20SAndroid Build Coastguard Worker 		high2 = c->u.port.high_port;
5025*2d543d20SAndroid Build Coastguard Worker 		if (protocol != prot2)
5026*2d543d20SAndroid Build Coastguard Worker 			continue;
5027*2d543d20SAndroid Build Coastguard Worker 		if (low == low2 && high == high2) {
5028*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate portcon entry for %s %d-%d ", id,
5029*2d543d20SAndroid Build Coastguard Worker 				 low, high);
5030*2d543d20SAndroid Build Coastguard Worker 			goto bad;
5031*2d543d20SAndroid Build Coastguard Worker 		}
5032*2d543d20SAndroid Build Coastguard Worker 		if (low2 <= low && high2 >= high) {
5033*2d543d20SAndroid Build Coastguard Worker 			yyerror2("portcon entry for %s %d-%d hidden by earlier "
5034*2d543d20SAndroid Build Coastguard Worker 				 "entry for %d-%d", id, low, high, low2, high2);
5035*2d543d20SAndroid Build Coastguard Worker 			goto bad;
5036*2d543d20SAndroid Build Coastguard Worker 		}
5037*2d543d20SAndroid Build Coastguard Worker 	}
5038*2d543d20SAndroid Build Coastguard Worker 
5039*2d543d20SAndroid Build Coastguard Worker 	if (l)
5040*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
5041*2d543d20SAndroid Build Coastguard Worker 	else
5042*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_PORT] = newc;
5043*2d543d20SAndroid Build Coastguard Worker 
5044*2d543d20SAndroid Build Coastguard Worker 	free(id);
5045*2d543d20SAndroid Build Coastguard Worker 	return 0;
5046*2d543d20SAndroid Build Coastguard Worker 
5047*2d543d20SAndroid Build Coastguard Worker       bad:
5048*2d543d20SAndroid Build Coastguard Worker 	free(id);
5049*2d543d20SAndroid Build Coastguard Worker 	free(newc);
5050*2d543d20SAndroid Build Coastguard Worker 	return -1;
5051*2d543d20SAndroid Build Coastguard Worker }
5052*2d543d20SAndroid Build Coastguard Worker 
define_ibpkey_context(unsigned int low,unsigned int high)5053*2d543d20SAndroid Build Coastguard Worker int define_ibpkey_context(unsigned int low, unsigned int high)
5054*2d543d20SAndroid Build Coastguard Worker {
5055*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
5056*2d543d20SAndroid Build Coastguard Worker 	struct in6_addr subnet_prefix;
5057*2d543d20SAndroid Build Coastguard Worker 	char *id;
5058*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
5059*2d543d20SAndroid Build Coastguard Worker 
5060*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5061*2d543d20SAndroid Build Coastguard Worker 		yyerror("ibpkeycon not supported for target");
5062*2d543d20SAndroid Build Coastguard Worker 		return -1;
5063*2d543d20SAndroid Build Coastguard Worker 	}
5064*2d543d20SAndroid Build Coastguard Worker 
5065*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5066*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
5067*2d543d20SAndroid Build Coastguard Worker 		free(id);
5068*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5069*2d543d20SAndroid Build Coastguard Worker 		return 0;
5070*2d543d20SAndroid Build Coastguard Worker 	}
5071*2d543d20SAndroid Build Coastguard Worker 
5072*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(*newc));
5073*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5074*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5075*2d543d20SAndroid Build Coastguard Worker 		return -1;
5076*2d543d20SAndroid Build Coastguard Worker 	}
5077*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(*newc));
5078*2d543d20SAndroid Build Coastguard Worker 
5079*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5080*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5081*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read the subnet prefix");
5082*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5083*2d543d20SAndroid Build Coastguard Worker 		goto out;
5084*2d543d20SAndroid Build Coastguard Worker 	}
5085*2d543d20SAndroid Build Coastguard Worker 
5086*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET6, id, &subnet_prefix);
5087*2d543d20SAndroid Build Coastguard Worker 	free(id);
5088*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5089*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to parse the subnet prefix");
5090*2d543d20SAndroid Build Coastguard Worker 		if (rc == 0)
5091*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
5092*2d543d20SAndroid Build Coastguard Worker 		goto out;
5093*2d543d20SAndroid Build Coastguard Worker 	}
5094*2d543d20SAndroid Build Coastguard Worker 
5095*2d543d20SAndroid Build Coastguard Worker 	if (subnet_prefix.s6_addr32[2] || subnet_prefix.s6_addr32[3]) {
5096*2d543d20SAndroid Build Coastguard Worker 		yyerror("subnet prefix should be 0's in the low order 64 bits.");
5097*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5098*2d543d20SAndroid Build Coastguard Worker 		goto out;
5099*2d543d20SAndroid Build Coastguard Worker 	}
5100*2d543d20SAndroid Build Coastguard Worker 
5101*2d543d20SAndroid Build Coastguard Worker 	if (low > 0xffff || high > 0xffff) {
5102*2d543d20SAndroid Build Coastguard Worker 		yyerror("pkey value too large, pkeys are 16 bits.");
5103*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5104*2d543d20SAndroid Build Coastguard Worker 		goto out;
5105*2d543d20SAndroid Build Coastguard Worker 	}
5106*2d543d20SAndroid Build Coastguard Worker 
5107*2d543d20SAndroid Build Coastguard Worker 	memcpy(&newc->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0],
5108*2d543d20SAndroid Build Coastguard Worker 	       sizeof(newc->u.ibpkey.subnet_prefix));
5109*2d543d20SAndroid Build Coastguard Worker 
5110*2d543d20SAndroid Build Coastguard Worker 	newc->u.ibpkey.low_pkey = low;
5111*2d543d20SAndroid Build Coastguard Worker 	newc->u.ibpkey.high_pkey = high;
5112*2d543d20SAndroid Build Coastguard Worker 
5113*2d543d20SAndroid Build Coastguard Worker 	if (low > high) {
5114*2d543d20SAndroid Build Coastguard Worker 		yyerror2("low pkey %d exceeds high pkey %d", low, high);
5115*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5116*2d543d20SAndroid Build Coastguard Worker 		goto out;
5117*2d543d20SAndroid Build Coastguard Worker 	}
5118*2d543d20SAndroid Build Coastguard Worker 
5119*2d543d20SAndroid Build Coastguard Worker 	rc = parse_security_context(&newc->context[0]);
5120*2d543d20SAndroid Build Coastguard Worker 	if (rc)
5121*2d543d20SAndroid Build Coastguard Worker 		goto out;
5122*2d543d20SAndroid Build Coastguard Worker 
5123*2d543d20SAndroid Build Coastguard Worker 	/* Preserve the matching order specified in the configuration. */
5124*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_IBPKEY];
5125*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
5126*2d543d20SAndroid Build Coastguard Worker 		unsigned int low2, high2;
5127*2d543d20SAndroid Build Coastguard Worker 
5128*2d543d20SAndroid Build Coastguard Worker 		low2 = c->u.ibpkey.low_pkey;
5129*2d543d20SAndroid Build Coastguard Worker 		high2 = c->u.ibpkey.high_pkey;
5130*2d543d20SAndroid Build Coastguard Worker 
5131*2d543d20SAndroid Build Coastguard Worker 		if (low == low2 && high == high2 &&
5132*2d543d20SAndroid Build Coastguard Worker 		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
5133*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate ibpkeycon entry for %d-%d ",
5134*2d543d20SAndroid Build Coastguard Worker 				 low, high);
5135*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
5136*2d543d20SAndroid Build Coastguard Worker 			goto out;
5137*2d543d20SAndroid Build Coastguard Worker 		}
5138*2d543d20SAndroid Build Coastguard Worker 		if (low2 <= low && high2 >= high &&
5139*2d543d20SAndroid Build Coastguard Worker 		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
5140*2d543d20SAndroid Build Coastguard Worker 			yyerror2("ibpkeycon entry for %d-%d hidden by earlier entry for %d-%d",
5141*2d543d20SAndroid Build Coastguard Worker 				 low, high, low2, high2);
5142*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
5143*2d543d20SAndroid Build Coastguard Worker 			goto out;
5144*2d543d20SAndroid Build Coastguard Worker 		}
5145*2d543d20SAndroid Build Coastguard Worker 	}
5146*2d543d20SAndroid Build Coastguard Worker 
5147*2d543d20SAndroid Build Coastguard Worker 	if (l)
5148*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
5149*2d543d20SAndroid Build Coastguard Worker 	else
5150*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_IBPKEY] = newc;
5151*2d543d20SAndroid Build Coastguard Worker 
5152*2d543d20SAndroid Build Coastguard Worker 	return 0;
5153*2d543d20SAndroid Build Coastguard Worker 
5154*2d543d20SAndroid Build Coastguard Worker out:
5155*2d543d20SAndroid Build Coastguard Worker 	free(newc);
5156*2d543d20SAndroid Build Coastguard Worker 	return rc;
5157*2d543d20SAndroid Build Coastguard Worker }
5158*2d543d20SAndroid Build Coastguard Worker 
define_ibendport_context(unsigned int port)5159*2d543d20SAndroid Build Coastguard Worker int define_ibendport_context(unsigned int port)
5160*2d543d20SAndroid Build Coastguard Worker {
5161*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *l, *head;
5162*2d543d20SAndroid Build Coastguard Worker 	char *id;
5163*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
5164*2d543d20SAndroid Build Coastguard Worker 
5165*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5166*2d543d20SAndroid Build Coastguard Worker 		yyerror("ibendportcon not supported for target");
5167*2d543d20SAndroid Build Coastguard Worker 		return -1;
5168*2d543d20SAndroid Build Coastguard Worker 	}
5169*2d543d20SAndroid Build Coastguard Worker 
5170*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5171*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
5172*2d543d20SAndroid Build Coastguard Worker 		free(id);
5173*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5174*2d543d20SAndroid Build Coastguard Worker 		return 0;
5175*2d543d20SAndroid Build Coastguard Worker 	}
5176*2d543d20SAndroid Build Coastguard Worker 
5177*2d543d20SAndroid Build Coastguard Worker 	if (port > 0xff || port == 0) {
5178*2d543d20SAndroid Build Coastguard Worker 		yyerror2("Invalid ibendport port number %d, should be 0 < port < 256", port);
5179*2d543d20SAndroid Build Coastguard Worker 		return -1;
5180*2d543d20SAndroid Build Coastguard Worker 	}
5181*2d543d20SAndroid Build Coastguard Worker 
5182*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(*newc));
5183*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5184*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5185*2d543d20SAndroid Build Coastguard Worker 		return -1;
5186*2d543d20SAndroid Build Coastguard Worker 	}
5187*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(*newc));
5188*2d543d20SAndroid Build Coastguard Worker 
5189*2d543d20SAndroid Build Coastguard Worker 	newc->u.ibendport.dev_name = queue_remove(id_queue);
5190*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.ibendport.dev_name) {
5191*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read infiniband device name.");
5192*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5193*2d543d20SAndroid Build Coastguard Worker 		goto out;
5194*2d543d20SAndroid Build Coastguard Worker 	}
5195*2d543d20SAndroid Build Coastguard Worker 
5196*2d543d20SAndroid Build Coastguard Worker 	if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
5197*2d543d20SAndroid Build Coastguard Worker 		yyerror2("infiniband device name %s exceeds max length of 63.", newc->u.ibendport.dev_name);
5198*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
5199*2d543d20SAndroid Build Coastguard Worker 		goto out;
5200*2d543d20SAndroid Build Coastguard Worker 	}
5201*2d543d20SAndroid Build Coastguard Worker 
5202*2d543d20SAndroid Build Coastguard Worker 	newc->u.ibendport.port = port;
5203*2d543d20SAndroid Build Coastguard Worker 
5204*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5205*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5206*2d543d20SAndroid Build Coastguard Worker 		return -1;
5207*2d543d20SAndroid Build Coastguard Worker 	}
5208*2d543d20SAndroid Build Coastguard Worker 
5209*2d543d20SAndroid Build Coastguard Worker 	/* Preserve the matching order specified in the configuration. */
5210*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_IBENDPORT];
5211*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = head; c; l = c, c = c->next) {
5212*2d543d20SAndroid Build Coastguard Worker 		unsigned int port2;
5213*2d543d20SAndroid Build Coastguard Worker 
5214*2d543d20SAndroid Build Coastguard Worker 		port2 = c->u.ibendport.port;
5215*2d543d20SAndroid Build Coastguard Worker 
5216*2d543d20SAndroid Build Coastguard Worker 		if (port == port2 &&
5217*2d543d20SAndroid Build Coastguard Worker 		    !strcmp(c->u.ibendport.dev_name,
5218*2d543d20SAndroid Build Coastguard Worker 			     newc->u.ibendport.dev_name)) {
5219*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate ibendportcon entry for %s port %u",
5220*2d543d20SAndroid Build Coastguard Worker 				 newc->u.ibendport.dev_name, port);
5221*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
5222*2d543d20SAndroid Build Coastguard Worker 			goto out;
5223*2d543d20SAndroid Build Coastguard Worker 		}
5224*2d543d20SAndroid Build Coastguard Worker 	}
5225*2d543d20SAndroid Build Coastguard Worker 
5226*2d543d20SAndroid Build Coastguard Worker 	if (l)
5227*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
5228*2d543d20SAndroid Build Coastguard Worker 	else
5229*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_IBENDPORT] = newc;
5230*2d543d20SAndroid Build Coastguard Worker 
5231*2d543d20SAndroid Build Coastguard Worker 	return 0;
5232*2d543d20SAndroid Build Coastguard Worker 
5233*2d543d20SAndroid Build Coastguard Worker out:
5234*2d543d20SAndroid Build Coastguard Worker 	free(newc->u.ibendport.dev_name);
5235*2d543d20SAndroid Build Coastguard Worker 	free(newc);
5236*2d543d20SAndroid Build Coastguard Worker 	return rc;
5237*2d543d20SAndroid Build Coastguard Worker }
5238*2d543d20SAndroid Build Coastguard Worker 
define_netif_context(void)5239*2d543d20SAndroid Build Coastguard Worker int define_netif_context(void)
5240*2d543d20SAndroid Build Coastguard Worker {
5241*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *head;
5242*2d543d20SAndroid Build Coastguard Worker 
5243*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5244*2d543d20SAndroid Build Coastguard Worker 		yyerror("netifcon not supported for target");
5245*2d543d20SAndroid Build Coastguard Worker 		return -1;
5246*2d543d20SAndroid Build Coastguard Worker 	}
5247*2d543d20SAndroid Build Coastguard Worker 
5248*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5249*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5250*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5251*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5252*2d543d20SAndroid Build Coastguard Worker 		return 0;
5253*2d543d20SAndroid Build Coastguard Worker 	}
5254*2d543d20SAndroid Build Coastguard Worker 
5255*2d543d20SAndroid Build Coastguard Worker 	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
5256*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5257*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5258*2d543d20SAndroid Build Coastguard Worker 		return -1;
5259*2d543d20SAndroid Build Coastguard Worker 	}
5260*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
5261*2d543d20SAndroid Build Coastguard Worker 
5262*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = (char *)queue_remove(id_queue);
5263*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.name) {
5264*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5265*2d543d20SAndroid Build Coastguard Worker 		return -1;
5266*2d543d20SAndroid Build Coastguard Worker 	}
5267*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5268*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
5269*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5270*2d543d20SAndroid Build Coastguard Worker 		return -1;
5271*2d543d20SAndroid Build Coastguard Worker 	}
5272*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[1])) {
5273*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&newc->context[0]);
5274*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
5275*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5276*2d543d20SAndroid Build Coastguard Worker 		return -1;
5277*2d543d20SAndroid Build Coastguard Worker 	}
5278*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_NETIF];
5279*2d543d20SAndroid Build Coastguard Worker 
5280*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
5281*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(newc->u.name, c->u.name)) {
5282*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate entry for network interface %s",
5283*2d543d20SAndroid Build Coastguard Worker 				 newc->u.name);
5284*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[0]);
5285*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[1]);
5286*2d543d20SAndroid Build Coastguard Worker 			free(newc->u.name);
5287*2d543d20SAndroid Build Coastguard Worker 			free(newc);
5288*2d543d20SAndroid Build Coastguard Worker 			return -1;
5289*2d543d20SAndroid Build Coastguard Worker 		}
5290*2d543d20SAndroid Build Coastguard Worker 	}
5291*2d543d20SAndroid Build Coastguard Worker 
5292*2d543d20SAndroid Build Coastguard Worker 	newc->next = head;
5293*2d543d20SAndroid Build Coastguard Worker 	policydbp->ocontexts[OCON_NETIF] = newc;
5294*2d543d20SAndroid Build Coastguard Worker 	return 0;
5295*2d543d20SAndroid Build Coastguard Worker }
5296*2d543d20SAndroid Build Coastguard Worker 
insert_ipv4_node(ocontext_t * newc)5297*2d543d20SAndroid Build Coastguard Worker static int insert_ipv4_node(ocontext_t *newc)
5298*2d543d20SAndroid Build Coastguard Worker {
5299*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *l;
5300*2d543d20SAndroid Build Coastguard Worker 	char addr[INET_ADDRSTRLEN];
5301*2d543d20SAndroid Build Coastguard Worker 	char mask[INET_ADDRSTRLEN];
5302*2d543d20SAndroid Build Coastguard Worker 
5303*2d543d20SAndroid Build Coastguard Worker 	/* Create order of most specific to least retaining
5304*2d543d20SAndroid Build Coastguard Worker 	   the order specified in the configuration. */
5305*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = policydbp->ocontexts[OCON_NODE]; c; l = c, c = c->next) {
5306*2d543d20SAndroid Build Coastguard Worker 		if (newc->u.node.mask == c->u.node.mask &&
5307*2d543d20SAndroid Build Coastguard Worker 		    newc->u.node.addr == c->u.node.addr) {
5308*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate entry for network node %s %s",
5309*2d543d20SAndroid Build Coastguard Worker 				 inet_ntop(AF_INET, &newc->u.node.addr, addr, INET_ADDRSTRLEN) ?: "<invalid>",
5310*2d543d20SAndroid Build Coastguard Worker 				 inet_ntop(AF_INET, &newc->u.node.mask, mask, INET_ADDRSTRLEN) ?: "<invalid>");
5311*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[0]);
5312*2d543d20SAndroid Build Coastguard Worker 			free(newc);
5313*2d543d20SAndroid Build Coastguard Worker 			return -1;
5314*2d543d20SAndroid Build Coastguard Worker 		}
5315*2d543d20SAndroid Build Coastguard Worker 
5316*2d543d20SAndroid Build Coastguard Worker 		if (newc->u.node.mask > c->u.node.mask)
5317*2d543d20SAndroid Build Coastguard Worker 			break;
5318*2d543d20SAndroid Build Coastguard Worker 	}
5319*2d543d20SAndroid Build Coastguard Worker 
5320*2d543d20SAndroid Build Coastguard Worker 	newc->next = c;
5321*2d543d20SAndroid Build Coastguard Worker 
5322*2d543d20SAndroid Build Coastguard Worker 	if (l)
5323*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
5324*2d543d20SAndroid Build Coastguard Worker 	else
5325*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_NODE] = newc;
5326*2d543d20SAndroid Build Coastguard Worker 
5327*2d543d20SAndroid Build Coastguard Worker 	return 0;
5328*2d543d20SAndroid Build Coastguard Worker }
5329*2d543d20SAndroid Build Coastguard Worker 
define_ipv4_node_context(void)5330*2d543d20SAndroid Build Coastguard Worker int define_ipv4_node_context(void)
5331*2d543d20SAndroid Build Coastguard Worker {
5332*2d543d20SAndroid Build Coastguard Worker 	char *id;
5333*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
5334*2d543d20SAndroid Build Coastguard Worker 	struct in_addr addr, mask;
5335*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc;
5336*2d543d20SAndroid Build Coastguard Worker 
5337*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5338*2d543d20SAndroid Build Coastguard Worker 		yyerror("nodecon not supported for target");
5339*2d543d20SAndroid Build Coastguard Worker 		return -1;
5340*2d543d20SAndroid Build Coastguard Worker 	}
5341*2d543d20SAndroid Build Coastguard Worker 
5342*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5343*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5344*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5345*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5346*2d543d20SAndroid Build Coastguard Worker 		return 0;
5347*2d543d20SAndroid Build Coastguard Worker 	}
5348*2d543d20SAndroid Build Coastguard Worker 
5349*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5350*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5351*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read ipv4 address");
5352*2d543d20SAndroid Build Coastguard Worker 		return -1;
5353*2d543d20SAndroid Build Coastguard Worker 	}
5354*2d543d20SAndroid Build Coastguard Worker 
5355*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET, id, &addr);
5356*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5357*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse ipv4 address %s", id);
5358*2d543d20SAndroid Build Coastguard Worker 		free(id);
5359*2d543d20SAndroid Build Coastguard Worker 		return -1;
5360*2d543d20SAndroid Build Coastguard Worker 	}
5361*2d543d20SAndroid Build Coastguard Worker 	free(id);
5362*2d543d20SAndroid Build Coastguard Worker 
5363*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5364*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5365*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read ipv4 address");
5366*2d543d20SAndroid Build Coastguard Worker 		return -1;
5367*2d543d20SAndroid Build Coastguard Worker 	}
5368*2d543d20SAndroid Build Coastguard Worker 
5369*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET, id, &mask);
5370*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5371*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse ipv4 mask %s", id);
5372*2d543d20SAndroid Build Coastguard Worker 		free(id);
5373*2d543d20SAndroid Build Coastguard Worker 		return -1;
5374*2d543d20SAndroid Build Coastguard Worker 	}
5375*2d543d20SAndroid Build Coastguard Worker 
5376*2d543d20SAndroid Build Coastguard Worker 	free(id);
5377*2d543d20SAndroid Build Coastguard Worker 
5378*2d543d20SAndroid Build Coastguard Worker 	if (mask.s_addr != 0 && ((~be32toh(mask.s_addr) + 1) & ~be32toh(mask.s_addr)) != 0) {
5379*2d543d20SAndroid Build Coastguard Worker 		yywarn("ipv4 mask is not contiguous");
5380*2d543d20SAndroid Build Coastguard Worker 	}
5381*2d543d20SAndroid Build Coastguard Worker 
5382*2d543d20SAndroid Build Coastguard Worker 	if ((~mask.s_addr & addr.s_addr) != 0) {
5383*2d543d20SAndroid Build Coastguard Worker 		yywarn("host bits in ipv4 address set");
5384*2d543d20SAndroid Build Coastguard Worker 	}
5385*2d543d20SAndroid Build Coastguard Worker 
5386*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
5387*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5388*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5389*2d543d20SAndroid Build Coastguard Worker 		return -1;
5390*2d543d20SAndroid Build Coastguard Worker 	}
5391*2d543d20SAndroid Build Coastguard Worker 
5392*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
5393*2d543d20SAndroid Build Coastguard Worker 	newc->u.node.addr = addr.s_addr;
5394*2d543d20SAndroid Build Coastguard Worker 	newc->u.node.mask = mask.s_addr;
5395*2d543d20SAndroid Build Coastguard Worker 
5396*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5397*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5398*2d543d20SAndroid Build Coastguard Worker 		return -1;
5399*2d543d20SAndroid Build Coastguard Worker 	}
5400*2d543d20SAndroid Build Coastguard Worker 
5401*2d543d20SAndroid Build Coastguard Worker 	return insert_ipv4_node(newc);
5402*2d543d20SAndroid Build Coastguard Worker }
5403*2d543d20SAndroid Build Coastguard Worker 
define_ipv4_cidr_node_context(void)5404*2d543d20SAndroid Build Coastguard Worker int define_ipv4_cidr_node_context(void)
5405*2d543d20SAndroid Build Coastguard Worker {
5406*2d543d20SAndroid Build Coastguard Worker 	char *endptr, *id, *split;
5407*2d543d20SAndroid Build Coastguard Worker 	unsigned long mask_bits;
5408*2d543d20SAndroid Build Coastguard Worker 	uint32_t mask;
5409*2d543d20SAndroid Build Coastguard Worker 	struct in_addr addr;
5410*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc;
5411*2d543d20SAndroid Build Coastguard Worker 	int rc;
5412*2d543d20SAndroid Build Coastguard Worker 
5413*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5414*2d543d20SAndroid Build Coastguard Worker 		yyerror("nodecon not supported for target");
5415*2d543d20SAndroid Build Coastguard Worker 		return -1;
5416*2d543d20SAndroid Build Coastguard Worker 	}
5417*2d543d20SAndroid Build Coastguard Worker 
5418*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5419*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5420*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5421*2d543d20SAndroid Build Coastguard Worker 		return 0;
5422*2d543d20SAndroid Build Coastguard Worker 	}
5423*2d543d20SAndroid Build Coastguard Worker 
5424*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5425*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5426*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read IPv4 address");
5427*2d543d20SAndroid Build Coastguard Worker 		return -1;
5428*2d543d20SAndroid Build Coastguard Worker 	}
5429*2d543d20SAndroid Build Coastguard Worker 
5430*2d543d20SAndroid Build Coastguard Worker 	split = strchr(id, '/');
5431*2d543d20SAndroid Build Coastguard Worker 	if (!split) {
5432*2d543d20SAndroid Build Coastguard Worker 		yyerror2("invalid IPv4 CIDR notation: %s", id);
5433*2d543d20SAndroid Build Coastguard Worker 		free(id);
5434*2d543d20SAndroid Build Coastguard Worker 		return -1;
5435*2d543d20SAndroid Build Coastguard Worker 	}
5436*2d543d20SAndroid Build Coastguard Worker 	*split = '\0';
5437*2d543d20SAndroid Build Coastguard Worker 
5438*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET, id, &addr);
5439*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5440*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse IPv4 address %s", id);
5441*2d543d20SAndroid Build Coastguard Worker 		free(id);
5442*2d543d20SAndroid Build Coastguard Worker 		return -1;
5443*2d543d20SAndroid Build Coastguard Worker 	}
5444*2d543d20SAndroid Build Coastguard Worker 
5445*2d543d20SAndroid Build Coastguard Worker 	errno = 0;
5446*2d543d20SAndroid Build Coastguard Worker 	mask_bits = strtoul(split + 1, &endptr, 10);
5447*2d543d20SAndroid Build Coastguard Worker 	if (errno || *endptr != '\0' || mask_bits > 32) {
5448*2d543d20SAndroid Build Coastguard Worker 		yyerror2("invalid mask in IPv4 CIDR notation: %s", split + 1);
5449*2d543d20SAndroid Build Coastguard Worker 		free(id);
5450*2d543d20SAndroid Build Coastguard Worker 		return -1;
5451*2d543d20SAndroid Build Coastguard Worker 	}
5452*2d543d20SAndroid Build Coastguard Worker 
5453*2d543d20SAndroid Build Coastguard Worker 	free(id);
5454*2d543d20SAndroid Build Coastguard Worker 
5455*2d543d20SAndroid Build Coastguard Worker 	if (mask_bits == 0) {
5456*2d543d20SAndroid Build Coastguard Worker 		yywarn("IPv4 CIDR mask of 0, matching all IPs");
5457*2d543d20SAndroid Build Coastguard Worker 		mask = 0;
5458*2d543d20SAndroid Build Coastguard Worker 	} else {
5459*2d543d20SAndroid Build Coastguard Worker 		mask = ~((UINT32_C(1) << (32 - mask_bits)) - 1);
5460*2d543d20SAndroid Build Coastguard Worker 		mask = htobe32(mask);
5461*2d543d20SAndroid Build Coastguard Worker 	}
5462*2d543d20SAndroid Build Coastguard Worker 
5463*2d543d20SAndroid Build Coastguard Worker 	if ((~mask & addr.s_addr) != 0)
5464*2d543d20SAndroid Build Coastguard Worker 		yywarn("host bits in IPv4 address set");
5465*2d543d20SAndroid Build Coastguard Worker 
5466*2d543d20SAndroid Build Coastguard Worker 	newc = calloc(1, sizeof(ocontext_t));
5467*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5468*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5469*2d543d20SAndroid Build Coastguard Worker 		return -1;
5470*2d543d20SAndroid Build Coastguard Worker 	}
5471*2d543d20SAndroid Build Coastguard Worker 
5472*2d543d20SAndroid Build Coastguard Worker 	newc->u.node.addr = addr.s_addr & mask;
5473*2d543d20SAndroid Build Coastguard Worker 	newc->u.node.mask = mask;
5474*2d543d20SAndroid Build Coastguard Worker 
5475*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5476*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5477*2d543d20SAndroid Build Coastguard Worker 		return -1;
5478*2d543d20SAndroid Build Coastguard Worker 	}
5479*2d543d20SAndroid Build Coastguard Worker 
5480*2d543d20SAndroid Build Coastguard Worker 	return insert_ipv4_node(newc);
5481*2d543d20SAndroid Build Coastguard Worker }
5482*2d543d20SAndroid Build Coastguard Worker 
ipv6_is_mask_contiguous(const struct in6_addr * mask)5483*2d543d20SAndroid Build Coastguard Worker static int ipv6_is_mask_contiguous(const struct in6_addr *mask)
5484*2d543d20SAndroid Build Coastguard Worker {
5485*2d543d20SAndroid Build Coastguard Worker 	int filled = 1;
5486*2d543d20SAndroid Build Coastguard Worker 	unsigned i;
5487*2d543d20SAndroid Build Coastguard Worker 
5488*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < 16; i++) {
5489*2d543d20SAndroid Build Coastguard Worker 		if ((((~mask->s6_addr[i] & 0xFF) + 1) & (~mask->s6_addr[i] & 0xFF)) != 0) {
5490*2d543d20SAndroid Build Coastguard Worker 			return 0;
5491*2d543d20SAndroid Build Coastguard Worker 		}
5492*2d543d20SAndroid Build Coastguard Worker 		if (!filled && mask->s6_addr[i] != 0) {
5493*2d543d20SAndroid Build Coastguard Worker 			return 0;
5494*2d543d20SAndroid Build Coastguard Worker 		}
5495*2d543d20SAndroid Build Coastguard Worker 
5496*2d543d20SAndroid Build Coastguard Worker 		if (filled && mask->s6_addr[i] != 0xFF) {
5497*2d543d20SAndroid Build Coastguard Worker 			filled = 0;
5498*2d543d20SAndroid Build Coastguard Worker 		}
5499*2d543d20SAndroid Build Coastguard Worker 	}
5500*2d543d20SAndroid Build Coastguard Worker 
5501*2d543d20SAndroid Build Coastguard Worker 	return 1;
5502*2d543d20SAndroid Build Coastguard Worker }
5503*2d543d20SAndroid Build Coastguard Worker 
ipv6_has_host_bits_set(const struct in6_addr * addr,const struct in6_addr * mask)5504*2d543d20SAndroid Build Coastguard Worker static int ipv6_has_host_bits_set(const struct in6_addr *addr, const struct in6_addr *mask)
5505*2d543d20SAndroid Build Coastguard Worker {
5506*2d543d20SAndroid Build Coastguard Worker 	unsigned i;
5507*2d543d20SAndroid Build Coastguard Worker 
5508*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < 16; i++) {
5509*2d543d20SAndroid Build Coastguard Worker 		if ((addr->s6_addr[i] & ~mask->s6_addr[i]) != 0) {
5510*2d543d20SAndroid Build Coastguard Worker 			return 1;
5511*2d543d20SAndroid Build Coastguard Worker 		}
5512*2d543d20SAndroid Build Coastguard Worker 	}
5513*2d543d20SAndroid Build Coastguard Worker 
5514*2d543d20SAndroid Build Coastguard Worker 	return 0;
5515*2d543d20SAndroid Build Coastguard Worker }
5516*2d543d20SAndroid Build Coastguard Worker 
ipv6_cidr_bits_to_mask(unsigned long cidr_bits,struct in6_addr * mask)5517*2d543d20SAndroid Build Coastguard Worker static void ipv6_cidr_bits_to_mask(unsigned long cidr_bits, struct in6_addr *mask)
5518*2d543d20SAndroid Build Coastguard Worker {
5519*2d543d20SAndroid Build Coastguard Worker 	unsigned i;
5520*2d543d20SAndroid Build Coastguard Worker 
5521*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < 4; i++) {
5522*2d543d20SAndroid Build Coastguard Worker 		if (cidr_bits == 0) {
5523*2d543d20SAndroid Build Coastguard Worker 			mask->s6_addr32[i] = 0;
5524*2d543d20SAndroid Build Coastguard Worker 		} else if (cidr_bits >= 32) {
5525*2d543d20SAndroid Build Coastguard Worker 			mask->s6_addr32[i] = ~UINT32_C(0);
5526*2d543d20SAndroid Build Coastguard Worker 		} else {
5527*2d543d20SAndroid Build Coastguard Worker 			mask->s6_addr32[i] = htobe32(~((UINT32_C(1) << (32 - cidr_bits)) - 1));
5528*2d543d20SAndroid Build Coastguard Worker 		}
5529*2d543d20SAndroid Build Coastguard Worker 
5530*2d543d20SAndroid Build Coastguard Worker 		if (cidr_bits >= 32)
5531*2d543d20SAndroid Build Coastguard Worker 			cidr_bits -= 32;
5532*2d543d20SAndroid Build Coastguard Worker 		else
5533*2d543d20SAndroid Build Coastguard Worker 			cidr_bits = 0;
5534*2d543d20SAndroid Build Coastguard Worker 	}
5535*2d543d20SAndroid Build Coastguard Worker }
5536*2d543d20SAndroid Build Coastguard Worker 
insert_ipv6_node(ocontext_t * newc)5537*2d543d20SAndroid Build Coastguard Worker static int insert_ipv6_node(ocontext_t *newc)
5538*2d543d20SAndroid Build Coastguard Worker {
5539*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *l;
5540*2d543d20SAndroid Build Coastguard Worker 	char addr[INET6_ADDRSTRLEN];
5541*2d543d20SAndroid Build Coastguard Worker 	char mask[INET6_ADDRSTRLEN];
5542*2d543d20SAndroid Build Coastguard Worker 
5543*2d543d20SAndroid Build Coastguard Worker 	/* Create order of most specific to least retaining
5544*2d543d20SAndroid Build Coastguard Worker 	   the order specified in the configuration. */
5545*2d543d20SAndroid Build Coastguard Worker 	for (l = NULL, c = policydbp->ocontexts[OCON_NODE6]; c; l = c, c = c->next) {
5546*2d543d20SAndroid Build Coastguard Worker 		if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) == 0 &&
5547*2d543d20SAndroid Build Coastguard Worker 		    memcmp(&newc->u.node6.addr, &c->u.node6.addr, 16) == 0) {
5548*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate entry for network node %s %s",
5549*2d543d20SAndroid Build Coastguard Worker 				 inet_ntop(AF_INET6, &newc->u.node6.addr, addr, INET6_ADDRSTRLEN) ?: "<invalid>",
5550*2d543d20SAndroid Build Coastguard Worker 				 inet_ntop(AF_INET6, &newc->u.node6.mask, mask, INET6_ADDRSTRLEN) ?: "<invalid>");
5551*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[0]);
5552*2d543d20SAndroid Build Coastguard Worker 			free(newc);
5553*2d543d20SAndroid Build Coastguard Worker 			return -1;
5554*2d543d20SAndroid Build Coastguard Worker 		}
5555*2d543d20SAndroid Build Coastguard Worker 
5556*2d543d20SAndroid Build Coastguard Worker 		if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0)
5557*2d543d20SAndroid Build Coastguard Worker 			break;
5558*2d543d20SAndroid Build Coastguard Worker 	}
5559*2d543d20SAndroid Build Coastguard Worker 
5560*2d543d20SAndroid Build Coastguard Worker 	newc->next = c;
5561*2d543d20SAndroid Build Coastguard Worker 
5562*2d543d20SAndroid Build Coastguard Worker 	if (l)
5563*2d543d20SAndroid Build Coastguard Worker 		l->next = newc;
5564*2d543d20SAndroid Build Coastguard Worker 	else
5565*2d543d20SAndroid Build Coastguard Worker 		policydbp->ocontexts[OCON_NODE6] = newc;
5566*2d543d20SAndroid Build Coastguard Worker 
5567*2d543d20SAndroid Build Coastguard Worker 	return 0;
5568*2d543d20SAndroid Build Coastguard Worker }
5569*2d543d20SAndroid Build Coastguard Worker 
define_ipv6_node_context(void)5570*2d543d20SAndroid Build Coastguard Worker int define_ipv6_node_context(void)
5571*2d543d20SAndroid Build Coastguard Worker {
5572*2d543d20SAndroid Build Coastguard Worker 	char *id;
5573*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
5574*2d543d20SAndroid Build Coastguard Worker 	struct in6_addr addr, mask;
5575*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc;
5576*2d543d20SAndroid Build Coastguard Worker 
5577*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5578*2d543d20SAndroid Build Coastguard Worker 		yyerror("nodecon not supported for target");
5579*2d543d20SAndroid Build Coastguard Worker 		return -1;
5580*2d543d20SAndroid Build Coastguard Worker 	}
5581*2d543d20SAndroid Build Coastguard Worker 
5582*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5583*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5584*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5585*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5586*2d543d20SAndroid Build Coastguard Worker 		return 0;
5587*2d543d20SAndroid Build Coastguard Worker 	}
5588*2d543d20SAndroid Build Coastguard Worker 
5589*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5590*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5591*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read ipv6 address");
5592*2d543d20SAndroid Build Coastguard Worker 		return -1;
5593*2d543d20SAndroid Build Coastguard Worker 	}
5594*2d543d20SAndroid Build Coastguard Worker 
5595*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET6, id, &addr);
5596*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5597*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse ipv6 address %s", id);
5598*2d543d20SAndroid Build Coastguard Worker 		free(id);
5599*2d543d20SAndroid Build Coastguard Worker 		return -1;
5600*2d543d20SAndroid Build Coastguard Worker 	}
5601*2d543d20SAndroid Build Coastguard Worker 
5602*2d543d20SAndroid Build Coastguard Worker 	free(id);
5603*2d543d20SAndroid Build Coastguard Worker 
5604*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5605*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5606*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read ipv6 address");
5607*2d543d20SAndroid Build Coastguard Worker 		return -1;
5608*2d543d20SAndroid Build Coastguard Worker 	}
5609*2d543d20SAndroid Build Coastguard Worker 
5610*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET6, id, &mask);
5611*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5612*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse ipv6 mask %s", id);
5613*2d543d20SAndroid Build Coastguard Worker 		free(id);
5614*2d543d20SAndroid Build Coastguard Worker 		return -1;
5615*2d543d20SAndroid Build Coastguard Worker 	}
5616*2d543d20SAndroid Build Coastguard Worker 
5617*2d543d20SAndroid Build Coastguard Worker 	free(id);
5618*2d543d20SAndroid Build Coastguard Worker 
5619*2d543d20SAndroid Build Coastguard Worker 	if (!ipv6_is_mask_contiguous(&mask)) {
5620*2d543d20SAndroid Build Coastguard Worker 		yywarn("ipv6 mask is not contiguous");
5621*2d543d20SAndroid Build Coastguard Worker 	}
5622*2d543d20SAndroid Build Coastguard Worker 
5623*2d543d20SAndroid Build Coastguard Worker 	if (ipv6_has_host_bits_set(&addr, &mask)) {
5624*2d543d20SAndroid Build Coastguard Worker 		yywarn("host bits in ipv6 address set");
5625*2d543d20SAndroid Build Coastguard Worker 	}
5626*2d543d20SAndroid Build Coastguard Worker 
5627*2d543d20SAndroid Build Coastguard Worker 	newc = malloc(sizeof(ocontext_t));
5628*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5629*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5630*2d543d20SAndroid Build Coastguard Worker 		return -1;
5631*2d543d20SAndroid Build Coastguard Worker 	}
5632*2d543d20SAndroid Build Coastguard Worker 
5633*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
5634*2d543d20SAndroid Build Coastguard Worker 	memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16);
5635*2d543d20SAndroid Build Coastguard Worker 	memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16);
5636*2d543d20SAndroid Build Coastguard Worker 
5637*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5638*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5639*2d543d20SAndroid Build Coastguard Worker 		return -1;
5640*2d543d20SAndroid Build Coastguard Worker 	}
5641*2d543d20SAndroid Build Coastguard Worker 
5642*2d543d20SAndroid Build Coastguard Worker 	return insert_ipv6_node(newc);
5643*2d543d20SAndroid Build Coastguard Worker }
5644*2d543d20SAndroid Build Coastguard Worker 
define_ipv6_cidr_node_context(void)5645*2d543d20SAndroid Build Coastguard Worker int define_ipv6_cidr_node_context(void)
5646*2d543d20SAndroid Build Coastguard Worker {
5647*2d543d20SAndroid Build Coastguard Worker 	char *endptr, *id, *split;
5648*2d543d20SAndroid Build Coastguard Worker 	unsigned long mask_bits;
5649*2d543d20SAndroid Build Coastguard Worker 	int rc;
5650*2d543d20SAndroid Build Coastguard Worker 	struct in6_addr addr, mask;
5651*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc;
5652*2d543d20SAndroid Build Coastguard Worker 
5653*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5654*2d543d20SAndroid Build Coastguard Worker 		yyerror("nodecon not supported for target");
5655*2d543d20SAndroid Build Coastguard Worker 		return -1;
5656*2d543d20SAndroid Build Coastguard Worker 	}
5657*2d543d20SAndroid Build Coastguard Worker 
5658*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5659*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5660*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5661*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5662*2d543d20SAndroid Build Coastguard Worker 		return 0;
5663*2d543d20SAndroid Build Coastguard Worker 	}
5664*2d543d20SAndroid Build Coastguard Worker 
5665*2d543d20SAndroid Build Coastguard Worker 	id = queue_remove(id_queue);
5666*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5667*2d543d20SAndroid Build Coastguard Worker 		yyerror("failed to read IPv6 address");
5668*2d543d20SAndroid Build Coastguard Worker 		return -1;
5669*2d543d20SAndroid Build Coastguard Worker 	}
5670*2d543d20SAndroid Build Coastguard Worker 
5671*2d543d20SAndroid Build Coastguard Worker 	split = strchr(id, '/');
5672*2d543d20SAndroid Build Coastguard Worker 	if (!split) {
5673*2d543d20SAndroid Build Coastguard Worker 		yyerror2("invalid IPv6 CIDR notation: %s", id);
5674*2d543d20SAndroid Build Coastguard Worker 		free(id);
5675*2d543d20SAndroid Build Coastguard Worker 		return -1;
5676*2d543d20SAndroid Build Coastguard Worker 	}
5677*2d543d20SAndroid Build Coastguard Worker 	*split = '\0';
5678*2d543d20SAndroid Build Coastguard Worker 
5679*2d543d20SAndroid Build Coastguard Worker 	rc = inet_pton(AF_INET6, id, &addr);
5680*2d543d20SAndroid Build Coastguard Worker 	if (rc < 1) {
5681*2d543d20SAndroid Build Coastguard Worker 		yyerror2("failed to parse IPv6 address %s", id);
5682*2d543d20SAndroid Build Coastguard Worker 		free(id);
5683*2d543d20SAndroid Build Coastguard Worker 		return -1;
5684*2d543d20SAndroid Build Coastguard Worker 	}
5685*2d543d20SAndroid Build Coastguard Worker 
5686*2d543d20SAndroid Build Coastguard Worker 	errno = 0;
5687*2d543d20SAndroid Build Coastguard Worker 	mask_bits = strtoul(split + 1, &endptr, 10);
5688*2d543d20SAndroid Build Coastguard Worker 	if (errno || *endptr != '\0' || mask_bits > 128) {
5689*2d543d20SAndroid Build Coastguard Worker 		yyerror2("invalid mask in IPv6 CIDR notation: %s", split + 1);
5690*2d543d20SAndroid Build Coastguard Worker 		free(id);
5691*2d543d20SAndroid Build Coastguard Worker 		return -1;
5692*2d543d20SAndroid Build Coastguard Worker 	}
5693*2d543d20SAndroid Build Coastguard Worker 
5694*2d543d20SAndroid Build Coastguard Worker 	if (mask_bits == 0) {
5695*2d543d20SAndroid Build Coastguard Worker 		yywarn("IPv6 CIDR mask of 0, matching all IPs");
5696*2d543d20SAndroid Build Coastguard Worker 	}
5697*2d543d20SAndroid Build Coastguard Worker 
5698*2d543d20SAndroid Build Coastguard Worker 	ipv6_cidr_bits_to_mask(mask_bits, &mask);
5699*2d543d20SAndroid Build Coastguard Worker 
5700*2d543d20SAndroid Build Coastguard Worker 	if (ipv6_has_host_bits_set(&addr, &mask)) {
5701*2d543d20SAndroid Build Coastguard Worker 		yywarn("host bits in ipv6 address set");
5702*2d543d20SAndroid Build Coastguard Worker 	}
5703*2d543d20SAndroid Build Coastguard Worker 
5704*2d543d20SAndroid Build Coastguard Worker 	free(id);
5705*2d543d20SAndroid Build Coastguard Worker 
5706*2d543d20SAndroid Build Coastguard Worker 	newc = calloc(1, sizeof(ocontext_t));
5707*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5708*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5709*2d543d20SAndroid Build Coastguard Worker 		return -1;
5710*2d543d20SAndroid Build Coastguard Worker 	}
5711*2d543d20SAndroid Build Coastguard Worker 
5712*2d543d20SAndroid Build Coastguard Worker 	memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16);
5713*2d543d20SAndroid Build Coastguard Worker 	memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16);
5714*2d543d20SAndroid Build Coastguard Worker 
5715*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5716*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5717*2d543d20SAndroid Build Coastguard Worker 		return -1;
5718*2d543d20SAndroid Build Coastguard Worker 	}
5719*2d543d20SAndroid Build Coastguard Worker 
5720*2d543d20SAndroid Build Coastguard Worker 	return insert_ipv6_node(newc);
5721*2d543d20SAndroid Build Coastguard Worker }
5722*2d543d20SAndroid Build Coastguard Worker 
define_fs_use(int behavior)5723*2d543d20SAndroid Build Coastguard Worker int define_fs_use(int behavior)
5724*2d543d20SAndroid Build Coastguard Worker {
5725*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *head;
5726*2d543d20SAndroid Build Coastguard Worker 
5727*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5728*2d543d20SAndroid Build Coastguard Worker 		yyerror("fsuse not supported for target");
5729*2d543d20SAndroid Build Coastguard Worker 		return -1;
5730*2d543d20SAndroid Build Coastguard Worker 	}
5731*2d543d20SAndroid Build Coastguard Worker 
5732*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5733*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5734*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5735*2d543d20SAndroid Build Coastguard Worker 		return 0;
5736*2d543d20SAndroid Build Coastguard Worker 	}
5737*2d543d20SAndroid Build Coastguard Worker 
5738*2d543d20SAndroid Build Coastguard Worker 	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
5739*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5740*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5741*2d543d20SAndroid Build Coastguard Worker 		return -1;
5742*2d543d20SAndroid Build Coastguard Worker 	}
5743*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
5744*2d543d20SAndroid Build Coastguard Worker 
5745*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = (char *)queue_remove(id_queue);
5746*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.name) {
5747*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5748*2d543d20SAndroid Build Coastguard Worker 		return -1;
5749*2d543d20SAndroid Build Coastguard Worker 	}
5750*2d543d20SAndroid Build Coastguard Worker 	newc->v.behavior = behavior;
5751*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0])) {
5752*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
5753*2d543d20SAndroid Build Coastguard Worker 		free(newc);
5754*2d543d20SAndroid Build Coastguard Worker 		return -1;
5755*2d543d20SAndroid Build Coastguard Worker 	}
5756*2d543d20SAndroid Build Coastguard Worker 
5757*2d543d20SAndroid Build Coastguard Worker 	head = policydbp->ocontexts[OCON_FSUSE];
5758*2d543d20SAndroid Build Coastguard Worker 
5759*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
5760*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(newc->u.name, c->u.name)) {
5761*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate fs_use entry for filesystem type %s",
5762*2d543d20SAndroid Build Coastguard Worker 				 newc->u.name);
5763*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&newc->context[0]);
5764*2d543d20SAndroid Build Coastguard Worker 			free(newc->u.name);
5765*2d543d20SAndroid Build Coastguard Worker 			free(newc);
5766*2d543d20SAndroid Build Coastguard Worker 			return -1;
5767*2d543d20SAndroid Build Coastguard Worker 		}
5768*2d543d20SAndroid Build Coastguard Worker 	}
5769*2d543d20SAndroid Build Coastguard Worker 
5770*2d543d20SAndroid Build Coastguard Worker 	newc->next = head;
5771*2d543d20SAndroid Build Coastguard Worker 	policydbp->ocontexts[OCON_FSUSE] = newc;
5772*2d543d20SAndroid Build Coastguard Worker 	return 0;
5773*2d543d20SAndroid Build Coastguard Worker }
5774*2d543d20SAndroid Build Coastguard Worker 
define_genfs_context_helper(char * fstype,int has_type)5775*2d543d20SAndroid Build Coastguard Worker static int define_genfs_context_helper(char *fstype, int has_type)
5776*2d543d20SAndroid Build Coastguard Worker {
5777*2d543d20SAndroid Build Coastguard Worker 	struct genfs *genfs_p, *genfs, *newgenfs;
5778*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *newc, *c, *head, *p;
5779*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
5780*2d543d20SAndroid Build Coastguard Worker 	char *type = NULL;
5781*2d543d20SAndroid Build Coastguard Worker 	const char *sclass;
5782*2d543d20SAndroid Build Coastguard Worker 	size_t len, len2;
5783*2d543d20SAndroid Build Coastguard Worker 
5784*2d543d20SAndroid Build Coastguard Worker 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5785*2d543d20SAndroid Build Coastguard Worker 		yyerror("genfs not supported for target");
5786*2d543d20SAndroid Build Coastguard Worker 		return -1;
5787*2d543d20SAndroid Build Coastguard Worker 	}
5788*2d543d20SAndroid Build Coastguard Worker 
5789*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5790*2d543d20SAndroid Build Coastguard Worker 		free(fstype);
5791*2d543d20SAndroid Build Coastguard Worker 		free(queue_remove(id_queue));
5792*2d543d20SAndroid Build Coastguard Worker 		if (has_type)
5793*2d543d20SAndroid Build Coastguard Worker 			free(queue_remove(id_queue));
5794*2d543d20SAndroid Build Coastguard Worker 		parse_security_context(NULL);
5795*2d543d20SAndroid Build Coastguard Worker 		return 0;
5796*2d543d20SAndroid Build Coastguard Worker 	}
5797*2d543d20SAndroid Build Coastguard Worker 
5798*2d543d20SAndroid Build Coastguard Worker 	for (genfs_p = NULL, genfs = policydbp->genfs;
5799*2d543d20SAndroid Build Coastguard Worker 	     genfs; genfs_p = genfs, genfs = genfs->next) {
5800*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(fstype, genfs->fstype) <= 0)
5801*2d543d20SAndroid Build Coastguard Worker 			break;
5802*2d543d20SAndroid Build Coastguard Worker 	}
5803*2d543d20SAndroid Build Coastguard Worker 
5804*2d543d20SAndroid Build Coastguard Worker 	if (!genfs || strcmp(fstype, genfs->fstype)) {
5805*2d543d20SAndroid Build Coastguard Worker 		newgenfs = malloc(sizeof(struct genfs));
5806*2d543d20SAndroid Build Coastguard Worker 		if (!newgenfs) {
5807*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
5808*2d543d20SAndroid Build Coastguard Worker 			return -1;
5809*2d543d20SAndroid Build Coastguard Worker 		}
5810*2d543d20SAndroid Build Coastguard Worker 		memset(newgenfs, 0, sizeof(struct genfs));
5811*2d543d20SAndroid Build Coastguard Worker 		newgenfs->fstype = fstype;
5812*2d543d20SAndroid Build Coastguard Worker 		newgenfs->next = genfs;
5813*2d543d20SAndroid Build Coastguard Worker 		if (genfs_p)
5814*2d543d20SAndroid Build Coastguard Worker 			genfs_p->next = newgenfs;
5815*2d543d20SAndroid Build Coastguard Worker 		else
5816*2d543d20SAndroid Build Coastguard Worker 			policydbp->genfs = newgenfs;
5817*2d543d20SAndroid Build Coastguard Worker 		genfs = newgenfs;
5818*2d543d20SAndroid Build Coastguard Worker 	} else {
5819*2d543d20SAndroid Build Coastguard Worker 		free(fstype);
5820*2d543d20SAndroid Build Coastguard Worker 		fstype = NULL;
5821*2d543d20SAndroid Build Coastguard Worker 	}
5822*2d543d20SAndroid Build Coastguard Worker 
5823*2d543d20SAndroid Build Coastguard Worker 	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
5824*2d543d20SAndroid Build Coastguard Worker 	if (!newc) {
5825*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5826*2d543d20SAndroid Build Coastguard Worker 		return -1;
5827*2d543d20SAndroid Build Coastguard Worker 	}
5828*2d543d20SAndroid Build Coastguard Worker 	memset(newc, 0, sizeof(ocontext_t));
5829*2d543d20SAndroid Build Coastguard Worker 
5830*2d543d20SAndroid Build Coastguard Worker 	newc->u.name = (char *)queue_remove(id_queue);
5831*2d543d20SAndroid Build Coastguard Worker 	if (!newc->u.name)
5832*2d543d20SAndroid Build Coastguard Worker 		goto fail;
5833*2d543d20SAndroid Build Coastguard Worker 	if (has_type) {
5834*2d543d20SAndroid Build Coastguard Worker 		type = (char *)queue_remove(id_queue);
5835*2d543d20SAndroid Build Coastguard Worker 		if (!type)
5836*2d543d20SAndroid Build Coastguard Worker 			goto fail;
5837*2d543d20SAndroid Build Coastguard Worker 		if (type[1] != 0) {
5838*2d543d20SAndroid Build Coastguard Worker 			yyerror2("invalid type %s", type);
5839*2d543d20SAndroid Build Coastguard Worker 			goto fail;
5840*2d543d20SAndroid Build Coastguard Worker 		}
5841*2d543d20SAndroid Build Coastguard Worker 		switch (type[0]) {
5842*2d543d20SAndroid Build Coastguard Worker 		case 'b':
5843*2d543d20SAndroid Build Coastguard Worker 			sclass = "blk_file";
5844*2d543d20SAndroid Build Coastguard Worker 			break;
5845*2d543d20SAndroid Build Coastguard Worker 		case 'c':
5846*2d543d20SAndroid Build Coastguard Worker 			sclass = "chr_file";
5847*2d543d20SAndroid Build Coastguard Worker 			break;
5848*2d543d20SAndroid Build Coastguard Worker 		case 'd':
5849*2d543d20SAndroid Build Coastguard Worker 			sclass = "dir";
5850*2d543d20SAndroid Build Coastguard Worker 			break;
5851*2d543d20SAndroid Build Coastguard Worker 		case 'p':
5852*2d543d20SAndroid Build Coastguard Worker 			sclass = "fifo_file";
5853*2d543d20SAndroid Build Coastguard Worker 			break;
5854*2d543d20SAndroid Build Coastguard Worker 		case 'l':
5855*2d543d20SAndroid Build Coastguard Worker 			sclass = "lnk_file";
5856*2d543d20SAndroid Build Coastguard Worker 			break;
5857*2d543d20SAndroid Build Coastguard Worker 		case 's':
5858*2d543d20SAndroid Build Coastguard Worker 			sclass = "sock_file";
5859*2d543d20SAndroid Build Coastguard Worker 			break;
5860*2d543d20SAndroid Build Coastguard Worker 		case '-':
5861*2d543d20SAndroid Build Coastguard Worker 			sclass = "file";
5862*2d543d20SAndroid Build Coastguard Worker 			break;
5863*2d543d20SAndroid Build Coastguard Worker 		default:
5864*2d543d20SAndroid Build Coastguard Worker 			yyerror2("invalid type %s", type);
5865*2d543d20SAndroid Build Coastguard Worker 			goto fail;
5866*2d543d20SAndroid Build Coastguard Worker 		}
5867*2d543d20SAndroid Build Coastguard Worker 
5868*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table,
5869*2d543d20SAndroid Build Coastguard Worker 					  sclass);
5870*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
5871*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not find class %s for "
5872*2d543d20SAndroid Build Coastguard Worker 				 "genfscon statement", sclass);
5873*2d543d20SAndroid Build Coastguard Worker 			goto fail;
5874*2d543d20SAndroid Build Coastguard Worker 		}
5875*2d543d20SAndroid Build Coastguard Worker 		newc->v.sclass = cladatum->s.value;
5876*2d543d20SAndroid Build Coastguard Worker 	}
5877*2d543d20SAndroid Build Coastguard Worker 	if (parse_security_context(&newc->context[0]))
5878*2d543d20SAndroid Build Coastguard Worker 		goto fail;
5879*2d543d20SAndroid Build Coastguard Worker 
5880*2d543d20SAndroid Build Coastguard Worker 	head = genfs->head;
5881*2d543d20SAndroid Build Coastguard Worker 
5882*2d543d20SAndroid Build Coastguard Worker 	for (p = NULL, c = head; c; p = c, c = c->next) {
5883*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(newc->u.name, c->u.name) &&
5884*2d543d20SAndroid Build Coastguard Worker 		    (!newc->v.sclass || !c->v.sclass
5885*2d543d20SAndroid Build Coastguard Worker 		     || newc->v.sclass == c->v.sclass)) {
5886*2d543d20SAndroid Build Coastguard Worker 			yyerror2("duplicate entry for genfs entry (%s, %s)",
5887*2d543d20SAndroid Build Coastguard Worker 				 genfs->fstype, newc->u.name);
5888*2d543d20SAndroid Build Coastguard Worker 			goto fail;
5889*2d543d20SAndroid Build Coastguard Worker 		}
5890*2d543d20SAndroid Build Coastguard Worker 		len = strlen(newc->u.name);
5891*2d543d20SAndroid Build Coastguard Worker 		len2 = strlen(c->u.name);
5892*2d543d20SAndroid Build Coastguard Worker 		if (len > len2)
5893*2d543d20SAndroid Build Coastguard Worker 			break;
5894*2d543d20SAndroid Build Coastguard Worker 	}
5895*2d543d20SAndroid Build Coastguard Worker 
5896*2d543d20SAndroid Build Coastguard Worker 	newc->next = c;
5897*2d543d20SAndroid Build Coastguard Worker 	if (p)
5898*2d543d20SAndroid Build Coastguard Worker 		p->next = newc;
5899*2d543d20SAndroid Build Coastguard Worker 	else
5900*2d543d20SAndroid Build Coastguard Worker 		genfs->head = newc;
5901*2d543d20SAndroid Build Coastguard Worker 	free(type);
5902*2d543d20SAndroid Build Coastguard Worker 	return 0;
5903*2d543d20SAndroid Build Coastguard Worker       fail:
5904*2d543d20SAndroid Build Coastguard Worker 	if (type)
5905*2d543d20SAndroid Build Coastguard Worker 		free(type);
5906*2d543d20SAndroid Build Coastguard Worker 	context_destroy(&newc->context[0]);
5907*2d543d20SAndroid Build Coastguard Worker 	if (fstype)
5908*2d543d20SAndroid Build Coastguard Worker 		free(fstype);
5909*2d543d20SAndroid Build Coastguard Worker 	if (newc->u.name)
5910*2d543d20SAndroid Build Coastguard Worker 		free(newc->u.name);
5911*2d543d20SAndroid Build Coastguard Worker 	free(newc);
5912*2d543d20SAndroid Build Coastguard Worker 	return -1;
5913*2d543d20SAndroid Build Coastguard Worker }
5914*2d543d20SAndroid Build Coastguard Worker 
define_genfs_context(int has_type)5915*2d543d20SAndroid Build Coastguard Worker int define_genfs_context(int has_type)
5916*2d543d20SAndroid Build Coastguard Worker {
5917*2d543d20SAndroid Build Coastguard Worker 	return define_genfs_context_helper(queue_remove(id_queue), has_type);
5918*2d543d20SAndroid Build Coastguard Worker }
5919*2d543d20SAndroid Build Coastguard Worker 
define_range_trans(int class_specified)5920*2d543d20SAndroid Build Coastguard Worker int define_range_trans(int class_specified)
5921*2d543d20SAndroid Build Coastguard Worker {
5922*2d543d20SAndroid Build Coastguard Worker 	char *id;
5923*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum = 0;
5924*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
5925*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_t *rule;
5926*2d543d20SAndroid Build Coastguard Worker 	int l, add = 1;
5927*2d543d20SAndroid Build Coastguard Worker 
5928*2d543d20SAndroid Build Coastguard Worker 	if (!mlspol) {
5929*2d543d20SAndroid Build Coastguard Worker 		yyerror("range_transition rule in non-MLS configuration");
5930*2d543d20SAndroid Build Coastguard Worker 		return -1;
5931*2d543d20SAndroid Build Coastguard Worker 	}
5932*2d543d20SAndroid Build Coastguard Worker 
5933*2d543d20SAndroid Build Coastguard Worker 	if (pass == 1) {
5934*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
5935*2d543d20SAndroid Build Coastguard Worker 			free(id);
5936*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue)))
5937*2d543d20SAndroid Build Coastguard Worker 			free(id);
5938*2d543d20SAndroid Build Coastguard Worker 		if (class_specified)
5939*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue)))
5940*2d543d20SAndroid Build Coastguard Worker 				free(id);
5941*2d543d20SAndroid Build Coastguard Worker 		id = queue_remove(id_queue);
5942*2d543d20SAndroid Build Coastguard Worker 		free(id);
5943*2d543d20SAndroid Build Coastguard Worker 		for (l = 0; l < 2; l++) {
5944*2d543d20SAndroid Build Coastguard Worker 			while ((id = queue_remove(id_queue))) {
5945*2d543d20SAndroid Build Coastguard Worker 				free(id);
5946*2d543d20SAndroid Build Coastguard Worker 			}
5947*2d543d20SAndroid Build Coastguard Worker 			id = queue_remove(id_queue);
5948*2d543d20SAndroid Build Coastguard Worker 			if (!id)
5949*2d543d20SAndroid Build Coastguard Worker 				break;
5950*2d543d20SAndroid Build Coastguard Worker 			free(id);
5951*2d543d20SAndroid Build Coastguard Worker 		}
5952*2d543d20SAndroid Build Coastguard Worker 		return 0;
5953*2d543d20SAndroid Build Coastguard Worker 	}
5954*2d543d20SAndroid Build Coastguard Worker 
5955*2d543d20SAndroid Build Coastguard Worker 	rule = malloc(sizeof(struct range_trans_rule));
5956*2d543d20SAndroid Build Coastguard Worker 	if (!rule) {
5957*2d543d20SAndroid Build Coastguard Worker 		yyerror("out of memory");
5958*2d543d20SAndroid Build Coastguard Worker 		return -1;
5959*2d543d20SAndroid Build Coastguard Worker 	}
5960*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_init(rule);
5961*2d543d20SAndroid Build Coastguard Worker 
5962*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
5963*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&rule->stypes, id, &add, 0))
5964*2d543d20SAndroid Build Coastguard Worker 			goto out;
5965*2d543d20SAndroid Build Coastguard Worker 	}
5966*2d543d20SAndroid Build Coastguard Worker 	add = 1;
5967*2d543d20SAndroid Build Coastguard Worker 	while ((id = queue_remove(id_queue))) {
5968*2d543d20SAndroid Build Coastguard Worker 		if (set_types(&rule->ttypes, id, &add, 0))
5969*2d543d20SAndroid Build Coastguard Worker 			goto out;
5970*2d543d20SAndroid Build Coastguard Worker 	}
5971*2d543d20SAndroid Build Coastguard Worker 
5972*2d543d20SAndroid Build Coastguard Worker 	if (class_specified) {
5973*2d543d20SAndroid Build Coastguard Worker 		if (read_classes(&rule->tclasses))
5974*2d543d20SAndroid Build Coastguard Worker 			goto out;
5975*2d543d20SAndroid Build Coastguard Worker 	} else {
5976*2d543d20SAndroid Build Coastguard Worker 		cladatum = hashtab_search(policydbp->p_classes.table,
5977*2d543d20SAndroid Build Coastguard Worker 		                          "process");
5978*2d543d20SAndroid Build Coastguard Worker 		if (!cladatum) {
5979*2d543d20SAndroid Build Coastguard Worker 			yyerror2("could not find process class for "
5980*2d543d20SAndroid Build Coastguard Worker 			         "legacy range_transition statement");
5981*2d543d20SAndroid Build Coastguard Worker 			goto out;
5982*2d543d20SAndroid Build Coastguard Worker 		}
5983*2d543d20SAndroid Build Coastguard Worker 
5984*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_set_bit(&rule->tclasses, cladatum->s.value - 1, TRUE)) {
5985*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
5986*2d543d20SAndroid Build Coastguard Worker 			goto out;
5987*2d543d20SAndroid Build Coastguard Worker 		}
5988*2d543d20SAndroid Build Coastguard Worker 	}
5989*2d543d20SAndroid Build Coastguard Worker 
5990*2d543d20SAndroid Build Coastguard Worker 	id = (char *)queue_remove(id_queue);
5991*2d543d20SAndroid Build Coastguard Worker 	if (!id) {
5992*2d543d20SAndroid Build Coastguard Worker 		yyerror("no range in range_transition definition?");
5993*2d543d20SAndroid Build Coastguard Worker 		goto out;
5994*2d543d20SAndroid Build Coastguard Worker 	}
5995*2d543d20SAndroid Build Coastguard Worker 	for (l = 0; l < 2; l++) {
5996*2d543d20SAndroid Build Coastguard Worker 		levdatum = hashtab_search(policydbp->p_levels.table, id);
5997*2d543d20SAndroid Build Coastguard Worker 		if (!levdatum) {
5998*2d543d20SAndroid Build Coastguard Worker 			yyerror2("unknown level %s used in range_transition "
5999*2d543d20SAndroid Build Coastguard Worker 			         "definition", id);
6000*2d543d20SAndroid Build Coastguard Worker 			free(id);
6001*2d543d20SAndroid Build Coastguard Worker 			goto out;
6002*2d543d20SAndroid Build Coastguard Worker 		}
6003*2d543d20SAndroid Build Coastguard Worker 		free(id);
6004*2d543d20SAndroid Build Coastguard Worker 
6005*2d543d20SAndroid Build Coastguard Worker 		rule->trange.level[l].sens = levdatum->level->sens;
6006*2d543d20SAndroid Build Coastguard Worker 
6007*2d543d20SAndroid Build Coastguard Worker 		while ((id = queue_remove(id_queue))) {
6008*2d543d20SAndroid Build Coastguard Worker 			if (parse_semantic_categories(id, levdatum,
6009*2d543d20SAndroid Build Coastguard Worker 			                          &rule->trange.level[l].cat)) {
6010*2d543d20SAndroid Build Coastguard Worker 				free(id);
6011*2d543d20SAndroid Build Coastguard Worker 				goto out;
6012*2d543d20SAndroid Build Coastguard Worker 			}
6013*2d543d20SAndroid Build Coastguard Worker 			free(id);
6014*2d543d20SAndroid Build Coastguard Worker 		}
6015*2d543d20SAndroid Build Coastguard Worker 
6016*2d543d20SAndroid Build Coastguard Worker 		id = (char *)queue_remove(id_queue);
6017*2d543d20SAndroid Build Coastguard Worker 		if (!id)
6018*2d543d20SAndroid Build Coastguard Worker 			break;
6019*2d543d20SAndroid Build Coastguard Worker 	}
6020*2d543d20SAndroid Build Coastguard Worker 	if (l == 0) {
6021*2d543d20SAndroid Build Coastguard Worker 		if (mls_semantic_level_cpy(&rule->trange.level[1],
6022*2d543d20SAndroid Build Coastguard Worker 		                           &rule->trange.level[0])) {
6023*2d543d20SAndroid Build Coastguard Worker 			yyerror("out of memory");
6024*2d543d20SAndroid Build Coastguard Worker 			goto out;
6025*2d543d20SAndroid Build Coastguard Worker 		}
6026*2d543d20SAndroid Build Coastguard Worker 	}
6027*2d543d20SAndroid Build Coastguard Worker 
6028*2d543d20SAndroid Build Coastguard Worker 	append_range_trans(rule);
6029*2d543d20SAndroid Build Coastguard Worker 	return 0;
6030*2d543d20SAndroid Build Coastguard Worker 
6031*2d543d20SAndroid Build Coastguard Worker out:
6032*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_destroy(rule);
6033*2d543d20SAndroid Build Coastguard Worker 	free(rule);
6034*2d543d20SAndroid Build Coastguard Worker 	return -1;
6035*2d543d20SAndroid Build Coastguard Worker }
6036*2d543d20SAndroid Build Coastguard Worker 
6037*2d543d20SAndroid Build Coastguard Worker /* FLASK */
6038