xref: /aosp_15_r20/external/selinux/libsepol/src/services.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  * Updated: Trusted Computer Solutions, Inc. <[email protected]>
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  *	Support for enhanced MLS infrastructure.
8*2d543d20SAndroid Build Coastguard Worker  *
9*2d543d20SAndroid Build Coastguard Worker  * Updated: Frank Mayer <[email protected]>
10*2d543d20SAndroid Build Coastguard Worker  *          and Karl MacMillan <[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: Red Hat, Inc.  James Morris <[email protected]>
15*2d543d20SAndroid Build Coastguard Worker  *
16*2d543d20SAndroid Build Coastguard Worker  *      Fine-grained netlink support
17*2d543d20SAndroid Build Coastguard Worker  *      IPv6 support
18*2d543d20SAndroid Build Coastguard Worker  *      Code cleanup
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 - 2004 Tresys Technology, LLC
22*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2003 - 2004 Red Hat, Inc.
23*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2017 Mellanox Technologies Inc.
24*2d543d20SAndroid Build Coastguard Worker  *
25*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
26*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
27*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
28*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
29*2d543d20SAndroid Build Coastguard Worker  *
30*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
31*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
32*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
33*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
34*2d543d20SAndroid Build Coastguard Worker  *
35*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
36*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
37*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
38*2d543d20SAndroid Build Coastguard Worker  */
39*2d543d20SAndroid Build Coastguard Worker 
40*2d543d20SAndroid Build Coastguard Worker /* FLASK */
41*2d543d20SAndroid Build Coastguard Worker 
42*2d543d20SAndroid Build Coastguard Worker /*
43*2d543d20SAndroid Build Coastguard Worker  * Implementation of the security services.
44*2d543d20SAndroid Build Coastguard Worker  */
45*2d543d20SAndroid Build Coastguard Worker 
46*2d543d20SAndroid Build Coastguard Worker /* Initial sizes malloc'd for sepol_compute_av_reason_buffer() support */
47*2d543d20SAndroid Build Coastguard Worker #define REASON_BUF_SIZE 2048
48*2d543d20SAndroid Build Coastguard Worker #define EXPR_BUF_SIZE 1024
49*2d543d20SAndroid Build Coastguard Worker #define STACK_LEN 32
50*2d543d20SAndroid Build Coastguard Worker 
51*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
52*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
53*2d543d20SAndroid Build Coastguard Worker #include <sys/socket.h>
54*2d543d20SAndroid Build Coastguard Worker #include <netinet/in.h>
55*2d543d20SAndroid Build Coastguard Worker #include <arpa/inet.h>
56*2d543d20SAndroid Build Coastguard Worker 
57*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
58*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/sidtab.h>
59*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/services.h>
60*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
61*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/util.h>
62*2d543d20SAndroid Build Coastguard Worker #include <sepol/sepol.h>
63*2d543d20SAndroid Build Coastguard Worker 
64*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
65*2d543d20SAndroid Build Coastguard Worker #include "private.h"
66*2d543d20SAndroid Build Coastguard Worker #include "context.h"
67*2d543d20SAndroid Build Coastguard Worker #include "mls.h"
68*2d543d20SAndroid Build Coastguard Worker #include "flask.h"
69*2d543d20SAndroid Build Coastguard Worker 
70*2d543d20SAndroid Build Coastguard Worker #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
71*2d543d20SAndroid Build Coastguard Worker 
72*2d543d20SAndroid Build Coastguard Worker static int selinux_enforcing = 1;
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker static sidtab_t mysidtab, *sidtab = &mysidtab;
75*2d543d20SAndroid Build Coastguard Worker static policydb_t mypolicydb, *policydb = &mypolicydb;
76*2d543d20SAndroid Build Coastguard Worker 
77*2d543d20SAndroid Build Coastguard Worker /* Used by sepol_compute_av_reason_buffer() to keep track of entries */
78*2d543d20SAndroid Build Coastguard Worker static int reason_buf_used;
79*2d543d20SAndroid Build Coastguard Worker static int reason_buf_len;
80*2d543d20SAndroid Build Coastguard Worker 
81*2d543d20SAndroid Build Coastguard Worker /* Stack services for RPN to infix conversion. */
82*2d543d20SAndroid Build Coastguard Worker static char **stack;
83*2d543d20SAndroid Build Coastguard Worker static int stack_len;
84*2d543d20SAndroid Build Coastguard Worker static int next_stack_entry;
85*2d543d20SAndroid Build Coastguard Worker 
push(char * expr_ptr)86*2d543d20SAndroid Build Coastguard Worker static void push(char *expr_ptr)
87*2d543d20SAndroid Build Coastguard Worker {
88*2d543d20SAndroid Build Coastguard Worker 	if (next_stack_entry >= stack_len) {
89*2d543d20SAndroid Build Coastguard Worker 		char **new_stack;
90*2d543d20SAndroid Build Coastguard Worker 		int new_stack_len;
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker 		if (stack_len == 0)
93*2d543d20SAndroid Build Coastguard Worker 			new_stack_len = STACK_LEN;
94*2d543d20SAndroid Build Coastguard Worker 		else
95*2d543d20SAndroid Build Coastguard Worker 			new_stack_len = stack_len * 2;
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker 		new_stack = reallocarray(stack, new_stack_len, sizeof(*stack));
98*2d543d20SAndroid Build Coastguard Worker 		if (!new_stack) {
99*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "unable to allocate stack space");
100*2d543d20SAndroid Build Coastguard Worker 			return;
101*2d543d20SAndroid Build Coastguard Worker 		}
102*2d543d20SAndroid Build Coastguard Worker 		stack_len = new_stack_len;
103*2d543d20SAndroid Build Coastguard Worker 		stack = new_stack;
104*2d543d20SAndroid Build Coastguard Worker 	}
105*2d543d20SAndroid Build Coastguard Worker 	stack[next_stack_entry] = expr_ptr;
106*2d543d20SAndroid Build Coastguard Worker 	next_stack_entry++;
107*2d543d20SAndroid Build Coastguard Worker }
108*2d543d20SAndroid Build Coastguard Worker 
pop(void)109*2d543d20SAndroid Build Coastguard Worker static char *pop(void)
110*2d543d20SAndroid Build Coastguard Worker {
111*2d543d20SAndroid Build Coastguard Worker 	next_stack_entry--;
112*2d543d20SAndroid Build Coastguard Worker 	if (next_stack_entry < 0) {
113*2d543d20SAndroid Build Coastguard Worker 		next_stack_entry = 0;
114*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "pop called with no stack entries");
115*2d543d20SAndroid Build Coastguard Worker 		return NULL;
116*2d543d20SAndroid Build Coastguard Worker 	}
117*2d543d20SAndroid Build Coastguard Worker 	return stack[next_stack_entry];
118*2d543d20SAndroid Build Coastguard Worker }
119*2d543d20SAndroid Build Coastguard Worker /* End Stack services */
120*2d543d20SAndroid Build Coastguard Worker 
sepol_set_sidtab(sidtab_t * s)121*2d543d20SAndroid Build Coastguard Worker int sepol_set_sidtab(sidtab_t * s)
122*2d543d20SAndroid Build Coastguard Worker {
123*2d543d20SAndroid Build Coastguard Worker 	sidtab = s;
124*2d543d20SAndroid Build Coastguard Worker 	return 0;
125*2d543d20SAndroid Build Coastguard Worker }
126*2d543d20SAndroid Build Coastguard Worker 
sepol_set_policydb(policydb_t * p)127*2d543d20SAndroid Build Coastguard Worker int sepol_set_policydb(policydb_t * p)
128*2d543d20SAndroid Build Coastguard Worker {
129*2d543d20SAndroid Build Coastguard Worker 	policydb = p;
130*2d543d20SAndroid Build Coastguard Worker 	return 0;
131*2d543d20SAndroid Build Coastguard Worker }
132*2d543d20SAndroid Build Coastguard Worker 
sepol_set_policydb_from_file(FILE * fp)133*2d543d20SAndroid Build Coastguard Worker int sepol_set_policydb_from_file(FILE * fp)
134*2d543d20SAndroid Build Coastguard Worker {
135*2d543d20SAndroid Build Coastguard Worker 	struct policy_file pf;
136*2d543d20SAndroid Build Coastguard Worker 
137*2d543d20SAndroid Build Coastguard Worker 	policy_file_init(&pf);
138*2d543d20SAndroid Build Coastguard Worker 	pf.fp = fp;
139*2d543d20SAndroid Build Coastguard Worker 	pf.type = PF_USE_STDIO;
140*2d543d20SAndroid Build Coastguard Worker 	if (mypolicydb.policy_type)
141*2d543d20SAndroid Build Coastguard Worker 		policydb_destroy(&mypolicydb);
142*2d543d20SAndroid Build Coastguard Worker 	if (policydb_init(&mypolicydb)) {
143*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "Out of memory!");
144*2d543d20SAndroid Build Coastguard Worker 		return -1;
145*2d543d20SAndroid Build Coastguard Worker 	}
146*2d543d20SAndroid Build Coastguard Worker 	if (policydb_read(&mypolicydb, &pf, 0)) {
147*2d543d20SAndroid Build Coastguard Worker 		policydb_destroy(&mypolicydb);
148*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "can't read binary policy: %m");
149*2d543d20SAndroid Build Coastguard Worker 		return -1;
150*2d543d20SAndroid Build Coastguard Worker 	}
151*2d543d20SAndroid Build Coastguard Worker 	policydb = &mypolicydb;
152*2d543d20SAndroid Build Coastguard Worker 	return sepol_sidtab_init(sidtab);
153*2d543d20SAndroid Build Coastguard Worker }
154*2d543d20SAndroid Build Coastguard Worker 
155*2d543d20SAndroid Build Coastguard Worker /*
156*2d543d20SAndroid Build Coastguard Worker  * The largest sequence number that has been used when
157*2d543d20SAndroid Build Coastguard Worker  * providing an access decision to the access vector cache.
158*2d543d20SAndroid Build Coastguard Worker  * The sequence number only changes when a policy change
159*2d543d20SAndroid Build Coastguard Worker  * occurs.
160*2d543d20SAndroid Build Coastguard Worker  */
161*2d543d20SAndroid Build Coastguard Worker static uint32_t latest_granting = 0;
162*2d543d20SAndroid Build Coastguard Worker 
163*2d543d20SAndroid Build Coastguard Worker /*
164*2d543d20SAndroid Build Coastguard Worker  * cat_expr_buf adds a string to an expression buffer and handles
165*2d543d20SAndroid Build Coastguard Worker  * realloc's if buffer is too small. The array of expression text
166*2d543d20SAndroid Build Coastguard Worker  * buffer pointers and its counter are globally defined here as
167*2d543d20SAndroid Build Coastguard Worker  * constraint_expr_eval_reason() sets them up and cat_expr_buf
168*2d543d20SAndroid Build Coastguard Worker  * updates the e_buf pointer.
169*2d543d20SAndroid Build Coastguard Worker  */
170*2d543d20SAndroid Build Coastguard Worker static int expr_counter;
171*2d543d20SAndroid Build Coastguard Worker static char **expr_list;
172*2d543d20SAndroid Build Coastguard Worker static int expr_buf_used;
173*2d543d20SAndroid Build Coastguard Worker static int expr_buf_len;
174*2d543d20SAndroid Build Coastguard Worker 
cat_expr_buf(char * e_buf,const char * string)175*2d543d20SAndroid Build Coastguard Worker static void cat_expr_buf(char *e_buf, const char *string)
176*2d543d20SAndroid Build Coastguard Worker {
177*2d543d20SAndroid Build Coastguard Worker 	int len, new_buf_len;
178*2d543d20SAndroid Build Coastguard Worker 	char *p, *new_buf;
179*2d543d20SAndroid Build Coastguard Worker 
180*2d543d20SAndroid Build Coastguard Worker 	while (1) {
181*2d543d20SAndroid Build Coastguard Worker 		p = e_buf + expr_buf_used;
182*2d543d20SAndroid Build Coastguard Worker 		len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string);
183*2d543d20SAndroid Build Coastguard Worker 		if (len < 0 || len >= expr_buf_len - expr_buf_used) {
184*2d543d20SAndroid Build Coastguard Worker 			new_buf_len = expr_buf_len + EXPR_BUF_SIZE;
185*2d543d20SAndroid Build Coastguard Worker 			new_buf = realloc(e_buf, new_buf_len);
186*2d543d20SAndroid Build Coastguard Worker 			if (!new_buf) {
187*2d543d20SAndroid Build Coastguard Worker 				ERR(NULL, "failed to realloc expr buffer");
188*2d543d20SAndroid Build Coastguard Worker 				return;
189*2d543d20SAndroid Build Coastguard Worker 			}
190*2d543d20SAndroid Build Coastguard Worker 			/* Update new ptr in expr list and locally + new len */
191*2d543d20SAndroid Build Coastguard Worker 			expr_list[expr_counter] = new_buf;
192*2d543d20SAndroid Build Coastguard Worker 			e_buf = new_buf;
193*2d543d20SAndroid Build Coastguard Worker 			expr_buf_len = new_buf_len;
194*2d543d20SAndroid Build Coastguard Worker 		} else {
195*2d543d20SAndroid Build Coastguard Worker 			expr_buf_used += len;
196*2d543d20SAndroid Build Coastguard Worker 			return;
197*2d543d20SAndroid Build Coastguard Worker 		}
198*2d543d20SAndroid Build Coastguard Worker 	}
199*2d543d20SAndroid Build Coastguard Worker }
200*2d543d20SAndroid Build Coastguard Worker 
201*2d543d20SAndroid Build Coastguard Worker /*
202*2d543d20SAndroid Build Coastguard Worker  * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES,
203*2d543d20SAndroid Build Coastguard Worker  * then for 'types' only, read the types_names->types list as it will
204*2d543d20SAndroid Build Coastguard Worker  * contain a list of types and attributes that were defined in the
205*2d543d20SAndroid Build Coastguard Worker  * policy source.
206*2d543d20SAndroid Build Coastguard Worker  * For user and role plus types (for policy vers <
207*2d543d20SAndroid Build Coastguard Worker  * POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list.
208*2d543d20SAndroid Build Coastguard Worker  */
get_name_list(constraint_expr_t * e,int type,const char * src,const char * op,int failed)209*2d543d20SAndroid Build Coastguard Worker static void get_name_list(constraint_expr_t *e, int type,
210*2d543d20SAndroid Build Coastguard Worker 							const char *src, const char *op, int failed)
211*2d543d20SAndroid Build Coastguard Worker {
212*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t *types;
213*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
214*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
215*2d543d20SAndroid Build Coastguard Worker 	char tmp_buf[128];
216*2d543d20SAndroid Build Coastguard Worker 	int counter = 0;
217*2d543d20SAndroid Build Coastguard Worker 
218*2d543d20SAndroid Build Coastguard Worker 	if (policydb->policy_type == POLICY_KERN &&
219*2d543d20SAndroid Build Coastguard Worker 			policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES &&
220*2d543d20SAndroid Build Coastguard Worker 			type == CEXPR_TYPE)
221*2d543d20SAndroid Build Coastguard Worker 		types = &e->type_names->types;
222*2d543d20SAndroid Build Coastguard Worker 	else
223*2d543d20SAndroid Build Coastguard Worker 		types = &e->names;
224*2d543d20SAndroid Build Coastguard Worker 
225*2d543d20SAndroid Build Coastguard Worker 	/* Find out how many entries */
226*2d543d20SAndroid Build Coastguard Worker 	for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
227*2d543d20SAndroid Build Coastguard Worker 		rc = ebitmap_get_bit(types, i);
228*2d543d20SAndroid Build Coastguard Worker 		if (rc == 0)
229*2d543d20SAndroid Build Coastguard Worker 			continue;
230*2d543d20SAndroid Build Coastguard Worker 		else
231*2d543d20SAndroid Build Coastguard Worker 			counter++;
232*2d543d20SAndroid Build Coastguard Worker 	}
233*2d543d20SAndroid Build Coastguard Worker 	snprintf(tmp_buf, sizeof(tmp_buf), "(%s%s", src, op);
234*2d543d20SAndroid Build Coastguard Worker 	cat_expr_buf(expr_list[expr_counter], tmp_buf);
235*2d543d20SAndroid Build Coastguard Worker 
236*2d543d20SAndroid Build Coastguard Worker 	if (counter == 0)
237*2d543d20SAndroid Build Coastguard Worker 		cat_expr_buf(expr_list[expr_counter], "<empty_set> ");
238*2d543d20SAndroid Build Coastguard Worker 	if (counter > 1)
239*2d543d20SAndroid Build Coastguard Worker 		cat_expr_buf(expr_list[expr_counter], " {");
240*2d543d20SAndroid Build Coastguard Worker 	if (counter >= 1) {
241*2d543d20SAndroid Build Coastguard Worker 		for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
242*2d543d20SAndroid Build Coastguard Worker 			rc = ebitmap_get_bit(types, i);
243*2d543d20SAndroid Build Coastguard Worker 			if (rc == 0)
244*2d543d20SAndroid Build Coastguard Worker 				continue;
245*2d543d20SAndroid Build Coastguard Worker 
246*2d543d20SAndroid Build Coastguard Worker 			/* Collect entries */
247*2d543d20SAndroid Build Coastguard Worker 			switch (type) {
248*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_USER:
249*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
250*2d543d20SAndroid Build Coastguard Worker 							policydb->p_user_val_to_name[i]);
251*2d543d20SAndroid Build Coastguard Worker 				break;
252*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_ROLE:
253*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
254*2d543d20SAndroid Build Coastguard Worker 							policydb->p_role_val_to_name[i]);
255*2d543d20SAndroid Build Coastguard Worker 				break;
256*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_TYPE:
257*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
258*2d543d20SAndroid Build Coastguard Worker 							policydb->p_type_val_to_name[i]);
259*2d543d20SAndroid Build Coastguard Worker 				break;
260*2d543d20SAndroid Build Coastguard Worker 			}
261*2d543d20SAndroid Build Coastguard Worker 			cat_expr_buf(expr_list[expr_counter], tmp_buf);
262*2d543d20SAndroid Build Coastguard Worker 		}
263*2d543d20SAndroid Build Coastguard Worker 	}
264*2d543d20SAndroid Build Coastguard Worker 	if (counter > 1)
265*2d543d20SAndroid Build Coastguard Worker 		cat_expr_buf(expr_list[expr_counter], " }");
266*2d543d20SAndroid Build Coastguard Worker 	if (failed)
267*2d543d20SAndroid Build Coastguard Worker 		cat_expr_buf(expr_list[expr_counter], " -Fail-) ");
268*2d543d20SAndroid Build Coastguard Worker 	else
269*2d543d20SAndroid Build Coastguard Worker 		cat_expr_buf(expr_list[expr_counter], ") ");
270*2d543d20SAndroid Build Coastguard Worker 
271*2d543d20SAndroid Build Coastguard Worker 	return;
272*2d543d20SAndroid Build Coastguard Worker }
273*2d543d20SAndroid Build Coastguard Worker 
msgcat(const char * src,const char * tgt,const char * op,int failed)274*2d543d20SAndroid Build Coastguard Worker static void msgcat(const char *src, const char *tgt, const char *op, int failed)
275*2d543d20SAndroid Build Coastguard Worker {
276*2d543d20SAndroid Build Coastguard Worker 	char tmp_buf[128];
277*2d543d20SAndroid Build Coastguard Worker 	if (failed)
278*2d543d20SAndroid Build Coastguard Worker 		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ",
279*2d543d20SAndroid Build Coastguard Worker 				src, op, tgt);
280*2d543d20SAndroid Build Coastguard Worker 	else
281*2d543d20SAndroid Build Coastguard Worker 		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s) ",
282*2d543d20SAndroid Build Coastguard Worker 				src, op, tgt);
283*2d543d20SAndroid Build Coastguard Worker 	cat_expr_buf(expr_list[expr_counter], tmp_buf);
284*2d543d20SAndroid Build Coastguard Worker }
285*2d543d20SAndroid Build Coastguard Worker 
286*2d543d20SAndroid Build Coastguard Worker /* Returns a buffer with class, statement type and permissions */
get_class_info(sepol_security_class_t tclass,constraint_node_t * constraint,context_struct_t * xcontext)287*2d543d20SAndroid Build Coastguard Worker static char *get_class_info(sepol_security_class_t tclass,
288*2d543d20SAndroid Build Coastguard Worker 							constraint_node_t *constraint,
289*2d543d20SAndroid Build Coastguard Worker 							context_struct_t *xcontext)
290*2d543d20SAndroid Build Coastguard Worker {
291*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *e;
292*2d543d20SAndroid Build Coastguard Worker 	int mls, state_num;
293*2d543d20SAndroid Build Coastguard Worker 	/* Determine statement type */
294*2d543d20SAndroid Build Coastguard Worker 	const char *statements[] = {
295*2d543d20SAndroid Build Coastguard Worker 		"constrain ",			/* 0 */
296*2d543d20SAndroid Build Coastguard Worker 		"mlsconstrain ",		/* 1 */
297*2d543d20SAndroid Build Coastguard Worker 		"validatetrans ",		/* 2 */
298*2d543d20SAndroid Build Coastguard Worker 		"mlsvalidatetrans ",	/* 3 */
299*2d543d20SAndroid Build Coastguard Worker 		0 };
300*2d543d20SAndroid Build Coastguard Worker 	size_t class_buf_len = 0;
301*2d543d20SAndroid Build Coastguard Worker 	size_t new_class_buf_len;
302*2d543d20SAndroid Build Coastguard Worker 	size_t buf_used;
303*2d543d20SAndroid Build Coastguard Worker 	int len;
304*2d543d20SAndroid Build Coastguard Worker 	char *class_buf = NULL, *p;
305*2d543d20SAndroid Build Coastguard Worker 	char *new_class_buf = NULL;
306*2d543d20SAndroid Build Coastguard Worker 
307*2d543d20SAndroid Build Coastguard Worker 	/* Find if MLS statement or not */
308*2d543d20SAndroid Build Coastguard Worker 	mls = 0;
309*2d543d20SAndroid Build Coastguard Worker 	for (e = constraint->expr; e; e = e->next) {
310*2d543d20SAndroid Build Coastguard Worker 		if (e->attr >= CEXPR_L1L2) {
311*2d543d20SAndroid Build Coastguard Worker 			mls = 1;
312*2d543d20SAndroid Build Coastguard Worker 			break;
313*2d543d20SAndroid Build Coastguard Worker 		}
314*2d543d20SAndroid Build Coastguard Worker 	}
315*2d543d20SAndroid Build Coastguard Worker 
316*2d543d20SAndroid Build Coastguard Worker 	if (xcontext == NULL)
317*2d543d20SAndroid Build Coastguard Worker 		state_num = mls + 0;
318*2d543d20SAndroid Build Coastguard Worker 	else
319*2d543d20SAndroid Build Coastguard Worker 		state_num = mls + 2;
320*2d543d20SAndroid Build Coastguard Worker 
321*2d543d20SAndroid Build Coastguard Worker 	while (1) {
322*2d543d20SAndroid Build Coastguard Worker 		new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
323*2d543d20SAndroid Build Coastguard Worker 		new_class_buf = realloc(class_buf, new_class_buf_len);
324*2d543d20SAndroid Build Coastguard Worker 		if (!new_class_buf) {
325*2d543d20SAndroid Build Coastguard Worker 			free(class_buf);
326*2d543d20SAndroid Build Coastguard Worker 			return NULL;
327*2d543d20SAndroid Build Coastguard Worker 		}
328*2d543d20SAndroid Build Coastguard Worker 		class_buf_len = new_class_buf_len;
329*2d543d20SAndroid Build Coastguard Worker 		class_buf = new_class_buf;
330*2d543d20SAndroid Build Coastguard Worker 		buf_used = 0;
331*2d543d20SAndroid Build Coastguard Worker 		p = class_buf;
332*2d543d20SAndroid Build Coastguard Worker 
333*2d543d20SAndroid Build Coastguard Worker 		/* Add statement type */
334*2d543d20SAndroid Build Coastguard Worker 		len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]);
335*2d543d20SAndroid Build Coastguard Worker 		if (len < 0 || (size_t)len >= class_buf_len - buf_used)
336*2d543d20SAndroid Build Coastguard Worker 			continue;
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker 		/* Add class entry */
339*2d543d20SAndroid Build Coastguard Worker 		p += len;
340*2d543d20SAndroid Build Coastguard Worker 		buf_used += len;
341*2d543d20SAndroid Build Coastguard Worker 		len = snprintf(p, class_buf_len - buf_used, "%s ",
342*2d543d20SAndroid Build Coastguard Worker 				policydb->p_class_val_to_name[tclass - 1]);
343*2d543d20SAndroid Build Coastguard Worker 		if (len < 0 || (size_t)len >= class_buf_len - buf_used)
344*2d543d20SAndroid Build Coastguard Worker 			continue;
345*2d543d20SAndroid Build Coastguard Worker 
346*2d543d20SAndroid Build Coastguard Worker 		/* Add permission entries (validatetrans does not have perms) */
347*2d543d20SAndroid Build Coastguard Worker 		p += len;
348*2d543d20SAndroid Build Coastguard Worker 		buf_used += len;
349*2d543d20SAndroid Build Coastguard Worker 		if (state_num < 2) {
350*2d543d20SAndroid Build Coastguard Worker 			char *permstr = sepol_av_to_string(policydb, tclass, constraint->permissions);
351*2d543d20SAndroid Build Coastguard Worker 
352*2d543d20SAndroid Build Coastguard Worker 			len = snprintf(p, class_buf_len - buf_used, "{%s } (",
353*2d543d20SAndroid Build Coastguard Worker 				       permstr ?: "<format-failure>");
354*2d543d20SAndroid Build Coastguard Worker 			free(permstr);
355*2d543d20SAndroid Build Coastguard Worker 		} else {
356*2d543d20SAndroid Build Coastguard Worker 			len = snprintf(p, class_buf_len - buf_used, "(");
357*2d543d20SAndroid Build Coastguard Worker 		}
358*2d543d20SAndroid Build Coastguard Worker 		if (len < 0 || (size_t)len >= class_buf_len - buf_used)
359*2d543d20SAndroid Build Coastguard Worker 			continue;
360*2d543d20SAndroid Build Coastguard Worker 		break;
361*2d543d20SAndroid Build Coastguard Worker 	}
362*2d543d20SAndroid Build Coastguard Worker 	return class_buf;
363*2d543d20SAndroid Build Coastguard Worker }
364*2d543d20SAndroid Build Coastguard Worker 
365*2d543d20SAndroid Build Coastguard Worker /*
366*2d543d20SAndroid Build Coastguard Worker  * Modified version of constraint_expr_eval that will process each
367*2d543d20SAndroid Build Coastguard Worker  * constraint as before but adds the information to text buffers that
368*2d543d20SAndroid Build Coastguard Worker  * will hold various components. The expression will be in RPN format,
369*2d543d20SAndroid Build Coastguard Worker  * therefore there is a stack based RPN to infix converter to produce
370*2d543d20SAndroid Build Coastguard Worker  * the final readable constraint.
371*2d543d20SAndroid Build Coastguard Worker  *
372*2d543d20SAndroid Build Coastguard Worker  * Return the boolean value of a constraint expression
373*2d543d20SAndroid Build Coastguard Worker  * when it is applied to the specified source and target
374*2d543d20SAndroid Build Coastguard Worker  * security contexts.
375*2d543d20SAndroid Build Coastguard Worker  *
376*2d543d20SAndroid Build Coastguard Worker  * xcontext is a special beast...  It is used by the validatetrans rules
377*2d543d20SAndroid Build Coastguard Worker  * only.  For these rules, scontext is the context before the transition,
378*2d543d20SAndroid Build Coastguard Worker  * tcontext is the context after the transition, and xcontext is the
379*2d543d20SAndroid Build Coastguard Worker  * context of the process performing the transition.  All other callers
380*2d543d20SAndroid Build Coastguard Worker  * of constraint_expr_eval_reason should pass in NULL for xcontext.
381*2d543d20SAndroid Build Coastguard Worker  *
382*2d543d20SAndroid Build Coastguard Worker  * This function will also build a buffer as the constraint is processed
383*2d543d20SAndroid Build Coastguard Worker  * for analysis. If this option is not required, then:
384*2d543d20SAndroid Build Coastguard Worker  *      'tclass' should be '0' and r_buf MUST be NULL.
385*2d543d20SAndroid Build Coastguard Worker  */
constraint_expr_eval_reason(context_struct_t * scontext,context_struct_t * tcontext,context_struct_t * xcontext,sepol_security_class_t tclass,constraint_node_t * constraint,char ** r_buf,unsigned int flags)386*2d543d20SAndroid Build Coastguard Worker static int constraint_expr_eval_reason(context_struct_t *scontext,
387*2d543d20SAndroid Build Coastguard Worker 				context_struct_t *tcontext,
388*2d543d20SAndroid Build Coastguard Worker 				context_struct_t *xcontext,
389*2d543d20SAndroid Build Coastguard Worker 				sepol_security_class_t tclass,
390*2d543d20SAndroid Build Coastguard Worker 				constraint_node_t *constraint,
391*2d543d20SAndroid Build Coastguard Worker 				char **r_buf,
392*2d543d20SAndroid Build Coastguard Worker 				unsigned int flags)
393*2d543d20SAndroid Build Coastguard Worker {
394*2d543d20SAndroid Build Coastguard Worker 	uint32_t val1, val2;
395*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *c;
396*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *r1, *r2;
397*2d543d20SAndroid Build Coastguard Worker 	mls_level_t *l1, *l2;
398*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *e;
399*2d543d20SAndroid Build Coastguard Worker 	int s[CEXPR_MAXDEPTH] = {};
400*2d543d20SAndroid Build Coastguard Worker 	int sp = -1;
401*2d543d20SAndroid Build Coastguard Worker 	char tmp_buf[128];
402*2d543d20SAndroid Build Coastguard Worker 
403*2d543d20SAndroid Build Coastguard Worker /*
404*2d543d20SAndroid Build Coastguard Worker  * Define the s_t_x_num values that make up r1, t2 etc. in text strings
405*2d543d20SAndroid Build Coastguard Worker  * Set 1 = source, 2 = target, 3 = xcontext for validatetrans
406*2d543d20SAndroid Build Coastguard Worker  */
407*2d543d20SAndroid Build Coastguard Worker #define SOURCE  1
408*2d543d20SAndroid Build Coastguard Worker #define TARGET  2
409*2d543d20SAndroid Build Coastguard Worker #define XTARGET 3
410*2d543d20SAndroid Build Coastguard Worker 
411*2d543d20SAndroid Build Coastguard Worker 	int s_t_x_num;
412*2d543d20SAndroid Build Coastguard Worker 
413*2d543d20SAndroid Build Coastguard Worker 	/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
414*2d543d20SAndroid Build Coastguard Worker 	int u_r_t = 0;
415*2d543d20SAndroid Build Coastguard Worker 
416*2d543d20SAndroid Build Coastguard Worker 	char *src = NULL;
417*2d543d20SAndroid Build Coastguard Worker 	char *tgt = NULL;
418*2d543d20SAndroid Build Coastguard Worker 	int rc = 0, x;
419*2d543d20SAndroid Build Coastguard Worker 	char *class_buf = NULL;
420*2d543d20SAndroid Build Coastguard Worker 	int expr_list_len = 0;
421*2d543d20SAndroid Build Coastguard Worker 	int expr_count;
422*2d543d20SAndroid Build Coastguard Worker 
423*2d543d20SAndroid Build Coastguard Worker 	/*
424*2d543d20SAndroid Build Coastguard Worker 	 * The array of expression answer buffer pointers and counter.
425*2d543d20SAndroid Build Coastguard Worker 	 */
426*2d543d20SAndroid Build Coastguard Worker 	char **answer_list = NULL;
427*2d543d20SAndroid Build Coastguard Worker 	int answer_counter = 0;
428*2d543d20SAndroid Build Coastguard Worker 
429*2d543d20SAndroid Build Coastguard Worker 	/* The pop operands */
430*2d543d20SAndroid Build Coastguard Worker 	char *a;
431*2d543d20SAndroid Build Coastguard Worker 	char *b;
432*2d543d20SAndroid Build Coastguard Worker 	int a_len, b_len;
433*2d543d20SAndroid Build Coastguard Worker 
434*2d543d20SAndroid Build Coastguard Worker 	class_buf = get_class_info(tclass, constraint, xcontext);
435*2d543d20SAndroid Build Coastguard Worker 	if (!class_buf) {
436*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "failed to allocate class buffer");
437*2d543d20SAndroid Build Coastguard Worker 		return -ENOMEM;
438*2d543d20SAndroid Build Coastguard Worker 	}
439*2d543d20SAndroid Build Coastguard Worker 
440*2d543d20SAndroid Build Coastguard Worker 	/* Original function but with buffer support */
441*2d543d20SAndroid Build Coastguard Worker 	expr_counter = 0;
442*2d543d20SAndroid Build Coastguard Worker 	expr_list = NULL;
443*2d543d20SAndroid Build Coastguard Worker 	for (e = constraint->expr; e; e = e->next) {
444*2d543d20SAndroid Build Coastguard Worker 		/* Allocate a stack to hold expression buffer entries */
445*2d543d20SAndroid Build Coastguard Worker 		if (expr_counter >= expr_list_len) {
446*2d543d20SAndroid Build Coastguard Worker 			char **new_expr_list;
447*2d543d20SAndroid Build Coastguard Worker 			int new_expr_list_len;
448*2d543d20SAndroid Build Coastguard Worker 
449*2d543d20SAndroid Build Coastguard Worker 			if (expr_list_len == 0)
450*2d543d20SAndroid Build Coastguard Worker 				new_expr_list_len = STACK_LEN;
451*2d543d20SAndroid Build Coastguard Worker 			else
452*2d543d20SAndroid Build Coastguard Worker 				new_expr_list_len = expr_list_len * 2;
453*2d543d20SAndroid Build Coastguard Worker 
454*2d543d20SAndroid Build Coastguard Worker 			new_expr_list = reallocarray(expr_list,
455*2d543d20SAndroid Build Coastguard Worker 					new_expr_list_len, sizeof(*expr_list));
456*2d543d20SAndroid Build Coastguard Worker 			if (!new_expr_list) {
457*2d543d20SAndroid Build Coastguard Worker 				ERR(NULL, "failed to allocate expr buffer stack");
458*2d543d20SAndroid Build Coastguard Worker 				rc = -ENOMEM;
459*2d543d20SAndroid Build Coastguard Worker 				goto out;
460*2d543d20SAndroid Build Coastguard Worker 			}
461*2d543d20SAndroid Build Coastguard Worker 			expr_list_len = new_expr_list_len;
462*2d543d20SAndroid Build Coastguard Worker 			expr_list = new_expr_list;
463*2d543d20SAndroid Build Coastguard Worker 		}
464*2d543d20SAndroid Build Coastguard Worker 
465*2d543d20SAndroid Build Coastguard Worker 		/*
466*2d543d20SAndroid Build Coastguard Worker 		 * malloc a buffer to store each expression text component. If
467*2d543d20SAndroid Build Coastguard Worker 		 * buffer is too small cat_expr_buf() will realloc extra space.
468*2d543d20SAndroid Build Coastguard Worker 		 */
469*2d543d20SAndroid Build Coastguard Worker 		expr_buf_len = EXPR_BUF_SIZE;
470*2d543d20SAndroid Build Coastguard Worker 		expr_list[expr_counter] = malloc(expr_buf_len);
471*2d543d20SAndroid Build Coastguard Worker 		if (!expr_list[expr_counter]) {
472*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL, "failed to allocate expr buffer");
473*2d543d20SAndroid Build Coastguard Worker 			rc = -ENOMEM;
474*2d543d20SAndroid Build Coastguard Worker 			goto out;
475*2d543d20SAndroid Build Coastguard Worker 		}
476*2d543d20SAndroid Build Coastguard Worker 		expr_buf_used = 0;
477*2d543d20SAndroid Build Coastguard Worker 
478*2d543d20SAndroid Build Coastguard Worker 		/* Now process each expression of the constraint */
479*2d543d20SAndroid Build Coastguard Worker 		switch (e->expr_type) {
480*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NOT:
481*2d543d20SAndroid Build Coastguard Worker 			if (sp < 0) {
482*2d543d20SAndroid Build Coastguard Worker 				BUG();
483*2d543d20SAndroid Build Coastguard Worker 				rc = -EINVAL;
484*2d543d20SAndroid Build Coastguard Worker 				goto out;
485*2d543d20SAndroid Build Coastguard Worker 			}
486*2d543d20SAndroid Build Coastguard Worker 			s[sp] = !s[sp];
487*2d543d20SAndroid Build Coastguard Worker 			cat_expr_buf(expr_list[expr_counter], "not");
488*2d543d20SAndroid Build Coastguard Worker 			break;
489*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_AND:
490*2d543d20SAndroid Build Coastguard Worker 			if (sp < 1) {
491*2d543d20SAndroid Build Coastguard Worker 				BUG();
492*2d543d20SAndroid Build Coastguard Worker 				rc = -EINVAL;
493*2d543d20SAndroid Build Coastguard Worker 				goto out;
494*2d543d20SAndroid Build Coastguard Worker 			}
495*2d543d20SAndroid Build Coastguard Worker 			sp--;
496*2d543d20SAndroid Build Coastguard Worker 			s[sp] &= s[sp + 1];
497*2d543d20SAndroid Build Coastguard Worker 			cat_expr_buf(expr_list[expr_counter], "and");
498*2d543d20SAndroid Build Coastguard Worker 			break;
499*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_OR:
500*2d543d20SAndroid Build Coastguard Worker 			if (sp < 1) {
501*2d543d20SAndroid Build Coastguard Worker 				BUG();
502*2d543d20SAndroid Build Coastguard Worker 				rc = -EINVAL;
503*2d543d20SAndroid Build Coastguard Worker 				goto out;
504*2d543d20SAndroid Build Coastguard Worker 			}
505*2d543d20SAndroid Build Coastguard Worker 			sp--;
506*2d543d20SAndroid Build Coastguard Worker 			s[sp] |= s[sp + 1];
507*2d543d20SAndroid Build Coastguard Worker 			cat_expr_buf(expr_list[expr_counter], "or");
508*2d543d20SAndroid Build Coastguard Worker 			break;
509*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_ATTR:
510*2d543d20SAndroid Build Coastguard Worker 			if (sp == (CEXPR_MAXDEPTH - 1))
511*2d543d20SAndroid Build Coastguard Worker 				goto out;
512*2d543d20SAndroid Build Coastguard Worker 
513*2d543d20SAndroid Build Coastguard Worker 			switch (e->attr) {
514*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_USER:
515*2d543d20SAndroid Build Coastguard Worker 				val1 = scontext->user;
516*2d543d20SAndroid Build Coastguard Worker 				val2 = tcontext->user;
517*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("u1");
518*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("u2");
519*2d543d20SAndroid Build Coastguard Worker 				break;
520*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_TYPE:
521*2d543d20SAndroid Build Coastguard Worker 				val1 = scontext->type;
522*2d543d20SAndroid Build Coastguard Worker 				val2 = tcontext->type;
523*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("t1");
524*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("t2");
525*2d543d20SAndroid Build Coastguard Worker 				break;
526*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_ROLE:
527*2d543d20SAndroid Build Coastguard Worker 				val1 = scontext->role;
528*2d543d20SAndroid Build Coastguard Worker 				val2 = tcontext->role;
529*2d543d20SAndroid Build Coastguard Worker 				r1 = policydb->role_val_to_struct[val1 - 1];
530*2d543d20SAndroid Build Coastguard Worker 				r2 = policydb->role_val_to_struct[val2 - 1];
531*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("r1");
532*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("r2");
533*2d543d20SAndroid Build Coastguard Worker 
534*2d543d20SAndroid Build Coastguard Worker 				switch (e->op) {
535*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_DOM:
536*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
537*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "dom", s[sp] == 0);
538*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
539*2d543d20SAndroid Build Coastguard Worker 					continue;
540*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_DOMBY:
541*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
542*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "domby", s[sp] == 0);
543*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
544*2d543d20SAndroid Build Coastguard Worker 					continue;
545*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_INCOMP:
546*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1)
547*2d543d20SAndroid Build Coastguard Worker 						 && !ebitmap_get_bit(&r2->dominates, val1 - 1));
548*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "incomp", s[sp] == 0);
549*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
550*2d543d20SAndroid Build Coastguard Worker 					continue;
551*2d543d20SAndroid Build Coastguard Worker 				default:
552*2d543d20SAndroid Build Coastguard Worker 					break;
553*2d543d20SAndroid Build Coastguard Worker 				}
554*2d543d20SAndroid Build Coastguard Worker 				break;
555*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_L1L2:
556*2d543d20SAndroid Build Coastguard Worker 				l1 = &(scontext->range.level[0]);
557*2d543d20SAndroid Build Coastguard Worker 				l2 = &(tcontext->range.level[0]);
558*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("l1");
559*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("l2");
560*2d543d20SAndroid Build Coastguard Worker 				goto mls_ops;
561*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_L1H2:
562*2d543d20SAndroid Build Coastguard Worker 				l1 = &(scontext->range.level[0]);
563*2d543d20SAndroid Build Coastguard Worker 				l2 = &(tcontext->range.level[1]);
564*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("l1");
565*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("h2");
566*2d543d20SAndroid Build Coastguard Worker 				goto mls_ops;
567*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_H1L2:
568*2d543d20SAndroid Build Coastguard Worker 				l1 = &(scontext->range.level[1]);
569*2d543d20SAndroid Build Coastguard Worker 				l2 = &(tcontext->range.level[0]);
570*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("h1");
571*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("l2");
572*2d543d20SAndroid Build Coastguard Worker 				goto mls_ops;
573*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_H1H2:
574*2d543d20SAndroid Build Coastguard Worker 				l1 = &(scontext->range.level[1]);
575*2d543d20SAndroid Build Coastguard Worker 				l2 = &(tcontext->range.level[1]);
576*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("h1");
577*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("h2");
578*2d543d20SAndroid Build Coastguard Worker 				goto mls_ops;
579*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_L1H1:
580*2d543d20SAndroid Build Coastguard Worker 				l1 = &(scontext->range.level[0]);
581*2d543d20SAndroid Build Coastguard Worker 				l2 = &(scontext->range.level[1]);
582*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("l1");
583*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("h1");
584*2d543d20SAndroid Build Coastguard Worker 				goto mls_ops;
585*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_L2H2:
586*2d543d20SAndroid Build Coastguard Worker 				l1 = &(tcontext->range.level[0]);
587*2d543d20SAndroid Build Coastguard Worker 				l2 = &(tcontext->range.level[1]);
588*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup("l2");
589*2d543d20SAndroid Build Coastguard Worker 				free(tgt); tgt = strdup("h2");
590*2d543d20SAndroid Build Coastguard Worker mls_ops:
591*2d543d20SAndroid Build Coastguard Worker 				switch (e->op) {
592*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_EQ:
593*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = mls_level_eq(l1, l2);
594*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "eq", s[sp] == 0);
595*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
596*2d543d20SAndroid Build Coastguard Worker 					continue;
597*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_NEQ:
598*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = !mls_level_eq(l1, l2);
599*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "!=", s[sp] == 0);
600*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
601*2d543d20SAndroid Build Coastguard Worker 					continue;
602*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_DOM:
603*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = mls_level_dom(l1, l2);
604*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "dom", s[sp] == 0);
605*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
606*2d543d20SAndroid Build Coastguard Worker 					continue;
607*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_DOMBY:
608*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = mls_level_dom(l2, l1);
609*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "domby", s[sp] == 0);
610*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
611*2d543d20SAndroid Build Coastguard Worker 					continue;
612*2d543d20SAndroid Build Coastguard Worker 				case CEXPR_INCOMP:
613*2d543d20SAndroid Build Coastguard Worker 					s[++sp] = mls_level_incomp(l2, l1);
614*2d543d20SAndroid Build Coastguard Worker 					msgcat(src, tgt, "incomp", s[sp] == 0);
615*2d543d20SAndroid Build Coastguard Worker 					expr_counter++;
616*2d543d20SAndroid Build Coastguard Worker 					continue;
617*2d543d20SAndroid Build Coastguard Worker 				default:
618*2d543d20SAndroid Build Coastguard Worker 					BUG();
619*2d543d20SAndroid Build Coastguard Worker 					goto out;
620*2d543d20SAndroid Build Coastguard Worker 				}
621*2d543d20SAndroid Build Coastguard Worker 				break;
622*2d543d20SAndroid Build Coastguard Worker 			default:
623*2d543d20SAndroid Build Coastguard Worker 				BUG();
624*2d543d20SAndroid Build Coastguard Worker 				goto out;
625*2d543d20SAndroid Build Coastguard Worker 			}
626*2d543d20SAndroid Build Coastguard Worker 
627*2d543d20SAndroid Build Coastguard Worker 			switch (e->op) {
628*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_EQ:
629*2d543d20SAndroid Build Coastguard Worker 				s[++sp] = (val1 == val2);
630*2d543d20SAndroid Build Coastguard Worker 				msgcat(src, tgt, "==", s[sp] == 0);
631*2d543d20SAndroid Build Coastguard Worker 				break;
632*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_NEQ:
633*2d543d20SAndroid Build Coastguard Worker 				s[++sp] = (val1 != val2);
634*2d543d20SAndroid Build Coastguard Worker 				msgcat(src, tgt, "!=", s[sp] == 0);
635*2d543d20SAndroid Build Coastguard Worker 				break;
636*2d543d20SAndroid Build Coastguard Worker 			default:
637*2d543d20SAndroid Build Coastguard Worker 				BUG();
638*2d543d20SAndroid Build Coastguard Worker 				goto out;
639*2d543d20SAndroid Build Coastguard Worker 			}
640*2d543d20SAndroid Build Coastguard Worker 			break;
641*2d543d20SAndroid Build Coastguard Worker 		case CEXPR_NAMES:
642*2d543d20SAndroid Build Coastguard Worker 			if (sp == (CEXPR_MAXDEPTH - 1))
643*2d543d20SAndroid Build Coastguard Worker 				goto out;
644*2d543d20SAndroid Build Coastguard Worker 			s_t_x_num = SOURCE;
645*2d543d20SAndroid Build Coastguard Worker 			c = scontext;
646*2d543d20SAndroid Build Coastguard Worker 			if (e->attr & CEXPR_TARGET) {
647*2d543d20SAndroid Build Coastguard Worker 				s_t_x_num = TARGET;
648*2d543d20SAndroid Build Coastguard Worker 				c = tcontext;
649*2d543d20SAndroid Build Coastguard Worker 			} else if (e->attr & CEXPR_XTARGET) {
650*2d543d20SAndroid Build Coastguard Worker 				s_t_x_num = XTARGET;
651*2d543d20SAndroid Build Coastguard Worker 				c = xcontext;
652*2d543d20SAndroid Build Coastguard Worker 			}
653*2d543d20SAndroid Build Coastguard Worker 			if (!c) {
654*2d543d20SAndroid Build Coastguard Worker 				BUG();
655*2d543d20SAndroid Build Coastguard Worker 				goto out;
656*2d543d20SAndroid Build Coastguard Worker 			}
657*2d543d20SAndroid Build Coastguard Worker 			if (e->attr & CEXPR_USER) {
658*2d543d20SAndroid Build Coastguard Worker 				u_r_t = CEXPR_USER;
659*2d543d20SAndroid Build Coastguard Worker 				val1 = c->user;
660*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), "u%d ", s_t_x_num);
661*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup(tmp_buf);
662*2d543d20SAndroid Build Coastguard Worker 			} else if (e->attr & CEXPR_ROLE) {
663*2d543d20SAndroid Build Coastguard Worker 				u_r_t = CEXPR_ROLE;
664*2d543d20SAndroid Build Coastguard Worker 				val1 = c->role;
665*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), "r%d ", s_t_x_num);
666*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup(tmp_buf);
667*2d543d20SAndroid Build Coastguard Worker 			} else if (e->attr & CEXPR_TYPE) {
668*2d543d20SAndroid Build Coastguard Worker 				u_r_t = CEXPR_TYPE;
669*2d543d20SAndroid Build Coastguard Worker 				val1 = c->type;
670*2d543d20SAndroid Build Coastguard Worker 				snprintf(tmp_buf, sizeof(tmp_buf), "t%d ", s_t_x_num);
671*2d543d20SAndroid Build Coastguard Worker 				free(src); src = strdup(tmp_buf);
672*2d543d20SAndroid Build Coastguard Worker 			} else {
673*2d543d20SAndroid Build Coastguard Worker 				BUG();
674*2d543d20SAndroid Build Coastguard Worker 				goto out;
675*2d543d20SAndroid Build Coastguard Worker 			}
676*2d543d20SAndroid Build Coastguard Worker 
677*2d543d20SAndroid Build Coastguard Worker 			switch (e->op) {
678*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_EQ:
679*2d543d20SAndroid Build Coastguard Worker 				s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
680*2d543d20SAndroid Build Coastguard Worker 				get_name_list(e, u_r_t, src, "==", s[sp] == 0);
681*2d543d20SAndroid Build Coastguard Worker 				break;
682*2d543d20SAndroid Build Coastguard Worker 
683*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_NEQ:
684*2d543d20SAndroid Build Coastguard Worker 				s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
685*2d543d20SAndroid Build Coastguard Worker 				get_name_list(e, u_r_t, src, "!=", s[sp] == 0);
686*2d543d20SAndroid Build Coastguard Worker 				break;
687*2d543d20SAndroid Build Coastguard Worker 			default:
688*2d543d20SAndroid Build Coastguard Worker 				BUG();
689*2d543d20SAndroid Build Coastguard Worker 				goto out;
690*2d543d20SAndroid Build Coastguard Worker 			}
691*2d543d20SAndroid Build Coastguard Worker 			break;
692*2d543d20SAndroid Build Coastguard Worker 		default:
693*2d543d20SAndroid Build Coastguard Worker 			BUG();
694*2d543d20SAndroid Build Coastguard Worker 			goto out;
695*2d543d20SAndroid Build Coastguard Worker 		}
696*2d543d20SAndroid Build Coastguard Worker 		expr_counter++;
697*2d543d20SAndroid Build Coastguard Worker 	}
698*2d543d20SAndroid Build Coastguard Worker 
699*2d543d20SAndroid Build Coastguard Worker 	/*
700*2d543d20SAndroid Build Coastguard Worker 	 * At this point each expression of the constraint is in
701*2d543d20SAndroid Build Coastguard Worker 	 * expr_list[n+1] and in RPN format. Now convert to 'infix'
702*2d543d20SAndroid Build Coastguard Worker 	 */
703*2d543d20SAndroid Build Coastguard Worker 
704*2d543d20SAndroid Build Coastguard Worker 	/*
705*2d543d20SAndroid Build Coastguard Worker 	 * Save expr count but zero expr_counter to detect if
706*2d543d20SAndroid Build Coastguard Worker 	 * 'BUG(); goto out;' was called as we need to release any used
707*2d543d20SAndroid Build Coastguard Worker 	 * expr_list malloc's. Normally they are released by the RPN to
708*2d543d20SAndroid Build Coastguard Worker 	 * infix code.
709*2d543d20SAndroid Build Coastguard Worker 	 */
710*2d543d20SAndroid Build Coastguard Worker 	expr_count = expr_counter;
711*2d543d20SAndroid Build Coastguard Worker 	expr_counter = 0;
712*2d543d20SAndroid Build Coastguard Worker 
713*2d543d20SAndroid Build Coastguard Worker 	/*
714*2d543d20SAndroid Build Coastguard Worker 	 * Generate the same number of answer buffer entries as expression
715*2d543d20SAndroid Build Coastguard Worker 	 * buffers (as there will never be more).
716*2d543d20SAndroid Build Coastguard Worker 	 */
717*2d543d20SAndroid Build Coastguard Worker 	answer_list = calloc(expr_count, sizeof(*answer_list));
718*2d543d20SAndroid Build Coastguard Worker 	if (!answer_list) {
719*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "failed to allocate answer stack");
720*2d543d20SAndroid Build Coastguard Worker 		rc = -ENOMEM;
721*2d543d20SAndroid Build Coastguard Worker 		goto out;
722*2d543d20SAndroid Build Coastguard Worker 	}
723*2d543d20SAndroid Build Coastguard Worker 
724*2d543d20SAndroid Build Coastguard Worker 	/* Convert constraint from RPN to infix notation. */
725*2d543d20SAndroid Build Coastguard Worker 	for (x = 0; x != expr_count; x++) {
726*2d543d20SAndroid Build Coastguard Worker 		if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
727*2d543d20SAndroid Build Coastguard Worker 					"or", 2) == 0) {
728*2d543d20SAndroid Build Coastguard Worker 			b = pop();
729*2d543d20SAndroid Build Coastguard Worker 			b_len = strlen(b);
730*2d543d20SAndroid Build Coastguard Worker 			a = pop();
731*2d543d20SAndroid Build Coastguard Worker 			a_len = strlen(a);
732*2d543d20SAndroid Build Coastguard Worker 
733*2d543d20SAndroid Build Coastguard Worker 			/* get a buffer to hold the answer */
734*2d543d20SAndroid Build Coastguard Worker 			answer_list[answer_counter] = malloc(a_len + b_len + 8);
735*2d543d20SAndroid Build Coastguard Worker 			if (!answer_list[answer_counter]) {
736*2d543d20SAndroid Build Coastguard Worker 				ERR(NULL, "failed to allocate answer buffer");
737*2d543d20SAndroid Build Coastguard Worker 				rc = -ENOMEM;
738*2d543d20SAndroid Build Coastguard Worker 				goto out;
739*2d543d20SAndroid Build Coastguard Worker 			}
740*2d543d20SAndroid Build Coastguard Worker 			memset(answer_list[answer_counter], '\0', a_len + b_len + 8);
741*2d543d20SAndroid Build Coastguard Worker 
742*2d543d20SAndroid Build Coastguard Worker 			sprintf(answer_list[answer_counter], "%s %s %s", a,
743*2d543d20SAndroid Build Coastguard Worker 					expr_list[x], b);
744*2d543d20SAndroid Build Coastguard Worker 			push(answer_list[answer_counter++]);
745*2d543d20SAndroid Build Coastguard Worker 			free(a);
746*2d543d20SAndroid Build Coastguard Worker 			free(b);
747*2d543d20SAndroid Build Coastguard Worker 			free(expr_list[x]);
748*2d543d20SAndroid Build Coastguard Worker 		} else if (strncmp(expr_list[x], "not", 3) == 0) {
749*2d543d20SAndroid Build Coastguard Worker 			b = pop();
750*2d543d20SAndroid Build Coastguard Worker 			b_len = strlen(b);
751*2d543d20SAndroid Build Coastguard Worker 
752*2d543d20SAndroid Build Coastguard Worker 			answer_list[answer_counter] = malloc(b_len + 8);
753*2d543d20SAndroid Build Coastguard Worker 			if (!answer_list[answer_counter]) {
754*2d543d20SAndroid Build Coastguard Worker 				ERR(NULL, "failed to allocate answer buffer");
755*2d543d20SAndroid Build Coastguard Worker 				rc = -ENOMEM;
756*2d543d20SAndroid Build Coastguard Worker 				goto out;
757*2d543d20SAndroid Build Coastguard Worker 			}
758*2d543d20SAndroid Build Coastguard Worker 			memset(answer_list[answer_counter], '\0', b_len + 8);
759*2d543d20SAndroid Build Coastguard Worker 
760*2d543d20SAndroid Build Coastguard Worker 			if (strncmp(b, "not", 3) == 0)
761*2d543d20SAndroid Build Coastguard Worker 				sprintf(answer_list[answer_counter], "%s (%s)",
762*2d543d20SAndroid Build Coastguard Worker 						expr_list[x], b);
763*2d543d20SAndroid Build Coastguard Worker 			else
764*2d543d20SAndroid Build Coastguard Worker 				sprintf(answer_list[answer_counter], "%s%s",
765*2d543d20SAndroid Build Coastguard Worker 						expr_list[x], b);
766*2d543d20SAndroid Build Coastguard Worker 			push(answer_list[answer_counter++]);
767*2d543d20SAndroid Build Coastguard Worker 			free(b);
768*2d543d20SAndroid Build Coastguard Worker 			free(expr_list[x]);
769*2d543d20SAndroid Build Coastguard Worker 		} else {
770*2d543d20SAndroid Build Coastguard Worker 			push(expr_list[x]);
771*2d543d20SAndroid Build Coastguard Worker 		}
772*2d543d20SAndroid Build Coastguard Worker 	}
773*2d543d20SAndroid Build Coastguard Worker 	/* Get the final answer from tos and build constraint text */
774*2d543d20SAndroid Build Coastguard Worker 	a = pop();
775*2d543d20SAndroid Build Coastguard Worker 
776*2d543d20SAndroid Build Coastguard Worker 	/* validatetrans / constraint calculation:
777*2d543d20SAndroid Build Coastguard Worker 				rc = 0 is denied, rc = 1 is granted */
778*2d543d20SAndroid Build Coastguard Worker 	sprintf(tmp_buf, "%s %s\n",
779*2d543d20SAndroid Build Coastguard Worker 			xcontext ? "Validatetrans" : "Constraint",
780*2d543d20SAndroid Build Coastguard Worker 			s[0] ? "GRANTED" : "DENIED");
781*2d543d20SAndroid Build Coastguard Worker 
782*2d543d20SAndroid Build Coastguard Worker 	/*
783*2d543d20SAndroid Build Coastguard Worker 	 * This will add the constraints to the callers reason buffer (who is
784*2d543d20SAndroid Build Coastguard Worker 	 * responsible for freeing the memory). It will handle any realloc's
785*2d543d20SAndroid Build Coastguard Worker 	 * should the buffer be too short.
786*2d543d20SAndroid Build Coastguard Worker 	 * The reason_buf_used and reason_buf_len counters are defined
787*2d543d20SAndroid Build Coastguard Worker 	 * globally as multiple constraints can be in the buffer.
788*2d543d20SAndroid Build Coastguard Worker 	 */
789*2d543d20SAndroid Build Coastguard Worker 
790*2d543d20SAndroid Build Coastguard Worker 	if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
791*2d543d20SAndroid Build Coastguard Worker 				(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
792*2d543d20SAndroid Build Coastguard Worker 		int len;
793*2d543d20SAndroid Build Coastguard Worker 		char *p;
794*2d543d20SAndroid Build Coastguard Worker 		/*
795*2d543d20SAndroid Build Coastguard Worker 		* These contain the constraint components that are added to the
796*2d543d20SAndroid Build Coastguard Worker 		* callers reason buffer.
797*2d543d20SAndroid Build Coastguard Worker 		*/
798*2d543d20SAndroid Build Coastguard Worker 		const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
799*2d543d20SAndroid Build Coastguard Worker 
800*2d543d20SAndroid Build Coastguard Worker 		for (x = 0; buffers[x] != NULL; x++) {
801*2d543d20SAndroid Build Coastguard Worker 			while (1) {
802*2d543d20SAndroid Build Coastguard Worker 				p = *r_buf ? (*r_buf + reason_buf_used) : NULL;
803*2d543d20SAndroid Build Coastguard Worker 				len = snprintf(p, reason_buf_len - reason_buf_used,
804*2d543d20SAndroid Build Coastguard Worker 						"%s", buffers[x]);
805*2d543d20SAndroid Build Coastguard Worker 				if (len < 0 || len >= reason_buf_len - reason_buf_used) {
806*2d543d20SAndroid Build Coastguard Worker 					int new_buf_len = reason_buf_len + REASON_BUF_SIZE;
807*2d543d20SAndroid Build Coastguard Worker 					char *new_buf = realloc(*r_buf, new_buf_len);
808*2d543d20SAndroid Build Coastguard Worker 					if (!new_buf) {
809*2d543d20SAndroid Build Coastguard Worker 						ERR(NULL, "failed to realloc reason buffer");
810*2d543d20SAndroid Build Coastguard Worker 						goto out1;
811*2d543d20SAndroid Build Coastguard Worker 					}
812*2d543d20SAndroid Build Coastguard Worker 					*r_buf = new_buf;
813*2d543d20SAndroid Build Coastguard Worker 					reason_buf_len = new_buf_len;
814*2d543d20SAndroid Build Coastguard Worker 					continue;
815*2d543d20SAndroid Build Coastguard Worker 				} else {
816*2d543d20SAndroid Build Coastguard Worker 					reason_buf_used += len;
817*2d543d20SAndroid Build Coastguard Worker 					break;
818*2d543d20SAndroid Build Coastguard Worker 				}
819*2d543d20SAndroid Build Coastguard Worker 			}
820*2d543d20SAndroid Build Coastguard Worker 		}
821*2d543d20SAndroid Build Coastguard Worker 	}
822*2d543d20SAndroid Build Coastguard Worker 
823*2d543d20SAndroid Build Coastguard Worker out1:
824*2d543d20SAndroid Build Coastguard Worker 	rc = s[0];
825*2d543d20SAndroid Build Coastguard Worker 	free(a);
826*2d543d20SAndroid Build Coastguard Worker 
827*2d543d20SAndroid Build Coastguard Worker out:
828*2d543d20SAndroid Build Coastguard Worker 	free(class_buf);
829*2d543d20SAndroid Build Coastguard Worker 	free(src);
830*2d543d20SAndroid Build Coastguard Worker 	free(tgt);
831*2d543d20SAndroid Build Coastguard Worker 
832*2d543d20SAndroid Build Coastguard Worker 	if (expr_counter) {
833*2d543d20SAndroid Build Coastguard Worker 		for (x = 0; expr_list[x] != NULL; x++)
834*2d543d20SAndroid Build Coastguard Worker 			free(expr_list[x]);
835*2d543d20SAndroid Build Coastguard Worker 	}
836*2d543d20SAndroid Build Coastguard Worker 	free(answer_list);
837*2d543d20SAndroid Build Coastguard Worker 	free(expr_list);
838*2d543d20SAndroid Build Coastguard Worker 	return rc;
839*2d543d20SAndroid Build Coastguard Worker }
840*2d543d20SAndroid Build Coastguard Worker 
841*2d543d20SAndroid Build Coastguard Worker /* Forward declaration */
842*2d543d20SAndroid Build Coastguard Worker static int context_struct_compute_av(context_struct_t * scontext,
843*2d543d20SAndroid Build Coastguard Worker 				     context_struct_t * tcontext,
844*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_class_t tclass,
845*2d543d20SAndroid Build Coastguard Worker 				     sepol_access_vector_t requested,
846*2d543d20SAndroid Build Coastguard Worker 				     struct sepol_av_decision *avd,
847*2d543d20SAndroid Build Coastguard Worker 				     unsigned int *reason,
848*2d543d20SAndroid Build Coastguard Worker 				     char **r_buf,
849*2d543d20SAndroid Build Coastguard Worker 				     unsigned int flags);
850*2d543d20SAndroid Build Coastguard Worker 
type_attribute_bounds_av(context_struct_t * scontext,context_struct_t * tcontext,sepol_security_class_t tclass,sepol_access_vector_t requested,struct sepol_av_decision * avd,unsigned int * reason)851*2d543d20SAndroid Build Coastguard Worker static void type_attribute_bounds_av(context_struct_t *scontext,
852*2d543d20SAndroid Build Coastguard Worker 				     context_struct_t *tcontext,
853*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_class_t tclass,
854*2d543d20SAndroid Build Coastguard Worker 				     sepol_access_vector_t requested,
855*2d543d20SAndroid Build Coastguard Worker 				     struct sepol_av_decision *avd,
856*2d543d20SAndroid Build Coastguard Worker 				     unsigned int *reason)
857*2d543d20SAndroid Build Coastguard Worker {
858*2d543d20SAndroid Build Coastguard Worker 	context_struct_t lo_scontext;
859*2d543d20SAndroid Build Coastguard Worker 	context_struct_t lo_tcontext, *tcontextp = tcontext;
860*2d543d20SAndroid Build Coastguard Worker 	struct sepol_av_decision lo_avd;
861*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *source;
862*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *target;
863*2d543d20SAndroid Build Coastguard Worker 	sepol_access_vector_t masked = 0;
864*2d543d20SAndroid Build Coastguard Worker 
865*2d543d20SAndroid Build Coastguard Worker 	source = policydb->type_val_to_struct[scontext->type - 1];
866*2d543d20SAndroid Build Coastguard Worker 	if (!source->bounds)
867*2d543d20SAndroid Build Coastguard Worker 		return;
868*2d543d20SAndroid Build Coastguard Worker 
869*2d543d20SAndroid Build Coastguard Worker 	target = policydb->type_val_to_struct[tcontext->type - 1];
870*2d543d20SAndroid Build Coastguard Worker 
871*2d543d20SAndroid Build Coastguard Worker 	memset(&lo_avd, 0, sizeof(lo_avd));
872*2d543d20SAndroid Build Coastguard Worker 
873*2d543d20SAndroid Build Coastguard Worker 	memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
874*2d543d20SAndroid Build Coastguard Worker 	lo_scontext.type = source->bounds;
875*2d543d20SAndroid Build Coastguard Worker 
876*2d543d20SAndroid Build Coastguard Worker 	if (target->bounds) {
877*2d543d20SAndroid Build Coastguard Worker 		memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
878*2d543d20SAndroid Build Coastguard Worker 		lo_tcontext.type = target->bounds;
879*2d543d20SAndroid Build Coastguard Worker 		tcontextp = &lo_tcontext;
880*2d543d20SAndroid Build Coastguard Worker 	}
881*2d543d20SAndroid Build Coastguard Worker 
882*2d543d20SAndroid Build Coastguard Worker 	context_struct_compute_av(&lo_scontext,
883*2d543d20SAndroid Build Coastguard Worker 				  tcontextp,
884*2d543d20SAndroid Build Coastguard Worker 				  tclass,
885*2d543d20SAndroid Build Coastguard Worker 				  requested,
886*2d543d20SAndroid Build Coastguard Worker 				  &lo_avd,
887*2d543d20SAndroid Build Coastguard Worker 				  NULL, /* reason intentionally omitted */
888*2d543d20SAndroid Build Coastguard Worker 				  NULL,
889*2d543d20SAndroid Build Coastguard Worker 				  0);
890*2d543d20SAndroid Build Coastguard Worker 
891*2d543d20SAndroid Build Coastguard Worker 	masked = ~lo_avd.allowed & avd->allowed;
892*2d543d20SAndroid Build Coastguard Worker 
893*2d543d20SAndroid Build Coastguard Worker 	if (!masked)
894*2d543d20SAndroid Build Coastguard Worker 		return;		/* no masked permission */
895*2d543d20SAndroid Build Coastguard Worker 
896*2d543d20SAndroid Build Coastguard Worker 	/* mask violated permissions */
897*2d543d20SAndroid Build Coastguard Worker 	avd->allowed &= ~masked;
898*2d543d20SAndroid Build Coastguard Worker 
899*2d543d20SAndroid Build Coastguard Worker 	if (reason)
900*2d543d20SAndroid Build Coastguard Worker 		*reason |= SEPOL_COMPUTEAV_BOUNDS;
901*2d543d20SAndroid Build Coastguard Worker }
902*2d543d20SAndroid Build Coastguard Worker 
903*2d543d20SAndroid Build Coastguard Worker /*
904*2d543d20SAndroid Build Coastguard Worker  * Compute access vectors based on a context structure pair for
905*2d543d20SAndroid Build Coastguard Worker  * the permissions in a particular class.
906*2d543d20SAndroid Build Coastguard Worker  */
context_struct_compute_av(context_struct_t * scontext,context_struct_t * tcontext,sepol_security_class_t tclass,sepol_access_vector_t requested,struct sepol_av_decision * avd,unsigned int * reason,char ** r_buf,unsigned int flags)907*2d543d20SAndroid Build Coastguard Worker static int context_struct_compute_av(context_struct_t * scontext,
908*2d543d20SAndroid Build Coastguard Worker 				     context_struct_t * tcontext,
909*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_class_t tclass,
910*2d543d20SAndroid Build Coastguard Worker 				     sepol_access_vector_t requested,
911*2d543d20SAndroid Build Coastguard Worker 				     struct sepol_av_decision *avd,
912*2d543d20SAndroid Build Coastguard Worker 				     unsigned int *reason,
913*2d543d20SAndroid Build Coastguard Worker 				     char **r_buf,
914*2d543d20SAndroid Build Coastguard Worker 				     unsigned int flags)
915*2d543d20SAndroid Build Coastguard Worker {
916*2d543d20SAndroid Build Coastguard Worker 	constraint_node_t *constraint;
917*2d543d20SAndroid Build Coastguard Worker 	struct role_allow *ra;
918*2d543d20SAndroid Build Coastguard Worker 	avtab_key_t avkey;
919*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *tclass_datum;
920*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t node;
921*2d543d20SAndroid Build Coastguard Worker 	ebitmap_t *sattr, *tattr;
922*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *snode, *tnode;
923*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j;
924*2d543d20SAndroid Build Coastguard Worker 
925*2d543d20SAndroid Build Coastguard Worker 	if (!tclass || tclass > policydb->p_classes.nprim) {
926*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized class %d", tclass);
927*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
928*2d543d20SAndroid Build Coastguard Worker 	}
929*2d543d20SAndroid Build Coastguard Worker 	tclass_datum = policydb->class_val_to_struct[tclass - 1];
930*2d543d20SAndroid Build Coastguard Worker 
931*2d543d20SAndroid Build Coastguard Worker 	/*
932*2d543d20SAndroid Build Coastguard Worker 	 * Initialize the access vectors to the default values.
933*2d543d20SAndroid Build Coastguard Worker 	 */
934*2d543d20SAndroid Build Coastguard Worker 	avd->allowed = 0;
935*2d543d20SAndroid Build Coastguard Worker 	avd->decided = 0xffffffff;
936*2d543d20SAndroid Build Coastguard Worker 	avd->auditallow = 0;
937*2d543d20SAndroid Build Coastguard Worker 	avd->auditdeny = 0xffffffff;
938*2d543d20SAndroid Build Coastguard Worker 	avd->seqno = latest_granting;
939*2d543d20SAndroid Build Coastguard Worker 	if (reason)
940*2d543d20SAndroid Build Coastguard Worker 		*reason = 0;
941*2d543d20SAndroid Build Coastguard Worker 
942*2d543d20SAndroid Build Coastguard Worker 	/*
943*2d543d20SAndroid Build Coastguard Worker 	 * If a specific type enforcement rule was defined for
944*2d543d20SAndroid Build Coastguard Worker 	 * this permission check, then use it.
945*2d543d20SAndroid Build Coastguard Worker 	 */
946*2d543d20SAndroid Build Coastguard Worker 	avkey.target_class = tclass;
947*2d543d20SAndroid Build Coastguard Worker 	avkey.specified = AVTAB_AV;
948*2d543d20SAndroid Build Coastguard Worker 	sattr = &policydb->type_attr_map[scontext->type - 1];
949*2d543d20SAndroid Build Coastguard Worker 	tattr = &policydb->type_attr_map[tcontext->type - 1];
950*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(sattr, snode, i) {
951*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
952*2d543d20SAndroid Build Coastguard Worker 			avkey.source_type = i + 1;
953*2d543d20SAndroid Build Coastguard Worker 			avkey.target_type = j + 1;
954*2d543d20SAndroid Build Coastguard Worker 			for (node =
955*2d543d20SAndroid Build Coastguard Worker 			     avtab_search_node(&policydb->te_avtab, &avkey);
956*2d543d20SAndroid Build Coastguard Worker 			     node != NULL;
957*2d543d20SAndroid Build Coastguard Worker 			     node =
958*2d543d20SAndroid Build Coastguard Worker 			     avtab_search_node_next(node, avkey.specified)) {
959*2d543d20SAndroid Build Coastguard Worker 				if (node->key.specified == AVTAB_ALLOWED)
960*2d543d20SAndroid Build Coastguard Worker 					avd->allowed |= node->datum.data;
961*2d543d20SAndroid Build Coastguard Worker 				else if (node->key.specified ==
962*2d543d20SAndroid Build Coastguard Worker 					 AVTAB_AUDITALLOW)
963*2d543d20SAndroid Build Coastguard Worker 					avd->auditallow |= node->datum.data;
964*2d543d20SAndroid Build Coastguard Worker 				else if (node->key.specified == AVTAB_AUDITDENY)
965*2d543d20SAndroid Build Coastguard Worker 					avd->auditdeny &= node->datum.data;
966*2d543d20SAndroid Build Coastguard Worker 			}
967*2d543d20SAndroid Build Coastguard Worker 
968*2d543d20SAndroid Build Coastguard Worker 			/* Check conditional av table for additional permissions */
969*2d543d20SAndroid Build Coastguard Worker 			cond_compute_av(&policydb->te_cond_avtab, &avkey, avd);
970*2d543d20SAndroid Build Coastguard Worker 
971*2d543d20SAndroid Build Coastguard Worker 		}
972*2d543d20SAndroid Build Coastguard Worker 	}
973*2d543d20SAndroid Build Coastguard Worker 
974*2d543d20SAndroid Build Coastguard Worker 	if (requested & ~avd->allowed) {
975*2d543d20SAndroid Build Coastguard Worker 		if (reason)
976*2d543d20SAndroid Build Coastguard Worker 			*reason |= SEPOL_COMPUTEAV_TE;
977*2d543d20SAndroid Build Coastguard Worker 		requested &= avd->allowed;
978*2d543d20SAndroid Build Coastguard Worker 	}
979*2d543d20SAndroid Build Coastguard Worker 
980*2d543d20SAndroid Build Coastguard Worker 	/*
981*2d543d20SAndroid Build Coastguard Worker 	 * Remove any permissions prohibited by a constraint (this includes
982*2d543d20SAndroid Build Coastguard Worker 	 * the MLS policy).
983*2d543d20SAndroid Build Coastguard Worker 	 */
984*2d543d20SAndroid Build Coastguard Worker 	constraint = tclass_datum->constraints;
985*2d543d20SAndroid Build Coastguard Worker 	while (constraint) {
986*2d543d20SAndroid Build Coastguard Worker 		if ((constraint->permissions & (avd->allowed)) &&
987*2d543d20SAndroid Build Coastguard Worker 		    !constraint_expr_eval_reason(scontext, tcontext, NULL,
988*2d543d20SAndroid Build Coastguard Worker 					  tclass, constraint, r_buf, flags)) {
989*2d543d20SAndroid Build Coastguard Worker 			avd->allowed =
990*2d543d20SAndroid Build Coastguard Worker 			    (avd->allowed) & ~(constraint->permissions);
991*2d543d20SAndroid Build Coastguard Worker 		}
992*2d543d20SAndroid Build Coastguard Worker 		constraint = constraint->next;
993*2d543d20SAndroid Build Coastguard Worker 	}
994*2d543d20SAndroid Build Coastguard Worker 
995*2d543d20SAndroid Build Coastguard Worker 	if (requested & ~avd->allowed) {
996*2d543d20SAndroid Build Coastguard Worker 		if (reason)
997*2d543d20SAndroid Build Coastguard Worker 			*reason |= SEPOL_COMPUTEAV_CONS;
998*2d543d20SAndroid Build Coastguard Worker 		requested &= avd->allowed;
999*2d543d20SAndroid Build Coastguard Worker 	}
1000*2d543d20SAndroid Build Coastguard Worker 
1001*2d543d20SAndroid Build Coastguard Worker 	/*
1002*2d543d20SAndroid Build Coastguard Worker 	 * If checking process transition permission and the
1003*2d543d20SAndroid Build Coastguard Worker 	 * role is changing, then check the (current_role, new_role)
1004*2d543d20SAndroid Build Coastguard Worker 	 * pair.
1005*2d543d20SAndroid Build Coastguard Worker 	 */
1006*2d543d20SAndroid Build Coastguard Worker 	if (tclass == policydb->process_class &&
1007*2d543d20SAndroid Build Coastguard Worker 	    (avd->allowed & policydb->process_trans_dyntrans) &&
1008*2d543d20SAndroid Build Coastguard Worker 	    scontext->role != tcontext->role) {
1009*2d543d20SAndroid Build Coastguard Worker 		for (ra = policydb->role_allow; ra; ra = ra->next) {
1010*2d543d20SAndroid Build Coastguard Worker 			if (scontext->role == ra->role &&
1011*2d543d20SAndroid Build Coastguard Worker 			    tcontext->role == ra->new_role)
1012*2d543d20SAndroid Build Coastguard Worker 				break;
1013*2d543d20SAndroid Build Coastguard Worker 		}
1014*2d543d20SAndroid Build Coastguard Worker 		if (!ra)
1015*2d543d20SAndroid Build Coastguard Worker 			avd->allowed &= ~policydb->process_trans_dyntrans;
1016*2d543d20SAndroid Build Coastguard Worker 	}
1017*2d543d20SAndroid Build Coastguard Worker 
1018*2d543d20SAndroid Build Coastguard Worker 	if (requested & ~avd->allowed) {
1019*2d543d20SAndroid Build Coastguard Worker 		if (reason)
1020*2d543d20SAndroid Build Coastguard Worker 			*reason |= SEPOL_COMPUTEAV_RBAC;
1021*2d543d20SAndroid Build Coastguard Worker 		requested &= avd->allowed;
1022*2d543d20SAndroid Build Coastguard Worker 	}
1023*2d543d20SAndroid Build Coastguard Worker 
1024*2d543d20SAndroid Build Coastguard Worker 	type_attribute_bounds_av(scontext, tcontext, tclass, requested, avd,
1025*2d543d20SAndroid Build Coastguard Worker 				 reason);
1026*2d543d20SAndroid Build Coastguard Worker 	return 0;
1027*2d543d20SAndroid Build Coastguard Worker }
1028*2d543d20SAndroid Build Coastguard Worker 
1029*2d543d20SAndroid Build Coastguard Worker /*
1030*2d543d20SAndroid Build Coastguard Worker  * sepol_validate_transition_reason_buffer - the reason buffer is realloc'd
1031*2d543d20SAndroid Build Coastguard Worker  * in the constraint_expr_eval_reason() function.
1032*2d543d20SAndroid Build Coastguard Worker  */
sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid,sepol_security_id_t newsid,sepol_security_id_t tasksid,sepol_security_class_t tclass,char ** reason_buf,unsigned int flags)1033*2d543d20SAndroid Build Coastguard Worker int sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid,
1034*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_id_t newsid,
1035*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_id_t tasksid,
1036*2d543d20SAndroid Build Coastguard Worker 				     sepol_security_class_t tclass,
1037*2d543d20SAndroid Build Coastguard Worker 				     char **reason_buf,
1038*2d543d20SAndroid Build Coastguard Worker 				     unsigned int flags)
1039*2d543d20SAndroid Build Coastguard Worker {
1040*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *ocontext;
1041*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *ncontext;
1042*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *tcontext;
1043*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *tclass_datum;
1044*2d543d20SAndroid Build Coastguard Worker 	constraint_node_t *constraint;
1045*2d543d20SAndroid Build Coastguard Worker 
1046*2d543d20SAndroid Build Coastguard Worker 	if (!tclass || tclass > policydb->p_classes.nprim) {
1047*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized class %d", tclass);
1048*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1049*2d543d20SAndroid Build Coastguard Worker 	}
1050*2d543d20SAndroid Build Coastguard Worker 	tclass_datum = policydb->class_val_to_struct[tclass - 1];
1051*2d543d20SAndroid Build Coastguard Worker 
1052*2d543d20SAndroid Build Coastguard Worker 	ocontext = sepol_sidtab_search(sidtab, oldsid);
1053*2d543d20SAndroid Build Coastguard Worker 	if (!ocontext) {
1054*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", oldsid);
1055*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1056*2d543d20SAndroid Build Coastguard Worker 	}
1057*2d543d20SAndroid Build Coastguard Worker 
1058*2d543d20SAndroid Build Coastguard Worker 	ncontext = sepol_sidtab_search(sidtab, newsid);
1059*2d543d20SAndroid Build Coastguard Worker 	if (!ncontext) {
1060*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", newsid);
1061*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1062*2d543d20SAndroid Build Coastguard Worker 	}
1063*2d543d20SAndroid Build Coastguard Worker 
1064*2d543d20SAndroid Build Coastguard Worker 	tcontext = sepol_sidtab_search(sidtab, tasksid);
1065*2d543d20SAndroid Build Coastguard Worker 	if (!tcontext) {
1066*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", tasksid);
1067*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1068*2d543d20SAndroid Build Coastguard Worker 	}
1069*2d543d20SAndroid Build Coastguard Worker 
1070*2d543d20SAndroid Build Coastguard Worker 	/*
1071*2d543d20SAndroid Build Coastguard Worker 	 * Set the buffer to NULL as mls/validatetrans may not be processed.
1072*2d543d20SAndroid Build Coastguard Worker 	 * If a buffer is required, then the routines in
1073*2d543d20SAndroid Build Coastguard Worker 	 * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE
1074*2d543d20SAndroid Build Coastguard Worker 	 * chunks (as it gets called for each mls/validatetrans processed).
1075*2d543d20SAndroid Build Coastguard Worker 	 * We just make sure these start from zero.
1076*2d543d20SAndroid Build Coastguard Worker 	 */
1077*2d543d20SAndroid Build Coastguard Worker 	*reason_buf = NULL;
1078*2d543d20SAndroid Build Coastguard Worker 	reason_buf_used = 0;
1079*2d543d20SAndroid Build Coastguard Worker 	reason_buf_len = 0;
1080*2d543d20SAndroid Build Coastguard Worker 	constraint = tclass_datum->validatetrans;
1081*2d543d20SAndroid Build Coastguard Worker 	while (constraint) {
1082*2d543d20SAndroid Build Coastguard Worker 		if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
1083*2d543d20SAndroid Build Coastguard Worker 				tclass, constraint, reason_buf, flags)) {
1084*2d543d20SAndroid Build Coastguard Worker 			return -EPERM;
1085*2d543d20SAndroid Build Coastguard Worker 		}
1086*2d543d20SAndroid Build Coastguard Worker 		constraint = constraint->next;
1087*2d543d20SAndroid Build Coastguard Worker 	}
1088*2d543d20SAndroid Build Coastguard Worker 	return 0;
1089*2d543d20SAndroid Build Coastguard Worker }
1090*2d543d20SAndroid Build Coastguard Worker 
sepol_compute_av_reason(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_access_vector_t requested,struct sepol_av_decision * avd,unsigned int * reason)1091*2d543d20SAndroid Build Coastguard Worker int sepol_compute_av_reason(sepol_security_id_t ssid,
1092*2d543d20SAndroid Build Coastguard Worker 				   sepol_security_id_t tsid,
1093*2d543d20SAndroid Build Coastguard Worker 				   sepol_security_class_t tclass,
1094*2d543d20SAndroid Build Coastguard Worker 				   sepol_access_vector_t requested,
1095*2d543d20SAndroid Build Coastguard Worker 				   struct sepol_av_decision *avd,
1096*2d543d20SAndroid Build Coastguard Worker 				   unsigned int *reason)
1097*2d543d20SAndroid Build Coastguard Worker {
1098*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *scontext = 0, *tcontext = 0;
1099*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1100*2d543d20SAndroid Build Coastguard Worker 
1101*2d543d20SAndroid Build Coastguard Worker 	scontext = sepol_sidtab_search(sidtab, ssid);
1102*2d543d20SAndroid Build Coastguard Worker 	if (!scontext) {
1103*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized source SID %d", ssid);
1104*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1105*2d543d20SAndroid Build Coastguard Worker 		goto out;
1106*2d543d20SAndroid Build Coastguard Worker 	}
1107*2d543d20SAndroid Build Coastguard Worker 	tcontext = sepol_sidtab_search(sidtab, tsid);
1108*2d543d20SAndroid Build Coastguard Worker 	if (!tcontext) {
1109*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized target SID %d", tsid);
1110*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1111*2d543d20SAndroid Build Coastguard Worker 		goto out;
1112*2d543d20SAndroid Build Coastguard Worker 	}
1113*2d543d20SAndroid Build Coastguard Worker 
1114*2d543d20SAndroid Build Coastguard Worker 	rc = context_struct_compute_av(scontext, tcontext, tclass,
1115*2d543d20SAndroid Build Coastguard Worker 					requested, avd, reason, NULL, 0);
1116*2d543d20SAndroid Build Coastguard Worker       out:
1117*2d543d20SAndroid Build Coastguard Worker 	return rc;
1118*2d543d20SAndroid Build Coastguard Worker }
1119*2d543d20SAndroid Build Coastguard Worker 
1120*2d543d20SAndroid Build Coastguard Worker /*
1121*2d543d20SAndroid Build Coastguard Worker  * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to
1122*2d543d20SAndroid Build Coastguard Worker  * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd
1123*2d543d20SAndroid Build Coastguard Worker  * in the constraint_expr_eval_reason() function.
1124*2d543d20SAndroid Build Coastguard Worker  */
sepol_compute_av_reason_buffer(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_access_vector_t requested,struct sepol_av_decision * avd,unsigned int * reason,char ** reason_buf,unsigned int flags)1125*2d543d20SAndroid Build Coastguard Worker int sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
1126*2d543d20SAndroid Build Coastguard Worker 				   sepol_security_id_t tsid,
1127*2d543d20SAndroid Build Coastguard Worker 				   sepol_security_class_t tclass,
1128*2d543d20SAndroid Build Coastguard Worker 				   sepol_access_vector_t requested,
1129*2d543d20SAndroid Build Coastguard Worker 				   struct sepol_av_decision *avd,
1130*2d543d20SAndroid Build Coastguard Worker 				   unsigned int *reason,
1131*2d543d20SAndroid Build Coastguard Worker 				   char **reason_buf,
1132*2d543d20SAndroid Build Coastguard Worker 				   unsigned int flags)
1133*2d543d20SAndroid Build Coastguard Worker {
1134*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *scontext = 0, *tcontext = 0;
1135*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1136*2d543d20SAndroid Build Coastguard Worker 
1137*2d543d20SAndroid Build Coastguard Worker 	scontext = sepol_sidtab_search(sidtab, ssid);
1138*2d543d20SAndroid Build Coastguard Worker 	if (!scontext) {
1139*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized source SID %d", ssid);
1140*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1141*2d543d20SAndroid Build Coastguard Worker 		goto out;
1142*2d543d20SAndroid Build Coastguard Worker 	}
1143*2d543d20SAndroid Build Coastguard Worker 	tcontext = sepol_sidtab_search(sidtab, tsid);
1144*2d543d20SAndroid Build Coastguard Worker 	if (!tcontext) {
1145*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized target SID %d", tsid);
1146*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1147*2d543d20SAndroid Build Coastguard Worker 		goto out;
1148*2d543d20SAndroid Build Coastguard Worker 	}
1149*2d543d20SAndroid Build Coastguard Worker 
1150*2d543d20SAndroid Build Coastguard Worker 	/*
1151*2d543d20SAndroid Build Coastguard Worker 	 * Set the buffer to NULL as constraints may not be processed.
1152*2d543d20SAndroid Build Coastguard Worker 	 * If a buffer is required, then the routines in
1153*2d543d20SAndroid Build Coastguard Worker 	 * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE
1154*2d543d20SAndroid Build Coastguard Worker 	 * chunks (as it gets called for each constraint processed).
1155*2d543d20SAndroid Build Coastguard Worker 	 * We just make sure these start from zero.
1156*2d543d20SAndroid Build Coastguard Worker 	 */
1157*2d543d20SAndroid Build Coastguard Worker 	*reason_buf = NULL;
1158*2d543d20SAndroid Build Coastguard Worker 	reason_buf_used = 0;
1159*2d543d20SAndroid Build Coastguard Worker 	reason_buf_len = 0;
1160*2d543d20SAndroid Build Coastguard Worker 
1161*2d543d20SAndroid Build Coastguard Worker 	rc = context_struct_compute_av(scontext, tcontext, tclass,
1162*2d543d20SAndroid Build Coastguard Worker 					   requested, avd, reason, reason_buf, flags);
1163*2d543d20SAndroid Build Coastguard Worker out:
1164*2d543d20SAndroid Build Coastguard Worker 	return rc;
1165*2d543d20SAndroid Build Coastguard Worker }
1166*2d543d20SAndroid Build Coastguard Worker 
sepol_compute_av(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_access_vector_t requested,struct sepol_av_decision * avd)1167*2d543d20SAndroid Build Coastguard Worker int sepol_compute_av(sepol_security_id_t ssid,
1168*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_id_t tsid,
1169*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_class_t tclass,
1170*2d543d20SAndroid Build Coastguard Worker 			    sepol_access_vector_t requested,
1171*2d543d20SAndroid Build Coastguard Worker 			    struct sepol_av_decision *avd)
1172*2d543d20SAndroid Build Coastguard Worker {
1173*2d543d20SAndroid Build Coastguard Worker 	unsigned int reason = 0;
1174*2d543d20SAndroid Build Coastguard Worker 	return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd,
1175*2d543d20SAndroid Build Coastguard Worker 				       &reason);
1176*2d543d20SAndroid Build Coastguard Worker }
1177*2d543d20SAndroid Build Coastguard Worker 
1178*2d543d20SAndroid Build Coastguard Worker /*
1179*2d543d20SAndroid Build Coastguard Worker  * Return a class ID associated with the class string specified by
1180*2d543d20SAndroid Build Coastguard Worker  * class_name.
1181*2d543d20SAndroid Build Coastguard Worker  */
sepol_string_to_security_class(const char * class_name,sepol_security_class_t * tclass)1182*2d543d20SAndroid Build Coastguard Worker int sepol_string_to_security_class(const char *class_name,
1183*2d543d20SAndroid Build Coastguard Worker 			sepol_security_class_t *tclass)
1184*2d543d20SAndroid Build Coastguard Worker {
1185*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *tclass_datum;
1186*2d543d20SAndroid Build Coastguard Worker 
1187*2d543d20SAndroid Build Coastguard Worker 	tclass_datum = hashtab_search(policydb->p_classes.table,
1188*2d543d20SAndroid Build Coastguard Worker 				      class_name);
1189*2d543d20SAndroid Build Coastguard Worker 	if (!tclass_datum) {
1190*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized class %s", class_name);
1191*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
1192*2d543d20SAndroid Build Coastguard Worker 	}
1193*2d543d20SAndroid Build Coastguard Worker 	*tclass = tclass_datum->s.value;
1194*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
1195*2d543d20SAndroid Build Coastguard Worker }
1196*2d543d20SAndroid Build Coastguard Worker 
1197*2d543d20SAndroid Build Coastguard Worker /*
1198*2d543d20SAndroid Build Coastguard Worker  * Return access vector bit associated with the class ID and permission
1199*2d543d20SAndroid Build Coastguard Worker  * string.
1200*2d543d20SAndroid Build Coastguard Worker  */
sepol_string_to_av_perm(sepol_security_class_t tclass,const char * perm_name,sepol_access_vector_t * av)1201*2d543d20SAndroid Build Coastguard Worker int sepol_string_to_av_perm(sepol_security_class_t tclass,
1202*2d543d20SAndroid Build Coastguard Worker 					const char *perm_name,
1203*2d543d20SAndroid Build Coastguard Worker 					sepol_access_vector_t *av)
1204*2d543d20SAndroid Build Coastguard Worker {
1205*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *tclass_datum;
1206*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perm_datum;
1207*2d543d20SAndroid Build Coastguard Worker 
1208*2d543d20SAndroid Build Coastguard Worker 	if (!tclass || tclass > policydb->p_classes.nprim) {
1209*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized class %d", tclass);
1210*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1211*2d543d20SAndroid Build Coastguard Worker 	}
1212*2d543d20SAndroid Build Coastguard Worker 	tclass_datum = policydb->class_val_to_struct[tclass - 1];
1213*2d543d20SAndroid Build Coastguard Worker 
1214*2d543d20SAndroid Build Coastguard Worker 	/* Check for unique perms then the common ones (if any) */
1215*2d543d20SAndroid Build Coastguard Worker 	perm_datum = (perm_datum_t *)
1216*2d543d20SAndroid Build Coastguard Worker 			hashtab_search(tclass_datum->permissions.table,
1217*2d543d20SAndroid Build Coastguard Worker 			perm_name);
1218*2d543d20SAndroid Build Coastguard Worker 	if (perm_datum != NULL) {
1219*2d543d20SAndroid Build Coastguard Worker 		*av = UINT32_C(1) << (perm_datum->s.value - 1);
1220*2d543d20SAndroid Build Coastguard Worker 		return STATUS_SUCCESS;
1221*2d543d20SAndroid Build Coastguard Worker 	}
1222*2d543d20SAndroid Build Coastguard Worker 
1223*2d543d20SAndroid Build Coastguard Worker 	if (tclass_datum->comdatum == NULL)
1224*2d543d20SAndroid Build Coastguard Worker 		goto out;
1225*2d543d20SAndroid Build Coastguard Worker 
1226*2d543d20SAndroid Build Coastguard Worker 	perm_datum = (perm_datum_t *)
1227*2d543d20SAndroid Build Coastguard Worker 			hashtab_search(tclass_datum->comdatum->permissions.table,
1228*2d543d20SAndroid Build Coastguard Worker 			perm_name);
1229*2d543d20SAndroid Build Coastguard Worker 
1230*2d543d20SAndroid Build Coastguard Worker 	if (perm_datum != NULL) {
1231*2d543d20SAndroid Build Coastguard Worker 		*av = UINT32_C(1) << (perm_datum->s.value - 1);
1232*2d543d20SAndroid Build Coastguard Worker 		return STATUS_SUCCESS;
1233*2d543d20SAndroid Build Coastguard Worker 	}
1234*2d543d20SAndroid Build Coastguard Worker out:
1235*2d543d20SAndroid Build Coastguard Worker 	ERR(NULL, "could not convert %s to av bit", perm_name);
1236*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
1237*2d543d20SAndroid Build Coastguard Worker }
1238*2d543d20SAndroid Build Coastguard Worker 
sepol_av_perm_to_string(sepol_security_class_t tclass,sepol_access_vector_t av)1239*2d543d20SAndroid Build Coastguard Worker  const char *sepol_av_perm_to_string(sepol_security_class_t tclass,
1240*2d543d20SAndroid Build Coastguard Worker 					sepol_access_vector_t av)
1241*2d543d20SAndroid Build Coastguard Worker {
1242*2d543d20SAndroid Build Coastguard Worker 	static char avbuf[1024];
1243*2d543d20SAndroid Build Coastguard Worker 	char *avstr = sepol_av_to_string(policydb, tclass, av);
1244*2d543d20SAndroid Build Coastguard Worker 	size_t len;
1245*2d543d20SAndroid Build Coastguard Worker 
1246*2d543d20SAndroid Build Coastguard Worker 	memset(avbuf, 0, sizeof(avbuf));
1247*2d543d20SAndroid Build Coastguard Worker 
1248*2d543d20SAndroid Build Coastguard Worker 	if (avstr) {
1249*2d543d20SAndroid Build Coastguard Worker 		len = strlen(avstr);
1250*2d543d20SAndroid Build Coastguard Worker 		if (len < sizeof(avbuf)) {
1251*2d543d20SAndroid Build Coastguard Worker 			strcpy(avbuf, avstr);
1252*2d543d20SAndroid Build Coastguard Worker 		} else {
1253*2d543d20SAndroid Build Coastguard Worker 			sprintf(avbuf, "<access-vector overflowed buffer>");
1254*2d543d20SAndroid Build Coastguard Worker 		}
1255*2d543d20SAndroid Build Coastguard Worker 		free(avstr);
1256*2d543d20SAndroid Build Coastguard Worker 	} else {
1257*2d543d20SAndroid Build Coastguard Worker 		sprintf(avbuf, "<format-failure>");
1258*2d543d20SAndroid Build Coastguard Worker 	}
1259*2d543d20SAndroid Build Coastguard Worker 
1260*2d543d20SAndroid Build Coastguard Worker 	return avbuf;
1261*2d543d20SAndroid Build Coastguard Worker }
1262*2d543d20SAndroid Build Coastguard Worker 
1263*2d543d20SAndroid Build Coastguard Worker /*
1264*2d543d20SAndroid Build Coastguard Worker  * Write the security context string representation of
1265*2d543d20SAndroid Build Coastguard Worker  * the context associated with `sid' into a dynamically
1266*2d543d20SAndroid Build Coastguard Worker  * allocated string of the correct size.  Set `*scontext'
1267*2d543d20SAndroid Build Coastguard Worker  * to point to this string and set `*scontext_len' to
1268*2d543d20SAndroid Build Coastguard Worker  * the length of the string.
1269*2d543d20SAndroid Build Coastguard Worker  */
sepol_sid_to_context(sepol_security_id_t sid,sepol_security_context_t * scontext,size_t * scontext_len)1270*2d543d20SAndroid Build Coastguard Worker int sepol_sid_to_context(sepol_security_id_t sid,
1271*2d543d20SAndroid Build Coastguard Worker 				sepol_security_context_t * scontext,
1272*2d543d20SAndroid Build Coastguard Worker 				size_t * scontext_len)
1273*2d543d20SAndroid Build Coastguard Worker {
1274*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *context;
1275*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1276*2d543d20SAndroid Build Coastguard Worker 
1277*2d543d20SAndroid Build Coastguard Worker 	context = sepol_sidtab_search(sidtab, sid);
1278*2d543d20SAndroid Build Coastguard Worker 	if (!context) {
1279*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", sid);
1280*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1281*2d543d20SAndroid Build Coastguard Worker 		goto out;
1282*2d543d20SAndroid Build Coastguard Worker 	}
1283*2d543d20SAndroid Build Coastguard Worker 	rc = context_to_string(NULL, policydb, context, scontext, scontext_len);
1284*2d543d20SAndroid Build Coastguard Worker       out:
1285*2d543d20SAndroid Build Coastguard Worker 	return rc;
1286*2d543d20SAndroid Build Coastguard Worker 
1287*2d543d20SAndroid Build Coastguard Worker }
1288*2d543d20SAndroid Build Coastguard Worker 
1289*2d543d20SAndroid Build Coastguard Worker /*
1290*2d543d20SAndroid Build Coastguard Worker  * Return a SID associated with the security context that
1291*2d543d20SAndroid Build Coastguard Worker  * has the string representation specified by `scontext'.
1292*2d543d20SAndroid Build Coastguard Worker  */
sepol_context_to_sid(sepol_const_security_context_t scontext,size_t scontext_len,sepol_security_id_t * sid)1293*2d543d20SAndroid Build Coastguard Worker int sepol_context_to_sid(sepol_const_security_context_t scontext,
1294*2d543d20SAndroid Build Coastguard Worker 				size_t scontext_len, sepol_security_id_t * sid)
1295*2d543d20SAndroid Build Coastguard Worker {
1296*2d543d20SAndroid Build Coastguard Worker 
1297*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *context = NULL;
1298*2d543d20SAndroid Build Coastguard Worker 
1299*2d543d20SAndroid Build Coastguard Worker 	/* First, create the context */
1300*2d543d20SAndroid Build Coastguard Worker 	if (context_from_string(NULL, policydb, &context,
1301*2d543d20SAndroid Build Coastguard Worker 				scontext, scontext_len) < 0)
1302*2d543d20SAndroid Build Coastguard Worker 		goto err;
1303*2d543d20SAndroid Build Coastguard Worker 
1304*2d543d20SAndroid Build Coastguard Worker 	/* Obtain the new sid */
1305*2d543d20SAndroid Build Coastguard Worker 	if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0))
1306*2d543d20SAndroid Build Coastguard Worker 		goto err;
1307*2d543d20SAndroid Build Coastguard Worker 
1308*2d543d20SAndroid Build Coastguard Worker 	context_destroy(context);
1309*2d543d20SAndroid Build Coastguard Worker 	free(context);
1310*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
1311*2d543d20SAndroid Build Coastguard Worker 
1312*2d543d20SAndroid Build Coastguard Worker       err:
1313*2d543d20SAndroid Build Coastguard Worker 	if (context) {
1314*2d543d20SAndroid Build Coastguard Worker 		context_destroy(context);
1315*2d543d20SAndroid Build Coastguard Worker 		free(context);
1316*2d543d20SAndroid Build Coastguard Worker 	}
1317*2d543d20SAndroid Build Coastguard Worker 	ERR(NULL, "could not convert %s to sid", scontext);
1318*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
1319*2d543d20SAndroid Build Coastguard Worker }
1320*2d543d20SAndroid Build Coastguard Worker 
compute_sid_handle_invalid_context(context_struct_t * scontext,context_struct_t * tcontext,sepol_security_class_t tclass,context_struct_t * newcontext)1321*2d543d20SAndroid Build Coastguard Worker static inline int compute_sid_handle_invalid_context(context_struct_t *
1322*2d543d20SAndroid Build Coastguard Worker 						     scontext,
1323*2d543d20SAndroid Build Coastguard Worker 						     context_struct_t *
1324*2d543d20SAndroid Build Coastguard Worker 						     tcontext,
1325*2d543d20SAndroid Build Coastguard Worker 						     sepol_security_class_t
1326*2d543d20SAndroid Build Coastguard Worker 						     tclass,
1327*2d543d20SAndroid Build Coastguard Worker 						     context_struct_t *
1328*2d543d20SAndroid Build Coastguard Worker 						     newcontext)
1329*2d543d20SAndroid Build Coastguard Worker {
1330*2d543d20SAndroid Build Coastguard Worker 	if (selinux_enforcing) {
1331*2d543d20SAndroid Build Coastguard Worker 		return -EACCES;
1332*2d543d20SAndroid Build Coastguard Worker 	} else {
1333*2d543d20SAndroid Build Coastguard Worker 		sepol_security_context_t s, t, n;
1334*2d543d20SAndroid Build Coastguard Worker 		size_t slen, tlen, nlen;
1335*2d543d20SAndroid Build Coastguard Worker 
1336*2d543d20SAndroid Build Coastguard Worker 		context_to_string(NULL, policydb, scontext, &s, &slen);
1337*2d543d20SAndroid Build Coastguard Worker 		context_to_string(NULL, policydb, tcontext, &t, &tlen);
1338*2d543d20SAndroid Build Coastguard Worker 		context_to_string(NULL, policydb, newcontext, &n, &nlen);
1339*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "invalid context %s for "
1340*2d543d20SAndroid Build Coastguard Worker 		    "scontext=%s tcontext=%s tclass=%s",
1341*2d543d20SAndroid Build Coastguard Worker 		    n, s, t, policydb->p_class_val_to_name[tclass - 1]);
1342*2d543d20SAndroid Build Coastguard Worker 		free(s);
1343*2d543d20SAndroid Build Coastguard Worker 		free(t);
1344*2d543d20SAndroid Build Coastguard Worker 		free(n);
1345*2d543d20SAndroid Build Coastguard Worker 		return 0;
1346*2d543d20SAndroid Build Coastguard Worker 	}
1347*2d543d20SAndroid Build Coastguard Worker }
1348*2d543d20SAndroid Build Coastguard Worker 
sepol_compute_sid(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,uint32_t specified,sepol_security_id_t * out_sid)1349*2d543d20SAndroid Build Coastguard Worker static int sepol_compute_sid(sepol_security_id_t ssid,
1350*2d543d20SAndroid Build Coastguard Worker 			     sepol_security_id_t tsid,
1351*2d543d20SAndroid Build Coastguard Worker 			     sepol_security_class_t tclass,
1352*2d543d20SAndroid Build Coastguard Worker 			     uint32_t specified, sepol_security_id_t * out_sid)
1353*2d543d20SAndroid Build Coastguard Worker {
1354*2d543d20SAndroid Build Coastguard Worker 	struct class_datum *cladatum = NULL;
1355*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *scontext = 0, *tcontext = 0, newcontext;
1356*2d543d20SAndroid Build Coastguard Worker 	struct role_trans *roletr = 0;
1357*2d543d20SAndroid Build Coastguard Worker 	avtab_key_t avkey;
1358*2d543d20SAndroid Build Coastguard Worker 	avtab_datum_t *avdatum;
1359*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t node;
1360*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1361*2d543d20SAndroid Build Coastguard Worker 
1362*2d543d20SAndroid Build Coastguard Worker 	scontext = sepol_sidtab_search(sidtab, ssid);
1363*2d543d20SAndroid Build Coastguard Worker 	if (!scontext) {
1364*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", ssid);
1365*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1366*2d543d20SAndroid Build Coastguard Worker 	}
1367*2d543d20SAndroid Build Coastguard Worker 	tcontext = sepol_sidtab_search(sidtab, tsid);
1368*2d543d20SAndroid Build Coastguard Worker 	if (!tcontext) {
1369*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "unrecognized SID %d", tsid);
1370*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1371*2d543d20SAndroid Build Coastguard Worker 	}
1372*2d543d20SAndroid Build Coastguard Worker 
1373*2d543d20SAndroid Build Coastguard Worker 	if (tclass && tclass <= policydb->p_classes.nprim)
1374*2d543d20SAndroid Build Coastguard Worker 		cladatum = policydb->class_val_to_struct[tclass - 1];
1375*2d543d20SAndroid Build Coastguard Worker 
1376*2d543d20SAndroid Build Coastguard Worker 	context_init(&newcontext);
1377*2d543d20SAndroid Build Coastguard Worker 
1378*2d543d20SAndroid Build Coastguard Worker 	/* Set the user identity. */
1379*2d543d20SAndroid Build Coastguard Worker 	switch (specified) {
1380*2d543d20SAndroid Build Coastguard Worker 	case AVTAB_TRANSITION:
1381*2d543d20SAndroid Build Coastguard Worker 	case AVTAB_CHANGE:
1382*2d543d20SAndroid Build Coastguard Worker 		if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
1383*2d543d20SAndroid Build Coastguard Worker 			newcontext.user = tcontext->user;
1384*2d543d20SAndroid Build Coastguard Worker 		} else {
1385*2d543d20SAndroid Build Coastguard Worker 			/* notice this gets both DEFAULT_SOURCE and unset */
1386*2d543d20SAndroid Build Coastguard Worker 			/* Use the process user identity. */
1387*2d543d20SAndroid Build Coastguard Worker 			newcontext.user = scontext->user;
1388*2d543d20SAndroid Build Coastguard Worker 		}
1389*2d543d20SAndroid Build Coastguard Worker 		break;
1390*2d543d20SAndroid Build Coastguard Worker 	case AVTAB_MEMBER:
1391*2d543d20SAndroid Build Coastguard Worker 		/* Use the related object owner. */
1392*2d543d20SAndroid Build Coastguard Worker 		newcontext.user = tcontext->user;
1393*2d543d20SAndroid Build Coastguard Worker 		break;
1394*2d543d20SAndroid Build Coastguard Worker 	}
1395*2d543d20SAndroid Build Coastguard Worker 
1396*2d543d20SAndroid Build Coastguard Worker 	/* Set the role to default values. */
1397*2d543d20SAndroid Build Coastguard Worker 	if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
1398*2d543d20SAndroid Build Coastguard Worker 		newcontext.role = scontext->role;
1399*2d543d20SAndroid Build Coastguard Worker 	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
1400*2d543d20SAndroid Build Coastguard Worker 		newcontext.role = tcontext->role;
1401*2d543d20SAndroid Build Coastguard Worker 	} else {
1402*2d543d20SAndroid Build Coastguard Worker 		if (tclass == policydb->process_class)
1403*2d543d20SAndroid Build Coastguard Worker 			newcontext.role = scontext->role;
1404*2d543d20SAndroid Build Coastguard Worker 		else
1405*2d543d20SAndroid Build Coastguard Worker 			newcontext.role = OBJECT_R_VAL;
1406*2d543d20SAndroid Build Coastguard Worker 	}
1407*2d543d20SAndroid Build Coastguard Worker 
1408*2d543d20SAndroid Build Coastguard Worker 	/* Set the type to default values. */
1409*2d543d20SAndroid Build Coastguard Worker 	if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
1410*2d543d20SAndroid Build Coastguard Worker 		newcontext.type = scontext->type;
1411*2d543d20SAndroid Build Coastguard Worker 	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
1412*2d543d20SAndroid Build Coastguard Worker 		newcontext.type = tcontext->type;
1413*2d543d20SAndroid Build Coastguard Worker 	} else {
1414*2d543d20SAndroid Build Coastguard Worker 		if (tclass == policydb->process_class) {
1415*2d543d20SAndroid Build Coastguard Worker 			/* Use the type of process. */
1416*2d543d20SAndroid Build Coastguard Worker 			newcontext.type = scontext->type;
1417*2d543d20SAndroid Build Coastguard Worker 		} else {
1418*2d543d20SAndroid Build Coastguard Worker 			/* Use the type of the related object. */
1419*2d543d20SAndroid Build Coastguard Worker 			newcontext.type = tcontext->type;
1420*2d543d20SAndroid Build Coastguard Worker 		}
1421*2d543d20SAndroid Build Coastguard Worker 	}
1422*2d543d20SAndroid Build Coastguard Worker 
1423*2d543d20SAndroid Build Coastguard Worker 	/* Look for a type transition/member/change rule. */
1424*2d543d20SAndroid Build Coastguard Worker 	avkey.source_type = scontext->type;
1425*2d543d20SAndroid Build Coastguard Worker 	avkey.target_type = tcontext->type;
1426*2d543d20SAndroid Build Coastguard Worker 	avkey.target_class = tclass;
1427*2d543d20SAndroid Build Coastguard Worker 	avkey.specified = specified;
1428*2d543d20SAndroid Build Coastguard Worker 	avdatum = avtab_search(&policydb->te_avtab, &avkey);
1429*2d543d20SAndroid Build Coastguard Worker 
1430*2d543d20SAndroid Build Coastguard Worker 	/* If no permanent rule, also check for enabled conditional rules */
1431*2d543d20SAndroid Build Coastguard Worker 	if (!avdatum) {
1432*2d543d20SAndroid Build Coastguard Worker 		node = avtab_search_node(&policydb->te_cond_avtab, &avkey);
1433*2d543d20SAndroid Build Coastguard Worker 		for (; node != NULL;
1434*2d543d20SAndroid Build Coastguard Worker 		     node = avtab_search_node_next(node, specified)) {
1435*2d543d20SAndroid Build Coastguard Worker 			if (node->key.specified & AVTAB_ENABLED) {
1436*2d543d20SAndroid Build Coastguard Worker 				avdatum = &node->datum;
1437*2d543d20SAndroid Build Coastguard Worker 				break;
1438*2d543d20SAndroid Build Coastguard Worker 			}
1439*2d543d20SAndroid Build Coastguard Worker 		}
1440*2d543d20SAndroid Build Coastguard Worker 	}
1441*2d543d20SAndroid Build Coastguard Worker 
1442*2d543d20SAndroid Build Coastguard Worker 	if (avdatum) {
1443*2d543d20SAndroid Build Coastguard Worker 		/* Use the type from the type transition/member/change rule. */
1444*2d543d20SAndroid Build Coastguard Worker 		newcontext.type = avdatum->data;
1445*2d543d20SAndroid Build Coastguard Worker 	}
1446*2d543d20SAndroid Build Coastguard Worker 
1447*2d543d20SAndroid Build Coastguard Worker 	/* Check for class-specific changes. */
1448*2d543d20SAndroid Build Coastguard Worker 	if (specified & AVTAB_TRANSITION) {
1449*2d543d20SAndroid Build Coastguard Worker 		/* Look for a role transition rule. */
1450*2d543d20SAndroid Build Coastguard Worker 		for (roletr = policydb->role_tr; roletr;
1451*2d543d20SAndroid Build Coastguard Worker 		     roletr = roletr->next) {
1452*2d543d20SAndroid Build Coastguard Worker 			if (roletr->role == scontext->role &&
1453*2d543d20SAndroid Build Coastguard Worker 			    roletr->type == tcontext->type &&
1454*2d543d20SAndroid Build Coastguard Worker 			    roletr->tclass == tclass) {
1455*2d543d20SAndroid Build Coastguard Worker 				/* Use the role transition rule. */
1456*2d543d20SAndroid Build Coastguard Worker 				newcontext.role = roletr->new_role;
1457*2d543d20SAndroid Build Coastguard Worker 				break;
1458*2d543d20SAndroid Build Coastguard Worker 			}
1459*2d543d20SAndroid Build Coastguard Worker 		}
1460*2d543d20SAndroid Build Coastguard Worker 	}
1461*2d543d20SAndroid Build Coastguard Worker 
1462*2d543d20SAndroid Build Coastguard Worker 	/* Set the MLS attributes.
1463*2d543d20SAndroid Build Coastguard Worker 	   This is done last because it may allocate memory. */
1464*2d543d20SAndroid Build Coastguard Worker 	rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified,
1465*2d543d20SAndroid Build Coastguard Worker 			     &newcontext);
1466*2d543d20SAndroid Build Coastguard Worker 	if (rc)
1467*2d543d20SAndroid Build Coastguard Worker 		goto out;
1468*2d543d20SAndroid Build Coastguard Worker 
1469*2d543d20SAndroid Build Coastguard Worker 	/* Check the validity of the context. */
1470*2d543d20SAndroid Build Coastguard Worker 	if (!policydb_context_isvalid(policydb, &newcontext)) {
1471*2d543d20SAndroid Build Coastguard Worker 		rc = compute_sid_handle_invalid_context(scontext,
1472*2d543d20SAndroid Build Coastguard Worker 							tcontext,
1473*2d543d20SAndroid Build Coastguard Worker 							tclass, &newcontext);
1474*2d543d20SAndroid Build Coastguard Worker 		if (rc)
1475*2d543d20SAndroid Build Coastguard Worker 			goto out;
1476*2d543d20SAndroid Build Coastguard Worker 	}
1477*2d543d20SAndroid Build Coastguard Worker 	/* Obtain the sid for the context. */
1478*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid);
1479*2d543d20SAndroid Build Coastguard Worker       out:
1480*2d543d20SAndroid Build Coastguard Worker 	context_destroy(&newcontext);
1481*2d543d20SAndroid Build Coastguard Worker 	return rc;
1482*2d543d20SAndroid Build Coastguard Worker }
1483*2d543d20SAndroid Build Coastguard Worker 
1484*2d543d20SAndroid Build Coastguard Worker /*
1485*2d543d20SAndroid Build Coastguard Worker  * Compute a SID to use for labeling a new object in the
1486*2d543d20SAndroid Build Coastguard Worker  * class `tclass' based on a SID pair.
1487*2d543d20SAndroid Build Coastguard Worker  */
sepol_transition_sid(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_security_id_t * out_sid)1488*2d543d20SAndroid Build Coastguard Worker int sepol_transition_sid(sepol_security_id_t ssid,
1489*2d543d20SAndroid Build Coastguard Worker 				sepol_security_id_t tsid,
1490*2d543d20SAndroid Build Coastguard Worker 				sepol_security_class_t tclass,
1491*2d543d20SAndroid Build Coastguard Worker 				sepol_security_id_t * out_sid)
1492*2d543d20SAndroid Build Coastguard Worker {
1493*2d543d20SAndroid Build Coastguard Worker 	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
1494*2d543d20SAndroid Build Coastguard Worker }
1495*2d543d20SAndroid Build Coastguard Worker 
1496*2d543d20SAndroid Build Coastguard Worker /*
1497*2d543d20SAndroid Build Coastguard Worker  * Compute a SID to use when selecting a member of a
1498*2d543d20SAndroid Build Coastguard Worker  * polyinstantiated object of class `tclass' based on
1499*2d543d20SAndroid Build Coastguard Worker  * a SID pair.
1500*2d543d20SAndroid Build Coastguard Worker  */
sepol_member_sid(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_security_id_t * out_sid)1501*2d543d20SAndroid Build Coastguard Worker int sepol_member_sid(sepol_security_id_t ssid,
1502*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_id_t tsid,
1503*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_class_t tclass,
1504*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_id_t * out_sid)
1505*2d543d20SAndroid Build Coastguard Worker {
1506*2d543d20SAndroid Build Coastguard Worker 	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
1507*2d543d20SAndroid Build Coastguard Worker }
1508*2d543d20SAndroid Build Coastguard Worker 
1509*2d543d20SAndroid Build Coastguard Worker /*
1510*2d543d20SAndroid Build Coastguard Worker  * Compute a SID to use for relabeling an object in the
1511*2d543d20SAndroid Build Coastguard Worker  * class `tclass' based on a SID pair.
1512*2d543d20SAndroid Build Coastguard Worker  */
sepol_change_sid(sepol_security_id_t ssid,sepol_security_id_t tsid,sepol_security_class_t tclass,sepol_security_id_t * out_sid)1513*2d543d20SAndroid Build Coastguard Worker int sepol_change_sid(sepol_security_id_t ssid,
1514*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_id_t tsid,
1515*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_class_t tclass,
1516*2d543d20SAndroid Build Coastguard Worker 			    sepol_security_id_t * out_sid)
1517*2d543d20SAndroid Build Coastguard Worker {
1518*2d543d20SAndroid Build Coastguard Worker 	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
1519*2d543d20SAndroid Build Coastguard Worker }
1520*2d543d20SAndroid Build Coastguard Worker 
1521*2d543d20SAndroid Build Coastguard Worker /*
1522*2d543d20SAndroid Build Coastguard Worker  * Verify that each permission that is defined under the
1523*2d543d20SAndroid Build Coastguard Worker  * existing policy is still defined with the same value
1524*2d543d20SAndroid Build Coastguard Worker  * in the new policy.
1525*2d543d20SAndroid Build Coastguard Worker  */
validate_perm(hashtab_key_t key,hashtab_datum_t datum,void * p)1526*2d543d20SAndroid Build Coastguard Worker static int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
1527*2d543d20SAndroid Build Coastguard Worker {
1528*2d543d20SAndroid Build Coastguard Worker 	hashtab_t h;
1529*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum, *perdatum2;
1530*2d543d20SAndroid Build Coastguard Worker 
1531*2d543d20SAndroid Build Coastguard Worker 	h = (hashtab_t) p;
1532*2d543d20SAndroid Build Coastguard Worker 	perdatum = (perm_datum_t *) datum;
1533*2d543d20SAndroid Build Coastguard Worker 
1534*2d543d20SAndroid Build Coastguard Worker 	perdatum2 = (perm_datum_t *) hashtab_search(h, key);
1535*2d543d20SAndroid Build Coastguard Worker 	if (!perdatum2) {
1536*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "permission %s disappeared", key);
1537*2d543d20SAndroid Build Coastguard Worker 		return -1;
1538*2d543d20SAndroid Build Coastguard Worker 	}
1539*2d543d20SAndroid Build Coastguard Worker 	if (perdatum->s.value != perdatum2->s.value) {
1540*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "the value of permissions %s changed", key);
1541*2d543d20SAndroid Build Coastguard Worker 		return -1;
1542*2d543d20SAndroid Build Coastguard Worker 	}
1543*2d543d20SAndroid Build Coastguard Worker 	return 0;
1544*2d543d20SAndroid Build Coastguard Worker }
1545*2d543d20SAndroid Build Coastguard Worker 
1546*2d543d20SAndroid Build Coastguard Worker /*
1547*2d543d20SAndroid Build Coastguard Worker  * Verify that each class that is defined under the
1548*2d543d20SAndroid Build Coastguard Worker  * existing policy is still defined with the same
1549*2d543d20SAndroid Build Coastguard Worker  * attributes in the new policy.
1550*2d543d20SAndroid Build Coastguard Worker  */
validate_class(hashtab_key_t key,hashtab_datum_t datum,void * p)1551*2d543d20SAndroid Build Coastguard Worker static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p)
1552*2d543d20SAndroid Build Coastguard Worker {
1553*2d543d20SAndroid Build Coastguard Worker 	policydb_t *newp;
1554*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum, *cladatum2;
1555*2d543d20SAndroid Build Coastguard Worker 
1556*2d543d20SAndroid Build Coastguard Worker 	newp = (policydb_t *) p;
1557*2d543d20SAndroid Build Coastguard Worker 	cladatum = (class_datum_t *) datum;
1558*2d543d20SAndroid Build Coastguard Worker 
1559*2d543d20SAndroid Build Coastguard Worker 	cladatum2 =
1560*2d543d20SAndroid Build Coastguard Worker 	    (class_datum_t *) hashtab_search(newp->p_classes.table, key);
1561*2d543d20SAndroid Build Coastguard Worker 	if (!cladatum2) {
1562*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "class %s disappeared", key);
1563*2d543d20SAndroid Build Coastguard Worker 		return -1;
1564*2d543d20SAndroid Build Coastguard Worker 	}
1565*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->s.value != cladatum2->s.value) {
1566*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "the value of class %s changed", key);
1567*2d543d20SAndroid Build Coastguard Worker 		return -1;
1568*2d543d20SAndroid Build Coastguard Worker 	}
1569*2d543d20SAndroid Build Coastguard Worker 	if ((cladatum->comdatum && !cladatum2->comdatum) ||
1570*2d543d20SAndroid Build Coastguard Worker 	    (!cladatum->comdatum && cladatum2->comdatum)) {
1571*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "the inherits clause for the access "
1572*2d543d20SAndroid Build Coastguard Worker 		    "vector definition for class %s changed", key);
1573*2d543d20SAndroid Build Coastguard Worker 		return -1;
1574*2d543d20SAndroid Build Coastguard Worker 	}
1575*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->comdatum) {
1576*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_map
1577*2d543d20SAndroid Build Coastguard Worker 		    (cladatum->comdatum->permissions.table, validate_perm,
1578*2d543d20SAndroid Build Coastguard Worker 		     cladatum2->comdatum->permissions.table)) {
1579*2d543d20SAndroid Build Coastguard Worker 			ERR(NULL,
1580*2d543d20SAndroid Build Coastguard Worker 			    " in the access vector definition "
1581*2d543d20SAndroid Build Coastguard Worker 			    "for class %s", key);
1582*2d543d20SAndroid Build Coastguard Worker 			return -1;
1583*2d543d20SAndroid Build Coastguard Worker 		}
1584*2d543d20SAndroid Build Coastguard Worker 	}
1585*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(cladatum->permissions.table, validate_perm,
1586*2d543d20SAndroid Build Coastguard Worker 			cladatum2->permissions.table)) {
1587*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, " in access vector definition for class %s", key);
1588*2d543d20SAndroid Build Coastguard Worker 		return -1;
1589*2d543d20SAndroid Build Coastguard Worker 	}
1590*2d543d20SAndroid Build Coastguard Worker 	return 0;
1591*2d543d20SAndroid Build Coastguard Worker }
1592*2d543d20SAndroid Build Coastguard Worker 
1593*2d543d20SAndroid Build Coastguard Worker /* Clone the SID into the new SID table. */
clone_sid(sepol_security_id_t sid,context_struct_t * context,void * arg)1594*2d543d20SAndroid Build Coastguard Worker static int clone_sid(sepol_security_id_t sid,
1595*2d543d20SAndroid Build Coastguard Worker 		     context_struct_t * context, void *arg)
1596*2d543d20SAndroid Build Coastguard Worker {
1597*2d543d20SAndroid Build Coastguard Worker 	sidtab_t *s = arg;
1598*2d543d20SAndroid Build Coastguard Worker 
1599*2d543d20SAndroid Build Coastguard Worker 	return sepol_sidtab_insert(s, sid, context);
1600*2d543d20SAndroid Build Coastguard Worker }
1601*2d543d20SAndroid Build Coastguard Worker 
convert_context_handle_invalid_context(context_struct_t * context)1602*2d543d20SAndroid Build Coastguard Worker static inline int convert_context_handle_invalid_context(context_struct_t *
1603*2d543d20SAndroid Build Coastguard Worker 							 context)
1604*2d543d20SAndroid Build Coastguard Worker {
1605*2d543d20SAndroid Build Coastguard Worker 	if (selinux_enforcing) {
1606*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1607*2d543d20SAndroid Build Coastguard Worker 	} else {
1608*2d543d20SAndroid Build Coastguard Worker 		sepol_security_context_t s;
1609*2d543d20SAndroid Build Coastguard Worker 		size_t len;
1610*2d543d20SAndroid Build Coastguard Worker 
1611*2d543d20SAndroid Build Coastguard Worker 		context_to_string(NULL, policydb, context, &s, &len);
1612*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "context %s is invalid", s);
1613*2d543d20SAndroid Build Coastguard Worker 		free(s);
1614*2d543d20SAndroid Build Coastguard Worker 		return 0;
1615*2d543d20SAndroid Build Coastguard Worker 	}
1616*2d543d20SAndroid Build Coastguard Worker }
1617*2d543d20SAndroid Build Coastguard Worker 
1618*2d543d20SAndroid Build Coastguard Worker typedef struct {
1619*2d543d20SAndroid Build Coastguard Worker 	policydb_t *oldp;
1620*2d543d20SAndroid Build Coastguard Worker 	policydb_t *newp;
1621*2d543d20SAndroid Build Coastguard Worker } convert_context_args_t;
1622*2d543d20SAndroid Build Coastguard Worker 
1623*2d543d20SAndroid Build Coastguard Worker /*
1624*2d543d20SAndroid Build Coastguard Worker  * Convert the values in the security context
1625*2d543d20SAndroid Build Coastguard Worker  * structure `c' from the values specified
1626*2d543d20SAndroid Build Coastguard Worker  * in the policy `p->oldp' to the values specified
1627*2d543d20SAndroid Build Coastguard Worker  * in the policy `p->newp'.  Verify that the
1628*2d543d20SAndroid Build Coastguard Worker  * context is valid under the new policy.
1629*2d543d20SAndroid Build Coastguard Worker  */
convert_context(sepol_security_id_t key,context_struct_t * c,void * p)1630*2d543d20SAndroid Build Coastguard Worker static int convert_context(sepol_security_id_t key __attribute__ ((unused)),
1631*2d543d20SAndroid Build Coastguard Worker 			   context_struct_t * c, void *p)
1632*2d543d20SAndroid Build Coastguard Worker {
1633*2d543d20SAndroid Build Coastguard Worker 	convert_context_args_t *args;
1634*2d543d20SAndroid Build Coastguard Worker 	context_struct_t oldc;
1635*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
1636*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *typdatum;
1637*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *usrdatum;
1638*2d543d20SAndroid Build Coastguard Worker 	sepol_security_context_t s;
1639*2d543d20SAndroid Build Coastguard Worker 	size_t len;
1640*2d543d20SAndroid Build Coastguard Worker 	int rc = -EINVAL;
1641*2d543d20SAndroid Build Coastguard Worker 
1642*2d543d20SAndroid Build Coastguard Worker 	args = (convert_context_args_t *) p;
1643*2d543d20SAndroid Build Coastguard Worker 
1644*2d543d20SAndroid Build Coastguard Worker 	if (context_cpy(&oldc, c))
1645*2d543d20SAndroid Build Coastguard Worker 		return -ENOMEM;
1646*2d543d20SAndroid Build Coastguard Worker 
1647*2d543d20SAndroid Build Coastguard Worker 	/* Convert the user. */
1648*2d543d20SAndroid Build Coastguard Worker 	usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table,
1649*2d543d20SAndroid Build Coastguard Worker 						   args->oldp->
1650*2d543d20SAndroid Build Coastguard Worker 						   p_user_val_to_name[c->user -
1651*2d543d20SAndroid Build Coastguard Worker 								      1]);
1652*2d543d20SAndroid Build Coastguard Worker 
1653*2d543d20SAndroid Build Coastguard Worker 	if (!usrdatum) {
1654*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1655*2d543d20SAndroid Build Coastguard Worker 	}
1656*2d543d20SAndroid Build Coastguard Worker 	c->user = usrdatum->s.value;
1657*2d543d20SAndroid Build Coastguard Worker 
1658*2d543d20SAndroid Build Coastguard Worker 	/* Convert the role. */
1659*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *) hashtab_search(args->newp->p_roles.table,
1660*2d543d20SAndroid Build Coastguard Worker 					       args->oldp->
1661*2d543d20SAndroid Build Coastguard Worker 					       p_role_val_to_name[c->role - 1]);
1662*2d543d20SAndroid Build Coastguard Worker 	if (!role) {
1663*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1664*2d543d20SAndroid Build Coastguard Worker 	}
1665*2d543d20SAndroid Build Coastguard Worker 	c->role = role->s.value;
1666*2d543d20SAndroid Build Coastguard Worker 
1667*2d543d20SAndroid Build Coastguard Worker 	/* Convert the type. */
1668*2d543d20SAndroid Build Coastguard Worker 	typdatum = (type_datum_t *)
1669*2d543d20SAndroid Build Coastguard Worker 	    hashtab_search(args->newp->p_types.table,
1670*2d543d20SAndroid Build Coastguard Worker 			   args->oldp->p_type_val_to_name[c->type - 1]);
1671*2d543d20SAndroid Build Coastguard Worker 	if (!typdatum) {
1672*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1673*2d543d20SAndroid Build Coastguard Worker 	}
1674*2d543d20SAndroid Build Coastguard Worker 	c->type = typdatum->s.value;
1675*2d543d20SAndroid Build Coastguard Worker 
1676*2d543d20SAndroid Build Coastguard Worker 	rc = mls_convert_context(args->oldp, args->newp, c);
1677*2d543d20SAndroid Build Coastguard Worker 	if (rc)
1678*2d543d20SAndroid Build Coastguard Worker 		goto bad;
1679*2d543d20SAndroid Build Coastguard Worker 
1680*2d543d20SAndroid Build Coastguard Worker 	/* Check the validity of the new context. */
1681*2d543d20SAndroid Build Coastguard Worker 	if (!policydb_context_isvalid(args->newp, c)) {
1682*2d543d20SAndroid Build Coastguard Worker 		rc = convert_context_handle_invalid_context(&oldc);
1683*2d543d20SAndroid Build Coastguard Worker 		if (rc)
1684*2d543d20SAndroid Build Coastguard Worker 			goto bad;
1685*2d543d20SAndroid Build Coastguard Worker 	}
1686*2d543d20SAndroid Build Coastguard Worker 
1687*2d543d20SAndroid Build Coastguard Worker 	context_destroy(&oldc);
1688*2d543d20SAndroid Build Coastguard Worker 	return 0;
1689*2d543d20SAndroid Build Coastguard Worker 
1690*2d543d20SAndroid Build Coastguard Worker       bad:
1691*2d543d20SAndroid Build Coastguard Worker 	context_to_string(NULL, policydb, &oldc, &s, &len);
1692*2d543d20SAndroid Build Coastguard Worker 	context_destroy(&oldc);
1693*2d543d20SAndroid Build Coastguard Worker 	ERR(NULL, "invalidating context %s", s);
1694*2d543d20SAndroid Build Coastguard Worker 	free(s);
1695*2d543d20SAndroid Build Coastguard Worker 	return rc;
1696*2d543d20SAndroid Build Coastguard Worker }
1697*2d543d20SAndroid Build Coastguard Worker 
1698*2d543d20SAndroid Build Coastguard Worker /* Reading from a policy "file". */
next_entry(void * buf,struct policy_file * fp,size_t bytes)1699*2d543d20SAndroid Build Coastguard Worker int next_entry(void *buf, struct policy_file *fp, size_t bytes)
1700*2d543d20SAndroid Build Coastguard Worker {
1701*2d543d20SAndroid Build Coastguard Worker 	size_t nread;
1702*2d543d20SAndroid Build Coastguard Worker 
1703*2d543d20SAndroid Build Coastguard Worker 	switch (fp->type) {
1704*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_STDIO:
1705*2d543d20SAndroid Build Coastguard Worker 		nread = fread(buf, bytes, 1, fp->fp);
1706*2d543d20SAndroid Build Coastguard Worker 
1707*2d543d20SAndroid Build Coastguard Worker 		if (nread != 1)
1708*2d543d20SAndroid Build Coastguard Worker 			return -1;
1709*2d543d20SAndroid Build Coastguard Worker 		break;
1710*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_MEMORY:
1711*2d543d20SAndroid Build Coastguard Worker 		if (bytes > fp->len) {
1712*2d543d20SAndroid Build Coastguard Worker 			errno = EOVERFLOW;
1713*2d543d20SAndroid Build Coastguard Worker 			return -1;
1714*2d543d20SAndroid Build Coastguard Worker 		}
1715*2d543d20SAndroid Build Coastguard Worker 		memcpy(buf, fp->data, bytes);
1716*2d543d20SAndroid Build Coastguard Worker 		fp->data += bytes;
1717*2d543d20SAndroid Build Coastguard Worker 		fp->len -= bytes;
1718*2d543d20SAndroid Build Coastguard Worker 		break;
1719*2d543d20SAndroid Build Coastguard Worker 	default:
1720*2d543d20SAndroid Build Coastguard Worker 		errno = EINVAL;
1721*2d543d20SAndroid Build Coastguard Worker 		return -1;
1722*2d543d20SAndroid Build Coastguard Worker 	}
1723*2d543d20SAndroid Build Coastguard Worker 	return 0;
1724*2d543d20SAndroid Build Coastguard Worker }
1725*2d543d20SAndroid Build Coastguard Worker 
put_entry(const void * ptr,size_t size,size_t n,struct policy_file * fp)1726*2d543d20SAndroid Build Coastguard Worker size_t put_entry(const void *ptr, size_t size, size_t n,
1727*2d543d20SAndroid Build Coastguard Worker 			struct policy_file *fp)
1728*2d543d20SAndroid Build Coastguard Worker {
1729*2d543d20SAndroid Build Coastguard Worker 	size_t bytes;
1730*2d543d20SAndroid Build Coastguard Worker 
1731*2d543d20SAndroid Build Coastguard Worker 	if (__builtin_mul_overflow(size, n, &bytes))
1732*2d543d20SAndroid Build Coastguard Worker 		return 0;
1733*2d543d20SAndroid Build Coastguard Worker 
1734*2d543d20SAndroid Build Coastguard Worker 	switch (fp->type) {
1735*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_STDIO:
1736*2d543d20SAndroid Build Coastguard Worker 		return fwrite(ptr, size, n, fp->fp);
1737*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_MEMORY:
1738*2d543d20SAndroid Build Coastguard Worker 		if (bytes > fp->len) {
1739*2d543d20SAndroid Build Coastguard Worker 			errno = ENOSPC;
1740*2d543d20SAndroid Build Coastguard Worker 			return 0;
1741*2d543d20SAndroid Build Coastguard Worker 		}
1742*2d543d20SAndroid Build Coastguard Worker 
1743*2d543d20SAndroid Build Coastguard Worker 		memcpy(fp->data, ptr, bytes);
1744*2d543d20SAndroid Build Coastguard Worker 		fp->data += bytes;
1745*2d543d20SAndroid Build Coastguard Worker 		fp->len -= bytes;
1746*2d543d20SAndroid Build Coastguard Worker 		return n;
1747*2d543d20SAndroid Build Coastguard Worker 	case PF_LEN:
1748*2d543d20SAndroid Build Coastguard Worker 		fp->len += bytes;
1749*2d543d20SAndroid Build Coastguard Worker 		return n;
1750*2d543d20SAndroid Build Coastguard Worker 	default:
1751*2d543d20SAndroid Build Coastguard Worker 		return 0;
1752*2d543d20SAndroid Build Coastguard Worker 	}
1753*2d543d20SAndroid Build Coastguard Worker 	return 0;
1754*2d543d20SAndroid Build Coastguard Worker }
1755*2d543d20SAndroid Build Coastguard Worker 
1756*2d543d20SAndroid Build Coastguard Worker /*
1757*2d543d20SAndroid Build Coastguard Worker  * Reads a string and null terminates it from the policy file.
1758*2d543d20SAndroid Build Coastguard Worker  * This is a port of str_read from the SE Linux kernel code.
1759*2d543d20SAndroid Build Coastguard Worker  *
1760*2d543d20SAndroid Build Coastguard Worker  * It returns:
1761*2d543d20SAndroid Build Coastguard Worker  *   0 - Success
1762*2d543d20SAndroid Build Coastguard Worker  *  -1 - Failure with errno set
1763*2d543d20SAndroid Build Coastguard Worker  */
str_read(char ** strp,struct policy_file * fp,size_t len)1764*2d543d20SAndroid Build Coastguard Worker int str_read(char **strp, struct policy_file *fp, size_t len)
1765*2d543d20SAndroid Build Coastguard Worker {
1766*2d543d20SAndroid Build Coastguard Worker 	int rc;
1767*2d543d20SAndroid Build Coastguard Worker 	char *str;
1768*2d543d20SAndroid Build Coastguard Worker 
1769*2d543d20SAndroid Build Coastguard Worker 	if (zero_or_saturated(len) || exceeds_available_bytes(fp, len, sizeof(char))) {
1770*2d543d20SAndroid Build Coastguard Worker 		errno = EINVAL;
1771*2d543d20SAndroid Build Coastguard Worker 		return -1;
1772*2d543d20SAndroid Build Coastguard Worker 	}
1773*2d543d20SAndroid Build Coastguard Worker 
1774*2d543d20SAndroid Build Coastguard Worker 	str = malloc(len + 1);
1775*2d543d20SAndroid Build Coastguard Worker 	if (!str)
1776*2d543d20SAndroid Build Coastguard Worker 		return -1;
1777*2d543d20SAndroid Build Coastguard Worker 
1778*2d543d20SAndroid Build Coastguard Worker 	/* it's expected the caller should free the str */
1779*2d543d20SAndroid Build Coastguard Worker 	*strp = str;
1780*2d543d20SAndroid Build Coastguard Worker 
1781*2d543d20SAndroid Build Coastguard Worker 	/* next_entry sets errno */
1782*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(str, fp, len);
1783*2d543d20SAndroid Build Coastguard Worker 	if (rc)
1784*2d543d20SAndroid Build Coastguard Worker 		return rc;
1785*2d543d20SAndroid Build Coastguard Worker 
1786*2d543d20SAndroid Build Coastguard Worker 	str[len] = '\0';
1787*2d543d20SAndroid Build Coastguard Worker 	return 0;
1788*2d543d20SAndroid Build Coastguard Worker }
1789*2d543d20SAndroid Build Coastguard Worker 
1790*2d543d20SAndroid Build Coastguard Worker /*
1791*2d543d20SAndroid Build Coastguard Worker  * Read a new set of configuration data from
1792*2d543d20SAndroid Build Coastguard Worker  * a policy database binary representation file.
1793*2d543d20SAndroid Build Coastguard Worker  *
1794*2d543d20SAndroid Build Coastguard Worker  * Verify that each class that is defined under the
1795*2d543d20SAndroid Build Coastguard Worker  * existing policy is still defined with the same
1796*2d543d20SAndroid Build Coastguard Worker  * attributes in the new policy.
1797*2d543d20SAndroid Build Coastguard Worker  *
1798*2d543d20SAndroid Build Coastguard Worker  * Convert the context structures in the SID table to the
1799*2d543d20SAndroid Build Coastguard Worker  * new representation and verify that all entries
1800*2d543d20SAndroid Build Coastguard Worker  * in the SID table are valid under the new policy.
1801*2d543d20SAndroid Build Coastguard Worker  *
1802*2d543d20SAndroid Build Coastguard Worker  * Change the active policy database to use the new
1803*2d543d20SAndroid Build Coastguard Worker  * configuration data.
1804*2d543d20SAndroid Build Coastguard Worker  *
1805*2d543d20SAndroid Build Coastguard Worker  * Reset the access vector cache.
1806*2d543d20SAndroid Build Coastguard Worker  */
sepol_load_policy(void * data,size_t len)1807*2d543d20SAndroid Build Coastguard Worker int sepol_load_policy(void *data, size_t len)
1808*2d543d20SAndroid Build Coastguard Worker {
1809*2d543d20SAndroid Build Coastguard Worker 	policydb_t oldpolicydb, newpolicydb;
1810*2d543d20SAndroid Build Coastguard Worker 	sidtab_t oldsidtab, newsidtab;
1811*2d543d20SAndroid Build Coastguard Worker 	convert_context_args_t args;
1812*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1813*2d543d20SAndroid Build Coastguard Worker 	struct policy_file file, *fp;
1814*2d543d20SAndroid Build Coastguard Worker 
1815*2d543d20SAndroid Build Coastguard Worker 	policy_file_init(&file);
1816*2d543d20SAndroid Build Coastguard Worker 	file.type = PF_USE_MEMORY;
1817*2d543d20SAndroid Build Coastguard Worker 	file.data = data;
1818*2d543d20SAndroid Build Coastguard Worker 	file.len = len;
1819*2d543d20SAndroid Build Coastguard Worker 	fp = &file;
1820*2d543d20SAndroid Build Coastguard Worker 
1821*2d543d20SAndroid Build Coastguard Worker 	if (policydb_init(&newpolicydb))
1822*2d543d20SAndroid Build Coastguard Worker 		return -ENOMEM;
1823*2d543d20SAndroid Build Coastguard Worker 
1824*2d543d20SAndroid Build Coastguard Worker 	if (policydb_read(&newpolicydb, fp, 1)) {
1825*2d543d20SAndroid Build Coastguard Worker 		policydb_destroy(&mypolicydb);
1826*2d543d20SAndroid Build Coastguard Worker 		return -EINVAL;
1827*2d543d20SAndroid Build Coastguard Worker 	}
1828*2d543d20SAndroid Build Coastguard Worker 
1829*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_init(&newsidtab);
1830*2d543d20SAndroid Build Coastguard Worker 
1831*2d543d20SAndroid Build Coastguard Worker 	/* Verify that the existing classes did not change. */
1832*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map
1833*2d543d20SAndroid Build Coastguard Worker 	    (policydb->p_classes.table, validate_class, &newpolicydb)) {
1834*2d543d20SAndroid Build Coastguard Worker 		ERR(NULL, "the definition of an existing class changed");
1835*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
1836*2d543d20SAndroid Build Coastguard Worker 		goto err;
1837*2d543d20SAndroid Build Coastguard Worker 	}
1838*2d543d20SAndroid Build Coastguard Worker 
1839*2d543d20SAndroid Build Coastguard Worker 	/* Clone the SID table. */
1840*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_shutdown(sidtab);
1841*2d543d20SAndroid Build Coastguard Worker 	if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) {
1842*2d543d20SAndroid Build Coastguard Worker 		rc = -ENOMEM;
1843*2d543d20SAndroid Build Coastguard Worker 		goto err;
1844*2d543d20SAndroid Build Coastguard Worker 	}
1845*2d543d20SAndroid Build Coastguard Worker 
1846*2d543d20SAndroid Build Coastguard Worker 	/* Convert the internal representations of contexts
1847*2d543d20SAndroid Build Coastguard Worker 	   in the new SID table and remove invalid SIDs. */
1848*2d543d20SAndroid Build Coastguard Worker 	args.oldp = policydb;
1849*2d543d20SAndroid Build Coastguard Worker 	args.newp = &newpolicydb;
1850*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
1851*2d543d20SAndroid Build Coastguard Worker 
1852*2d543d20SAndroid Build Coastguard Worker 	/* Save the old policydb and SID table to free later. */
1853*2d543d20SAndroid Build Coastguard Worker 	memcpy(&oldpolicydb, policydb, sizeof *policydb);
1854*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_set(&oldsidtab, sidtab);
1855*2d543d20SAndroid Build Coastguard Worker 
1856*2d543d20SAndroid Build Coastguard Worker 	/* Install the new policydb and SID table. */
1857*2d543d20SAndroid Build Coastguard Worker 	memcpy(policydb, &newpolicydb, sizeof *policydb);
1858*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_set(sidtab, &newsidtab);
1859*2d543d20SAndroid Build Coastguard Worker 
1860*2d543d20SAndroid Build Coastguard Worker 	/* Free the old policydb and SID table. */
1861*2d543d20SAndroid Build Coastguard Worker 	policydb_destroy(&oldpolicydb);
1862*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_destroy(&oldsidtab);
1863*2d543d20SAndroid Build Coastguard Worker 
1864*2d543d20SAndroid Build Coastguard Worker 	return 0;
1865*2d543d20SAndroid Build Coastguard Worker 
1866*2d543d20SAndroid Build Coastguard Worker       err:
1867*2d543d20SAndroid Build Coastguard Worker 	sepol_sidtab_destroy(&newsidtab);
1868*2d543d20SAndroid Build Coastguard Worker 	policydb_destroy(&newpolicydb);
1869*2d543d20SAndroid Build Coastguard Worker 	return rc;
1870*2d543d20SAndroid Build Coastguard Worker 
1871*2d543d20SAndroid Build Coastguard Worker }
1872*2d543d20SAndroid Build Coastguard Worker 
1873*2d543d20SAndroid Build Coastguard Worker /*
1874*2d543d20SAndroid Build Coastguard Worker  * Return the SIDs to use for an unlabeled file system
1875*2d543d20SAndroid Build Coastguard Worker  * that is being mounted from the device with the
1876*2d543d20SAndroid Build Coastguard Worker  * the kdevname `name'.  The `fs_sid' SID is returned for
1877*2d543d20SAndroid Build Coastguard Worker  * the file system and the `file_sid' SID is returned
1878*2d543d20SAndroid Build Coastguard Worker  * for all files within that file system.
1879*2d543d20SAndroid Build Coastguard Worker  */
sepol_fs_sid(char * name,sepol_security_id_t * fs_sid,sepol_security_id_t * file_sid)1880*2d543d20SAndroid Build Coastguard Worker int sepol_fs_sid(char *name,
1881*2d543d20SAndroid Build Coastguard Worker 			sepol_security_id_t * fs_sid,
1882*2d543d20SAndroid Build Coastguard Worker 			sepol_security_id_t * file_sid)
1883*2d543d20SAndroid Build Coastguard Worker {
1884*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1885*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1886*2d543d20SAndroid Build Coastguard Worker 
1887*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_FS];
1888*2d543d20SAndroid Build Coastguard Worker 	while (c) {
1889*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(c->u.name, name) == 0)
1890*2d543d20SAndroid Build Coastguard Worker 			break;
1891*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
1892*2d543d20SAndroid Build Coastguard Worker 	}
1893*2d543d20SAndroid Build Coastguard Worker 
1894*2d543d20SAndroid Build Coastguard Worker 	if (c) {
1895*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0] || !c->sid[1]) {
1896*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
1897*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
1898*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
1899*2d543d20SAndroid Build Coastguard Worker 			if (rc)
1900*2d543d20SAndroid Build Coastguard Worker 				goto out;
1901*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
1902*2d543d20SAndroid Build Coastguard Worker 							 &c->context[1],
1903*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[1]);
1904*2d543d20SAndroid Build Coastguard Worker 			if (rc)
1905*2d543d20SAndroid Build Coastguard Worker 				goto out;
1906*2d543d20SAndroid Build Coastguard Worker 		}
1907*2d543d20SAndroid Build Coastguard Worker 		*fs_sid = c->sid[0];
1908*2d543d20SAndroid Build Coastguard Worker 		*file_sid = c->sid[1];
1909*2d543d20SAndroid Build Coastguard Worker 	} else {
1910*2d543d20SAndroid Build Coastguard Worker 		*fs_sid = SECINITSID_FS;
1911*2d543d20SAndroid Build Coastguard Worker 		*file_sid = SECINITSID_FILE;
1912*2d543d20SAndroid Build Coastguard Worker 	}
1913*2d543d20SAndroid Build Coastguard Worker 
1914*2d543d20SAndroid Build Coastguard Worker       out:
1915*2d543d20SAndroid Build Coastguard Worker 	return rc;
1916*2d543d20SAndroid Build Coastguard Worker }
1917*2d543d20SAndroid Build Coastguard Worker 
1918*2d543d20SAndroid Build Coastguard Worker /*
1919*2d543d20SAndroid Build Coastguard Worker  * Return the SID of the ibpkey specified by
1920*2d543d20SAndroid Build Coastguard Worker  * `subnet prefix', and `pkey number'.
1921*2d543d20SAndroid Build Coastguard Worker  */
sepol_ibpkey_sid(uint64_t subnet_prefix,uint16_t pkey,sepol_security_id_t * out_sid)1922*2d543d20SAndroid Build Coastguard Worker int sepol_ibpkey_sid(uint64_t subnet_prefix,
1923*2d543d20SAndroid Build Coastguard Worker 			    uint16_t pkey, sepol_security_id_t *out_sid)
1924*2d543d20SAndroid Build Coastguard Worker {
1925*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1926*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1927*2d543d20SAndroid Build Coastguard Worker 
1928*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_IBPKEY];
1929*2d543d20SAndroid Build Coastguard Worker 	while (c) {
1930*2d543d20SAndroid Build Coastguard Worker 		if (c->u.ibpkey.low_pkey <= pkey &&
1931*2d543d20SAndroid Build Coastguard Worker 		    c->u.ibpkey.high_pkey >= pkey &&
1932*2d543d20SAndroid Build Coastguard Worker 		    subnet_prefix == c->u.ibpkey.subnet_prefix)
1933*2d543d20SAndroid Build Coastguard Worker 			break;
1934*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
1935*2d543d20SAndroid Build Coastguard Worker 	}
1936*2d543d20SAndroid Build Coastguard Worker 
1937*2d543d20SAndroid Build Coastguard Worker 	if (c) {
1938*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0]) {
1939*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
1940*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
1941*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
1942*2d543d20SAndroid Build Coastguard Worker 			if (rc)
1943*2d543d20SAndroid Build Coastguard Worker 				goto out;
1944*2d543d20SAndroid Build Coastguard Worker 		}
1945*2d543d20SAndroid Build Coastguard Worker 		*out_sid = c->sid[0];
1946*2d543d20SAndroid Build Coastguard Worker 	} else {
1947*2d543d20SAndroid Build Coastguard Worker 		*out_sid = SECINITSID_UNLABELED;
1948*2d543d20SAndroid Build Coastguard Worker 	}
1949*2d543d20SAndroid Build Coastguard Worker 
1950*2d543d20SAndroid Build Coastguard Worker out:
1951*2d543d20SAndroid Build Coastguard Worker 	return rc;
1952*2d543d20SAndroid Build Coastguard Worker }
1953*2d543d20SAndroid Build Coastguard Worker 
1954*2d543d20SAndroid Build Coastguard Worker /*
1955*2d543d20SAndroid Build Coastguard Worker  * Return the SID of the subnet management interface specified by
1956*2d543d20SAndroid Build Coastguard Worker  * `device name', and `port'.
1957*2d543d20SAndroid Build Coastguard Worker  */
sepol_ibendport_sid(char * dev_name,uint8_t port,sepol_security_id_t * out_sid)1958*2d543d20SAndroid Build Coastguard Worker int sepol_ibendport_sid(char *dev_name,
1959*2d543d20SAndroid Build Coastguard Worker 			       uint8_t port,
1960*2d543d20SAndroid Build Coastguard Worker 			       sepol_security_id_t *out_sid)
1961*2d543d20SAndroid Build Coastguard Worker {
1962*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1963*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
1964*2d543d20SAndroid Build Coastguard Worker 
1965*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_IBENDPORT];
1966*2d543d20SAndroid Build Coastguard Worker 	while (c) {
1967*2d543d20SAndroid Build Coastguard Worker 		if (c->u.ibendport.port == port &&
1968*2d543d20SAndroid Build Coastguard Worker 		    !strcmp(dev_name, c->u.ibendport.dev_name))
1969*2d543d20SAndroid Build Coastguard Worker 			break;
1970*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
1971*2d543d20SAndroid Build Coastguard Worker 	}
1972*2d543d20SAndroid Build Coastguard Worker 
1973*2d543d20SAndroid Build Coastguard Worker 	if (c) {
1974*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0]) {
1975*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
1976*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
1977*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
1978*2d543d20SAndroid Build Coastguard Worker 			if (rc)
1979*2d543d20SAndroid Build Coastguard Worker 				goto out;
1980*2d543d20SAndroid Build Coastguard Worker 		}
1981*2d543d20SAndroid Build Coastguard Worker 		*out_sid = c->sid[0];
1982*2d543d20SAndroid Build Coastguard Worker 	} else {
1983*2d543d20SAndroid Build Coastguard Worker 		*out_sid = SECINITSID_UNLABELED;
1984*2d543d20SAndroid Build Coastguard Worker 	}
1985*2d543d20SAndroid Build Coastguard Worker 
1986*2d543d20SAndroid Build Coastguard Worker out:
1987*2d543d20SAndroid Build Coastguard Worker 	return rc;
1988*2d543d20SAndroid Build Coastguard Worker }
1989*2d543d20SAndroid Build Coastguard Worker 
1990*2d543d20SAndroid Build Coastguard Worker 
1991*2d543d20SAndroid Build Coastguard Worker /*
1992*2d543d20SAndroid Build Coastguard Worker  * Return the SID of the port specified by
1993*2d543d20SAndroid Build Coastguard Worker  * `domain', `type', `protocol', and `port'.
1994*2d543d20SAndroid Build Coastguard Worker  */
sepol_port_sid(uint16_t domain,uint16_t type,uint8_t protocol,uint16_t port,sepol_security_id_t * out_sid)1995*2d543d20SAndroid Build Coastguard Worker int sepol_port_sid(uint16_t domain __attribute__ ((unused)),
1996*2d543d20SAndroid Build Coastguard Worker 			  uint16_t type __attribute__ ((unused)),
1997*2d543d20SAndroid Build Coastguard Worker 			  uint8_t protocol,
1998*2d543d20SAndroid Build Coastguard Worker 			  uint16_t port, sepol_security_id_t * out_sid)
1999*2d543d20SAndroid Build Coastguard Worker {
2000*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
2001*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2002*2d543d20SAndroid Build Coastguard Worker 
2003*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_PORT];
2004*2d543d20SAndroid Build Coastguard Worker 	while (c) {
2005*2d543d20SAndroid Build Coastguard Worker 		if (c->u.port.protocol == protocol &&
2006*2d543d20SAndroid Build Coastguard Worker 		    c->u.port.low_port <= port && c->u.port.high_port >= port)
2007*2d543d20SAndroid Build Coastguard Worker 			break;
2008*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
2009*2d543d20SAndroid Build Coastguard Worker 	}
2010*2d543d20SAndroid Build Coastguard Worker 
2011*2d543d20SAndroid Build Coastguard Worker 	if (c) {
2012*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0]) {
2013*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
2014*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
2015*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
2016*2d543d20SAndroid Build Coastguard Worker 			if (rc)
2017*2d543d20SAndroid Build Coastguard Worker 				goto out;
2018*2d543d20SAndroid Build Coastguard Worker 		}
2019*2d543d20SAndroid Build Coastguard Worker 		*out_sid = c->sid[0];
2020*2d543d20SAndroid Build Coastguard Worker 	} else {
2021*2d543d20SAndroid Build Coastguard Worker 		*out_sid = SECINITSID_PORT;
2022*2d543d20SAndroid Build Coastguard Worker 	}
2023*2d543d20SAndroid Build Coastguard Worker 
2024*2d543d20SAndroid Build Coastguard Worker       out:
2025*2d543d20SAndroid Build Coastguard Worker 	return rc;
2026*2d543d20SAndroid Build Coastguard Worker }
2027*2d543d20SAndroid Build Coastguard Worker 
2028*2d543d20SAndroid Build Coastguard Worker /*
2029*2d543d20SAndroid Build Coastguard Worker  * Return the SIDs to use for a network interface
2030*2d543d20SAndroid Build Coastguard Worker  * with the name `name'.  The `if_sid' SID is returned for
2031*2d543d20SAndroid Build Coastguard Worker  * the interface and the `msg_sid' SID is returned as
2032*2d543d20SAndroid Build Coastguard Worker  * the default SID for messages received on the
2033*2d543d20SAndroid Build Coastguard Worker  * interface.
2034*2d543d20SAndroid Build Coastguard Worker  */
sepol_netif_sid(char * name,sepol_security_id_t * if_sid,sepol_security_id_t * msg_sid)2035*2d543d20SAndroid Build Coastguard Worker int sepol_netif_sid(char *name,
2036*2d543d20SAndroid Build Coastguard Worker 			   sepol_security_id_t * if_sid,
2037*2d543d20SAndroid Build Coastguard Worker 			   sepol_security_id_t * msg_sid)
2038*2d543d20SAndroid Build Coastguard Worker {
2039*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2040*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
2041*2d543d20SAndroid Build Coastguard Worker 
2042*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_NETIF];
2043*2d543d20SAndroid Build Coastguard Worker 	while (c) {
2044*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(name, c->u.name) == 0)
2045*2d543d20SAndroid Build Coastguard Worker 			break;
2046*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
2047*2d543d20SAndroid Build Coastguard Worker 	}
2048*2d543d20SAndroid Build Coastguard Worker 
2049*2d543d20SAndroid Build Coastguard Worker 	if (c) {
2050*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0] || !c->sid[1]) {
2051*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
2052*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
2053*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
2054*2d543d20SAndroid Build Coastguard Worker 			if (rc)
2055*2d543d20SAndroid Build Coastguard Worker 				goto out;
2056*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
2057*2d543d20SAndroid Build Coastguard Worker 							 &c->context[1],
2058*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[1]);
2059*2d543d20SAndroid Build Coastguard Worker 			if (rc)
2060*2d543d20SAndroid Build Coastguard Worker 				goto out;
2061*2d543d20SAndroid Build Coastguard Worker 		}
2062*2d543d20SAndroid Build Coastguard Worker 		*if_sid = c->sid[0];
2063*2d543d20SAndroid Build Coastguard Worker 		*msg_sid = c->sid[1];
2064*2d543d20SAndroid Build Coastguard Worker 	} else {
2065*2d543d20SAndroid Build Coastguard Worker 		*if_sid = SECINITSID_NETIF;
2066*2d543d20SAndroid Build Coastguard Worker 		*msg_sid = SECINITSID_NETMSG;
2067*2d543d20SAndroid Build Coastguard Worker 	}
2068*2d543d20SAndroid Build Coastguard Worker 
2069*2d543d20SAndroid Build Coastguard Worker       out:
2070*2d543d20SAndroid Build Coastguard Worker 	return rc;
2071*2d543d20SAndroid Build Coastguard Worker }
2072*2d543d20SAndroid Build Coastguard Worker 
match_ipv6_addrmask(uint32_t * input,uint32_t * addr,uint32_t * mask)2073*2d543d20SAndroid Build Coastguard Worker static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr,
2074*2d543d20SAndroid Build Coastguard Worker 			       uint32_t * mask)
2075*2d543d20SAndroid Build Coastguard Worker {
2076*2d543d20SAndroid Build Coastguard Worker 	int i, fail = 0;
2077*2d543d20SAndroid Build Coastguard Worker 
2078*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < 4; i++)
2079*2d543d20SAndroid Build Coastguard Worker 		if (addr[i] != (input[i] & mask[i])) {
2080*2d543d20SAndroid Build Coastguard Worker 			fail = 1;
2081*2d543d20SAndroid Build Coastguard Worker 			break;
2082*2d543d20SAndroid Build Coastguard Worker 		}
2083*2d543d20SAndroid Build Coastguard Worker 
2084*2d543d20SAndroid Build Coastguard Worker 	return !fail;
2085*2d543d20SAndroid Build Coastguard Worker }
2086*2d543d20SAndroid Build Coastguard Worker 
2087*2d543d20SAndroid Build Coastguard Worker /*
2088*2d543d20SAndroid Build Coastguard Worker  * Return the SID of the node specified by the address
2089*2d543d20SAndroid Build Coastguard Worker  * `addrp' where `addrlen' is the length of the address
2090*2d543d20SAndroid Build Coastguard Worker  * in bytes and `domain' is the communications domain or
2091*2d543d20SAndroid Build Coastguard Worker  * address family in which the address should be interpreted.
2092*2d543d20SAndroid Build Coastguard Worker  */
sepol_node_sid(uint16_t domain,void * addrp,size_t addrlen,sepol_security_id_t * out_sid)2093*2d543d20SAndroid Build Coastguard Worker int sepol_node_sid(uint16_t domain,
2094*2d543d20SAndroid Build Coastguard Worker 			  void *addrp,
2095*2d543d20SAndroid Build Coastguard Worker 			  size_t addrlen, sepol_security_id_t * out_sid)
2096*2d543d20SAndroid Build Coastguard Worker {
2097*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2098*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
2099*2d543d20SAndroid Build Coastguard Worker 
2100*2d543d20SAndroid Build Coastguard Worker 	switch (domain) {
2101*2d543d20SAndroid Build Coastguard Worker 	case AF_INET:{
2102*2d543d20SAndroid Build Coastguard Worker 			uint32_t addr;
2103*2d543d20SAndroid Build Coastguard Worker 
2104*2d543d20SAndroid Build Coastguard Worker 			if (addrlen != sizeof(uint32_t)) {
2105*2d543d20SAndroid Build Coastguard Worker 				rc = -EINVAL;
2106*2d543d20SAndroid Build Coastguard Worker 				goto out;
2107*2d543d20SAndroid Build Coastguard Worker 			}
2108*2d543d20SAndroid Build Coastguard Worker 
2109*2d543d20SAndroid Build Coastguard Worker 			addr = *((uint32_t *) addrp);
2110*2d543d20SAndroid Build Coastguard Worker 
2111*2d543d20SAndroid Build Coastguard Worker 			c = policydb->ocontexts[OCON_NODE];
2112*2d543d20SAndroid Build Coastguard Worker 			while (c) {
2113*2d543d20SAndroid Build Coastguard Worker 				if (c->u.node.addr == (addr & c->u.node.mask))
2114*2d543d20SAndroid Build Coastguard Worker 					break;
2115*2d543d20SAndroid Build Coastguard Worker 				c = c->next;
2116*2d543d20SAndroid Build Coastguard Worker 			}
2117*2d543d20SAndroid Build Coastguard Worker 			break;
2118*2d543d20SAndroid Build Coastguard Worker 		}
2119*2d543d20SAndroid Build Coastguard Worker 
2120*2d543d20SAndroid Build Coastguard Worker 	case AF_INET6:
2121*2d543d20SAndroid Build Coastguard Worker 		if (addrlen != sizeof(uint64_t) * 2) {
2122*2d543d20SAndroid Build Coastguard Worker 			rc = -EINVAL;
2123*2d543d20SAndroid Build Coastguard Worker 			goto out;
2124*2d543d20SAndroid Build Coastguard Worker 		}
2125*2d543d20SAndroid Build Coastguard Worker 
2126*2d543d20SAndroid Build Coastguard Worker 		c = policydb->ocontexts[OCON_NODE6];
2127*2d543d20SAndroid Build Coastguard Worker 		while (c) {
2128*2d543d20SAndroid Build Coastguard Worker 			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
2129*2d543d20SAndroid Build Coastguard Worker 						c->u.node6.mask))
2130*2d543d20SAndroid Build Coastguard Worker 				break;
2131*2d543d20SAndroid Build Coastguard Worker 			c = c->next;
2132*2d543d20SAndroid Build Coastguard Worker 		}
2133*2d543d20SAndroid Build Coastguard Worker 		break;
2134*2d543d20SAndroid Build Coastguard Worker 
2135*2d543d20SAndroid Build Coastguard Worker 	default:
2136*2d543d20SAndroid Build Coastguard Worker 		*out_sid = SECINITSID_NODE;
2137*2d543d20SAndroid Build Coastguard Worker 		goto out;
2138*2d543d20SAndroid Build Coastguard Worker 	}
2139*2d543d20SAndroid Build Coastguard Worker 
2140*2d543d20SAndroid Build Coastguard Worker 	if (c) {
2141*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0]) {
2142*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
2143*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
2144*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
2145*2d543d20SAndroid Build Coastguard Worker 			if (rc)
2146*2d543d20SAndroid Build Coastguard Worker 				goto out;
2147*2d543d20SAndroid Build Coastguard Worker 		}
2148*2d543d20SAndroid Build Coastguard Worker 		*out_sid = c->sid[0];
2149*2d543d20SAndroid Build Coastguard Worker 	} else {
2150*2d543d20SAndroid Build Coastguard Worker 		*out_sid = SECINITSID_NODE;
2151*2d543d20SAndroid Build Coastguard Worker 	}
2152*2d543d20SAndroid Build Coastguard Worker 
2153*2d543d20SAndroid Build Coastguard Worker       out:
2154*2d543d20SAndroid Build Coastguard Worker 	return rc;
2155*2d543d20SAndroid Build Coastguard Worker }
2156*2d543d20SAndroid Build Coastguard Worker 
2157*2d543d20SAndroid Build Coastguard Worker /*
2158*2d543d20SAndroid Build Coastguard Worker  * Generate the set of SIDs for legal security contexts
2159*2d543d20SAndroid Build Coastguard Worker  * for a given user that can be reached by `fromsid'.
2160*2d543d20SAndroid Build Coastguard Worker  * Set `*sids' to point to a dynamically allocated
2161*2d543d20SAndroid Build Coastguard Worker  * array containing the set of SIDs.  Set `*nel' to the
2162*2d543d20SAndroid Build Coastguard Worker  * number of elements in the array.
2163*2d543d20SAndroid Build Coastguard Worker  */
2164*2d543d20SAndroid Build Coastguard Worker #define SIDS_NEL 25
2165*2d543d20SAndroid Build Coastguard Worker 
sepol_get_user_sids(sepol_security_id_t fromsid,char * username,sepol_security_id_t ** sids,uint32_t * nel)2166*2d543d20SAndroid Build Coastguard Worker int sepol_get_user_sids(sepol_security_id_t fromsid,
2167*2d543d20SAndroid Build Coastguard Worker 			       char *username,
2168*2d543d20SAndroid Build Coastguard Worker 			       sepol_security_id_t ** sids, uint32_t * nel)
2169*2d543d20SAndroid Build Coastguard Worker {
2170*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *fromcon, usercon;
2171*2d543d20SAndroid Build Coastguard Worker 	sepol_security_id_t *mysids, *mysids2, sid;
2172*2d543d20SAndroid Build Coastguard Worker 	uint32_t mynel = 0, maxnel = SIDS_NEL;
2173*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *user;
2174*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
2175*2d543d20SAndroid Build Coastguard Worker 	struct sepol_av_decision avd;
2176*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2177*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j, reason;
2178*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *rnode, *tnode;
2179*2d543d20SAndroid Build Coastguard Worker 
2180*2d543d20SAndroid Build Coastguard Worker 	fromcon = sepol_sidtab_search(sidtab, fromsid);
2181*2d543d20SAndroid Build Coastguard Worker 	if (!fromcon) {
2182*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
2183*2d543d20SAndroid Build Coastguard Worker 		goto out;
2184*2d543d20SAndroid Build Coastguard Worker 	}
2185*2d543d20SAndroid Build Coastguard Worker 
2186*2d543d20SAndroid Build Coastguard Worker 	user = (user_datum_t *) hashtab_search(policydb->p_users.table,
2187*2d543d20SAndroid Build Coastguard Worker 					       username);
2188*2d543d20SAndroid Build Coastguard Worker 	if (!user) {
2189*2d543d20SAndroid Build Coastguard Worker 		rc = -EINVAL;
2190*2d543d20SAndroid Build Coastguard Worker 		goto out;
2191*2d543d20SAndroid Build Coastguard Worker 	}
2192*2d543d20SAndroid Build Coastguard Worker 	usercon.user = user->s.value;
2193*2d543d20SAndroid Build Coastguard Worker 
2194*2d543d20SAndroid Build Coastguard Worker 	mysids = calloc(maxnel, sizeof(sepol_security_id_t));
2195*2d543d20SAndroid Build Coastguard Worker 	if (!mysids) {
2196*2d543d20SAndroid Build Coastguard Worker 		rc = -ENOMEM;
2197*2d543d20SAndroid Build Coastguard Worker 		goto out;
2198*2d543d20SAndroid Build Coastguard Worker 	}
2199*2d543d20SAndroid Build Coastguard Worker 
2200*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(&user->roles.roles, rnode, i) {
2201*2d543d20SAndroid Build Coastguard Worker 		role = policydb->role_val_to_struct[i];
2202*2d543d20SAndroid Build Coastguard Worker 		usercon.role = i + 1;
2203*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&role->types.types, tnode, j) {
2204*2d543d20SAndroid Build Coastguard Worker 			usercon.type = j + 1;
2205*2d543d20SAndroid Build Coastguard Worker 			if (usercon.type == fromcon->type)
2206*2d543d20SAndroid Build Coastguard Worker 				continue;
2207*2d543d20SAndroid Build Coastguard Worker 
2208*2d543d20SAndroid Build Coastguard Worker 			if (mls_setup_user_range
2209*2d543d20SAndroid Build Coastguard Worker 			    (fromcon, user, &usercon, policydb->mls))
2210*2d543d20SAndroid Build Coastguard Worker 				continue;
2211*2d543d20SAndroid Build Coastguard Worker 
2212*2d543d20SAndroid Build Coastguard Worker 			rc = context_struct_compute_av(fromcon, &usercon,
2213*2d543d20SAndroid Build Coastguard Worker 						       policydb->process_class,
2214*2d543d20SAndroid Build Coastguard Worker 						       policydb->process_trans,
2215*2d543d20SAndroid Build Coastguard Worker 						       &avd, &reason, NULL, 0);
2216*2d543d20SAndroid Build Coastguard Worker 			if (rc || !(avd.allowed & policydb->process_trans))
2217*2d543d20SAndroid Build Coastguard Worker 				continue;
2218*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
2219*2d543d20SAndroid Build Coastguard Worker 							 &sid);
2220*2d543d20SAndroid Build Coastguard Worker 			if (rc) {
2221*2d543d20SAndroid Build Coastguard Worker 				free(mysids);
2222*2d543d20SAndroid Build Coastguard Worker 				goto out;
2223*2d543d20SAndroid Build Coastguard Worker 			}
2224*2d543d20SAndroid Build Coastguard Worker 			if (mynel < maxnel) {
2225*2d543d20SAndroid Build Coastguard Worker 				mysids[mynel++] = sid;
2226*2d543d20SAndroid Build Coastguard Worker 			} else {
2227*2d543d20SAndroid Build Coastguard Worker 				maxnel += SIDS_NEL;
2228*2d543d20SAndroid Build Coastguard Worker 				mysids2 = calloc(maxnel, sizeof(sepol_security_id_t));
2229*2d543d20SAndroid Build Coastguard Worker 				if (!mysids2) {
2230*2d543d20SAndroid Build Coastguard Worker 					rc = -ENOMEM;
2231*2d543d20SAndroid Build Coastguard Worker 					free(mysids);
2232*2d543d20SAndroid Build Coastguard Worker 					goto out;
2233*2d543d20SAndroid Build Coastguard Worker 				}
2234*2d543d20SAndroid Build Coastguard Worker 				memcpy(mysids2, mysids,
2235*2d543d20SAndroid Build Coastguard Worker 				       mynel * sizeof(sepol_security_id_t));
2236*2d543d20SAndroid Build Coastguard Worker 				free(mysids);
2237*2d543d20SAndroid Build Coastguard Worker 				mysids = mysids2;
2238*2d543d20SAndroid Build Coastguard Worker 				mysids[mynel++] = sid;
2239*2d543d20SAndroid Build Coastguard Worker 			}
2240*2d543d20SAndroid Build Coastguard Worker 		}
2241*2d543d20SAndroid Build Coastguard Worker 	}
2242*2d543d20SAndroid Build Coastguard Worker 
2243*2d543d20SAndroid Build Coastguard Worker 	*sids = mysids;
2244*2d543d20SAndroid Build Coastguard Worker 	*nel = mynel;
2245*2d543d20SAndroid Build Coastguard Worker 
2246*2d543d20SAndroid Build Coastguard Worker       out:
2247*2d543d20SAndroid Build Coastguard Worker 	return rc;
2248*2d543d20SAndroid Build Coastguard Worker }
2249*2d543d20SAndroid Build Coastguard Worker 
2250*2d543d20SAndroid Build Coastguard Worker /*
2251*2d543d20SAndroid Build Coastguard Worker  * Return the SID to use for a file in a filesystem
2252*2d543d20SAndroid Build Coastguard Worker  * that cannot support a persistent label mapping or use another
2253*2d543d20SAndroid Build Coastguard Worker  * fixed labeling behavior like transition SIDs or task SIDs.
2254*2d543d20SAndroid Build Coastguard Worker  */
sepol_genfs_sid(const char * fstype,const char * path,sepol_security_class_t sclass,sepol_security_id_t * sid)2255*2d543d20SAndroid Build Coastguard Worker int sepol_genfs_sid(const char *fstype,
2256*2d543d20SAndroid Build Coastguard Worker 			   const char *path,
2257*2d543d20SAndroid Build Coastguard Worker 			   sepol_security_class_t sclass,
2258*2d543d20SAndroid Build Coastguard Worker 			   sepol_security_id_t * sid)
2259*2d543d20SAndroid Build Coastguard Worker {
2260*2d543d20SAndroid Build Coastguard Worker 	size_t len;
2261*2d543d20SAndroid Build Coastguard Worker 	genfs_t *genfs;
2262*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
2263*2d543d20SAndroid Build Coastguard Worker 	int rc = 0, cmp = 0;
2264*2d543d20SAndroid Build Coastguard Worker 
2265*2d543d20SAndroid Build Coastguard Worker 	for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
2266*2d543d20SAndroid Build Coastguard Worker 		cmp = strcmp(fstype, genfs->fstype);
2267*2d543d20SAndroid Build Coastguard Worker 		if (cmp <= 0)
2268*2d543d20SAndroid Build Coastguard Worker 			break;
2269*2d543d20SAndroid Build Coastguard Worker 	}
2270*2d543d20SAndroid Build Coastguard Worker 
2271*2d543d20SAndroid Build Coastguard Worker 	if (!genfs || cmp) {
2272*2d543d20SAndroid Build Coastguard Worker 		*sid = SECINITSID_UNLABELED;
2273*2d543d20SAndroid Build Coastguard Worker 		rc = -ENOENT;
2274*2d543d20SAndroid Build Coastguard Worker 		goto out;
2275*2d543d20SAndroid Build Coastguard Worker 	}
2276*2d543d20SAndroid Build Coastguard Worker 
2277*2d543d20SAndroid Build Coastguard Worker 	for (c = genfs->head; c; c = c->next) {
2278*2d543d20SAndroid Build Coastguard Worker 		len = strlen(c->u.name);
2279*2d543d20SAndroid Build Coastguard Worker 		if ((!c->v.sclass || sclass == c->v.sclass) &&
2280*2d543d20SAndroid Build Coastguard Worker 		    (strncmp(c->u.name, path, len) == 0))
2281*2d543d20SAndroid Build Coastguard Worker 			break;
2282*2d543d20SAndroid Build Coastguard Worker 	}
2283*2d543d20SAndroid Build Coastguard Worker 
2284*2d543d20SAndroid Build Coastguard Worker 	if (!c) {
2285*2d543d20SAndroid Build Coastguard Worker 		*sid = SECINITSID_UNLABELED;
2286*2d543d20SAndroid Build Coastguard Worker 		rc = -ENOENT;
2287*2d543d20SAndroid Build Coastguard Worker 		goto out;
2288*2d543d20SAndroid Build Coastguard Worker 	}
2289*2d543d20SAndroid Build Coastguard Worker 
2290*2d543d20SAndroid Build Coastguard Worker 	if (!c->sid[0]) {
2291*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_sidtab_context_to_sid(sidtab,
2292*2d543d20SAndroid Build Coastguard Worker 						 &c->context[0], &c->sid[0]);
2293*2d543d20SAndroid Build Coastguard Worker 		if (rc)
2294*2d543d20SAndroid Build Coastguard Worker 			goto out;
2295*2d543d20SAndroid Build Coastguard Worker 	}
2296*2d543d20SAndroid Build Coastguard Worker 
2297*2d543d20SAndroid Build Coastguard Worker 	*sid = c->sid[0];
2298*2d543d20SAndroid Build Coastguard Worker       out:
2299*2d543d20SAndroid Build Coastguard Worker 	return rc;
2300*2d543d20SAndroid Build Coastguard Worker }
2301*2d543d20SAndroid Build Coastguard Worker 
sepol_fs_use(const char * fstype,unsigned int * behavior,sepol_security_id_t * sid)2302*2d543d20SAndroid Build Coastguard Worker int sepol_fs_use(const char *fstype,
2303*2d543d20SAndroid Build Coastguard Worker 			unsigned int *behavior, sepol_security_id_t * sid)
2304*2d543d20SAndroid Build Coastguard Worker {
2305*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
2306*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
2307*2d543d20SAndroid Build Coastguard Worker 
2308*2d543d20SAndroid Build Coastguard Worker 	c = policydb->ocontexts[OCON_FSUSE];
2309*2d543d20SAndroid Build Coastguard Worker 	while (c) {
2310*2d543d20SAndroid Build Coastguard Worker 		if (strcmp(fstype, c->u.name) == 0)
2311*2d543d20SAndroid Build Coastguard Worker 			break;
2312*2d543d20SAndroid Build Coastguard Worker 		c = c->next;
2313*2d543d20SAndroid Build Coastguard Worker 	}
2314*2d543d20SAndroid Build Coastguard Worker 
2315*2d543d20SAndroid Build Coastguard Worker 	if (c) {
2316*2d543d20SAndroid Build Coastguard Worker 		*behavior = c->v.behavior;
2317*2d543d20SAndroid Build Coastguard Worker 		if (!c->sid[0]) {
2318*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_sidtab_context_to_sid(sidtab,
2319*2d543d20SAndroid Build Coastguard Worker 							 &c->context[0],
2320*2d543d20SAndroid Build Coastguard Worker 							 &c->sid[0]);
2321*2d543d20SAndroid Build Coastguard Worker 			if (rc)
2322*2d543d20SAndroid Build Coastguard Worker 				goto out;
2323*2d543d20SAndroid Build Coastguard Worker 		}
2324*2d543d20SAndroid Build Coastguard Worker 		*sid = c->sid[0];
2325*2d543d20SAndroid Build Coastguard Worker 	} else {
2326*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_genfs_sid(fstype, "/", policydb->dir_class, sid);
2327*2d543d20SAndroid Build Coastguard Worker 		if (rc) {
2328*2d543d20SAndroid Build Coastguard Worker 			*behavior = SECURITY_FS_USE_NONE;
2329*2d543d20SAndroid Build Coastguard Worker 			rc = 0;
2330*2d543d20SAndroid Build Coastguard Worker 		} else {
2331*2d543d20SAndroid Build Coastguard Worker 			*behavior = SECURITY_FS_USE_GENFS;
2332*2d543d20SAndroid Build Coastguard Worker 		}
2333*2d543d20SAndroid Build Coastguard Worker 	}
2334*2d543d20SAndroid Build Coastguard Worker 
2335*2d543d20SAndroid Build Coastguard Worker       out:
2336*2d543d20SAndroid Build Coastguard Worker 	return rc;
2337*2d543d20SAndroid Build Coastguard Worker }
2338*2d543d20SAndroid Build Coastguard Worker 
2339*2d543d20SAndroid Build Coastguard Worker /* FLASK */
2340