1255e72915d4cbddceb435e13d81601755714e9fSE Android
2255e72915d4cbddceb435e13d81601755714e9fSE Android/*
3255e72915d4cbddceb435e13d81601755714e9fSE Android * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
4255e72915d4cbddceb435e13d81601755714e9fSE Android */
5255e72915d4cbddceb435e13d81601755714e9fSE Android/*
6255e72915d4cbddceb435e13d81601755714e9fSE Android * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
7255e72915d4cbddceb435e13d81601755714e9fSE Android *
8255e72915d4cbddceb435e13d81601755714e9fSE Android *	Support for enhanced MLS infrastructure.
9255e72915d4cbddceb435e13d81601755714e9fSE Android *
10255e72915d4cbddceb435e13d81601755714e9fSE Android * Updated: Frank Mayer <mayerf@tresys.com>
11255e72915d4cbddceb435e13d81601755714e9fSE Android *          and Karl MacMillan <kmacmillan@tresys.com>
12255e72915d4cbddceb435e13d81601755714e9fSE Android *
13255e72915d4cbddceb435e13d81601755714e9fSE Android * 	Added conditional policy language extensions
14255e72915d4cbddceb435e13d81601755714e9fSE Android *
15255e72915d4cbddceb435e13d81601755714e9fSE Android * Updated: Red Hat, Inc.  James Morris <jmorris@redhat.com>
16255e72915d4cbddceb435e13d81601755714e9fSE Android *
17255e72915d4cbddceb435e13d81601755714e9fSE Android *      Fine-grained netlink support
18255e72915d4cbddceb435e13d81601755714e9fSE Android *      IPv6 support
19255e72915d4cbddceb435e13d81601755714e9fSE Android *      Code cleanup
20255e72915d4cbddceb435e13d81601755714e9fSE Android *
21255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
22255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2003 - 2004 Tresys Technology, LLC
23255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2003 - 2004 Red Hat, Inc.
24255e72915d4cbddceb435e13d81601755714e9fSE Android *
25255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is free software; you can redistribute it and/or
26255e72915d4cbddceb435e13d81601755714e9fSE Android *  modify it under the terms of the GNU Lesser General Public
27255e72915d4cbddceb435e13d81601755714e9fSE Android *  License as published by the Free Software Foundation; either
28255e72915d4cbddceb435e13d81601755714e9fSE Android *  version 2.1 of the License, or (at your option) any later version.
29255e72915d4cbddceb435e13d81601755714e9fSE Android *
30255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is distributed in the hope that it will be useful,
31255e72915d4cbddceb435e13d81601755714e9fSE Android *  but WITHOUT ANY WARRANTY; without even the implied warranty of
32255e72915d4cbddceb435e13d81601755714e9fSE Android *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
33255e72915d4cbddceb435e13d81601755714e9fSE Android *  Lesser General Public License for more details.
34255e72915d4cbddceb435e13d81601755714e9fSE Android *
35255e72915d4cbddceb435e13d81601755714e9fSE Android *  You should have received a copy of the GNU Lesser General Public
36255e72915d4cbddceb435e13d81601755714e9fSE Android *  License along with this library; if not, write to the Free Software
37255e72915d4cbddceb435e13d81601755714e9fSE Android *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
38255e72915d4cbddceb435e13d81601755714e9fSE Android */
39255e72915d4cbddceb435e13d81601755714e9fSE Android
40255e72915d4cbddceb435e13d81601755714e9fSE Android/* FLASK */
41255e72915d4cbddceb435e13d81601755714e9fSE Android
42255e72915d4cbddceb435e13d81601755714e9fSE Android/*
43255e72915d4cbddceb435e13d81601755714e9fSE Android * Implementation of the security services.
44255e72915d4cbddceb435e13d81601755714e9fSE Android */
45255e72915d4cbddceb435e13d81601755714e9fSE Android
46dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/* Initial sizes malloc'd for sepol_compute_av_reason_buffer() support */
47dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define REASON_BUF_SIZE 2048
48dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define EXPR_BUF_SIZE 1024
49dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define STACK_LEN 32
50dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
51255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
52255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sys/types.h>
53255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sys/socket.h>
54255e72915d4cbddceb435e13d81601755714e9fSE Android#include <netinet/in.h>
55255e72915d4cbddceb435e13d81601755714e9fSE Android#include <arpa/inet.h>
56255e72915d4cbddceb435e13d81601755714e9fSE Android
57255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h>
58255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/sidtab.h>
59255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/services.h>
60255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/conditional.h>
61255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/flask.h>
62dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#include <sepol/policydb/util.h>
63255e72915d4cbddceb435e13d81601755714e9fSE Android
64255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
65255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h"
66255e72915d4cbddceb435e13d81601755714e9fSE Android#include "context.h"
67255e72915d4cbddceb435e13d81601755714e9fSE Android#include "av_permissions.h"
68255e72915d4cbddceb435e13d81601755714e9fSE Android#include "dso.h"
69255e72915d4cbddceb435e13d81601755714e9fSE Android#include "mls.h"
70255e72915d4cbddceb435e13d81601755714e9fSE Android
71255e72915d4cbddceb435e13d81601755714e9fSE Android#define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
72255e72915d4cbddceb435e13d81601755714e9fSE Android#define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
73255e72915d4cbddceb435e13d81601755714e9fSE Android
74255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int selinux_enforcing = 1;
75255e72915d4cbddceb435e13d81601755714e9fSE Android
76255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic sidtab_t mysidtab, *sidtab = &mysidtab;
77255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic policydb_t mypolicydb, *policydb = &mypolicydb;
78255e72915d4cbddceb435e13d81601755714e9fSE Android
79dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/* Used by sepol_compute_av_reason_buffer() to keep track of entries */
80dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int reason_buf_used;
81dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int reason_buf_len;
82dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
83dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/* Stack services for RPN to infix conversion. */
84dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic char **stack;
85dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int stack_len;
86dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int next_stack_entry;
87dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
88dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic void push(char *expr_ptr)
89dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
90dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (next_stack_entry >= stack_len) {
91dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		char **new_stack = stack;
92dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		int new_stack_len;
93dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
94dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (stack_len == 0)
95dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			new_stack_len = STACK_LEN;
96dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		else
97dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			new_stack_len = stack_len * 2;
98dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
99dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		new_stack = realloc(stack, new_stack_len * sizeof(*stack));
100dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (!new_stack) {
101dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			ERR(NULL, "unable to allocate stack space");
102dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			return;
103dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
104dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		stack_len = new_stack_len;
105dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		stack = new_stack;
106dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
107dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	stack[next_stack_entry] = expr_ptr;
108dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	next_stack_entry++;
109dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
110dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
111dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic char *pop(void)
112dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
113dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	next_stack_entry--;
114dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (next_stack_entry < 0) {
115dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		next_stack_entry = 0;
116dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "pop called with no stack entries");
117dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		return NULL;
118dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
119dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return stack[next_stack_entry];
120dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
121dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/* End Stack services */
122dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
123255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_set_sidtab(sidtab_t * s)
124255e72915d4cbddceb435e13d81601755714e9fSE Android{
125255e72915d4cbddceb435e13d81601755714e9fSE Android	sidtab = s;
126255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
127255e72915d4cbddceb435e13d81601755714e9fSE Android}
128255e72915d4cbddceb435e13d81601755714e9fSE Android
129255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_set_policydb(policydb_t * p)
130255e72915d4cbddceb435e13d81601755714e9fSE Android{
131255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb = p;
132255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
133255e72915d4cbddceb435e13d81601755714e9fSE Android}
134255e72915d4cbddceb435e13d81601755714e9fSE Android
135255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_set_policydb_from_file(FILE * fp)
136255e72915d4cbddceb435e13d81601755714e9fSE Android{
137255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policy_file pf;
138255e72915d4cbddceb435e13d81601755714e9fSE Android
139255e72915d4cbddceb435e13d81601755714e9fSE Android	policy_file_init(&pf);
140255e72915d4cbddceb435e13d81601755714e9fSE Android	pf.fp = fp;
141255e72915d4cbddceb435e13d81601755714e9fSE Android	pf.type = PF_USE_STDIO;
142255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mypolicydb.policy_type)
143255e72915d4cbddceb435e13d81601755714e9fSE Android		policydb_destroy(&mypolicydb);
144255e72915d4cbddceb435e13d81601755714e9fSE Android	if (policydb_init(&mypolicydb)) {
145255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "Out of memory!");
146255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
147255e72915d4cbddceb435e13d81601755714e9fSE Android	}
148255e72915d4cbddceb435e13d81601755714e9fSE Android	if (policydb_read(&mypolicydb, &pf, 0)) {
149b0e0162a246f2c051427154909c0ecd694cc4805Alice Chu		policydb_destroy(&mypolicydb);
150255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "can't read binary policy: %s", strerror(errno));
151255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
152255e72915d4cbddceb435e13d81601755714e9fSE Android	}
153255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb = &mypolicydb;
154255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_sidtab_init(sidtab);
155255e72915d4cbddceb435e13d81601755714e9fSE Android}
156255e72915d4cbddceb435e13d81601755714e9fSE Android
157255e72915d4cbddceb435e13d81601755714e9fSE Android/*
158255e72915d4cbddceb435e13d81601755714e9fSE Android * The largest sequence number that has been used when
159255e72915d4cbddceb435e13d81601755714e9fSE Android * providing an access decision to the access vector cache.
160255e72915d4cbddceb435e13d81601755714e9fSE Android * The sequence number only changes when a policy change
161255e72915d4cbddceb435e13d81601755714e9fSE Android * occurs.
162255e72915d4cbddceb435e13d81601755714e9fSE Android */
163255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic uint32_t latest_granting = 0;
164255e72915d4cbddceb435e13d81601755714e9fSE Android
165255e72915d4cbddceb435e13d81601755714e9fSE Android/*
166dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * cat_expr_buf adds a string to an expression buffer and handles
167dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * realloc's if buffer is too small. The array of expression text
168dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * buffer pointers and its counter are globally defined here as
169dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * constraint_expr_eval_reason() sets them up and cat_expr_buf
170dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * updates the e_buf pointer.
171dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
172dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int expr_counter;
173dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic char **expr_list;
174dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int expr_buf_used;
175dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int expr_buf_len;
176dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
177dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic void cat_expr_buf(char *e_buf, char *string)
178dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
179dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int len, new_buf_len;
180dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *p, *new_buf = e_buf;
181dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
182dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	while (1) {
183dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		p = e_buf + expr_buf_used;
184dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string);
185dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (len < 0 || len >= expr_buf_len - expr_buf_used) {
186dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			new_buf_len = expr_buf_len + EXPR_BUF_SIZE;
187dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			new_buf = realloc(e_buf, new_buf_len);
188dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!new_buf) {
189dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				ERR(NULL, "failed to realloc expr buffer");
190dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				return;
191dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
192dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			/* Update new ptr in expr list and locally + new len */
193dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			expr_list[expr_counter] = new_buf;
194dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			e_buf = new_buf;
195dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			expr_buf_len = new_buf_len;
196dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		} else {
197dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			expr_buf_used += len;
198dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			return;
199dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
200dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
201dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
202dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
203dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
204dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES,
205dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * then for 'types' only, read the types_names->types list as it will
206dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * contain a list of types and attributes that were defined in the
207dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * policy source.
208dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * For user and role plus types (for policy vers <
209dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list.
210dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
211dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic void get_name_list(constraint_expr_t *e, int type,
212dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							char *src, char *op, int failed)
213dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
214dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	ebitmap_t *types;
215dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int rc = 0;
216dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	unsigned int i;
217dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char tmp_buf[128];
218dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int counter = 0;
219dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
220dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (policydb->policy_type == POLICY_KERN &&
221dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES &&
222dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			type == CEXPR_TYPE)
223dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		types = &e->type_names->types;
224dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	else
225dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		types = &e->names;
226dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
227dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Find out how many entries */
228dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
229dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		rc = ebitmap_get_bit(types, i);
230dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (rc == 0)
231dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			continue;
232dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		else
233dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			counter++;
234dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
235dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	snprintf(tmp_buf, sizeof(tmp_buf), "(%s%s", src, op);
236dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	cat_expr_buf(expr_list[expr_counter], tmp_buf);
237dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
238dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (counter == 0)
239dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		cat_expr_buf(expr_list[expr_counter], "<empty_set> ");
240dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (counter > 1)
241dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		cat_expr_buf(expr_list[expr_counter], " {");
242dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (counter >= 1) {
243dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
244dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			rc = ebitmap_get_bit(types, i);
245dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (rc == 0)
246dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				continue;
247dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
248dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			/* Collect entries */
249dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			switch (type) {
250dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			case CEXPR_USER:
251dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
252dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							policydb->p_user_val_to_name[i]);
253dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				break;
254dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			case CEXPR_ROLE:
255dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
256dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							policydb->p_role_val_to_name[i]);
257dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				break;
258dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			case CEXPR_TYPE:
259dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), " %s",
260dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							policydb->p_type_val_to_name[i]);
261dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				break;
262dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
263dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			cat_expr_buf(expr_list[expr_counter], tmp_buf);
264dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
265dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
266dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (counter > 1)
267dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		cat_expr_buf(expr_list[expr_counter], " }");
268dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (failed)
269dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		cat_expr_buf(expr_list[expr_counter], " -Fail-) ");
270dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	else
271dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		cat_expr_buf(expr_list[expr_counter], ") ");
272dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
273dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return;
274dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
275dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
276dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic void msgcat(char *src, char *tgt, char *op, int failed)
277dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
278dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char tmp_buf[128];
279dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (failed)
280dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ",
281dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				src, op, tgt);
282dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	else
283dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s) ",
284dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				src, op, tgt);
285dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	cat_expr_buf(expr_list[expr_counter], tmp_buf);
286dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
287dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
288dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/* Returns a buffer with class, statement type and permissions */
289dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic char *get_class_info(sepol_security_class_t tclass,
290dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							constraint_node_t *constraint,
291dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley							context_struct_t *xcontext)
292dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
293dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	constraint_expr_t *e;
294dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int mls, state_num;
295dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
296dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Find if MLS statement or not */
297dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	mls = 0;
298dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	for (e = constraint->expr; e; e = e->next) {
299dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (e->attr >= CEXPR_L1L2) {
300dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			mls = 1;
301dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			break;
302dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
303dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
304dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
305dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Determine statement type */
306dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *statements[] = {
307dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		"constrain ",			/* 0 */
308dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		"mlsconstrain ",		/* 1 */
309dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		"validatetrans ",		/* 2 */
310dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		"mlsvalidatetrans ",	/* 3 */
311dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		0 };
312dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
313dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (xcontext == NULL)
314dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		state_num = mls + 0;
315dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	else
316dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		state_num = mls + 2;
317dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
318dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int class_buf_len = 0;
319dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int new_class_buf_len;
320dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int len, buf_used;
321dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *class_buf = NULL, *p;
322dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *new_class_buf = NULL;
323dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
324dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	while (1) {
325dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
326dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		new_class_buf = realloc(class_buf, new_class_buf_len);
327dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!new_class_buf)
328dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				return NULL;
329dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		class_buf_len = new_class_buf_len;
330dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		class_buf = new_class_buf;
331dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		buf_used = 0;
332dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		p = class_buf;
333dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
334dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/* Add statement type */
335dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]);
336dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (len < 0 || len >= class_buf_len - buf_used)
337dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			continue;
338dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
339dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/* Add class entry */
340dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		p += len;
341dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		buf_used += len;
342dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		len = snprintf(p, class_buf_len - buf_used, "%s ",
343dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				policydb->p_class_val_to_name[tclass - 1]);
344dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (len < 0 || len >= class_buf_len - buf_used)
345dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			continue;
346dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
347dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/* Add permission entries */
348dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		p += len;
349dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		buf_used += len;
350dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		len = snprintf(p, class_buf_len - buf_used, "{%s } (",
351dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				sepol_av_to_string(policydb, tclass, constraint->permissions));
352dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (len < 0 || len >= class_buf_len - buf_used)
353dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			continue;
354dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		break;
355dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
356dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return class_buf;
357dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
358dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
359dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
360dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Modified version of constraint_expr_eval that will process each
361dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * constraint as before but adds the information to text buffers that
362dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * will hold various components. The expression will be in RPN format,
363dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * therefore there is a stack based RPN to infix converter to produce
364dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * the final readable constraint.
365dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley *
366dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Return the boolean value of a constraint expression
367dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * when it is applied to the specified source and target
368255e72915d4cbddceb435e13d81601755714e9fSE Android * security contexts.
369255e72915d4cbddceb435e13d81601755714e9fSE Android *
370255e72915d4cbddceb435e13d81601755714e9fSE Android * xcontext is a special beast...  It is used by the validatetrans rules
371255e72915d4cbddceb435e13d81601755714e9fSE Android * only.  For these rules, scontext is the context before the transition,
372dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * tcontext is the context after the transition, and xcontext is the
373dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * context of the process performing the transition.  All other callers
374dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * of constraint_expr_eval_reason should pass in NULL for xcontext.
375dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley *
376dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * This function will also build a buffer as the constraint is processed
377dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * for analysis. If this option is not required, then:
378dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley *      'tclass' should be '0' and r_buf MUST be NULL.
379255e72915d4cbddceb435e13d81601755714e9fSE Android */
380dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleystatic int constraint_expr_eval_reason(context_struct_t *scontext,
381dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				context_struct_t *tcontext,
382dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				context_struct_t *xcontext,
383dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				sepol_security_class_t tclass,
384dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				constraint_node_t *constraint,
385dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				char **r_buf,
386dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				unsigned int flags)
387255e72915d4cbddceb435e13d81601755714e9fSE Android{
388255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t val1, val2;
389255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *c;
390255e72915d4cbddceb435e13d81601755714e9fSE Android	role_datum_t *r1, *r2;
391255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_level_t *l1, *l2;
392255e72915d4cbddceb435e13d81601755714e9fSE Android	constraint_expr_t *e;
393255e72915d4cbddceb435e13d81601755714e9fSE Android	int s[CEXPR_MAXDEPTH];
394255e72915d4cbddceb435e13d81601755714e9fSE Android	int sp = -1;
395dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char tmp_buf[128];
396dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
397dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
398dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Define the s_t_x_num values that make up r1, t2 etc. in text strings
399dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Set 1 = source, 2 = target, 3 = xcontext for validatetrans
400dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
401dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define SOURCE  1
402dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define TARGET  2
403dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley#define XTARGET 3
404dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
405dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int s_t_x_num = SOURCE;
406dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
407dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
408dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int u_r_t = 0;
409dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
410dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *src = NULL;
411dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *tgt = NULL;
412dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int rc = 0, x;
413dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *class_buf = NULL;
414dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
415dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	class_buf = get_class_info(tclass, constraint, xcontext);
416dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (!class_buf) {
417dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "failed to allocate class buffer");
418dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		return -ENOMEM;
419dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
420dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
421dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Original function but with buffer support */
422dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int expr_list_len = 0;
423dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	expr_counter = 0;
424dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	expr_list = NULL;
425dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	for (e = constraint->expr; e; e = e->next) {
426dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/* Allocate a stack to hold expression buffer entries */
427dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (expr_counter >= expr_list_len) {
428dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			char **new_expr_list = expr_list;
429dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			int new_expr_list_len;
430dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
431dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (expr_list_len == 0)
432dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				new_expr_list_len = STACK_LEN;
433dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			else
434dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				new_expr_list_len = expr_list_len * 2;
435dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
436dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			new_expr_list = realloc(expr_list,
437dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					new_expr_list_len * sizeof(*expr_list));
438dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!new_expr_list) {
439dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				ERR(NULL, "failed to allocate expr buffer stack");
440dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				rc = -ENOMEM;
441dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
442dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
443dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			expr_list_len = new_expr_list_len;
444dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			expr_list = new_expr_list;
445dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
446dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
447dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/*
448dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		 * malloc a buffer to store each expression text component. If
449dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		 * buffer is too small cat_expr_buf() will realloc extra space.
450dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		 */
451dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		expr_buf_len = EXPR_BUF_SIZE;
452dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		expr_list[expr_counter] = malloc(expr_buf_len);
453dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (!expr_list[expr_counter]) {
454dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			ERR(NULL, "failed to allocate expr buffer");
455dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			rc = -ENOMEM;
456dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			goto out;
457dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
458dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		expr_buf_used = 0;
459255e72915d4cbddceb435e13d81601755714e9fSE Android
460dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		/* Now process each expression of the constraint */
461255e72915d4cbddceb435e13d81601755714e9fSE Android		switch (e->expr_type) {
462255e72915d4cbddceb435e13d81601755714e9fSE Android		case CEXPR_NOT:
463255e72915d4cbddceb435e13d81601755714e9fSE Android			BUG_ON(sp < 0);
464255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] = !s[sp];
465dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			cat_expr_buf(expr_list[expr_counter], "not");
466255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
467255e72915d4cbddceb435e13d81601755714e9fSE Android		case CEXPR_AND:
468255e72915d4cbddceb435e13d81601755714e9fSE Android			BUG_ON(sp < 1);
469255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
470255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] &= s[sp + 1];
471dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			cat_expr_buf(expr_list[expr_counter], "and");
472255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
473255e72915d4cbddceb435e13d81601755714e9fSE Android		case CEXPR_OR:
474255e72915d4cbddceb435e13d81601755714e9fSE Android			BUG_ON(sp < 1);
475255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
476255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] |= s[sp + 1];
477dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			cat_expr_buf(expr_list[expr_counter], "or");
478255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
479255e72915d4cbddceb435e13d81601755714e9fSE Android		case CEXPR_ATTR:
480255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp == (CEXPR_MAXDEPTH - 1))
481dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
482dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
483255e72915d4cbddceb435e13d81601755714e9fSE Android			switch (e->attr) {
484255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_USER:
485255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = scontext->user;
486255e72915d4cbddceb435e13d81601755714e9fSE Android				val2 = tcontext->user;
487dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("u1");
488dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("u2");
489255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
490255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_TYPE:
491255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = scontext->type;
492255e72915d4cbddceb435e13d81601755714e9fSE Android				val2 = tcontext->type;
493dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("t1");
494dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("t2");
495255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
496255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_ROLE:
497255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = scontext->role;
498255e72915d4cbddceb435e13d81601755714e9fSE Android				val2 = tcontext->role;
499255e72915d4cbddceb435e13d81601755714e9fSE Android				r1 = policydb->role_val_to_struct[val1 - 1];
500255e72915d4cbddceb435e13d81601755714e9fSE Android				r2 = policydb->role_val_to_struct[val2 - 1];
501dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("r1");
502dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("r2");
503dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
504255e72915d4cbddceb435e13d81601755714e9fSE Android				switch (e->op) {
505255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_DOM:
506dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
507dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "dom", s[sp] == 0);
508dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
509255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
510255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_DOMBY:
511dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
512dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "domby", s[sp] == 0);
513dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
514255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
515255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_INCOMP:
516dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1)
517dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						 && !ebitmap_get_bit(&r2->dominates, val1 - 1));
518dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "incomp", s[sp] == 0);
519dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
520255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
521255e72915d4cbddceb435e13d81601755714e9fSE Android				default:
522255e72915d4cbddceb435e13d81601755714e9fSE Android					break;
523255e72915d4cbddceb435e13d81601755714e9fSE Android				}
524255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
525255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_L1L2:
526255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(scontext->range.level[0]);
527255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(tcontext->range.level[0]);
528dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("l1");
529dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("l2");
530255e72915d4cbddceb435e13d81601755714e9fSE Android				goto mls_ops;
531255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_L1H2:
532255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(scontext->range.level[0]);
533255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(tcontext->range.level[1]);
534dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("l1");
535dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("h2");
536255e72915d4cbddceb435e13d81601755714e9fSE Android				goto mls_ops;
537255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_H1L2:
538255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(scontext->range.level[1]);
539255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(tcontext->range.level[0]);
540dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("h1");
541dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("l2");
542255e72915d4cbddceb435e13d81601755714e9fSE Android				goto mls_ops;
543255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_H1H2:
544255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(scontext->range.level[1]);
545255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(tcontext->range.level[1]);
546dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("h1");
547dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("h2");
548255e72915d4cbddceb435e13d81601755714e9fSE Android				goto mls_ops;
549255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_L1H1:
550255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(scontext->range.level[0]);
551255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(scontext->range.level[1]);
552dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("l1");
553dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("h1");
554255e72915d4cbddceb435e13d81601755714e9fSE Android				goto mls_ops;
555255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_L2H2:
556255e72915d4cbddceb435e13d81601755714e9fSE Android				l1 = &(tcontext->range.level[0]);
557255e72915d4cbddceb435e13d81601755714e9fSE Android				l2 = &(tcontext->range.level[1]);
558dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup("l2");
559dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(tgt); tgt = strdup("h2");
560dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleymls_ops:
561255e72915d4cbddceb435e13d81601755714e9fSE Android				switch (e->op) {
562255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_EQ:
563255e72915d4cbddceb435e13d81601755714e9fSE Android					s[++sp] = mls_level_eq(l1, l2);
564dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "eq", s[sp] == 0);
565dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
566255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
567255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_NEQ:
568255e72915d4cbddceb435e13d81601755714e9fSE Android					s[++sp] = !mls_level_eq(l1, l2);
569dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "!=", s[sp] == 0);
570dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
571255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
572255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_DOM:
573255e72915d4cbddceb435e13d81601755714e9fSE Android					s[++sp] = mls_level_dom(l1, l2);
574dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "dom", s[sp] == 0);
575dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
576255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
577255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_DOMBY:
578255e72915d4cbddceb435e13d81601755714e9fSE Android					s[++sp] = mls_level_dom(l2, l1);
579dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "domby", s[sp] == 0);
580dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
581255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
582255e72915d4cbddceb435e13d81601755714e9fSE Android				case CEXPR_INCOMP:
583255e72915d4cbddceb435e13d81601755714e9fSE Android					s[++sp] = mls_level_incomp(l2, l1);
584dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					msgcat(src, tgt, "incomp", s[sp] == 0);
585dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_counter++;
586255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
587255e72915d4cbddceb435e13d81601755714e9fSE Android				default:
588255e72915d4cbddceb435e13d81601755714e9fSE Android					BUG();
589dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					goto out;
590255e72915d4cbddceb435e13d81601755714e9fSE Android				}
591255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
592255e72915d4cbddceb435e13d81601755714e9fSE Android			default:
593255e72915d4cbddceb435e13d81601755714e9fSE Android				BUG();
594dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
595255e72915d4cbddceb435e13d81601755714e9fSE Android			}
596255e72915d4cbddceb435e13d81601755714e9fSE Android
597255e72915d4cbddceb435e13d81601755714e9fSE Android			switch (e->op) {
598255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_EQ:
599255e72915d4cbddceb435e13d81601755714e9fSE Android				s[++sp] = (val1 == val2);
600dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				msgcat(src, tgt, "==", s[sp] == 0);
601255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
602255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_NEQ:
603255e72915d4cbddceb435e13d81601755714e9fSE Android				s[++sp] = (val1 != val2);
604dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				msgcat(src, tgt, "!=", s[sp] == 0);
605255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
606255e72915d4cbddceb435e13d81601755714e9fSE Android			default:
607255e72915d4cbddceb435e13d81601755714e9fSE Android				BUG();
608dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
609255e72915d4cbddceb435e13d81601755714e9fSE Android			}
610255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
611255e72915d4cbddceb435e13d81601755714e9fSE Android		case CEXPR_NAMES:
612255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp == (CEXPR_MAXDEPTH - 1))
613dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
614dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			s_t_x_num = SOURCE;
615255e72915d4cbddceb435e13d81601755714e9fSE Android			c = scontext;
616dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (e->attr & CEXPR_TARGET) {
617dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				s_t_x_num = TARGET;
618255e72915d4cbddceb435e13d81601755714e9fSE Android				c = tcontext;
619dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			} else if (e->attr & CEXPR_XTARGET) {
620dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				s_t_x_num = XTARGET;
621255e72915d4cbddceb435e13d81601755714e9fSE Android				c = xcontext;
622255e72915d4cbddceb435e13d81601755714e9fSE Android			}
623dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!c) {
624dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				BUG();
625dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
626dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
627dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (e->attr & CEXPR_USER) {
628dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				u_r_t = CEXPR_USER;
629255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = c->user;
630dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), "u%d ", s_t_x_num);
631dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup(tmp_buf);
632dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			} else if (e->attr & CEXPR_ROLE) {
633dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				u_r_t = CEXPR_ROLE;
634255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = c->role;
635dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), "r%d ", s_t_x_num);
636dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup(tmp_buf);
637dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			} else if (e->attr & CEXPR_TYPE) {
638dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				u_r_t = CEXPR_TYPE;
639255e72915d4cbddceb435e13d81601755714e9fSE Android				val1 = c->type;
640dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				snprintf(tmp_buf, sizeof(tmp_buf), "t%d ", s_t_x_num);
641dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				free(src); src = strdup(tmp_buf);
642dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			} else {
643255e72915d4cbddceb435e13d81601755714e9fSE Android				BUG();
644dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
645255e72915d4cbddceb435e13d81601755714e9fSE Android			}
646255e72915d4cbddceb435e13d81601755714e9fSE Android
647255e72915d4cbddceb435e13d81601755714e9fSE Android			switch (e->op) {
648255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_EQ:
649255e72915d4cbddceb435e13d81601755714e9fSE Android				s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
650dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				get_name_list(e, u_r_t, src, "==", s[sp] == 0);
651255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
652dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
653255e72915d4cbddceb435e13d81601755714e9fSE Android			case CEXPR_NEQ:
654255e72915d4cbddceb435e13d81601755714e9fSE Android				s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
655dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				get_name_list(e, u_r_t, src, "!=", s[sp] == 0);
656255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
657255e72915d4cbddceb435e13d81601755714e9fSE Android			default:
658255e72915d4cbddceb435e13d81601755714e9fSE Android				BUG();
659dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
660255e72915d4cbddceb435e13d81601755714e9fSE Android			}
661255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
662255e72915d4cbddceb435e13d81601755714e9fSE Android		default:
663255e72915d4cbddceb435e13d81601755714e9fSE Android			BUG();
664dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			goto out;
665255e72915d4cbddceb435e13d81601755714e9fSE Android		}
666dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		expr_counter++;
667255e72915d4cbddceb435e13d81601755714e9fSE Android	}
668255e72915d4cbddceb435e13d81601755714e9fSE Android
669dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
670dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * At this point each expression of the constraint is in
671dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * expr_list[n+1] and in RPN format. Now convert to 'infix'
672dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
673dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
674dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
675dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * Save expr count but zero expr_counter to detect if
676dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * 'BUG(); goto out;' was called as we need to release any used
677dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * expr_list malloc's. Normally they are released by the RPN to
678dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * infix code.
679dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
680dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int expr_count = expr_counter;
681dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	expr_counter = 0;
682dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
683dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
684dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * The array of expression answer buffer pointers and counter.
685dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * Generate the same number of answer buffer entries as expression
686dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * buffers (as there will never be more).
687dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
688dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char **answer_list;
689dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int answer_counter = 0;
690dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
691dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	answer_list = malloc(expr_count * sizeof(*answer_list));
692dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (!answer_list) {
693dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "failed to allocate answer stack");
694dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		rc = -ENOMEM;
695dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		goto out;
696dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
697dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
698dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* The pop operands */
699dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *a;
700dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *b;
701dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int a_len, b_len;
702dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
703dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Convert constraint from RPN to infix notation. */
704dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	for (x = 0; x != expr_count; x++) {
705dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
706dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					"or", 2) == 0) {
707dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			b = pop();
708dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			b_len = strlen(b);
709dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			a = pop();
710dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			a_len = strlen(a);
711dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
712dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			/* get a buffer to hold the answer */
713dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			answer_list[answer_counter] = malloc(a_len + b_len + 8);
714dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!answer_list[answer_counter]) {
715dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				ERR(NULL, "failed to allocate answer buffer");
716dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				rc = -ENOMEM;
717dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
718dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
719dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			memset(answer_list[answer_counter], '\0', a_len + b_len + 8);
720dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
721dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			sprintf(answer_list[answer_counter], "%s %s %s", a,
722dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					expr_list[x], b);
723dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			push(answer_list[answer_counter++]);
724dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			free(a);
725dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			free(b);
726dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		} else if (strncmp(expr_list[x], "not", 3) == 0) {
727dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			b = pop();
728dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			b_len = strlen(b);
729dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
730dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			answer_list[answer_counter] = malloc(b_len + 8);
731dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (!answer_list[answer_counter]) {
732dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				ERR(NULL, "failed to allocate answer buffer");
733dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				rc = -ENOMEM;
734dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				goto out;
735dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
736dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			memset(answer_list[answer_counter], '\0', b_len + 8);
737dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
738dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			if (strncmp(b, "not", 3) == 0)
739dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				sprintf(answer_list[answer_counter], "%s (%s)",
740dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						expr_list[x], b);
741dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			else
742dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				sprintf(answer_list[answer_counter], "%s%s",
743dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						expr_list[x], b);
744dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			push(answer_list[answer_counter++]);
745dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			free(b);
746dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		} else {
747dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			push(expr_list[x]);
748dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
749dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
750dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Get the final answer from tos and build constraint text */
751dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	a = pop();
752dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
753dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Constraint calculation: rc = 0 is denied, rc = 1 is granted */
754dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	sprintf(tmp_buf, "Constraint %s\n", s[0] ? "GRANTED" : "DENIED");
755dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
756dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int len, new_buf_len;
757dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *p, **new_buf = r_buf;
758dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
759dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * These contain the constraint components that are added to the
760dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * callers reason buffer.
761dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
762dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
763dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
764dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
765dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * This will add the constraints to the callers reason buffer (who is
766dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * responsible for freeing the memory). It will handle any realloc's
767dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * should the buffer be too short.
768dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * The reason_buf_used and reason_buf_len counters are defined
769dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * globally as multiple constraints can be in the buffer.
770dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
771dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
772dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
773dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
774dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		for (x = 0; buffers[x] != NULL; x++) {
775dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			while (1) {
776dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				p = *r_buf + reason_buf_used;
777dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				len = snprintf(p, reason_buf_len - reason_buf_used,
778dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						"%s", buffers[x]);
779dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				if (len < 0 || len >= reason_buf_len - reason_buf_used) {
780dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					new_buf_len = reason_buf_len + REASON_BUF_SIZE;
781dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					*new_buf = realloc(*r_buf, new_buf_len);
782dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					if (!new_buf) {
783dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						ERR(NULL, "failed to realloc reason buffer");
784dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						goto out1;
785dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					}
786dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					**r_buf = **new_buf;
787dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					reason_buf_len = new_buf_len;
788dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					continue;
789dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				} else {
790dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					reason_buf_used += len;
791dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					break;
792dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				}
793dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			}
794dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
795dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
796dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
797dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyout1:
798dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	rc = s[0];
799dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	free(a);
800dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
801dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyout:
802dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	free(class_buf);
803dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	free(src);
804dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	free(tgt);
805dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
806dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (expr_counter) {
807dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		for (x = 0; expr_list[x] != NULL; x++)
808dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			free(expr_list[x]);
809dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
810dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return rc;
811255e72915d4cbddceb435e13d81601755714e9fSE Android}
812255e72915d4cbddceb435e13d81601755714e9fSE Android
813255e72915d4cbddceb435e13d81601755714e9fSE Android/*
814255e72915d4cbddceb435e13d81601755714e9fSE Android * Compute access vectors based on a context structure pair for
815255e72915d4cbddceb435e13d81601755714e9fSE Android * the permissions in a particular class.
816255e72915d4cbddceb435e13d81601755714e9fSE Android */
817255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int context_struct_compute_av(context_struct_t * scontext,
818255e72915d4cbddceb435e13d81601755714e9fSE Android				     context_struct_t * tcontext,
819255e72915d4cbddceb435e13d81601755714e9fSE Android				     sepol_security_class_t tclass,
820255e72915d4cbddceb435e13d81601755714e9fSE Android				     sepol_access_vector_t requested,
821255e72915d4cbddceb435e13d81601755714e9fSE Android				     struct sepol_av_decision *avd,
822dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				     unsigned int *reason,
823dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				     char **r_buf,
824dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					 unsigned int flags)
825255e72915d4cbddceb435e13d81601755714e9fSE Android{
826255e72915d4cbddceb435e13d81601755714e9fSE Android	constraint_node_t *constraint;
827255e72915d4cbddceb435e13d81601755714e9fSE Android	struct role_allow *ra;
828255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_key_t avkey;
829255e72915d4cbddceb435e13d81601755714e9fSE Android	class_datum_t *tclass_datum;
830255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_ptr_t node;
831255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_t *sattr, *tattr;
832255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *snode, *tnode;
833255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, j;
834255e72915d4cbddceb435e13d81601755714e9fSE Android
835255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tclass || tclass > policydb->p_classes.nprim) {
836255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized class %d", tclass);
837255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
838255e72915d4cbddceb435e13d81601755714e9fSE Android	}
839255e72915d4cbddceb435e13d81601755714e9fSE Android	tclass_datum = policydb->class_val_to_struct[tclass - 1];
840255e72915d4cbddceb435e13d81601755714e9fSE Android
841255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
842255e72915d4cbddceb435e13d81601755714e9fSE Android	 * Initialize the access vectors to the default values.
843255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
844255e72915d4cbddceb435e13d81601755714e9fSE Android	avd->allowed = 0;
845255e72915d4cbddceb435e13d81601755714e9fSE Android	avd->decided = 0xffffffff;
846255e72915d4cbddceb435e13d81601755714e9fSE Android	avd->auditallow = 0;
847255e72915d4cbddceb435e13d81601755714e9fSE Android	avd->auditdeny = 0xffffffff;
848255e72915d4cbddceb435e13d81601755714e9fSE Android	avd->seqno = latest_granting;
849255e72915d4cbddceb435e13d81601755714e9fSE Android	*reason = 0;
850255e72915d4cbddceb435e13d81601755714e9fSE Android
851255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
852255e72915d4cbddceb435e13d81601755714e9fSE Android	 * If a specific type enforcement rule was defined for
853255e72915d4cbddceb435e13d81601755714e9fSE Android	 * this permission check, then use it.
854255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
855255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.target_class = tclass;
856255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.specified = AVTAB_AV;
857255e72915d4cbddceb435e13d81601755714e9fSE Android	sattr = &policydb->type_attr_map[scontext->type - 1];
858255e72915d4cbddceb435e13d81601755714e9fSE Android	tattr = &policydb->type_attr_map[tcontext->type - 1];
859255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_for_each_bit(sattr, snode, i) {
860255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!ebitmap_node_get_bit(snode, i))
861255e72915d4cbddceb435e13d81601755714e9fSE Android			continue;
862255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(tattr, tnode, j) {
863255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!ebitmap_node_get_bit(tnode, j))
864255e72915d4cbddceb435e13d81601755714e9fSE Android				continue;
865255e72915d4cbddceb435e13d81601755714e9fSE Android			avkey.source_type = i + 1;
866255e72915d4cbddceb435e13d81601755714e9fSE Android			avkey.target_type = j + 1;
867255e72915d4cbddceb435e13d81601755714e9fSE Android			for (node =
868255e72915d4cbddceb435e13d81601755714e9fSE Android			     avtab_search_node(&policydb->te_avtab, &avkey);
869255e72915d4cbddceb435e13d81601755714e9fSE Android			     node != NULL;
870255e72915d4cbddceb435e13d81601755714e9fSE Android			     node =
871255e72915d4cbddceb435e13d81601755714e9fSE Android			     avtab_search_node_next(node, avkey.specified)) {
872255e72915d4cbddceb435e13d81601755714e9fSE Android				if (node->key.specified == AVTAB_ALLOWED)
873255e72915d4cbddceb435e13d81601755714e9fSE Android					avd->allowed |= node->datum.data;
874255e72915d4cbddceb435e13d81601755714e9fSE Android				else if (node->key.specified ==
875255e72915d4cbddceb435e13d81601755714e9fSE Android					 AVTAB_AUDITALLOW)
876255e72915d4cbddceb435e13d81601755714e9fSE Android					avd->auditallow |= node->datum.data;
877255e72915d4cbddceb435e13d81601755714e9fSE Android				else if (node->key.specified == AVTAB_AUDITDENY)
878255e72915d4cbddceb435e13d81601755714e9fSE Android					avd->auditdeny &= node->datum.data;
879255e72915d4cbddceb435e13d81601755714e9fSE Android			}
880255e72915d4cbddceb435e13d81601755714e9fSE Android
881255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Check conditional av table for additional permissions */
882255e72915d4cbddceb435e13d81601755714e9fSE Android			cond_compute_av(&policydb->te_cond_avtab, &avkey, avd);
883255e72915d4cbddceb435e13d81601755714e9fSE Android
884255e72915d4cbddceb435e13d81601755714e9fSE Android		}
885255e72915d4cbddceb435e13d81601755714e9fSE Android	}
886255e72915d4cbddceb435e13d81601755714e9fSE Android
887255e72915d4cbddceb435e13d81601755714e9fSE Android	if (requested & ~avd->allowed) {
888255e72915d4cbddceb435e13d81601755714e9fSE Android		*reason |= SEPOL_COMPUTEAV_TE;
889255e72915d4cbddceb435e13d81601755714e9fSE Android		requested &= avd->allowed;
890255e72915d4cbddceb435e13d81601755714e9fSE Android	}
891255e72915d4cbddceb435e13d81601755714e9fSE Android
892255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
893255e72915d4cbddceb435e13d81601755714e9fSE Android	 * Remove any permissions prohibited by a constraint (this includes
894255e72915d4cbddceb435e13d81601755714e9fSE Android	 * the MLS policy).
895255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
896255e72915d4cbddceb435e13d81601755714e9fSE Android	constraint = tclass_datum->constraints;
897255e72915d4cbddceb435e13d81601755714e9fSE Android	while (constraint) {
898255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((constraint->permissions & (avd->allowed)) &&
899dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		    !constraint_expr_eval_reason(scontext, tcontext, NULL,
900dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					  tclass, constraint, r_buf, flags)) {
901255e72915d4cbddceb435e13d81601755714e9fSE Android			avd->allowed =
902255e72915d4cbddceb435e13d81601755714e9fSE Android			    (avd->allowed) & ~(constraint->permissions);
903255e72915d4cbddceb435e13d81601755714e9fSE Android		}
904255e72915d4cbddceb435e13d81601755714e9fSE Android		constraint = constraint->next;
905255e72915d4cbddceb435e13d81601755714e9fSE Android	}
906255e72915d4cbddceb435e13d81601755714e9fSE Android
907255e72915d4cbddceb435e13d81601755714e9fSE Android	if (requested & ~avd->allowed) {
908255e72915d4cbddceb435e13d81601755714e9fSE Android		*reason |= SEPOL_COMPUTEAV_CONS;
909255e72915d4cbddceb435e13d81601755714e9fSE Android		requested &= avd->allowed;
910255e72915d4cbddceb435e13d81601755714e9fSE Android	}
911255e72915d4cbddceb435e13d81601755714e9fSE Android
912255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
913255e72915d4cbddceb435e13d81601755714e9fSE Android	 * If checking process transition permission and the
914255e72915d4cbddceb435e13d81601755714e9fSE Android	 * role is changing, then check the (current_role, new_role)
915255e72915d4cbddceb435e13d81601755714e9fSE Android	 * pair.
916255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
917255e72915d4cbddceb435e13d81601755714e9fSE Android	if (tclass == SECCLASS_PROCESS &&
918255e72915d4cbddceb435e13d81601755714e9fSE Android	    (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
919255e72915d4cbddceb435e13d81601755714e9fSE Android	    scontext->role != tcontext->role) {
920255e72915d4cbddceb435e13d81601755714e9fSE Android		for (ra = policydb->role_allow; ra; ra = ra->next) {
921255e72915d4cbddceb435e13d81601755714e9fSE Android			if (scontext->role == ra->role &&
922255e72915d4cbddceb435e13d81601755714e9fSE Android			    tcontext->role == ra->new_role)
923255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
924255e72915d4cbddceb435e13d81601755714e9fSE Android		}
925255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!ra)
926255e72915d4cbddceb435e13d81601755714e9fSE Android			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
927255e72915d4cbddceb435e13d81601755714e9fSE Android							  PROCESS__DYNTRANSITION);
928255e72915d4cbddceb435e13d81601755714e9fSE Android	}
929255e72915d4cbddceb435e13d81601755714e9fSE Android
930255e72915d4cbddceb435e13d81601755714e9fSE Android	if (requested & ~avd->allowed) {
931255e72915d4cbddceb435e13d81601755714e9fSE Android		*reason |= SEPOL_COMPUTEAV_RBAC;
932255e72915d4cbddceb435e13d81601755714e9fSE Android		requested &= avd->allowed;
933255e72915d4cbddceb435e13d81601755714e9fSE Android	}
934255e72915d4cbddceb435e13d81601755714e9fSE Android
935255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
936255e72915d4cbddceb435e13d81601755714e9fSE Android}
937255e72915d4cbddceb435e13d81601755714e9fSE Android
938255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_validate_transition(sepol_security_id_t oldsid,
939255e72915d4cbddceb435e13d81601755714e9fSE Android				     sepol_security_id_t newsid,
940255e72915d4cbddceb435e13d81601755714e9fSE Android				     sepol_security_id_t tasksid,
941255e72915d4cbddceb435e13d81601755714e9fSE Android				     sepol_security_class_t tclass)
942255e72915d4cbddceb435e13d81601755714e9fSE Android{
943255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *ocontext;
944255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *ncontext;
945255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *tcontext;
946255e72915d4cbddceb435e13d81601755714e9fSE Android	class_datum_t *tclass_datum;
947255e72915d4cbddceb435e13d81601755714e9fSE Android	constraint_node_t *constraint;
948255e72915d4cbddceb435e13d81601755714e9fSE Android
949255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tclass || tclass > policydb->p_classes.nprim) {
950255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized class %d", tclass);
951255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
952255e72915d4cbddceb435e13d81601755714e9fSE Android	}
953255e72915d4cbddceb435e13d81601755714e9fSE Android	tclass_datum = policydb->class_val_to_struct[tclass - 1];
954255e72915d4cbddceb435e13d81601755714e9fSE Android
955255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext = sepol_sidtab_search(sidtab, oldsid);
956255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!ocontext) {
957255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", oldsid);
958255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
959255e72915d4cbddceb435e13d81601755714e9fSE Android	}
960255e72915d4cbddceb435e13d81601755714e9fSE Android
961255e72915d4cbddceb435e13d81601755714e9fSE Android	ncontext = sepol_sidtab_search(sidtab, newsid);
962255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!ncontext) {
963255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", newsid);
964255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
965255e72915d4cbddceb435e13d81601755714e9fSE Android	}
966255e72915d4cbddceb435e13d81601755714e9fSE Android
967255e72915d4cbddceb435e13d81601755714e9fSE Android	tcontext = sepol_sidtab_search(sidtab, tasksid);
968255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tcontext) {
969255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", tasksid);
970255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
971255e72915d4cbddceb435e13d81601755714e9fSE Android	}
972255e72915d4cbddceb435e13d81601755714e9fSE Android
973255e72915d4cbddceb435e13d81601755714e9fSE Android	constraint = tclass_datum->validatetrans;
974255e72915d4cbddceb435e13d81601755714e9fSE Android	while (constraint) {
975dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
976dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					  0, constraint, NULL, 0)) {
977255e72915d4cbddceb435e13d81601755714e9fSE Android			return -EPERM;
978255e72915d4cbddceb435e13d81601755714e9fSE Android		}
979255e72915d4cbddceb435e13d81601755714e9fSE Android		constraint = constraint->next;
980255e72915d4cbddceb435e13d81601755714e9fSE Android	}
981255e72915d4cbddceb435e13d81601755714e9fSE Android
982255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
983255e72915d4cbddceb435e13d81601755714e9fSE Android}
984255e72915d4cbddceb435e13d81601755714e9fSE Android
985255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_compute_av_reason(sepol_security_id_t ssid,
986255e72915d4cbddceb435e13d81601755714e9fSE Android				   sepol_security_id_t tsid,
987255e72915d4cbddceb435e13d81601755714e9fSE Android				   sepol_security_class_t tclass,
988255e72915d4cbddceb435e13d81601755714e9fSE Android				   sepol_access_vector_t requested,
989255e72915d4cbddceb435e13d81601755714e9fSE Android				   struct sepol_av_decision *avd,
990255e72915d4cbddceb435e13d81601755714e9fSE Android				   unsigned int *reason)
991255e72915d4cbddceb435e13d81601755714e9fSE Android{
992255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *scontext = 0, *tcontext = 0;
993255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
994255e72915d4cbddceb435e13d81601755714e9fSE Android
995255e72915d4cbddceb435e13d81601755714e9fSE Android	scontext = sepol_sidtab_search(sidtab, ssid);
996255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!scontext) {
997255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", ssid);
998255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
999255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1000255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1001255e72915d4cbddceb435e13d81601755714e9fSE Android	tcontext = sepol_sidtab_search(sidtab, tsid);
1002255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tcontext) {
1003255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", tsid);
1004255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1005255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1006255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1007255e72915d4cbddceb435e13d81601755714e9fSE Android
1008255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = context_struct_compute_av(scontext, tcontext, tclass,
1009dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					requested, avd, reason, NULL, 0);
1010255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1011255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1012255e72915d4cbddceb435e13d81601755714e9fSE Android}
1013255e72915d4cbddceb435e13d81601755714e9fSE Android
1014dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
1015dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to
1016dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd
1017dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * in the constraint_expr_eval_reason() function.
1018dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
1019dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyint hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
1020dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   sepol_security_id_t tsid,
1021dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   sepol_security_class_t tclass,
1022dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   sepol_access_vector_t requested,
1023dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   struct sepol_av_decision *avd,
1024dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   unsigned int *reason,
1025dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   char **reason_buf,
1026dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley				   unsigned int flags)
1027dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
1028dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	context_struct_t *scontext = 0, *tcontext = 0;
1029dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	int rc = 0;
1030dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1031dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	scontext = sepol_sidtab_search(sidtab, ssid);
1032dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (!scontext) {
1033dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "unrecognized SID %d", ssid);
1034dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		rc = -EINVAL;
1035dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		goto out;
1036dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1037dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	tcontext = sepol_sidtab_search(sidtab, tsid);
1038dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (!tcontext) {
1039dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "unrecognized SID %d", tsid);
1040dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		rc = -EINVAL;
1041dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		goto out;
1042dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1043dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1044dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/*
1045dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * Set the buffer to NULL as constraints may not be processed.
1046dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * If a buffer is required, then the routines in
1047dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE
1048dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * chunks (as it gets called for each constraint processed).
1049dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 * We just make sure these start from zero.
1050dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	 */
1051dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	*reason_buf = NULL;
1052dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	reason_buf_used = 0;
1053dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	reason_buf_len = 0;
1054dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1055dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	rc = context_struct_compute_av(scontext, tcontext, tclass,
1056dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					   requested, avd, reason, reason_buf, flags);
1057dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyout:
1058dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return rc;
1059dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
1060dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1061255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_compute_av(sepol_security_id_t ssid,
1062255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_id_t tsid,
1063255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_class_t tclass,
1064255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_access_vector_t requested,
1065255e72915d4cbddceb435e13d81601755714e9fSE Android			    struct sepol_av_decision *avd)
1066255e72915d4cbddceb435e13d81601755714e9fSE Android{
1067255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int reason = 0;
1068255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd,
1069255e72915d4cbddceb435e13d81601755714e9fSE Android				       &reason);
1070255e72915d4cbddceb435e13d81601755714e9fSE Android}
1071255e72915d4cbddceb435e13d81601755714e9fSE Android
1072255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1073dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Return a class ID associated with the class string specified by
1074dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * class_name.
1075dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
1076dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyint hidden sepol_string_to_security_class(const char *class_name,
1077dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			sepol_security_class_t *tclass)
1078dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
1079dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	char *class = NULL;
1080dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	sepol_security_class_t id;
1081dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1082dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	for (id = 1;; id++) {
1083dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		class = policydb->p_class_val_to_name[id - 1];
1084dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if (class == NULL) {
1085dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			ERR(NULL, "could not convert %s to class id", class_name);
1086dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			return STATUS_ERR;
1087dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
1088dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		if ((strcmp(class, class_name)) == 0) {
1089dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			*tclass = id;
1090dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			return STATUS_SUCCESS;
1091dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		}
1092dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1093dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
1094dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1095dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
1096dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * Return access vector bit associated with the class ID and permission
1097dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley * string.
1098dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley */
1099dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyint hidden sepol_string_to_av_perm(sepol_security_class_t tclass,
1100dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					const char *perm_name,
1101dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley					sepol_access_vector_t *av)
1102dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley{
1103dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	class_datum_t *tclass_datum;
1104dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	perm_datum_t *perm_datum;
1105dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1106dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (!tclass || tclass > policydb->p_classes.nprim) {
1107dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		ERR(NULL, "unrecognized class %d", tclass);
1108dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		return -EINVAL;
1109dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1110dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	tclass_datum = policydb->class_val_to_struct[tclass - 1];
1111dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1112dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	/* Check for unique perms then the common ones (if any) */
1113dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	perm_datum = (perm_datum_t *)
1114dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			hashtab_search(tclass_datum->permissions.table,
1115dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			(hashtab_key_t)perm_name);
1116dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (perm_datum != NULL) {
1117dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		*av = 0x1 << (perm_datum->s.value - 1);
1118dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		return STATUS_SUCCESS;
1119dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1120dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1121dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (tclass_datum->comdatum == NULL)
1122dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		goto out;
1123dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1124dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	perm_datum = (perm_datum_t *)
1125dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			hashtab_search(tclass_datum->comdatum->permissions.table,
1126dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley			(hashtab_key_t)perm_name);
1127dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1128dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	if (perm_datum != NULL) {
1129dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		*av = 0x1 << (perm_datum->s.value - 1);
1130dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		return STATUS_SUCCESS;
1131dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	}
1132dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalleyout:
1133dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	ERR(NULL, "could not convert %s to av bit", perm_name);
1134dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley	return STATUS_ERR;
1135dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley}
1136dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley
1137dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley/*
1138255e72915d4cbddceb435e13d81601755714e9fSE Android * Write the security context string representation of
1139255e72915d4cbddceb435e13d81601755714e9fSE Android * the context associated with `sid' into a dynamically
1140255e72915d4cbddceb435e13d81601755714e9fSE Android * allocated string of the correct size.  Set `*scontext'
1141255e72915d4cbddceb435e13d81601755714e9fSE Android * to point to this string and set `*scontext_len' to
1142255e72915d4cbddceb435e13d81601755714e9fSE Android * the length of the string.
1143255e72915d4cbddceb435e13d81601755714e9fSE Android */
1144255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_sid_to_context(sepol_security_id_t sid,
1145255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_security_context_t * scontext,
1146255e72915d4cbddceb435e13d81601755714e9fSE Android				size_t * scontext_len)
1147255e72915d4cbddceb435e13d81601755714e9fSE Android{
1148255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *context;
1149255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1150255e72915d4cbddceb435e13d81601755714e9fSE Android
1151255e72915d4cbddceb435e13d81601755714e9fSE Android	context = sepol_sidtab_search(sidtab, sid);
1152255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!context) {
1153255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", sid);
1154255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1155255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1156255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1157255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = context_to_string(NULL, policydb, context, scontext, scontext_len);
1158255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1159255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1160255e72915d4cbddceb435e13d81601755714e9fSE Android
1161255e72915d4cbddceb435e13d81601755714e9fSE Android}
1162255e72915d4cbddceb435e13d81601755714e9fSE Android
1163255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1164255e72915d4cbddceb435e13d81601755714e9fSE Android * Return a SID associated with the security context that
1165255e72915d4cbddceb435e13d81601755714e9fSE Android * has the string representation specified by `scontext'.
1166255e72915d4cbddceb435e13d81601755714e9fSE Android */
1167255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_context_to_sid(const sepol_security_context_t scontext,
1168255e72915d4cbddceb435e13d81601755714e9fSE Android				size_t scontext_len, sepol_security_id_t * sid)
1169255e72915d4cbddceb435e13d81601755714e9fSE Android{
1170255e72915d4cbddceb435e13d81601755714e9fSE Android
1171255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *context = NULL;
1172255e72915d4cbddceb435e13d81601755714e9fSE Android
1173255e72915d4cbddceb435e13d81601755714e9fSE Android	/* First, create the context */
1174255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_from_string(NULL, policydb, &context,
1175255e72915d4cbddceb435e13d81601755714e9fSE Android				scontext, scontext_len) < 0)
1176255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
1177255e72915d4cbddceb435e13d81601755714e9fSE Android
1178255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Obtain the new sid */
1179255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0))
1180255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
1181255e72915d4cbddceb435e13d81601755714e9fSE Android
1182255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(context);
1183255e72915d4cbddceb435e13d81601755714e9fSE Android	free(context);
1184255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
1185255e72915d4cbddceb435e13d81601755714e9fSE Android
1186255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
1187255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context) {
1188255e72915d4cbddceb435e13d81601755714e9fSE Android		context_destroy(context);
1189255e72915d4cbddceb435e13d81601755714e9fSE Android		free(context);
1190255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1191255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(NULL, "could not convert %s to sid", scontext);
1192255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
1193255e72915d4cbddceb435e13d81601755714e9fSE Android}
1194255e72915d4cbddceb435e13d81601755714e9fSE Android
1195255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int compute_sid_handle_invalid_context(context_struct_t *
1196255e72915d4cbddceb435e13d81601755714e9fSE Android						     scontext,
1197255e72915d4cbddceb435e13d81601755714e9fSE Android						     context_struct_t *
1198255e72915d4cbddceb435e13d81601755714e9fSE Android						     tcontext,
1199255e72915d4cbddceb435e13d81601755714e9fSE Android						     sepol_security_class_t
1200255e72915d4cbddceb435e13d81601755714e9fSE Android						     tclass,
1201255e72915d4cbddceb435e13d81601755714e9fSE Android						     context_struct_t *
1202255e72915d4cbddceb435e13d81601755714e9fSE Android						     newcontext)
1203255e72915d4cbddceb435e13d81601755714e9fSE Android{
1204255e72915d4cbddceb435e13d81601755714e9fSE Android	if (selinux_enforcing) {
1205255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EACCES;
1206255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1207255e72915d4cbddceb435e13d81601755714e9fSE Android		sepol_security_context_t s, t, n;
1208255e72915d4cbddceb435e13d81601755714e9fSE Android		size_t slen, tlen, nlen;
1209255e72915d4cbddceb435e13d81601755714e9fSE Android
1210255e72915d4cbddceb435e13d81601755714e9fSE Android		context_to_string(NULL, policydb, scontext, &s, &slen);
1211255e72915d4cbddceb435e13d81601755714e9fSE Android		context_to_string(NULL, policydb, tcontext, &t, &tlen);
1212255e72915d4cbddceb435e13d81601755714e9fSE Android		context_to_string(NULL, policydb, newcontext, &n, &nlen);
1213255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "invalid context %s for "
1214255e72915d4cbddceb435e13d81601755714e9fSE Android		    "scontext=%s tcontext=%s tclass=%s",
1215255e72915d4cbddceb435e13d81601755714e9fSE Android		    n, s, t, policydb->p_class_val_to_name[tclass - 1]);
1216255e72915d4cbddceb435e13d81601755714e9fSE Android		free(s);
1217255e72915d4cbddceb435e13d81601755714e9fSE Android		free(t);
1218255e72915d4cbddceb435e13d81601755714e9fSE Android		free(n);
1219255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
1220255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1221255e72915d4cbddceb435e13d81601755714e9fSE Android}
1222255e72915d4cbddceb435e13d81601755714e9fSE Android
1223255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int sepol_compute_sid(sepol_security_id_t ssid,
1224255e72915d4cbddceb435e13d81601755714e9fSE Android			     sepol_security_id_t tsid,
1225255e72915d4cbddceb435e13d81601755714e9fSE Android			     sepol_security_class_t tclass,
1226255e72915d4cbddceb435e13d81601755714e9fSE Android			     uint32_t specified, sepol_security_id_t * out_sid)
1227255e72915d4cbddceb435e13d81601755714e9fSE Android{
1228255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *scontext = 0, *tcontext = 0, newcontext;
1229255e72915d4cbddceb435e13d81601755714e9fSE Android	struct role_trans *roletr = 0;
1230255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_key_t avkey;
1231255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_datum_t *avdatum;
1232255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_ptr_t node;
1233255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1234255e72915d4cbddceb435e13d81601755714e9fSE Android
1235255e72915d4cbddceb435e13d81601755714e9fSE Android	scontext = sepol_sidtab_search(sidtab, ssid);
1236255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!scontext) {
1237255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", ssid);
1238255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1239255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1240255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1241255e72915d4cbddceb435e13d81601755714e9fSE Android	tcontext = sepol_sidtab_search(sidtab, tsid);
1242255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tcontext) {
1243255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "unrecognized SID %d", tsid);
1244255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1245255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1246255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1247255e72915d4cbddceb435e13d81601755714e9fSE Android
1248255e72915d4cbddceb435e13d81601755714e9fSE Android	context_init(&newcontext);
1249255e72915d4cbddceb435e13d81601755714e9fSE Android
1250255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Set the user identity. */
1251255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (specified) {
1252255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_TRANSITION:
1253255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_CHANGE:
1254255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the process user identity. */
1255255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.user = scontext->user;
1256255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1257255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_MEMBER:
1258255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the related object owner. */
1259255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.user = tcontext->user;
1260255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1261255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1262255e72915d4cbddceb435e13d81601755714e9fSE Android
1263255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Set the role and type to default values. */
1264255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (tclass) {
1265255e72915d4cbddceb435e13d81601755714e9fSE Android	case SECCLASS_PROCESS:
1266255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the current role and type of process. */
1267255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.role = scontext->role;
1268255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.type = scontext->type;
1269255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1270255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
1271255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the well-defined object role. */
1272255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.role = OBJECT_R_VAL;
1273255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the type of the related object. */
1274255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.type = tcontext->type;
1275255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1276255e72915d4cbddceb435e13d81601755714e9fSE Android
1277255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Look for a type transition/member/change rule. */
1278255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.source_type = scontext->type;
1279255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.target_type = tcontext->type;
1280255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.target_class = tclass;
1281255e72915d4cbddceb435e13d81601755714e9fSE Android	avkey.specified = specified;
1282255e72915d4cbddceb435e13d81601755714e9fSE Android	avdatum = avtab_search(&policydb->te_avtab, &avkey);
1283255e72915d4cbddceb435e13d81601755714e9fSE Android
1284255e72915d4cbddceb435e13d81601755714e9fSE Android	/* If no permanent rule, also check for enabled conditional rules */
1285255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!avdatum) {
1286255e72915d4cbddceb435e13d81601755714e9fSE Android		node = avtab_search_node(&policydb->te_cond_avtab, &avkey);
1287255e72915d4cbddceb435e13d81601755714e9fSE Android		for (; node != NULL;
1288255e72915d4cbddceb435e13d81601755714e9fSE Android		     node = avtab_search_node_next(node, specified)) {
1289255e72915d4cbddceb435e13d81601755714e9fSE Android			if (node->key.specified & AVTAB_ENABLED) {
1290255e72915d4cbddceb435e13d81601755714e9fSE Android				avdatum = &node->datum;
1291255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
1292255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1293255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1294255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1295255e72915d4cbddceb435e13d81601755714e9fSE Android
1296255e72915d4cbddceb435e13d81601755714e9fSE Android	if (avdatum) {
1297255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Use the type from the type transition/member/change rule. */
1298255e72915d4cbddceb435e13d81601755714e9fSE Android		newcontext.type = avdatum->data;
1299255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1300255e72915d4cbddceb435e13d81601755714e9fSE Android
1301255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Check for class-specific changes. */
1302255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (tclass) {
1303255e72915d4cbddceb435e13d81601755714e9fSE Android	case SECCLASS_PROCESS:
1304255e72915d4cbddceb435e13d81601755714e9fSE Android		if (specified & AVTAB_TRANSITION) {
1305255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Look for a role transition rule. */
1306255e72915d4cbddceb435e13d81601755714e9fSE Android			for (roletr = policydb->role_tr; roletr;
1307255e72915d4cbddceb435e13d81601755714e9fSE Android			     roletr = roletr->next) {
1308255e72915d4cbddceb435e13d81601755714e9fSE Android				if (roletr->role == scontext->role &&
1309255e72915d4cbddceb435e13d81601755714e9fSE Android				    roletr->type == tcontext->type) {
1310255e72915d4cbddceb435e13d81601755714e9fSE Android					/* Use the role transition rule. */
1311255e72915d4cbddceb435e13d81601755714e9fSE Android					newcontext.role = roletr->new_role;
1312255e72915d4cbddceb435e13d81601755714e9fSE Android					break;
1313255e72915d4cbddceb435e13d81601755714e9fSE Android				}
1314255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1315255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1316255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1317255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
1318255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1319255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1320255e72915d4cbddceb435e13d81601755714e9fSE Android
1321255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Set the MLS attributes.
1322255e72915d4cbddceb435e13d81601755714e9fSE Android	   This is done last because it may allocate memory. */
1323255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified,
1324255e72915d4cbddceb435e13d81601755714e9fSE Android			     &newcontext);
1325255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc)
1326255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1327255e72915d4cbddceb435e13d81601755714e9fSE Android
1328255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Check the validity of the context. */
1329255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb_context_isvalid(policydb, &newcontext)) {
1330255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = compute_sid_handle_invalid_context(scontext,
1331255e72915d4cbddceb435e13d81601755714e9fSE Android							tcontext,
1332255e72915d4cbddceb435e13d81601755714e9fSE Android							tclass, &newcontext);
1333255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
1334255e72915d4cbddceb435e13d81601755714e9fSE Android			goto out;
1335255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1336255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Obtain the sid for the context. */
1337255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid);
1338255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1339255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(&newcontext);
1340255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1341255e72915d4cbddceb435e13d81601755714e9fSE Android}
1342255e72915d4cbddceb435e13d81601755714e9fSE Android
1343255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1344255e72915d4cbddceb435e13d81601755714e9fSE Android * Compute a SID to use for labeling a new object in the
1345255e72915d4cbddceb435e13d81601755714e9fSE Android * class `tclass' based on a SID pair.
1346255e72915d4cbddceb435e13d81601755714e9fSE Android */
1347255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_transition_sid(sepol_security_id_t ssid,
1348255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_security_id_t tsid,
1349255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_security_class_t tclass,
1350255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_security_id_t * out_sid)
1351255e72915d4cbddceb435e13d81601755714e9fSE Android{
1352255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
1353255e72915d4cbddceb435e13d81601755714e9fSE Android}
1354255e72915d4cbddceb435e13d81601755714e9fSE Android
1355255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1356255e72915d4cbddceb435e13d81601755714e9fSE Android * Compute a SID to use when selecting a member of a
1357255e72915d4cbddceb435e13d81601755714e9fSE Android * polyinstantiated object of class `tclass' based on
1358255e72915d4cbddceb435e13d81601755714e9fSE Android * a SID pair.
1359255e72915d4cbddceb435e13d81601755714e9fSE Android */
1360255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_member_sid(sepol_security_id_t ssid,
1361255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_id_t tsid,
1362255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_class_t tclass,
1363255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_id_t * out_sid)
1364255e72915d4cbddceb435e13d81601755714e9fSE Android{
1365255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
1366255e72915d4cbddceb435e13d81601755714e9fSE Android}
1367255e72915d4cbddceb435e13d81601755714e9fSE Android
1368255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1369255e72915d4cbddceb435e13d81601755714e9fSE Android * Compute a SID to use for relabeling an object in the
1370255e72915d4cbddceb435e13d81601755714e9fSE Android * class `tclass' based on a SID pair.
1371255e72915d4cbddceb435e13d81601755714e9fSE Android */
1372255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_change_sid(sepol_security_id_t ssid,
1373255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_id_t tsid,
1374255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_class_t tclass,
1375255e72915d4cbddceb435e13d81601755714e9fSE Android			    sepol_security_id_t * out_sid)
1376255e72915d4cbddceb435e13d81601755714e9fSE Android{
1377255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
1378255e72915d4cbddceb435e13d81601755714e9fSE Android}
1379255e72915d4cbddceb435e13d81601755714e9fSE Android
1380255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1381255e72915d4cbddceb435e13d81601755714e9fSE Android * Verify that each permission that is defined under the
1382255e72915d4cbddceb435e13d81601755714e9fSE Android * existing policy is still defined with the same value
1383255e72915d4cbddceb435e13d81601755714e9fSE Android * in the new policy.
1384255e72915d4cbddceb435e13d81601755714e9fSE Android */
1385255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
1386255e72915d4cbddceb435e13d81601755714e9fSE Android{
1387255e72915d4cbddceb435e13d81601755714e9fSE Android	hashtab_t h;
1388255e72915d4cbddceb435e13d81601755714e9fSE Android	perm_datum_t *perdatum, *perdatum2;
1389255e72915d4cbddceb435e13d81601755714e9fSE Android
1390255e72915d4cbddceb435e13d81601755714e9fSE Android	h = (hashtab_t) p;
1391255e72915d4cbddceb435e13d81601755714e9fSE Android	perdatum = (perm_datum_t *) datum;
1392255e72915d4cbddceb435e13d81601755714e9fSE Android
1393255e72915d4cbddceb435e13d81601755714e9fSE Android	perdatum2 = (perm_datum_t *) hashtab_search(h, key);
1394255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!perdatum2) {
1395255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "permission %s disappeared", key);
1396255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1397255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1398255e72915d4cbddceb435e13d81601755714e9fSE Android	if (perdatum->s.value != perdatum2->s.value) {
1399255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "the value of permissions %s changed", key);
1400255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1401255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1402255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1403255e72915d4cbddceb435e13d81601755714e9fSE Android}
1404255e72915d4cbddceb435e13d81601755714e9fSE Android
1405255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1406255e72915d4cbddceb435e13d81601755714e9fSE Android * Verify that each class that is defined under the
1407255e72915d4cbddceb435e13d81601755714e9fSE Android * existing policy is still defined with the same
1408255e72915d4cbddceb435e13d81601755714e9fSE Android * attributes in the new policy.
1409255e72915d4cbddceb435e13d81601755714e9fSE Android */
1410255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p)
1411255e72915d4cbddceb435e13d81601755714e9fSE Android{
1412255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *newp;
1413255e72915d4cbddceb435e13d81601755714e9fSE Android	class_datum_t *cladatum, *cladatum2;
1414255e72915d4cbddceb435e13d81601755714e9fSE Android
1415255e72915d4cbddceb435e13d81601755714e9fSE Android	newp = (policydb_t *) p;
1416255e72915d4cbddceb435e13d81601755714e9fSE Android	cladatum = (class_datum_t *) datum;
1417255e72915d4cbddceb435e13d81601755714e9fSE Android
1418255e72915d4cbddceb435e13d81601755714e9fSE Android	cladatum2 =
1419255e72915d4cbddceb435e13d81601755714e9fSE Android	    (class_datum_t *) hashtab_search(newp->p_classes.table, key);
1420255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!cladatum2) {
1421255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "class %s disappeared", key);
1422255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1423255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1424255e72915d4cbddceb435e13d81601755714e9fSE Android	if (cladatum->s.value != cladatum2->s.value) {
1425255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "the value of class %s changed", key);
1426255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1427255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1428255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((cladatum->comdatum && !cladatum2->comdatum) ||
1429255e72915d4cbddceb435e13d81601755714e9fSE Android	    (!cladatum->comdatum && cladatum2->comdatum)) {
1430255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "the inherits clause for the access "
1431255e72915d4cbddceb435e13d81601755714e9fSE Android		    "vector definition for class %s changed", key);
1432255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1433255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1434255e72915d4cbddceb435e13d81601755714e9fSE Android	if (cladatum->comdatum) {
1435255e72915d4cbddceb435e13d81601755714e9fSE Android		if (hashtab_map
1436255e72915d4cbddceb435e13d81601755714e9fSE Android		    (cladatum->comdatum->permissions.table, validate_perm,
1437255e72915d4cbddceb435e13d81601755714e9fSE Android		     cladatum2->comdatum->permissions.table)) {
1438255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(NULL,
1439255e72915d4cbddceb435e13d81601755714e9fSE Android			    " in the access vector definition "
1440255e72915d4cbddceb435e13d81601755714e9fSE Android			    "for class %s\n", key);
1441255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
1442255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1443255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1444255e72915d4cbddceb435e13d81601755714e9fSE Android	if (hashtab_map(cladatum->permissions.table, validate_perm,
1445255e72915d4cbddceb435e13d81601755714e9fSE Android			cladatum2->permissions.table)) {
1446255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, " in access vector definition for class %s", key);
1447255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1448255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1449255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1450255e72915d4cbddceb435e13d81601755714e9fSE Android}
1451255e72915d4cbddceb435e13d81601755714e9fSE Android
1452255e72915d4cbddceb435e13d81601755714e9fSE Android/* Clone the SID into the new SID table. */
1453255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int clone_sid(sepol_security_id_t sid,
1454255e72915d4cbddceb435e13d81601755714e9fSE Android		     context_struct_t * context, void *arg)
1455255e72915d4cbddceb435e13d81601755714e9fSE Android{
1456255e72915d4cbddceb435e13d81601755714e9fSE Android	sidtab_t *s = arg;
1457255e72915d4cbddceb435e13d81601755714e9fSE Android
1458255e72915d4cbddceb435e13d81601755714e9fSE Android	return sepol_sidtab_insert(s, sid, context);
1459255e72915d4cbddceb435e13d81601755714e9fSE Android}
1460255e72915d4cbddceb435e13d81601755714e9fSE Android
1461255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int convert_context_handle_invalid_context(context_struct_t *
1462255e72915d4cbddceb435e13d81601755714e9fSE Android							 context)
1463255e72915d4cbddceb435e13d81601755714e9fSE Android{
1464255e72915d4cbddceb435e13d81601755714e9fSE Android	if (selinux_enforcing) {
1465255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
1466255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1467255e72915d4cbddceb435e13d81601755714e9fSE Android		sepol_security_context_t s;
1468255e72915d4cbddceb435e13d81601755714e9fSE Android		size_t len;
1469255e72915d4cbddceb435e13d81601755714e9fSE Android
1470255e72915d4cbddceb435e13d81601755714e9fSE Android		context_to_string(NULL, policydb, context, &s, &len);
1471255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "context %s is invalid", s);
1472255e72915d4cbddceb435e13d81601755714e9fSE Android		free(s);
1473255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
1474255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1475255e72915d4cbddceb435e13d81601755714e9fSE Android}
1476255e72915d4cbddceb435e13d81601755714e9fSE Android
1477255e72915d4cbddceb435e13d81601755714e9fSE Androidtypedef struct {
1478255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *oldp;
1479255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *newp;
1480255e72915d4cbddceb435e13d81601755714e9fSE Android} convert_context_args_t;
1481255e72915d4cbddceb435e13d81601755714e9fSE Android
1482255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1483255e72915d4cbddceb435e13d81601755714e9fSE Android * Convert the values in the security context
1484255e72915d4cbddceb435e13d81601755714e9fSE Android * structure `c' from the values specified
1485255e72915d4cbddceb435e13d81601755714e9fSE Android * in the policy `p->oldp' to the values specified
1486255e72915d4cbddceb435e13d81601755714e9fSE Android * in the policy `p->newp'.  Verify that the
1487255e72915d4cbddceb435e13d81601755714e9fSE Android * context is valid under the new policy.
1488255e72915d4cbddceb435e13d81601755714e9fSE Android */
1489255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int convert_context(sepol_security_id_t key __attribute__ ((unused)),
1490255e72915d4cbddceb435e13d81601755714e9fSE Android			   context_struct_t * c, void *p)
1491255e72915d4cbddceb435e13d81601755714e9fSE Android{
1492255e72915d4cbddceb435e13d81601755714e9fSE Android	convert_context_args_t *args;
1493255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t oldc;
1494255e72915d4cbddceb435e13d81601755714e9fSE Android	role_datum_t *role;
1495255e72915d4cbddceb435e13d81601755714e9fSE Android	type_datum_t *typdatum;
1496255e72915d4cbddceb435e13d81601755714e9fSE Android	user_datum_t *usrdatum;
1497255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_security_context_t s;
1498255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t len;
1499255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = -EINVAL;
1500255e72915d4cbddceb435e13d81601755714e9fSE Android
1501255e72915d4cbddceb435e13d81601755714e9fSE Android	args = (convert_context_args_t *) p;
1502255e72915d4cbddceb435e13d81601755714e9fSE Android
1503255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_cpy(&oldc, c))
1504255e72915d4cbddceb435e13d81601755714e9fSE Android		return -ENOMEM;
1505255e72915d4cbddceb435e13d81601755714e9fSE Android
1506255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Convert the user. */
1507255e72915d4cbddceb435e13d81601755714e9fSE Android	usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table,
1508255e72915d4cbddceb435e13d81601755714e9fSE Android						   args->oldp->
1509255e72915d4cbddceb435e13d81601755714e9fSE Android						   p_user_val_to_name[c->user -
1510255e72915d4cbddceb435e13d81601755714e9fSE Android								      1]);
1511255e72915d4cbddceb435e13d81601755714e9fSE Android
1512255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!usrdatum) {
1513255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
1514255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1515255e72915d4cbddceb435e13d81601755714e9fSE Android	c->user = usrdatum->s.value;
1516255e72915d4cbddceb435e13d81601755714e9fSE Android
1517255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Convert the role. */
1518255e72915d4cbddceb435e13d81601755714e9fSE Android	role = (role_datum_t *) hashtab_search(args->newp->p_roles.table,
1519255e72915d4cbddceb435e13d81601755714e9fSE Android					       args->oldp->
1520255e72915d4cbddceb435e13d81601755714e9fSE Android					       p_role_val_to_name[c->role - 1]);
1521255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!role) {
1522255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
1523255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1524255e72915d4cbddceb435e13d81601755714e9fSE Android	c->role = role->s.value;
1525255e72915d4cbddceb435e13d81601755714e9fSE Android
1526255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Convert the type. */
1527255e72915d4cbddceb435e13d81601755714e9fSE Android	typdatum = (type_datum_t *)
1528255e72915d4cbddceb435e13d81601755714e9fSE Android	    hashtab_search(args->newp->p_types.table,
1529255e72915d4cbddceb435e13d81601755714e9fSE Android			   args->oldp->p_type_val_to_name[c->type - 1]);
1530255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!typdatum) {
1531255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
1532255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1533255e72915d4cbddceb435e13d81601755714e9fSE Android	c->type = typdatum->s.value;
1534255e72915d4cbddceb435e13d81601755714e9fSE Android
1535255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = mls_convert_context(args->oldp, args->newp, c);
1536255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc)
1537255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
1538255e72915d4cbddceb435e13d81601755714e9fSE Android
1539255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Check the validity of the new context. */
1540255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb_context_isvalid(args->newp, c)) {
1541255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = convert_context_handle_invalid_context(&oldc);
1542255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
1543255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad;
1544255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1545255e72915d4cbddceb435e13d81601755714e9fSE Android
1546255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(&oldc);
1547255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1548255e72915d4cbddceb435e13d81601755714e9fSE Android
1549255e72915d4cbddceb435e13d81601755714e9fSE Android      bad:
1550255e72915d4cbddceb435e13d81601755714e9fSE Android	context_to_string(NULL, policydb, &oldc, &s, &len);
1551255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(&oldc);
1552255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(NULL, "invalidating context %s", s);
1553255e72915d4cbddceb435e13d81601755714e9fSE Android	free(s);
1554255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1555255e72915d4cbddceb435e13d81601755714e9fSE Android}
1556255e72915d4cbddceb435e13d81601755714e9fSE Android
1557255e72915d4cbddceb435e13d81601755714e9fSE Android/* Reading from a policy "file". */
1558255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden next_entry(void *buf, struct policy_file *fp, size_t bytes)
1559255e72915d4cbddceb435e13d81601755714e9fSE Android{
1560255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t nread;
1561255e72915d4cbddceb435e13d81601755714e9fSE Android
1562255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (fp->type) {
1563255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_STDIO:
1564255e72915d4cbddceb435e13d81601755714e9fSE Android		nread = fread(buf, bytes, 1, fp->fp);
1565255e72915d4cbddceb435e13d81601755714e9fSE Android
1566255e72915d4cbddceb435e13d81601755714e9fSE Android		if (nread != 1)
1567255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
1568255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1569255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_MEMORY:
1570255e72915d4cbddceb435e13d81601755714e9fSE Android		if (bytes > fp->len)
1571255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
1572255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(buf, fp->data, bytes);
1573255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->data += bytes;
1574255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->len -= bytes;
1575255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1576255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
1577255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
1578255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1579255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1580255e72915d4cbddceb435e13d81601755714e9fSE Android}
1581255e72915d4cbddceb435e13d81601755714e9fSE Android
1582255e72915d4cbddceb435e13d81601755714e9fSE Androidsize_t hidden put_entry(const void *ptr, size_t size, size_t n,
1583255e72915d4cbddceb435e13d81601755714e9fSE Android			struct policy_file *fp)
1584255e72915d4cbddceb435e13d81601755714e9fSE Android{
1585255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t bytes = size * n;
1586255e72915d4cbddceb435e13d81601755714e9fSE Android
1587255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (fp->type) {
1588255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_STDIO:
1589255e72915d4cbddceb435e13d81601755714e9fSE Android		return fwrite(ptr, size, n, fp->fp);
1590255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_MEMORY:
1591255e72915d4cbddceb435e13d81601755714e9fSE Android		if (bytes > fp->len) {
1592255e72915d4cbddceb435e13d81601755714e9fSE Android			errno = ENOSPC;
1593255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
1594255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1595255e72915d4cbddceb435e13d81601755714e9fSE Android
1596255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(fp->data, ptr, bytes);
1597255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->data += bytes;
1598255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->len -= bytes;
1599255e72915d4cbddceb435e13d81601755714e9fSE Android		return n;
1600255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_LEN:
1601255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->len += bytes;
1602255e72915d4cbddceb435e13d81601755714e9fSE Android		return n;
1603255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
1604255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
1605255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1606255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1607255e72915d4cbddceb435e13d81601755714e9fSE Android}
1608255e72915d4cbddceb435e13d81601755714e9fSE Android
1609255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1610255e72915d4cbddceb435e13d81601755714e9fSE Android * Read a new set of configuration data from
1611255e72915d4cbddceb435e13d81601755714e9fSE Android * a policy database binary representation file.
1612255e72915d4cbddceb435e13d81601755714e9fSE Android *
1613255e72915d4cbddceb435e13d81601755714e9fSE Android * Verify that each class that is defined under the
1614255e72915d4cbddceb435e13d81601755714e9fSE Android * existing policy is still defined with the same
1615255e72915d4cbddceb435e13d81601755714e9fSE Android * attributes in the new policy.
1616255e72915d4cbddceb435e13d81601755714e9fSE Android *
1617255e72915d4cbddceb435e13d81601755714e9fSE Android * Convert the context structures in the SID table to the
1618255e72915d4cbddceb435e13d81601755714e9fSE Android * new representation and verify that all entries
1619255e72915d4cbddceb435e13d81601755714e9fSE Android * in the SID table are valid under the new policy.
1620255e72915d4cbddceb435e13d81601755714e9fSE Android *
1621255e72915d4cbddceb435e13d81601755714e9fSE Android * Change the active policy database to use the new
1622255e72915d4cbddceb435e13d81601755714e9fSE Android * configuration data.
1623255e72915d4cbddceb435e13d81601755714e9fSE Android *
1624255e72915d4cbddceb435e13d81601755714e9fSE Android * Reset the access vector cache.
1625255e72915d4cbddceb435e13d81601755714e9fSE Android */
1626255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_load_policy(void *data, size_t len)
1627255e72915d4cbddceb435e13d81601755714e9fSE Android{
1628255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t oldpolicydb, newpolicydb;
1629255e72915d4cbddceb435e13d81601755714e9fSE Android	sidtab_t oldsidtab, newsidtab;
1630255e72915d4cbddceb435e13d81601755714e9fSE Android	convert_context_args_t args;
1631255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1632255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policy_file file, *fp;
1633255e72915d4cbddceb435e13d81601755714e9fSE Android
1634255e72915d4cbddceb435e13d81601755714e9fSE Android	policy_file_init(&file);
1635255e72915d4cbddceb435e13d81601755714e9fSE Android	file.type = PF_USE_MEMORY;
1636255e72915d4cbddceb435e13d81601755714e9fSE Android	file.data = data;
1637255e72915d4cbddceb435e13d81601755714e9fSE Android	file.len = len;
1638255e72915d4cbddceb435e13d81601755714e9fSE Android	fp = &file;
1639255e72915d4cbddceb435e13d81601755714e9fSE Android
1640255e72915d4cbddceb435e13d81601755714e9fSE Android	if (policydb_init(&newpolicydb))
1641255e72915d4cbddceb435e13d81601755714e9fSE Android		return -ENOMEM;
1642255e72915d4cbddceb435e13d81601755714e9fSE Android
1643255e72915d4cbddceb435e13d81601755714e9fSE Android	if (policydb_read(&newpolicydb, fp, 1)) {
1644dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley		policydb_destroy(&mypolicydb);
1645255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
1646255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1647255e72915d4cbddceb435e13d81601755714e9fSE Android
1648255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_init(&newsidtab);
1649255e72915d4cbddceb435e13d81601755714e9fSE Android
1650255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Verify that the existing classes did not change. */
1651255e72915d4cbddceb435e13d81601755714e9fSE Android	if (hashtab_map
1652255e72915d4cbddceb435e13d81601755714e9fSE Android	    (policydb->p_classes.table, validate_class, &newpolicydb)) {
1653255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "the definition of an existing class changed");
1654255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1655255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
1656255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1657255e72915d4cbddceb435e13d81601755714e9fSE Android
1658255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Clone the SID table. */
1659255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_shutdown(sidtab);
1660255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) {
1661255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -ENOMEM;
1662255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
1663255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1664255e72915d4cbddceb435e13d81601755714e9fSE Android
1665255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Convert the internal representations of contexts
1666255e72915d4cbddceb435e13d81601755714e9fSE Android	   in the new SID table and remove invalid SIDs. */
1667255e72915d4cbddceb435e13d81601755714e9fSE Android	args.oldp = policydb;
1668255e72915d4cbddceb435e13d81601755714e9fSE Android	args.newp = &newpolicydb;
1669255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
1670255e72915d4cbddceb435e13d81601755714e9fSE Android
1671255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Save the old policydb and SID table to free later. */
1672255e72915d4cbddceb435e13d81601755714e9fSE Android	memcpy(&oldpolicydb, policydb, sizeof *policydb);
1673255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_set(&oldsidtab, sidtab);
1674255e72915d4cbddceb435e13d81601755714e9fSE Android
1675255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Install the new policydb and SID table. */
1676255e72915d4cbddceb435e13d81601755714e9fSE Android	memcpy(policydb, &newpolicydb, sizeof *policydb);
1677255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_set(sidtab, &newsidtab);
1678255e72915d4cbddceb435e13d81601755714e9fSE Android
1679255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Free the old policydb and SID table. */
1680255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_destroy(&oldpolicydb);
1681255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_destroy(&oldsidtab);
1682255e72915d4cbddceb435e13d81601755714e9fSE Android
1683255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
1684255e72915d4cbddceb435e13d81601755714e9fSE Android
1685255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
1686255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_sidtab_destroy(&newsidtab);
1687255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_destroy(&newpolicydb);
1688255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1689255e72915d4cbddceb435e13d81601755714e9fSE Android
1690255e72915d4cbddceb435e13d81601755714e9fSE Android}
1691255e72915d4cbddceb435e13d81601755714e9fSE Android
1692255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1693255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the SIDs to use for an unlabeled file system
1694255e72915d4cbddceb435e13d81601755714e9fSE Android * that is being mounted from the device with the
1695255e72915d4cbddceb435e13d81601755714e9fSE Android * the kdevname `name'.  The `fs_sid' SID is returned for
1696255e72915d4cbddceb435e13d81601755714e9fSE Android * the file system and the `file_sid' SID is returned
1697255e72915d4cbddceb435e13d81601755714e9fSE Android * for all files within that file system.
1698255e72915d4cbddceb435e13d81601755714e9fSE Android */
1699255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_fs_sid(char *name,
1700255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_security_id_t * fs_sid,
1701255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_security_id_t * file_sid)
1702255e72915d4cbddceb435e13d81601755714e9fSE Android{
1703255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1704255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
1705255e72915d4cbddceb435e13d81601755714e9fSE Android
1706255e72915d4cbddceb435e13d81601755714e9fSE Android	c = policydb->ocontexts[OCON_FS];
1707255e72915d4cbddceb435e13d81601755714e9fSE Android	while (c) {
1708255e72915d4cbddceb435e13d81601755714e9fSE Android		if (strcmp(c->u.name, name) == 0)
1709255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
1710255e72915d4cbddceb435e13d81601755714e9fSE Android		c = c->next;
1711255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1712255e72915d4cbddceb435e13d81601755714e9fSE Android
1713255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c) {
1714255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->sid[0] || !c->sid[1]) {
1715255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1716255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[0],
1717255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[0]);
1718255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1719255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1720255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1721255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[1],
1722255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[1]);
1723255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1724255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1725255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1726255e72915d4cbddceb435e13d81601755714e9fSE Android		*fs_sid = c->sid[0];
1727255e72915d4cbddceb435e13d81601755714e9fSE Android		*file_sid = c->sid[1];
1728255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1729255e72915d4cbddceb435e13d81601755714e9fSE Android		*fs_sid = SECINITSID_FS;
1730255e72915d4cbddceb435e13d81601755714e9fSE Android		*file_sid = SECINITSID_FILE;
1731255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1732255e72915d4cbddceb435e13d81601755714e9fSE Android
1733255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1734255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1735255e72915d4cbddceb435e13d81601755714e9fSE Android}
1736255e72915d4cbddceb435e13d81601755714e9fSE Android
1737255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1738255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the SID of the port specified by
1739255e72915d4cbddceb435e13d81601755714e9fSE Android * `domain', `type', `protocol', and `port'.
1740255e72915d4cbddceb435e13d81601755714e9fSE Android */
1741255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)),
1742255e72915d4cbddceb435e13d81601755714e9fSE Android			  uint16_t type __attribute__ ((unused)),
1743255e72915d4cbddceb435e13d81601755714e9fSE Android			  uint8_t protocol,
1744255e72915d4cbddceb435e13d81601755714e9fSE Android			  uint16_t port, sepol_security_id_t * out_sid)
1745255e72915d4cbddceb435e13d81601755714e9fSE Android{
1746255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
1747255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1748255e72915d4cbddceb435e13d81601755714e9fSE Android
1749255e72915d4cbddceb435e13d81601755714e9fSE Android	c = policydb->ocontexts[OCON_PORT];
1750255e72915d4cbddceb435e13d81601755714e9fSE Android	while (c) {
1751255e72915d4cbddceb435e13d81601755714e9fSE Android		if (c->u.port.protocol == protocol &&
1752255e72915d4cbddceb435e13d81601755714e9fSE Android		    c->u.port.low_port <= port && c->u.port.high_port >= port)
1753255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
1754255e72915d4cbddceb435e13d81601755714e9fSE Android		c = c->next;
1755255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1756255e72915d4cbddceb435e13d81601755714e9fSE Android
1757255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c) {
1758255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->sid[0]) {
1759255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1760255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[0],
1761255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[0]);
1762255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1763255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1764255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1765255e72915d4cbddceb435e13d81601755714e9fSE Android		*out_sid = c->sid[0];
1766255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1767255e72915d4cbddceb435e13d81601755714e9fSE Android		*out_sid = SECINITSID_PORT;
1768255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1769255e72915d4cbddceb435e13d81601755714e9fSE Android
1770255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1771255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1772255e72915d4cbddceb435e13d81601755714e9fSE Android}
1773255e72915d4cbddceb435e13d81601755714e9fSE Android
1774255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1775255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the SIDs to use for a network interface
1776255e72915d4cbddceb435e13d81601755714e9fSE Android * with the name `name'.  The `if_sid' SID is returned for
1777255e72915d4cbddceb435e13d81601755714e9fSE Android * the interface and the `msg_sid' SID is returned as
1778255e72915d4cbddceb435e13d81601755714e9fSE Android * the default SID for messages received on the
1779255e72915d4cbddceb435e13d81601755714e9fSE Android * interface.
1780255e72915d4cbddceb435e13d81601755714e9fSE Android */
1781255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_netif_sid(char *name,
1782255e72915d4cbddceb435e13d81601755714e9fSE Android			   sepol_security_id_t * if_sid,
1783255e72915d4cbddceb435e13d81601755714e9fSE Android			   sepol_security_id_t * msg_sid)
1784255e72915d4cbddceb435e13d81601755714e9fSE Android{
1785255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1786255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
1787255e72915d4cbddceb435e13d81601755714e9fSE Android
1788255e72915d4cbddceb435e13d81601755714e9fSE Android	c = policydb->ocontexts[OCON_NETIF];
1789255e72915d4cbddceb435e13d81601755714e9fSE Android	while (c) {
1790255e72915d4cbddceb435e13d81601755714e9fSE Android		if (strcmp(name, c->u.name) == 0)
1791255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
1792255e72915d4cbddceb435e13d81601755714e9fSE Android		c = c->next;
1793255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1794255e72915d4cbddceb435e13d81601755714e9fSE Android
1795255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c) {
1796255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->sid[0] || !c->sid[1]) {
1797255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1798255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[0],
1799255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[0]);
1800255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1801255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1802255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1803255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[1],
1804255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[1]);
1805255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1806255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1807255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1808255e72915d4cbddceb435e13d81601755714e9fSE Android		*if_sid = c->sid[0];
1809255e72915d4cbddceb435e13d81601755714e9fSE Android		*msg_sid = c->sid[1];
1810255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1811255e72915d4cbddceb435e13d81601755714e9fSE Android		*if_sid = SECINITSID_NETIF;
1812255e72915d4cbddceb435e13d81601755714e9fSE Android		*msg_sid = SECINITSID_NETMSG;
1813255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1814255e72915d4cbddceb435e13d81601755714e9fSE Android
1815255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1816255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1817255e72915d4cbddceb435e13d81601755714e9fSE Android}
1818255e72915d4cbddceb435e13d81601755714e9fSE Android
1819255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int match_ipv6_addrmask(uint32_t * input, uint32_t * addr,
1820255e72915d4cbddceb435e13d81601755714e9fSE Android			       uint32_t * mask)
1821255e72915d4cbddceb435e13d81601755714e9fSE Android{
1822255e72915d4cbddceb435e13d81601755714e9fSE Android	int i, fail = 0;
1823255e72915d4cbddceb435e13d81601755714e9fSE Android
1824255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < 4; i++)
1825255e72915d4cbddceb435e13d81601755714e9fSE Android		if (addr[i] != (input[i] & mask[i])) {
1826255e72915d4cbddceb435e13d81601755714e9fSE Android			fail = 1;
1827255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
1828255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1829255e72915d4cbddceb435e13d81601755714e9fSE Android
1830255e72915d4cbddceb435e13d81601755714e9fSE Android	return !fail;
1831255e72915d4cbddceb435e13d81601755714e9fSE Android}
1832255e72915d4cbddceb435e13d81601755714e9fSE Android
1833255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1834255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the SID of the node specified by the address
1835255e72915d4cbddceb435e13d81601755714e9fSE Android * `addrp' where `addrlen' is the length of the address
1836255e72915d4cbddceb435e13d81601755714e9fSE Android * in bytes and `domain' is the communications domain or
1837255e72915d4cbddceb435e13d81601755714e9fSE Android * address family in which the address should be interpreted.
1838255e72915d4cbddceb435e13d81601755714e9fSE Android */
1839255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_node_sid(uint16_t domain,
1840255e72915d4cbddceb435e13d81601755714e9fSE Android			  void *addrp,
1841255e72915d4cbddceb435e13d81601755714e9fSE Android			  size_t addrlen, sepol_security_id_t * out_sid)
1842255e72915d4cbddceb435e13d81601755714e9fSE Android{
1843255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1844255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
1845255e72915d4cbddceb435e13d81601755714e9fSE Android
1846255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (domain) {
1847255e72915d4cbddceb435e13d81601755714e9fSE Android	case AF_INET:{
1848255e72915d4cbddceb435e13d81601755714e9fSE Android			uint32_t addr;
1849255e72915d4cbddceb435e13d81601755714e9fSE Android
1850255e72915d4cbddceb435e13d81601755714e9fSE Android			if (addrlen != sizeof(uint32_t)) {
1851255e72915d4cbddceb435e13d81601755714e9fSE Android				rc = -EINVAL;
1852255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1853255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1854255e72915d4cbddceb435e13d81601755714e9fSE Android
1855255e72915d4cbddceb435e13d81601755714e9fSE Android			addr = *((uint32_t *) addrp);
1856255e72915d4cbddceb435e13d81601755714e9fSE Android
1857255e72915d4cbddceb435e13d81601755714e9fSE Android			c = policydb->ocontexts[OCON_NODE];
1858255e72915d4cbddceb435e13d81601755714e9fSE Android			while (c) {
1859255e72915d4cbddceb435e13d81601755714e9fSE Android				if (c->u.node.addr == (addr & c->u.node.mask))
1860255e72915d4cbddceb435e13d81601755714e9fSE Android					break;
1861255e72915d4cbddceb435e13d81601755714e9fSE Android				c = c->next;
1862255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1863255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
1864255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1865255e72915d4cbddceb435e13d81601755714e9fSE Android
1866255e72915d4cbddceb435e13d81601755714e9fSE Android	case AF_INET6:
1867255e72915d4cbddceb435e13d81601755714e9fSE Android		if (addrlen != sizeof(uint64_t) * 2) {
1868255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = -EINVAL;
1869255e72915d4cbddceb435e13d81601755714e9fSE Android			goto out;
1870255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1871255e72915d4cbddceb435e13d81601755714e9fSE Android
1872255e72915d4cbddceb435e13d81601755714e9fSE Android		c = policydb->ocontexts[OCON_NODE6];
1873255e72915d4cbddceb435e13d81601755714e9fSE Android		while (c) {
1874255e72915d4cbddceb435e13d81601755714e9fSE Android			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
1875255e72915d4cbddceb435e13d81601755714e9fSE Android						c->u.node6.mask))
1876255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
1877255e72915d4cbddceb435e13d81601755714e9fSE Android			c = c->next;
1878255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1879255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
1880255e72915d4cbddceb435e13d81601755714e9fSE Android
1881255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
1882255e72915d4cbddceb435e13d81601755714e9fSE Android		*out_sid = SECINITSID_NODE;
1883255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1884255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1885255e72915d4cbddceb435e13d81601755714e9fSE Android
1886255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c) {
1887255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->sid[0]) {
1888255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
1889255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[0],
1890255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[0]);
1891255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
1892255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1893255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1894255e72915d4cbddceb435e13d81601755714e9fSE Android		*out_sid = c->sid[0];
1895255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
1896255e72915d4cbddceb435e13d81601755714e9fSE Android		*out_sid = SECINITSID_NODE;
1897255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1898255e72915d4cbddceb435e13d81601755714e9fSE Android
1899255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
1900255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
1901255e72915d4cbddceb435e13d81601755714e9fSE Android}
1902255e72915d4cbddceb435e13d81601755714e9fSE Android
1903255e72915d4cbddceb435e13d81601755714e9fSE Android/*
1904255e72915d4cbddceb435e13d81601755714e9fSE Android * Generate the set of SIDs for legal security contexts
1905255e72915d4cbddceb435e13d81601755714e9fSE Android * for a given user that can be reached by `fromsid'.
1906255e72915d4cbddceb435e13d81601755714e9fSE Android * Set `*sids' to point to a dynamically allocated
1907255e72915d4cbddceb435e13d81601755714e9fSE Android * array containing the set of SIDs.  Set `*nel' to the
1908255e72915d4cbddceb435e13d81601755714e9fSE Android * number of elements in the array.
1909255e72915d4cbddceb435e13d81601755714e9fSE Android */
1910255e72915d4cbddceb435e13d81601755714e9fSE Android#define SIDS_NEL 25
1911255e72915d4cbddceb435e13d81601755714e9fSE Android
1912255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_get_user_sids(sepol_security_id_t fromsid,
1913255e72915d4cbddceb435e13d81601755714e9fSE Android			       char *username,
1914255e72915d4cbddceb435e13d81601755714e9fSE Android			       sepol_security_id_t ** sids, uint32_t * nel)
1915255e72915d4cbddceb435e13d81601755714e9fSE Android{
1916255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *fromcon, usercon;
1917255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_security_id_t *mysids, *mysids2, sid;
1918255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t mynel = 0, maxnel = SIDS_NEL;
1919255e72915d4cbddceb435e13d81601755714e9fSE Android	user_datum_t *user;
1920255e72915d4cbddceb435e13d81601755714e9fSE Android	role_datum_t *role;
1921255e72915d4cbddceb435e13d81601755714e9fSE Android	struct sepol_av_decision avd;
1922255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
1923255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, j, reason;
1924255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *rnode, *tnode;
1925255e72915d4cbddceb435e13d81601755714e9fSE Android
1926255e72915d4cbddceb435e13d81601755714e9fSE Android	fromcon = sepol_sidtab_search(sidtab, fromsid);
1927255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!fromcon) {
1928255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1929255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1930255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1931255e72915d4cbddceb435e13d81601755714e9fSE Android
1932255e72915d4cbddceb435e13d81601755714e9fSE Android	user = (user_datum_t *) hashtab_search(policydb->p_users.table,
1933255e72915d4cbddceb435e13d81601755714e9fSE Android					       username);
1934255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!user) {
1935255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
1936255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1937255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1938255e72915d4cbddceb435e13d81601755714e9fSE Android	usercon.user = user->s.value;
1939255e72915d4cbddceb435e13d81601755714e9fSE Android
1940255e72915d4cbddceb435e13d81601755714e9fSE Android	mysids = malloc(maxnel * sizeof(sepol_security_id_t));
1941255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!mysids) {
1942255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -ENOMEM;
1943255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
1944255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1945255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(mysids, 0, maxnel * sizeof(sepol_security_id_t));
1946255e72915d4cbddceb435e13d81601755714e9fSE Android
1947255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_for_each_bit(&user->roles.roles, rnode, i) {
1948255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!ebitmap_node_get_bit(rnode, i))
1949255e72915d4cbddceb435e13d81601755714e9fSE Android			continue;
1950255e72915d4cbddceb435e13d81601755714e9fSE Android		role = policydb->role_val_to_struct[i];
1951255e72915d4cbddceb435e13d81601755714e9fSE Android		usercon.role = i + 1;
1952255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(&role->types.types, tnode, j) {
1953255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!ebitmap_node_get_bit(tnode, j))
1954255e72915d4cbddceb435e13d81601755714e9fSE Android				continue;
1955255e72915d4cbddceb435e13d81601755714e9fSE Android			usercon.type = j + 1;
1956255e72915d4cbddceb435e13d81601755714e9fSE Android			if (usercon.type == fromcon->type)
1957255e72915d4cbddceb435e13d81601755714e9fSE Android				continue;
1958255e72915d4cbddceb435e13d81601755714e9fSE Android
1959255e72915d4cbddceb435e13d81601755714e9fSE Android			if (mls_setup_user_range
1960255e72915d4cbddceb435e13d81601755714e9fSE Android			    (fromcon, user, &usercon, policydb->mls))
1961255e72915d4cbddceb435e13d81601755714e9fSE Android				continue;
1962255e72915d4cbddceb435e13d81601755714e9fSE Android
1963255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = context_struct_compute_av(fromcon, &usercon,
1964255e72915d4cbddceb435e13d81601755714e9fSE Android						       SECCLASS_PROCESS,
1965255e72915d4cbddceb435e13d81601755714e9fSE Android						       PROCESS__TRANSITION,
1966dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley						       &avd, &reason, NULL, 0);
1967255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc || !(avd.allowed & PROCESS__TRANSITION))
1968255e72915d4cbddceb435e13d81601755714e9fSE Android				continue;
1969255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
1970255e72915d4cbddceb435e13d81601755714e9fSE Android							 &sid);
1971255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc) {
1972255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mysids);
1973255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
1974255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1975255e72915d4cbddceb435e13d81601755714e9fSE Android			if (mynel < maxnel) {
1976255e72915d4cbddceb435e13d81601755714e9fSE Android				mysids[mynel++] = sid;
1977255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
1978255e72915d4cbddceb435e13d81601755714e9fSE Android				maxnel += SIDS_NEL;
1979255e72915d4cbddceb435e13d81601755714e9fSE Android				mysids2 =
1980255e72915d4cbddceb435e13d81601755714e9fSE Android				    malloc(maxnel *
1981255e72915d4cbddceb435e13d81601755714e9fSE Android					   sizeof(sepol_security_id_t));
1982255e72915d4cbddceb435e13d81601755714e9fSE Android
1983255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!mysids2) {
1984255e72915d4cbddceb435e13d81601755714e9fSE Android					rc = -ENOMEM;
1985255e72915d4cbddceb435e13d81601755714e9fSE Android					free(mysids);
1986255e72915d4cbddceb435e13d81601755714e9fSE Android					goto out;
1987255e72915d4cbddceb435e13d81601755714e9fSE Android				}
1988255e72915d4cbddceb435e13d81601755714e9fSE Android				memset(mysids2, 0,
1989255e72915d4cbddceb435e13d81601755714e9fSE Android				       maxnel * sizeof(sepol_security_id_t));
1990255e72915d4cbddceb435e13d81601755714e9fSE Android				memcpy(mysids2, mysids,
1991255e72915d4cbddceb435e13d81601755714e9fSE Android				       mynel * sizeof(sepol_security_id_t));
1992255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mysids);
1993255e72915d4cbddceb435e13d81601755714e9fSE Android				mysids = mysids2;
1994255e72915d4cbddceb435e13d81601755714e9fSE Android				mysids[mynel++] = sid;
1995255e72915d4cbddceb435e13d81601755714e9fSE Android			}
1996255e72915d4cbddceb435e13d81601755714e9fSE Android		}
1997255e72915d4cbddceb435e13d81601755714e9fSE Android	}
1998255e72915d4cbddceb435e13d81601755714e9fSE Android
1999255e72915d4cbddceb435e13d81601755714e9fSE Android	*sids = mysids;
2000255e72915d4cbddceb435e13d81601755714e9fSE Android	*nel = mynel;
2001255e72915d4cbddceb435e13d81601755714e9fSE Android
2002255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
2003255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
2004255e72915d4cbddceb435e13d81601755714e9fSE Android}
2005255e72915d4cbddceb435e13d81601755714e9fSE Android
2006255e72915d4cbddceb435e13d81601755714e9fSE Android/*
2007255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the SID to use for a file in a filesystem
2008255e72915d4cbddceb435e13d81601755714e9fSE Android * that cannot support a persistent label mapping or use another
2009255e72915d4cbddceb435e13d81601755714e9fSE Android * fixed labeling behavior like transition SIDs or task SIDs.
2010255e72915d4cbddceb435e13d81601755714e9fSE Android */
2011255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_genfs_sid(const char *fstype,
2012255e72915d4cbddceb435e13d81601755714e9fSE Android			   char *path,
2013255e72915d4cbddceb435e13d81601755714e9fSE Android			   sepol_security_class_t sclass,
2014255e72915d4cbddceb435e13d81601755714e9fSE Android			   sepol_security_id_t * sid)
2015255e72915d4cbddceb435e13d81601755714e9fSE Android{
2016255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t len;
2017255e72915d4cbddceb435e13d81601755714e9fSE Android	genfs_t *genfs;
2018255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
2019255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0, cmp = 0;
2020255e72915d4cbddceb435e13d81601755714e9fSE Android
2021255e72915d4cbddceb435e13d81601755714e9fSE Android	for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
2022255e72915d4cbddceb435e13d81601755714e9fSE Android		cmp = strcmp(fstype, genfs->fstype);
2023255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cmp <= 0)
2024255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
2025255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2026255e72915d4cbddceb435e13d81601755714e9fSE Android
2027255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!genfs || cmp) {
2028255e72915d4cbddceb435e13d81601755714e9fSE Android		*sid = SECINITSID_UNLABELED;
2029255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -ENOENT;
2030255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
2031255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2032255e72915d4cbddceb435e13d81601755714e9fSE Android
2033255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = genfs->head; c; c = c->next) {
2034255e72915d4cbddceb435e13d81601755714e9fSE Android		len = strlen(c->u.name);
2035255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((!c->v.sclass || sclass == c->v.sclass) &&
2036255e72915d4cbddceb435e13d81601755714e9fSE Android		    (strncmp(c->u.name, path, len) == 0))
2037255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
2038255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2039255e72915d4cbddceb435e13d81601755714e9fSE Android
2040255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!c) {
2041255e72915d4cbddceb435e13d81601755714e9fSE Android		*sid = SECINITSID_UNLABELED;
2042255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -ENOENT;
2043255e72915d4cbddceb435e13d81601755714e9fSE Android		goto out;
2044255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2045255e72915d4cbddceb435e13d81601755714e9fSE Android
2046255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!c->sid[0]) {
2047255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = sepol_sidtab_context_to_sid(sidtab,
2048255e72915d4cbddceb435e13d81601755714e9fSE Android						 &c->context[0], &c->sid[0]);
2049255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
2050255e72915d4cbddceb435e13d81601755714e9fSE Android			goto out;
2051255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2052255e72915d4cbddceb435e13d81601755714e9fSE Android
2053255e72915d4cbddceb435e13d81601755714e9fSE Android	*sid = c->sid[0];
2054255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
2055255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
2056255e72915d4cbddceb435e13d81601755714e9fSE Android}
2057255e72915d4cbddceb435e13d81601755714e9fSE Android
2058255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_fs_use(const char *fstype,
2059255e72915d4cbddceb435e13d81601755714e9fSE Android			unsigned int *behavior, sepol_security_id_t * sid)
2060255e72915d4cbddceb435e13d81601755714e9fSE Android{
2061255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc = 0;
2062255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c;
2063255e72915d4cbddceb435e13d81601755714e9fSE Android
2064255e72915d4cbddceb435e13d81601755714e9fSE Android	c = policydb->ocontexts[OCON_FSUSE];
2065255e72915d4cbddceb435e13d81601755714e9fSE Android	while (c) {
2066255e72915d4cbddceb435e13d81601755714e9fSE Android		if (strcmp(fstype, c->u.name) == 0)
2067255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
2068255e72915d4cbddceb435e13d81601755714e9fSE Android		c = c->next;
2069255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2070255e72915d4cbddceb435e13d81601755714e9fSE Android
2071255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c) {
2072255e72915d4cbddceb435e13d81601755714e9fSE Android		*behavior = c->v.behavior;
2073255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->sid[0]) {
2074255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = sepol_sidtab_context_to_sid(sidtab,
2075255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->context[0],
2076255e72915d4cbddceb435e13d81601755714e9fSE Android							 &c->sid[0]);
2077255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc)
2078255e72915d4cbddceb435e13d81601755714e9fSE Android				goto out;
2079255e72915d4cbddceb435e13d81601755714e9fSE Android		}
2080255e72915d4cbddceb435e13d81601755714e9fSE Android		*sid = c->sid[0];
2081255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
2082255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
2083255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc) {
2084255e72915d4cbddceb435e13d81601755714e9fSE Android			*behavior = SECURITY_FS_USE_NONE;
2085255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = 0;
2086255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
2087255e72915d4cbddceb435e13d81601755714e9fSE Android			*behavior = SECURITY_FS_USE_GENFS;
2088255e72915d4cbddceb435e13d81601755714e9fSE Android		}
2089255e72915d4cbddceb435e13d81601755714e9fSE Android	}
2090255e72915d4cbddceb435e13d81601755714e9fSE Android
2091255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
2092255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
2093255e72915d4cbddceb435e13d81601755714e9fSE Android}
2094255e72915d4cbddceb435e13d81601755714e9fSE Android
2095255e72915d4cbddceb435e13d81601755714e9fSE Android/* FLASK */
2096