xref: /aosp_15_r20/external/selinux/libselinux/src/avc.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * Implementation of the userspace access vector cache (AVC).
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Author : Eamon Walsh <[email protected]>
5*2d543d20SAndroid Build Coastguard Worker  *
6*2d543d20SAndroid Build Coastguard Worker  * Derived from the kernel AVC implementation by
7*2d543d20SAndroid Build Coastguard Worker  * Stephen Smalley <[email protected]> and
8*2d543d20SAndroid Build Coastguard Worker  * James Morris <[email protected]>.
9*2d543d20SAndroid Build Coastguard Worker  */
10*2d543d20SAndroid Build Coastguard Worker #include <selinux/avc.h>
11*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
12*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
13*2d543d20SAndroid Build Coastguard Worker #include "avc_sidtab.h"
14*2d543d20SAndroid Build Coastguard Worker #include "avc_internal.h"
15*2d543d20SAndroid Build Coastguard Worker 
16*2d543d20SAndroid Build Coastguard Worker #define AVC_CACHE_SLOTS		512
17*2d543d20SAndroid Build Coastguard Worker #define AVC_CACHE_MAXNODES	410
18*2d543d20SAndroid Build Coastguard Worker 
19*2d543d20SAndroid Build Coastguard Worker struct avc_entry {
20*2d543d20SAndroid Build Coastguard Worker 	security_id_t ssid;
21*2d543d20SAndroid Build Coastguard Worker 	security_id_t tsid;
22*2d543d20SAndroid Build Coastguard Worker 	security_class_t tclass;
23*2d543d20SAndroid Build Coastguard Worker 	struct av_decision avd;
24*2d543d20SAndroid Build Coastguard Worker 	security_id_t	create_sid;
25*2d543d20SAndroid Build Coastguard Worker 	int used;		/* used recently */
26*2d543d20SAndroid Build Coastguard Worker };
27*2d543d20SAndroid Build Coastguard Worker 
28*2d543d20SAndroid Build Coastguard Worker struct avc_node {
29*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry ae;
30*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *next;
31*2d543d20SAndroid Build Coastguard Worker };
32*2d543d20SAndroid Build Coastguard Worker 
33*2d543d20SAndroid Build Coastguard Worker struct avc_cache {
34*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *slots[AVC_CACHE_SLOTS];
35*2d543d20SAndroid Build Coastguard Worker 	uint32_t lru_hint;	/* LRU hint for reclaim scan */
36*2d543d20SAndroid Build Coastguard Worker 	uint32_t active_nodes;
37*2d543d20SAndroid Build Coastguard Worker 	uint32_t latest_notif;	/* latest revocation notification */
38*2d543d20SAndroid Build Coastguard Worker };
39*2d543d20SAndroid Build Coastguard Worker 
40*2d543d20SAndroid Build Coastguard Worker struct avc_callback_node {
41*2d543d20SAndroid Build Coastguard Worker 	int (*callback) (uint32_t event, security_id_t ssid,
42*2d543d20SAndroid Build Coastguard Worker 			 security_id_t tsid,
43*2d543d20SAndroid Build Coastguard Worker 			 security_class_t tclass, access_vector_t perms,
44*2d543d20SAndroid Build Coastguard Worker 			 access_vector_t * out_retained);
45*2d543d20SAndroid Build Coastguard Worker 	uint32_t events;
46*2d543d20SAndroid Build Coastguard Worker 	security_id_t ssid;
47*2d543d20SAndroid Build Coastguard Worker 	security_id_t tsid;
48*2d543d20SAndroid Build Coastguard Worker 	security_class_t tclass;
49*2d543d20SAndroid Build Coastguard Worker 	access_vector_t perms;
50*2d543d20SAndroid Build Coastguard Worker 	struct avc_callback_node *next;
51*2d543d20SAndroid Build Coastguard Worker };
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker static void *avc_lock = NULL;
54*2d543d20SAndroid Build Coastguard Worker static void *avc_log_lock = NULL;
55*2d543d20SAndroid Build Coastguard Worker static struct avc_node *avc_node_freelist = NULL;
56*2d543d20SAndroid Build Coastguard Worker static struct avc_cache avc_cache;
57*2d543d20SAndroid Build Coastguard Worker static char *avc_audit_buf = NULL;
58*2d543d20SAndroid Build Coastguard Worker static struct avc_cache_stats cache_stats;
59*2d543d20SAndroid Build Coastguard Worker static struct avc_callback_node *avc_callbacks = NULL;
60*2d543d20SAndroid Build Coastguard Worker static struct sidtab avc_sidtab;
61*2d543d20SAndroid Build Coastguard Worker 
avc_hash(security_id_t ssid,security_id_t tsid,security_class_t tclass)62*2d543d20SAndroid Build Coastguard Worker static inline int avc_hash(security_id_t ssid,
63*2d543d20SAndroid Build Coastguard Worker 			   security_id_t tsid, security_class_t tclass)
64*2d543d20SAndroid Build Coastguard Worker {
65*2d543d20SAndroid Build Coastguard Worker 	return ((uintptr_t) ssid ^ ((uintptr_t) tsid << 2) ^ tclass)
66*2d543d20SAndroid Build Coastguard Worker 	    & (AVC_CACHE_SLOTS - 1);
67*2d543d20SAndroid Build Coastguard Worker }
68*2d543d20SAndroid Build Coastguard Worker 
avc_context_to_sid_raw(const char * ctx,security_id_t * sid)69*2d543d20SAndroid Build Coastguard Worker int avc_context_to_sid_raw(const char * ctx, security_id_t * sid)
70*2d543d20SAndroid Build Coastguard Worker {
71*2d543d20SAndroid Build Coastguard Worker 	int rc;
72*2d543d20SAndroid Build Coastguard Worker 	/* avc_init needs to be called before this function */
73*2d543d20SAndroid Build Coastguard Worker 	assert(avc_running);
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
76*2d543d20SAndroid Build Coastguard Worker 	rc = sidtab_context_to_sid(&avc_sidtab, ctx, sid);
77*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
78*2d543d20SAndroid Build Coastguard Worker 	return rc;
79*2d543d20SAndroid Build Coastguard Worker }
80*2d543d20SAndroid Build Coastguard Worker 
avc_context_to_sid(const char * ctx,security_id_t * sid)81*2d543d20SAndroid Build Coastguard Worker int avc_context_to_sid(const char * ctx, security_id_t * sid)
82*2d543d20SAndroid Build Coastguard Worker {
83*2d543d20SAndroid Build Coastguard Worker 	int ret;
84*2d543d20SAndroid Build Coastguard Worker 	char * rctx;
85*2d543d20SAndroid Build Coastguard Worker 
86*2d543d20SAndroid Build Coastguard Worker 	if (selinux_trans_to_raw_context(ctx, &rctx))
87*2d543d20SAndroid Build Coastguard Worker 		return -1;
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	ret = avc_context_to_sid_raw(rctx, sid);
90*2d543d20SAndroid Build Coastguard Worker 
91*2d543d20SAndroid Build Coastguard Worker 	freecon(rctx);
92*2d543d20SAndroid Build Coastguard Worker 
93*2d543d20SAndroid Build Coastguard Worker 	return ret;
94*2d543d20SAndroid Build Coastguard Worker }
95*2d543d20SAndroid Build Coastguard Worker 
avc_sid_to_context_raw(security_id_t sid,char ** ctx)96*2d543d20SAndroid Build Coastguard Worker int avc_sid_to_context_raw(security_id_t sid, char ** ctx)
97*2d543d20SAndroid Build Coastguard Worker {
98*2d543d20SAndroid Build Coastguard Worker 	int rc;
99*2d543d20SAndroid Build Coastguard Worker 	*ctx = NULL;
100*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
101*2d543d20SAndroid Build Coastguard Worker 	*ctx = strdup(sid->ctx);	/* caller must free via freecon */
102*2d543d20SAndroid Build Coastguard Worker 	rc = *ctx ? 0 : -1;
103*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
104*2d543d20SAndroid Build Coastguard Worker 	return rc;
105*2d543d20SAndroid Build Coastguard Worker }
106*2d543d20SAndroid Build Coastguard Worker 
avc_sid_to_context(security_id_t sid,char ** ctx)107*2d543d20SAndroid Build Coastguard Worker int avc_sid_to_context(security_id_t sid, char ** ctx)
108*2d543d20SAndroid Build Coastguard Worker {
109*2d543d20SAndroid Build Coastguard Worker 	int ret;
110*2d543d20SAndroid Build Coastguard Worker 	char * rctx;
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker 	ret = avc_sid_to_context_raw(sid, &rctx);
113*2d543d20SAndroid Build Coastguard Worker 
114*2d543d20SAndroid Build Coastguard Worker 	if (ret == 0) {
115*2d543d20SAndroid Build Coastguard Worker 		ret = selinux_raw_to_trans_context(rctx, ctx);
116*2d543d20SAndroid Build Coastguard Worker 		freecon(rctx);
117*2d543d20SAndroid Build Coastguard Worker 	}
118*2d543d20SAndroid Build Coastguard Worker 
119*2d543d20SAndroid Build Coastguard Worker 	return ret;
120*2d543d20SAndroid Build Coastguard Worker }
121*2d543d20SAndroid Build Coastguard Worker 
sidget(security_id_t sid)122*2d543d20SAndroid Build Coastguard Worker int sidget(security_id_t sid __attribute__((unused)))
123*2d543d20SAndroid Build Coastguard Worker {
124*2d543d20SAndroid Build Coastguard Worker 	return 1;
125*2d543d20SAndroid Build Coastguard Worker }
126*2d543d20SAndroid Build Coastguard Worker 
sidput(security_id_t sid)127*2d543d20SAndroid Build Coastguard Worker int sidput(security_id_t sid __attribute__((unused)))
128*2d543d20SAndroid Build Coastguard Worker {
129*2d543d20SAndroid Build Coastguard Worker 	return 1;
130*2d543d20SAndroid Build Coastguard Worker }
131*2d543d20SAndroid Build Coastguard Worker 
avc_get_initial_sid(const char * name,security_id_t * sid)132*2d543d20SAndroid Build Coastguard Worker int avc_get_initial_sid(const char * name, security_id_t * sid)
133*2d543d20SAndroid Build Coastguard Worker {
134*2d543d20SAndroid Build Coastguard Worker 	int rc;
135*2d543d20SAndroid Build Coastguard Worker 	char * con;
136*2d543d20SAndroid Build Coastguard Worker 
137*2d543d20SAndroid Build Coastguard Worker 	rc = security_get_initial_context_raw(name, &con);
138*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
139*2d543d20SAndroid Build Coastguard Worker 		return rc;
140*2d543d20SAndroid Build Coastguard Worker 	rc = avc_context_to_sid_raw(con, sid);
141*2d543d20SAndroid Build Coastguard Worker 
142*2d543d20SAndroid Build Coastguard Worker 	freecon(con);
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 	return rc;
145*2d543d20SAndroid Build Coastguard Worker }
146*2d543d20SAndroid Build Coastguard Worker 
avc_init_internal(const char * prefix,const struct avc_memory_callback * mem_cb,const struct avc_log_callback * log_cb,const struct avc_thread_callback * thread_cb,const struct avc_lock_callback * lock_cb)147*2d543d20SAndroid Build Coastguard Worker static int avc_init_internal(const char *prefix,
148*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_memory_callback *mem_cb,
149*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_log_callback *log_cb,
150*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_thread_callback *thread_cb,
151*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_lock_callback *lock_cb)
152*2d543d20SAndroid Build Coastguard Worker {
153*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *new;
154*2d543d20SAndroid Build Coastguard Worker 	int i, rc = 0;
155*2d543d20SAndroid Build Coastguard Worker 
156*2d543d20SAndroid Build Coastguard Worker 	if (avc_running)
157*2d543d20SAndroid Build Coastguard Worker 		return 0;
158*2d543d20SAndroid Build Coastguard Worker 
159*2d543d20SAndroid Build Coastguard Worker 	if (prefix)
160*2d543d20SAndroid Build Coastguard Worker 		strncpy(avc_prefix, prefix, AVC_PREFIX_SIZE - 1);
161*2d543d20SAndroid Build Coastguard Worker 
162*2d543d20SAndroid Build Coastguard Worker 	set_callbacks(mem_cb, log_cb, thread_cb, lock_cb);
163*2d543d20SAndroid Build Coastguard Worker 
164*2d543d20SAndroid Build Coastguard Worker 	avc_lock = avc_alloc_lock();
165*2d543d20SAndroid Build Coastguard Worker 	avc_log_lock = avc_alloc_lock();
166*2d543d20SAndroid Build Coastguard Worker 
167*2d543d20SAndroid Build Coastguard Worker 	memset(&cache_stats, 0, sizeof(cache_stats));
168*2d543d20SAndroid Build Coastguard Worker 
169*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < AVC_CACHE_SLOTS; i++)
170*2d543d20SAndroid Build Coastguard Worker 		avc_cache.slots[i] = 0;
171*2d543d20SAndroid Build Coastguard Worker 	avc_cache.lru_hint = 0;
172*2d543d20SAndroid Build Coastguard Worker 	avc_cache.active_nodes = 0;
173*2d543d20SAndroid Build Coastguard Worker 	avc_cache.latest_notif = 0;
174*2d543d20SAndroid Build Coastguard Worker 
175*2d543d20SAndroid Build Coastguard Worker 	rc = sidtab_init(&avc_sidtab);
176*2d543d20SAndroid Build Coastguard Worker 	if (rc) {
177*2d543d20SAndroid Build Coastguard Worker 		avc_log(SELINUX_ERROR,
178*2d543d20SAndroid Build Coastguard Worker 			"%s:  unable to initialize SID table\n",
179*2d543d20SAndroid Build Coastguard Worker 			avc_prefix);
180*2d543d20SAndroid Build Coastguard Worker 		goto out;
181*2d543d20SAndroid Build Coastguard Worker 	}
182*2d543d20SAndroid Build Coastguard Worker 
183*2d543d20SAndroid Build Coastguard Worker 	avc_audit_buf = (char *)avc_malloc(AVC_AUDIT_BUFSIZE);
184*2d543d20SAndroid Build Coastguard Worker 	if (!avc_audit_buf) {
185*2d543d20SAndroid Build Coastguard Worker 		avc_log(SELINUX_ERROR,
186*2d543d20SAndroid Build Coastguard Worker 			"%s:  unable to allocate audit buffer\n",
187*2d543d20SAndroid Build Coastguard Worker 			avc_prefix);
188*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
189*2d543d20SAndroid Build Coastguard Worker 		goto out;
190*2d543d20SAndroid Build Coastguard Worker 	}
191*2d543d20SAndroid Build Coastguard Worker 
192*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < AVC_CACHE_MAXNODES; i++) {
193*2d543d20SAndroid Build Coastguard Worker 		new = avc_malloc(sizeof(*new));
194*2d543d20SAndroid Build Coastguard Worker 		if (!new) {
195*2d543d20SAndroid Build Coastguard Worker 			avc_log(SELINUX_WARNING,
196*2d543d20SAndroid Build Coastguard Worker 				"%s:  warning: only got %d av entries\n",
197*2d543d20SAndroid Build Coastguard Worker 				avc_prefix, i);
198*2d543d20SAndroid Build Coastguard Worker 			break;
199*2d543d20SAndroid Build Coastguard Worker 		}
200*2d543d20SAndroid Build Coastguard Worker 		memset(new, 0, sizeof(*new));
201*2d543d20SAndroid Build Coastguard Worker 		new->next = avc_node_freelist;
202*2d543d20SAndroid Build Coastguard Worker 		avc_node_freelist = new;
203*2d543d20SAndroid Build Coastguard Worker 	}
204*2d543d20SAndroid Build Coastguard Worker 
205*2d543d20SAndroid Build Coastguard Worker 	if (!avc_setenforce) {
206*2d543d20SAndroid Build Coastguard Worker 		rc = security_getenforce();
207*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
208*2d543d20SAndroid Build Coastguard Worker 			avc_log(SELINUX_ERROR,
209*2d543d20SAndroid Build Coastguard Worker 				"%s:  could not determine enforcing mode: %m\n",
210*2d543d20SAndroid Build Coastguard Worker 				avc_prefix);
211*2d543d20SAndroid Build Coastguard Worker 			goto out;
212*2d543d20SAndroid Build Coastguard Worker 		}
213*2d543d20SAndroid Build Coastguard Worker 		avc_enforcing = rc;
214*2d543d20SAndroid Build Coastguard Worker 	}
215*2d543d20SAndroid Build Coastguard Worker 
216*2d543d20SAndroid Build Coastguard Worker 	rc = selinux_status_open(0);
217*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
218*2d543d20SAndroid Build Coastguard Worker 		avc_log(SELINUX_ERROR,
219*2d543d20SAndroid Build Coastguard Worker 			"%s: could not open selinux status page: %d (%m)\n",
220*2d543d20SAndroid Build Coastguard Worker 			avc_prefix, errno);
221*2d543d20SAndroid Build Coastguard Worker 		goto out;
222*2d543d20SAndroid Build Coastguard Worker 	}
223*2d543d20SAndroid Build Coastguard Worker 	avc_running = 1;
224*2d543d20SAndroid Build Coastguard Worker       out:
225*2d543d20SAndroid Build Coastguard Worker 	return rc;
226*2d543d20SAndroid Build Coastguard Worker }
227*2d543d20SAndroid Build Coastguard Worker 
avc_open(const struct selinux_opt * opts,unsigned nopts)228*2d543d20SAndroid Build Coastguard Worker int avc_open(const struct selinux_opt *opts, unsigned nopts)
229*2d543d20SAndroid Build Coastguard Worker {
230*2d543d20SAndroid Build Coastguard Worker 	avc_setenforce = 0;
231*2d543d20SAndroid Build Coastguard Worker 
232*2d543d20SAndroid Build Coastguard Worker 	while (nopts) {
233*2d543d20SAndroid Build Coastguard Worker 		nopts--;
234*2d543d20SAndroid Build Coastguard Worker 		switch(opts[nopts].type) {
235*2d543d20SAndroid Build Coastguard Worker 		case AVC_OPT_SETENFORCE:
236*2d543d20SAndroid Build Coastguard Worker 			avc_setenforce = 1;
237*2d543d20SAndroid Build Coastguard Worker 			avc_enforcing = !!opts[nopts].value;
238*2d543d20SAndroid Build Coastguard Worker 			break;
239*2d543d20SAndroid Build Coastguard Worker 		}
240*2d543d20SAndroid Build Coastguard Worker 	}
241*2d543d20SAndroid Build Coastguard Worker 
242*2d543d20SAndroid Build Coastguard Worker 	return avc_init_internal("avc", NULL, NULL, NULL, NULL);
243*2d543d20SAndroid Build Coastguard Worker }
244*2d543d20SAndroid Build Coastguard Worker 
avc_init(const char * prefix,const struct avc_memory_callback * mem_cb,const struct avc_log_callback * log_cb,const struct avc_thread_callback * thread_cb,const struct avc_lock_callback * lock_cb)245*2d543d20SAndroid Build Coastguard Worker int avc_init(const char *prefix,
246*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_memory_callback *mem_cb,
247*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_log_callback *log_cb,
248*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_thread_callback *thread_cb,
249*2d543d20SAndroid Build Coastguard Worker 	     const struct avc_lock_callback *lock_cb)
250*2d543d20SAndroid Build Coastguard Worker {
251*2d543d20SAndroid Build Coastguard Worker 	return avc_init_internal(prefix, mem_cb, log_cb, thread_cb, lock_cb);
252*2d543d20SAndroid Build Coastguard Worker }
253*2d543d20SAndroid Build Coastguard Worker 
avc_cache_stats(struct avc_cache_stats * p)254*2d543d20SAndroid Build Coastguard Worker void avc_cache_stats(struct avc_cache_stats *p)
255*2d543d20SAndroid Build Coastguard Worker {
256*2d543d20SAndroid Build Coastguard Worker 	memcpy(p, &cache_stats, sizeof(cache_stats));
257*2d543d20SAndroid Build Coastguard Worker }
258*2d543d20SAndroid Build Coastguard Worker 
avc_sid_stats(void)259*2d543d20SAndroid Build Coastguard Worker void avc_sid_stats(void)
260*2d543d20SAndroid Build Coastguard Worker {
261*2d543d20SAndroid Build Coastguard Worker 	/* avc_init needs to be called before this function */
262*2d543d20SAndroid Build Coastguard Worker 	assert(avc_running);
263*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_log_lock);
264*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
265*2d543d20SAndroid Build Coastguard Worker 	sidtab_sid_stats(&avc_sidtab, avc_audit_buf, AVC_AUDIT_BUFSIZE);
266*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
267*2d543d20SAndroid Build Coastguard Worker 	avc_log(SELINUX_INFO, "%s", avc_audit_buf);
268*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_log_lock);
269*2d543d20SAndroid Build Coastguard Worker }
270*2d543d20SAndroid Build Coastguard Worker 
avc_av_stats(void)271*2d543d20SAndroid Build Coastguard Worker void avc_av_stats(void)
272*2d543d20SAndroid Build Coastguard Worker {
273*2d543d20SAndroid Build Coastguard Worker 	int i, chain_len, max_chain_len, slots_used;
274*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node;
275*2d543d20SAndroid Build Coastguard Worker 
276*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
277*2d543d20SAndroid Build Coastguard Worker 
278*2d543d20SAndroid Build Coastguard Worker 	slots_used = 0;
279*2d543d20SAndroid Build Coastguard Worker 	max_chain_len = 0;
280*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
281*2d543d20SAndroid Build Coastguard Worker 		node = avc_cache.slots[i];
282*2d543d20SAndroid Build Coastguard Worker 		if (node) {
283*2d543d20SAndroid Build Coastguard Worker 			slots_used++;
284*2d543d20SAndroid Build Coastguard Worker 			chain_len = 0;
285*2d543d20SAndroid Build Coastguard Worker 			while (node) {
286*2d543d20SAndroid Build Coastguard Worker 				chain_len++;
287*2d543d20SAndroid Build Coastguard Worker 				node = node->next;
288*2d543d20SAndroid Build Coastguard Worker 			}
289*2d543d20SAndroid Build Coastguard Worker 			if (chain_len > max_chain_len)
290*2d543d20SAndroid Build Coastguard Worker 				max_chain_len = chain_len;
291*2d543d20SAndroid Build Coastguard Worker 		}
292*2d543d20SAndroid Build Coastguard Worker 	}
293*2d543d20SAndroid Build Coastguard Worker 
294*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
295*2d543d20SAndroid Build Coastguard Worker 
296*2d543d20SAndroid Build Coastguard Worker 	avc_log(SELINUX_INFO, "%s:  %u AV entries and %d/%d buckets used, "
297*2d543d20SAndroid Build Coastguard Worker 		"longest chain length %d\n", avc_prefix,
298*2d543d20SAndroid Build Coastguard Worker 		avc_cache.active_nodes,
299*2d543d20SAndroid Build Coastguard Worker 		slots_used, AVC_CACHE_SLOTS, max_chain_len);
300*2d543d20SAndroid Build Coastguard Worker }
301*2d543d20SAndroid Build Coastguard Worker 
302*2d543d20SAndroid Build Coastguard Worker 
avc_reclaim_node(void)303*2d543d20SAndroid Build Coastguard Worker static inline struct avc_node *avc_reclaim_node(void)
304*2d543d20SAndroid Build Coastguard Worker {
305*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *prev, *cur;
306*2d543d20SAndroid Build Coastguard Worker 	int try;
307*2d543d20SAndroid Build Coastguard Worker 	uint32_t hvalue;
308*2d543d20SAndroid Build Coastguard Worker 
309*2d543d20SAndroid Build Coastguard Worker 	hvalue = avc_cache.lru_hint;
310*2d543d20SAndroid Build Coastguard Worker 	for (try = 0; try < 2; try++) {
311*2d543d20SAndroid Build Coastguard Worker 		do {
312*2d543d20SAndroid Build Coastguard Worker 			prev = NULL;
313*2d543d20SAndroid Build Coastguard Worker 			cur = avc_cache.slots[hvalue];
314*2d543d20SAndroid Build Coastguard Worker 			while (cur) {
315*2d543d20SAndroid Build Coastguard Worker 				if (!cur->ae.used)
316*2d543d20SAndroid Build Coastguard Worker 					goto found;
317*2d543d20SAndroid Build Coastguard Worker 
318*2d543d20SAndroid Build Coastguard Worker 				cur->ae.used = 0;
319*2d543d20SAndroid Build Coastguard Worker 
320*2d543d20SAndroid Build Coastguard Worker 				prev = cur;
321*2d543d20SAndroid Build Coastguard Worker 				cur = cur->next;
322*2d543d20SAndroid Build Coastguard Worker 			}
323*2d543d20SAndroid Build Coastguard Worker 			hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1);
324*2d543d20SAndroid Build Coastguard Worker 		} while (hvalue != avc_cache.lru_hint);
325*2d543d20SAndroid Build Coastguard Worker 	}
326*2d543d20SAndroid Build Coastguard Worker 
327*2d543d20SAndroid Build Coastguard Worker 	errno = ENOMEM;		/* this was a panic in the kernel... */
328*2d543d20SAndroid Build Coastguard Worker 	return NULL;
329*2d543d20SAndroid Build Coastguard Worker 
330*2d543d20SAndroid Build Coastguard Worker       found:
331*2d543d20SAndroid Build Coastguard Worker 	avc_cache.lru_hint = hvalue;
332*2d543d20SAndroid Build Coastguard Worker 
333*2d543d20SAndroid Build Coastguard Worker 	if (prev == NULL)
334*2d543d20SAndroid Build Coastguard Worker 		avc_cache.slots[hvalue] = cur->next;
335*2d543d20SAndroid Build Coastguard Worker 	else
336*2d543d20SAndroid Build Coastguard Worker 		prev->next = cur->next;
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker 	return cur;
339*2d543d20SAndroid Build Coastguard Worker }
340*2d543d20SAndroid Build Coastguard Worker 
avc_clear_avc_entry(struct avc_entry * ae)341*2d543d20SAndroid Build Coastguard Worker static inline void avc_clear_avc_entry(struct avc_entry *ae)
342*2d543d20SAndroid Build Coastguard Worker {
343*2d543d20SAndroid Build Coastguard Worker 	memset(ae, 0, sizeof(*ae));
344*2d543d20SAndroid Build Coastguard Worker }
345*2d543d20SAndroid Build Coastguard Worker 
avc_claim_node(security_id_t ssid,security_id_t tsid,security_class_t tclass)346*2d543d20SAndroid Build Coastguard Worker static inline struct avc_node *avc_claim_node(security_id_t ssid,
347*2d543d20SAndroid Build Coastguard Worker 					      security_id_t tsid,
348*2d543d20SAndroid Build Coastguard Worker 					      security_class_t tclass)
349*2d543d20SAndroid Build Coastguard Worker {
350*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *new;
351*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
352*2d543d20SAndroid Build Coastguard Worker 
353*2d543d20SAndroid Build Coastguard Worker 	if (!avc_node_freelist)
354*2d543d20SAndroid Build Coastguard Worker 		avc_cleanup();
355*2d543d20SAndroid Build Coastguard Worker 
356*2d543d20SAndroid Build Coastguard Worker 	if (avc_node_freelist) {
357*2d543d20SAndroid Build Coastguard Worker 		new = avc_node_freelist;
358*2d543d20SAndroid Build Coastguard Worker 		avc_node_freelist = avc_node_freelist->next;
359*2d543d20SAndroid Build Coastguard Worker 		avc_cache.active_nodes++;
360*2d543d20SAndroid Build Coastguard Worker 	} else {
361*2d543d20SAndroid Build Coastguard Worker 		new = avc_reclaim_node();
362*2d543d20SAndroid Build Coastguard Worker 		if (!new)
363*2d543d20SAndroid Build Coastguard Worker 			goto out;
364*2d543d20SAndroid Build Coastguard Worker 	}
365*2d543d20SAndroid Build Coastguard Worker 
366*2d543d20SAndroid Build Coastguard Worker 	hvalue = avc_hash(ssid, tsid, tclass);
367*2d543d20SAndroid Build Coastguard Worker 	avc_clear_avc_entry(&new->ae);
368*2d543d20SAndroid Build Coastguard Worker 	new->ae.used = 1;
369*2d543d20SAndroid Build Coastguard Worker 	new->ae.ssid = ssid;
370*2d543d20SAndroid Build Coastguard Worker 	new->ae.tsid = tsid;
371*2d543d20SAndroid Build Coastguard Worker 	new->ae.tclass = tclass;
372*2d543d20SAndroid Build Coastguard Worker 	new->next = avc_cache.slots[hvalue];
373*2d543d20SAndroid Build Coastguard Worker 	avc_cache.slots[hvalue] = new;
374*2d543d20SAndroid Build Coastguard Worker 
375*2d543d20SAndroid Build Coastguard Worker       out:
376*2d543d20SAndroid Build Coastguard Worker 	return new;
377*2d543d20SAndroid Build Coastguard Worker }
378*2d543d20SAndroid Build Coastguard Worker 
avc_search_node(security_id_t ssid,security_id_t tsid,security_class_t tclass,int * probes)379*2d543d20SAndroid Build Coastguard Worker static inline struct avc_node *avc_search_node(security_id_t ssid,
380*2d543d20SAndroid Build Coastguard Worker 					       security_id_t tsid,
381*2d543d20SAndroid Build Coastguard Worker 					       security_class_t tclass,
382*2d543d20SAndroid Build Coastguard Worker 					       int *probes)
383*2d543d20SAndroid Build Coastguard Worker {
384*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *cur;
385*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
386*2d543d20SAndroid Build Coastguard Worker 	int tprobes = 1;
387*2d543d20SAndroid Build Coastguard Worker 
388*2d543d20SAndroid Build Coastguard Worker 	hvalue = avc_hash(ssid, tsid, tclass);
389*2d543d20SAndroid Build Coastguard Worker 	cur = avc_cache.slots[hvalue];
390*2d543d20SAndroid Build Coastguard Worker 	while (cur != NULL &&
391*2d543d20SAndroid Build Coastguard Worker 	       (ssid != cur->ae.ssid ||
392*2d543d20SAndroid Build Coastguard Worker 		tclass != cur->ae.tclass || tsid != cur->ae.tsid)) {
393*2d543d20SAndroid Build Coastguard Worker 		tprobes++;
394*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
395*2d543d20SAndroid Build Coastguard Worker 	}
396*2d543d20SAndroid Build Coastguard Worker 
397*2d543d20SAndroid Build Coastguard Worker 	if (cur == NULL) {
398*2d543d20SAndroid Build Coastguard Worker 		/* cache miss */
399*2d543d20SAndroid Build Coastguard Worker 		goto out;
400*2d543d20SAndroid Build Coastguard Worker 	}
401*2d543d20SAndroid Build Coastguard Worker 
402*2d543d20SAndroid Build Coastguard Worker 	/* cache hit */
403*2d543d20SAndroid Build Coastguard Worker 	if (probes)
404*2d543d20SAndroid Build Coastguard Worker 		*probes = tprobes;
405*2d543d20SAndroid Build Coastguard Worker 
406*2d543d20SAndroid Build Coastguard Worker 	cur->ae.used = 1;
407*2d543d20SAndroid Build Coastguard Worker 
408*2d543d20SAndroid Build Coastguard Worker       out:
409*2d543d20SAndroid Build Coastguard Worker 	return cur;
410*2d543d20SAndroid Build Coastguard Worker }
411*2d543d20SAndroid Build Coastguard Worker 
412*2d543d20SAndroid Build Coastguard Worker /**
413*2d543d20SAndroid Build Coastguard Worker  * avc_lookup - Look up an AVC entry.
414*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier
415*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier
416*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
417*2d543d20SAndroid Build Coastguard Worker  * @requested: requested permissions, interpreted based on @tclass
418*2d543d20SAndroid Build Coastguard Worker  * @aeref:  AVC entry reference
419*2d543d20SAndroid Build Coastguard Worker  *
420*2d543d20SAndroid Build Coastguard Worker  * Look up an AVC entry that is valid for the
421*2d543d20SAndroid Build Coastguard Worker  * @requested permissions between the SID pair
422*2d543d20SAndroid Build Coastguard Worker  * (@ssid, @tsid), interpreting the permissions
423*2d543d20SAndroid Build Coastguard Worker  * based on @tclass.  If a valid AVC entry exists,
424*2d543d20SAndroid Build Coastguard Worker  * then this function updates @aeref to refer to the
425*2d543d20SAndroid Build Coastguard Worker  * entry and returns %0.  Otherwise, -1 is returned.
426*2d543d20SAndroid Build Coastguard Worker  */
avc_lookup(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct avc_entry_ref * aeref)427*2d543d20SAndroid Build Coastguard Worker static int avc_lookup(security_id_t ssid, security_id_t tsid,
428*2d543d20SAndroid Build Coastguard Worker 		      security_class_t tclass,
429*2d543d20SAndroid Build Coastguard Worker 		      access_vector_t requested, struct avc_entry_ref *aeref)
430*2d543d20SAndroid Build Coastguard Worker {
431*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node;
432*2d543d20SAndroid Build Coastguard Worker 	int probes, rc = 0;
433*2d543d20SAndroid Build Coastguard Worker 
434*2d543d20SAndroid Build Coastguard Worker 	avc_cache_stats_incr(cav_lookups);
435*2d543d20SAndroid Build Coastguard Worker 	node = avc_search_node(ssid, tsid, tclass, &probes);
436*2d543d20SAndroid Build Coastguard Worker 
437*2d543d20SAndroid Build Coastguard Worker 	if (node && ((node->ae.avd.decided & requested) == requested)) {
438*2d543d20SAndroid Build Coastguard Worker 		avc_cache_stats_incr(cav_hits);
439*2d543d20SAndroid Build Coastguard Worker 		avc_cache_stats_add(cav_probes, probes);
440*2d543d20SAndroid Build Coastguard Worker 		aeref->ae = &node->ae;
441*2d543d20SAndroid Build Coastguard Worker 		goto out;
442*2d543d20SAndroid Build Coastguard Worker 	}
443*2d543d20SAndroid Build Coastguard Worker 
444*2d543d20SAndroid Build Coastguard Worker 	avc_cache_stats_incr(cav_misses);
445*2d543d20SAndroid Build Coastguard Worker 	rc = -1;
446*2d543d20SAndroid Build Coastguard Worker       out:
447*2d543d20SAndroid Build Coastguard Worker 	return rc;
448*2d543d20SAndroid Build Coastguard Worker }
449*2d543d20SAndroid Build Coastguard Worker 
450*2d543d20SAndroid Build Coastguard Worker /**
451*2d543d20SAndroid Build Coastguard Worker  * avc_insert - Insert an AVC entry.
452*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier
453*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier
454*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
455*2d543d20SAndroid Build Coastguard Worker  * @ae: AVC entry
456*2d543d20SAndroid Build Coastguard Worker  * @aeref:  AVC entry reference
457*2d543d20SAndroid Build Coastguard Worker  *
458*2d543d20SAndroid Build Coastguard Worker  * Insert an AVC entry for the SID pair
459*2d543d20SAndroid Build Coastguard Worker  * (@ssid, @tsid) and class @tclass.
460*2d543d20SAndroid Build Coastguard Worker  * The access vectors and the sequence number are
461*2d543d20SAndroid Build Coastguard Worker  * normally provided by the security server in
462*2d543d20SAndroid Build Coastguard Worker  * response to a security_compute_av() call.  If the
463*2d543d20SAndroid Build Coastguard Worker  * sequence number @ae->avd.seqno is not less than the latest
464*2d543d20SAndroid Build Coastguard Worker  * revocation notification, then the function copies
465*2d543d20SAndroid Build Coastguard Worker  * the access vectors into a cache entry, updates
466*2d543d20SAndroid Build Coastguard Worker  * @aeref to refer to the entry, and returns %0.
467*2d543d20SAndroid Build Coastguard Worker  * Otherwise, this function returns -%1 with @errno set to %EAGAIN.
468*2d543d20SAndroid Build Coastguard Worker  */
avc_insert(security_id_t ssid,security_id_t tsid,security_class_t tclass,struct avc_entry * ae,struct avc_entry_ref * aeref)469*2d543d20SAndroid Build Coastguard Worker static int avc_insert(security_id_t ssid, security_id_t tsid,
470*2d543d20SAndroid Build Coastguard Worker 		      security_class_t tclass,
471*2d543d20SAndroid Build Coastguard Worker 		      struct avc_entry *ae, struct avc_entry_ref *aeref)
472*2d543d20SAndroid Build Coastguard Worker {
473*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node;
474*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
475*2d543d20SAndroid Build Coastguard Worker 
476*2d543d20SAndroid Build Coastguard Worker 	if (ae->avd.seqno < avc_cache.latest_notif) {
477*2d543d20SAndroid Build Coastguard Worker 		avc_log(SELINUX_WARNING,
478*2d543d20SAndroid Build Coastguard Worker 			"%s:  seqno %u < latest_notif %u\n", avc_prefix,
479*2d543d20SAndroid Build Coastguard Worker 			ae->avd.seqno, avc_cache.latest_notif);
480*2d543d20SAndroid Build Coastguard Worker 		errno = EAGAIN;
481*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
482*2d543d20SAndroid Build Coastguard Worker 		goto out;
483*2d543d20SAndroid Build Coastguard Worker 	}
484*2d543d20SAndroid Build Coastguard Worker 
485*2d543d20SAndroid Build Coastguard Worker 	node = avc_claim_node(ssid, tsid, tclass);
486*2d543d20SAndroid Build Coastguard Worker 	if (!node) {
487*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
488*2d543d20SAndroid Build Coastguard Worker 		goto out;
489*2d543d20SAndroid Build Coastguard Worker 	}
490*2d543d20SAndroid Build Coastguard Worker 
491*2d543d20SAndroid Build Coastguard Worker 	memcpy(&node->ae.avd, &ae->avd, sizeof(ae->avd));
492*2d543d20SAndroid Build Coastguard Worker 	aeref->ae = &node->ae;
493*2d543d20SAndroid Build Coastguard Worker       out:
494*2d543d20SAndroid Build Coastguard Worker 	return rc;
495*2d543d20SAndroid Build Coastguard Worker }
496*2d543d20SAndroid Build Coastguard Worker 
avc_cleanup(void)497*2d543d20SAndroid Build Coastguard Worker void avc_cleanup(void)
498*2d543d20SAndroid Build Coastguard Worker {
499*2d543d20SAndroid Build Coastguard Worker }
500*2d543d20SAndroid Build Coastguard Worker 
501*2d543d20SAndroid Build Coastguard Worker 
avc_reset(void)502*2d543d20SAndroid Build Coastguard Worker int avc_reset(void)
503*2d543d20SAndroid Build Coastguard Worker {
504*2d543d20SAndroid Build Coastguard Worker 	struct avc_callback_node *c;
505*2d543d20SAndroid Build Coastguard Worker 	int i, ret, rc = 0, errsave = 0;
506*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node, *tmp;
507*2d543d20SAndroid Build Coastguard Worker 	errno = 0;
508*2d543d20SAndroid Build Coastguard Worker 
509*2d543d20SAndroid Build Coastguard Worker 	if (!avc_running)
510*2d543d20SAndroid Build Coastguard Worker 		return 0;
511*2d543d20SAndroid Build Coastguard Worker 
512*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
513*2d543d20SAndroid Build Coastguard Worker 
514*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
515*2d543d20SAndroid Build Coastguard Worker 		node = avc_cache.slots[i];
516*2d543d20SAndroid Build Coastguard Worker 		while (node) {
517*2d543d20SAndroid Build Coastguard Worker 			tmp = node;
518*2d543d20SAndroid Build Coastguard Worker 			node = node->next;
519*2d543d20SAndroid Build Coastguard Worker 			avc_clear_avc_entry(&tmp->ae);
520*2d543d20SAndroid Build Coastguard Worker 			tmp->next = avc_node_freelist;
521*2d543d20SAndroid Build Coastguard Worker 			avc_node_freelist = tmp;
522*2d543d20SAndroid Build Coastguard Worker 			avc_cache.active_nodes--;
523*2d543d20SAndroid Build Coastguard Worker 		}
524*2d543d20SAndroid Build Coastguard Worker 		avc_cache.slots[i] = 0;
525*2d543d20SAndroid Build Coastguard Worker 	}
526*2d543d20SAndroid Build Coastguard Worker 	avc_cache.lru_hint = 0;
527*2d543d20SAndroid Build Coastguard Worker 
528*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
529*2d543d20SAndroid Build Coastguard Worker 
530*2d543d20SAndroid Build Coastguard Worker 	memset(&cache_stats, 0, sizeof(cache_stats));
531*2d543d20SAndroid Build Coastguard Worker 
532*2d543d20SAndroid Build Coastguard Worker 	for (c = avc_callbacks; c; c = c->next) {
533*2d543d20SAndroid Build Coastguard Worker 		if (c->events & AVC_CALLBACK_RESET) {
534*2d543d20SAndroid Build Coastguard Worker 			ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0);
535*2d543d20SAndroid Build Coastguard Worker 			if (ret && !rc) {
536*2d543d20SAndroid Build Coastguard Worker 				rc = ret;
537*2d543d20SAndroid Build Coastguard Worker 				errsave = errno;
538*2d543d20SAndroid Build Coastguard Worker 			}
539*2d543d20SAndroid Build Coastguard Worker 		}
540*2d543d20SAndroid Build Coastguard Worker 	}
541*2d543d20SAndroid Build Coastguard Worker 	errno = errsave;
542*2d543d20SAndroid Build Coastguard Worker 	return rc;
543*2d543d20SAndroid Build Coastguard Worker }
544*2d543d20SAndroid Build Coastguard Worker 
545*2d543d20SAndroid Build Coastguard Worker 
avc_destroy(void)546*2d543d20SAndroid Build Coastguard Worker void avc_destroy(void)
547*2d543d20SAndroid Build Coastguard Worker {
548*2d543d20SAndroid Build Coastguard Worker 	struct avc_callback_node *c;
549*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node, *tmp;
550*2d543d20SAndroid Build Coastguard Worker 	int i;
551*2d543d20SAndroid Build Coastguard Worker 	/* avc_init needs to be called before this function */
552*2d543d20SAndroid Build Coastguard Worker 	assert(avc_running);
553*2d543d20SAndroid Build Coastguard Worker 
554*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
555*2d543d20SAndroid Build Coastguard Worker 
556*2d543d20SAndroid Build Coastguard Worker 	selinux_status_close();
557*2d543d20SAndroid Build Coastguard Worker 
558*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
559*2d543d20SAndroid Build Coastguard Worker 		node = avc_cache.slots[i];
560*2d543d20SAndroid Build Coastguard Worker 		while (node) {
561*2d543d20SAndroid Build Coastguard Worker 			tmp = node;
562*2d543d20SAndroid Build Coastguard Worker 			node = node->next;
563*2d543d20SAndroid Build Coastguard Worker 			avc_free(tmp);
564*2d543d20SAndroid Build Coastguard Worker 		}
565*2d543d20SAndroid Build Coastguard Worker 	}
566*2d543d20SAndroid Build Coastguard Worker 	while (avc_node_freelist) {
567*2d543d20SAndroid Build Coastguard Worker 		tmp = avc_node_freelist;
568*2d543d20SAndroid Build Coastguard Worker 		avc_node_freelist = tmp->next;
569*2d543d20SAndroid Build Coastguard Worker 		avc_free(tmp);
570*2d543d20SAndroid Build Coastguard Worker 	}
571*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
572*2d543d20SAndroid Build Coastguard Worker 
573*2d543d20SAndroid Build Coastguard Worker 	while (avc_callbacks) {
574*2d543d20SAndroid Build Coastguard Worker 		c = avc_callbacks;
575*2d543d20SAndroid Build Coastguard Worker 		avc_callbacks = c->next;
576*2d543d20SAndroid Build Coastguard Worker 		avc_free(c);
577*2d543d20SAndroid Build Coastguard Worker 	}
578*2d543d20SAndroid Build Coastguard Worker 	sidtab_destroy(&avc_sidtab);
579*2d543d20SAndroid Build Coastguard Worker 	avc_free_lock(avc_lock);
580*2d543d20SAndroid Build Coastguard Worker 	avc_free_lock(avc_log_lock);
581*2d543d20SAndroid Build Coastguard Worker 	avc_free(avc_audit_buf);
582*2d543d20SAndroid Build Coastguard Worker 	avc_running = 0;
583*2d543d20SAndroid Build Coastguard Worker }
584*2d543d20SAndroid Build Coastguard Worker 
585*2d543d20SAndroid Build Coastguard Worker /* ratelimit stuff put aside for now --EFW */
586*2d543d20SAndroid Build Coastguard Worker #if 0
587*2d543d20SAndroid Build Coastguard Worker /*
588*2d543d20SAndroid Build Coastguard Worker  * Copied from net/core/utils.c:net_ratelimit and modified for
589*2d543d20SAndroid Build Coastguard Worker  * use by the AVC audit facility.
590*2d543d20SAndroid Build Coastguard Worker  */
591*2d543d20SAndroid Build Coastguard Worker #define AVC_MSG_COST	5*HZ
592*2d543d20SAndroid Build Coastguard Worker #define AVC_MSG_BURST	10*5*HZ
593*2d543d20SAndroid Build Coastguard Worker 
594*2d543d20SAndroid Build Coastguard Worker /*
595*2d543d20SAndroid Build Coastguard Worker  * This enforces a rate limit: not more than one kernel message
596*2d543d20SAndroid Build Coastguard Worker  * every 5secs to make a denial-of-service attack impossible.
597*2d543d20SAndroid Build Coastguard Worker  */
598*2d543d20SAndroid Build Coastguard Worker static int avc_ratelimit(void)
599*2d543d20SAndroid Build Coastguard Worker {
600*2d543d20SAndroid Build Coastguard Worker 	static unsigned long toks = 10 * 5 * HZ;
601*2d543d20SAndroid Build Coastguard Worker 	static unsigned long last_msg;
602*2d543d20SAndroid Build Coastguard Worker 	static int missed, rc = 0;
603*2d543d20SAndroid Build Coastguard Worker 	unsigned long now = jiffies;
604*2d543d20SAndroid Build Coastguard Worker 	void *ratelimit_lock = avc_alloc_lock();
605*2d543d20SAndroid Build Coastguard Worker 
606*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(ratelimit_lock);
607*2d543d20SAndroid Build Coastguard Worker 	toks += now - last_msg;
608*2d543d20SAndroid Build Coastguard Worker 	last_msg = now;
609*2d543d20SAndroid Build Coastguard Worker 	if (toks > AVC_MSG_BURST)
610*2d543d20SAndroid Build Coastguard Worker 		toks = AVC_MSG_BURST;
611*2d543d20SAndroid Build Coastguard Worker 	if (toks >= AVC_MSG_COST) {
612*2d543d20SAndroid Build Coastguard Worker 		int lost = missed;
613*2d543d20SAndroid Build Coastguard Worker 		missed = 0;
614*2d543d20SAndroid Build Coastguard Worker 		toks -= AVC_MSG_COST;
615*2d543d20SAndroid Build Coastguard Worker 		avc_release_lock(ratelimit_lock);
616*2d543d20SAndroid Build Coastguard Worker 		if (lost) {
617*2d543d20SAndroid Build Coastguard Worker 			avc_log(SELINUX_WARNING,
618*2d543d20SAndroid Build Coastguard Worker 				"%s:  %d messages suppressed.\n", avc_prefix,
619*2d543d20SAndroid Build Coastguard Worker 				lost);
620*2d543d20SAndroid Build Coastguard Worker 		}
621*2d543d20SAndroid Build Coastguard Worker 		rc = 1;
622*2d543d20SAndroid Build Coastguard Worker 		goto out;
623*2d543d20SAndroid Build Coastguard Worker 	}
624*2d543d20SAndroid Build Coastguard Worker 	missed++;
625*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(ratelimit_lock);
626*2d543d20SAndroid Build Coastguard Worker       out:
627*2d543d20SAndroid Build Coastguard Worker 	avc_free_lock(ratelimit_lock);
628*2d543d20SAndroid Build Coastguard Worker 	return rc;
629*2d543d20SAndroid Build Coastguard Worker }
630*2d543d20SAndroid Build Coastguard Worker 
631*2d543d20SAndroid Build Coastguard Worker static inline int check_avc_ratelimit(void)
632*2d543d20SAndroid Build Coastguard Worker {
633*2d543d20SAndroid Build Coastguard Worker 	if (avc_enforcing)
634*2d543d20SAndroid Build Coastguard Worker 		return avc_ratelimit();
635*2d543d20SAndroid Build Coastguard Worker 	else {
636*2d543d20SAndroid Build Coastguard Worker 		/* If permissive, then never suppress messages. */
637*2d543d20SAndroid Build Coastguard Worker 		return 1;
638*2d543d20SAndroid Build Coastguard Worker 	}
639*2d543d20SAndroid Build Coastguard Worker }
640*2d543d20SAndroid Build Coastguard Worker #endif				/* ratelimit stuff */
641*2d543d20SAndroid Build Coastguard Worker 
642*2d543d20SAndroid Build Coastguard Worker /**
643*2d543d20SAndroid Build Coastguard Worker  * avc_dump_av - Display an access vector in human-readable form.
644*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
645*2d543d20SAndroid Build Coastguard Worker  * @av: access vector
646*2d543d20SAndroid Build Coastguard Worker  */
avc_dump_av(security_class_t tclass,access_vector_t av)647*2d543d20SAndroid Build Coastguard Worker static void avc_dump_av(security_class_t tclass, access_vector_t av)
648*2d543d20SAndroid Build Coastguard Worker {
649*2d543d20SAndroid Build Coastguard Worker 	const char *permstr;
650*2d543d20SAndroid Build Coastguard Worker 	access_vector_t bit = 1;
651*2d543d20SAndroid Build Coastguard Worker 
652*2d543d20SAndroid Build Coastguard Worker 	if (av == 0) {
653*2d543d20SAndroid Build Coastguard Worker 		log_append(avc_audit_buf, " null");
654*2d543d20SAndroid Build Coastguard Worker 		return;
655*2d543d20SAndroid Build Coastguard Worker 	}
656*2d543d20SAndroid Build Coastguard Worker 
657*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, " {");
658*2d543d20SAndroid Build Coastguard Worker 
659*2d543d20SAndroid Build Coastguard Worker 	while (av) {
660*2d543d20SAndroid Build Coastguard Worker 		if (av & bit) {
661*2d543d20SAndroid Build Coastguard Worker 			permstr = security_av_perm_to_string(tclass, bit);
662*2d543d20SAndroid Build Coastguard Worker 			if (!permstr)
663*2d543d20SAndroid Build Coastguard Worker 				break;
664*2d543d20SAndroid Build Coastguard Worker 			log_append(avc_audit_buf, " %s", permstr);
665*2d543d20SAndroid Build Coastguard Worker 			av &= ~bit;
666*2d543d20SAndroid Build Coastguard Worker 		}
667*2d543d20SAndroid Build Coastguard Worker 		bit <<= 1;
668*2d543d20SAndroid Build Coastguard Worker 	}
669*2d543d20SAndroid Build Coastguard Worker 
670*2d543d20SAndroid Build Coastguard Worker 	if (av)
671*2d543d20SAndroid Build Coastguard Worker 		log_append(avc_audit_buf, " 0x%x", av);
672*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, " }");
673*2d543d20SAndroid Build Coastguard Worker }
674*2d543d20SAndroid Build Coastguard Worker 
675*2d543d20SAndroid Build Coastguard Worker /**
676*2d543d20SAndroid Build Coastguard Worker  * avc_dump_query - Display a SID pair and a class in human-readable form.
677*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier
678*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier
679*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
680*2d543d20SAndroid Build Coastguard Worker  */
avc_dump_query(security_id_t ssid,security_id_t tsid,security_class_t tclass)681*2d543d20SAndroid Build Coastguard Worker static void avc_dump_query(security_id_t ssid, security_id_t tsid,
682*2d543d20SAndroid Build Coastguard Worker 			   security_class_t tclass)
683*2d543d20SAndroid Build Coastguard Worker {
684*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
685*2d543d20SAndroid Build Coastguard Worker 
686*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, "scontext=%s tcontext=%s",
687*2d543d20SAndroid Build Coastguard Worker 		   ssid->ctx, tsid->ctx);
688*2d543d20SAndroid Build Coastguard Worker 
689*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
690*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, " tclass=%s",
691*2d543d20SAndroid Build Coastguard Worker 		   security_class_to_string(tclass));
692*2d543d20SAndroid Build Coastguard Worker }
693*2d543d20SAndroid Build Coastguard Worker 
avc_audit(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct av_decision * avd,int result,void * a)694*2d543d20SAndroid Build Coastguard Worker void avc_audit(security_id_t ssid, security_id_t tsid,
695*2d543d20SAndroid Build Coastguard Worker 	       security_class_t tclass, access_vector_t requested,
696*2d543d20SAndroid Build Coastguard Worker 	       struct av_decision *avd, int result, void *a)
697*2d543d20SAndroid Build Coastguard Worker {
698*2d543d20SAndroid Build Coastguard Worker 	access_vector_t denied, audited;
699*2d543d20SAndroid Build Coastguard Worker 
700*2d543d20SAndroid Build Coastguard Worker 	denied = requested & ~avd->allowed;
701*2d543d20SAndroid Build Coastguard Worker 	if (denied)
702*2d543d20SAndroid Build Coastguard Worker 		audited = denied & avd->auditdeny;
703*2d543d20SAndroid Build Coastguard Worker 	else if (!requested || result)
704*2d543d20SAndroid Build Coastguard Worker 		audited = denied = requested;
705*2d543d20SAndroid Build Coastguard Worker 	else
706*2d543d20SAndroid Build Coastguard Worker 		audited = requested & avd->auditallow;
707*2d543d20SAndroid Build Coastguard Worker 	if (!audited)
708*2d543d20SAndroid Build Coastguard Worker 		return;
709*2d543d20SAndroid Build Coastguard Worker #if 0
710*2d543d20SAndroid Build Coastguard Worker 	if (!check_avc_ratelimit())
711*2d543d20SAndroid Build Coastguard Worker 		return;
712*2d543d20SAndroid Build Coastguard Worker #endif
713*2d543d20SAndroid Build Coastguard Worker 	/* prevent overlapping buffer writes */
714*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_log_lock);
715*2d543d20SAndroid Build Coastguard Worker 	snprintf(avc_audit_buf, AVC_AUDIT_BUFSIZE,
716*2d543d20SAndroid Build Coastguard Worker 		 "%s:  %s ", avc_prefix, (denied || !requested) ? "denied" : "granted");
717*2d543d20SAndroid Build Coastguard Worker 	avc_dump_av(tclass, audited);
718*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, " for ");
719*2d543d20SAndroid Build Coastguard Worker 
720*2d543d20SAndroid Build Coastguard Worker 	/* get any extra information printed by the callback */
721*2d543d20SAndroid Build Coastguard Worker 	avc_suppl_audit(a, tclass, avc_audit_buf + strlen(avc_audit_buf),
722*2d543d20SAndroid Build Coastguard Worker 			AVC_AUDIT_BUFSIZE - strlen(avc_audit_buf));
723*2d543d20SAndroid Build Coastguard Worker 
724*2d543d20SAndroid Build Coastguard Worker 	log_append(avc_audit_buf, " ");
725*2d543d20SAndroid Build Coastguard Worker 	avc_dump_query(ssid, tsid, tclass);
726*2d543d20SAndroid Build Coastguard Worker 
727*2d543d20SAndroid Build Coastguard Worker 	if (denied)
728*2d543d20SAndroid Build Coastguard Worker 		log_append(avc_audit_buf, " permissive=%u", result ? 0 : 1);
729*2d543d20SAndroid Build Coastguard Worker 
730*2d543d20SAndroid Build Coastguard Worker 	avc_log(SELINUX_AVC, "%s", avc_audit_buf);
731*2d543d20SAndroid Build Coastguard Worker 
732*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_log_lock);
733*2d543d20SAndroid Build Coastguard Worker }
734*2d543d20SAndroid Build Coastguard Worker 
735*2d543d20SAndroid Build Coastguard Worker 
736*2d543d20SAndroid Build Coastguard Worker 
avd_init(struct av_decision * avd)737*2d543d20SAndroid Build Coastguard Worker static void avd_init(struct av_decision *avd)
738*2d543d20SAndroid Build Coastguard Worker {
739*2d543d20SAndroid Build Coastguard Worker 	avd->allowed = 0;
740*2d543d20SAndroid Build Coastguard Worker 	avd->auditallow = 0;
741*2d543d20SAndroid Build Coastguard Worker 	avd->auditdeny = 0xffffffff;
742*2d543d20SAndroid Build Coastguard Worker 	avd->seqno = avc_cache.latest_notif;
743*2d543d20SAndroid Build Coastguard Worker 	avd->flags = 0;
744*2d543d20SAndroid Build Coastguard Worker }
745*2d543d20SAndroid Build Coastguard Worker 
avc_has_perm_noaudit(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct avc_entry_ref * aeref,struct av_decision * avd)746*2d543d20SAndroid Build Coastguard Worker int avc_has_perm_noaudit(security_id_t ssid,
747*2d543d20SAndroid Build Coastguard Worker 			 security_id_t tsid,
748*2d543d20SAndroid Build Coastguard Worker 			 security_class_t tclass,
749*2d543d20SAndroid Build Coastguard Worker 			 access_vector_t requested,
750*2d543d20SAndroid Build Coastguard Worker 			 struct avc_entry_ref *aeref, struct av_decision *avd)
751*2d543d20SAndroid Build Coastguard Worker {
752*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry *ae;
753*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
754*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry entry;
755*2d543d20SAndroid Build Coastguard Worker 	access_vector_t denied;
756*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry_ref ref;
757*2d543d20SAndroid Build Coastguard Worker 
758*2d543d20SAndroid Build Coastguard Worker 	if (avd)
759*2d543d20SAndroid Build Coastguard Worker 		avd_init(avd);
760*2d543d20SAndroid Build Coastguard Worker 
761*2d543d20SAndroid Build Coastguard Worker 	if (!avc_using_threads && !avc_app_main_loop) {
762*2d543d20SAndroid Build Coastguard Worker 		(void) selinux_status_updated();
763*2d543d20SAndroid Build Coastguard Worker 	}
764*2d543d20SAndroid Build Coastguard Worker 
765*2d543d20SAndroid Build Coastguard Worker 	if (!aeref) {
766*2d543d20SAndroid Build Coastguard Worker 		avc_entry_ref_init(&ref);
767*2d543d20SAndroid Build Coastguard Worker 		aeref = &ref;
768*2d543d20SAndroid Build Coastguard Worker 	}
769*2d543d20SAndroid Build Coastguard Worker 
770*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
771*2d543d20SAndroid Build Coastguard Worker 	avc_cache_stats_incr(entry_lookups);
772*2d543d20SAndroid Build Coastguard Worker 	ae = aeref->ae;
773*2d543d20SAndroid Build Coastguard Worker 	if (ae) {
774*2d543d20SAndroid Build Coastguard Worker 		if (ae->ssid == ssid &&
775*2d543d20SAndroid Build Coastguard Worker 		    ae->tsid == tsid &&
776*2d543d20SAndroid Build Coastguard Worker 		    ae->tclass == tclass &&
777*2d543d20SAndroid Build Coastguard Worker 		    ((ae->avd.decided & requested) == requested)) {
778*2d543d20SAndroid Build Coastguard Worker 			avc_cache_stats_incr(entry_hits);
779*2d543d20SAndroid Build Coastguard Worker 			ae->used = 1;
780*2d543d20SAndroid Build Coastguard Worker 		} else {
781*2d543d20SAndroid Build Coastguard Worker 			avc_cache_stats_incr(entry_discards);
782*2d543d20SAndroid Build Coastguard Worker 			ae = 0;
783*2d543d20SAndroid Build Coastguard Worker 		}
784*2d543d20SAndroid Build Coastguard Worker 	}
785*2d543d20SAndroid Build Coastguard Worker 
786*2d543d20SAndroid Build Coastguard Worker 	if (!ae) {
787*2d543d20SAndroid Build Coastguard Worker 		avc_cache_stats_incr(entry_misses);
788*2d543d20SAndroid Build Coastguard Worker 		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
789*2d543d20SAndroid Build Coastguard Worker 		if (rc) {
790*2d543d20SAndroid Build Coastguard Worker 			rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
791*2d543d20SAndroid Build Coastguard Worker 							   tclass, requested,
792*2d543d20SAndroid Build Coastguard Worker 							   &entry.avd);
793*2d543d20SAndroid Build Coastguard Worker 			if (rc && errno == EINVAL && !avc_enforcing) {
794*2d543d20SAndroid Build Coastguard Worker 				rc = errno = 0;
795*2d543d20SAndroid Build Coastguard Worker 				goto out;
796*2d543d20SAndroid Build Coastguard Worker 			}
797*2d543d20SAndroid Build Coastguard Worker 			if (rc)
798*2d543d20SAndroid Build Coastguard Worker 				goto out;
799*2d543d20SAndroid Build Coastguard Worker 			rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
800*2d543d20SAndroid Build Coastguard Worker 			if (rc)
801*2d543d20SAndroid Build Coastguard Worker 				goto out;
802*2d543d20SAndroid Build Coastguard Worker 		}
803*2d543d20SAndroid Build Coastguard Worker 		ae = aeref->ae;
804*2d543d20SAndroid Build Coastguard Worker 	}
805*2d543d20SAndroid Build Coastguard Worker 
806*2d543d20SAndroid Build Coastguard Worker 	if (avd)
807*2d543d20SAndroid Build Coastguard Worker 		memcpy(avd, &ae->avd, sizeof(*avd));
808*2d543d20SAndroid Build Coastguard Worker 
809*2d543d20SAndroid Build Coastguard Worker 	denied = requested & ~(ae->avd.allowed);
810*2d543d20SAndroid Build Coastguard Worker 
811*2d543d20SAndroid Build Coastguard Worker 	if (!requested || denied) {
812*2d543d20SAndroid Build Coastguard Worker 		if (!avc_enforcing ||
813*2d543d20SAndroid Build Coastguard Worker 		    (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
814*2d543d20SAndroid Build Coastguard Worker 			ae->avd.allowed |= requested;
815*2d543d20SAndroid Build Coastguard Worker 		else {
816*2d543d20SAndroid Build Coastguard Worker 			errno = EACCES;
817*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
818*2d543d20SAndroid Build Coastguard Worker 		}
819*2d543d20SAndroid Build Coastguard Worker 	}
820*2d543d20SAndroid Build Coastguard Worker 
821*2d543d20SAndroid Build Coastguard Worker       out:
822*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
823*2d543d20SAndroid Build Coastguard Worker 	return rc;
824*2d543d20SAndroid Build Coastguard Worker }
825*2d543d20SAndroid Build Coastguard Worker 
826*2d543d20SAndroid Build Coastguard Worker 
avc_has_perm(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct avc_entry_ref * aeref,void * auditdata)827*2d543d20SAndroid Build Coastguard Worker int avc_has_perm(security_id_t ssid, security_id_t tsid,
828*2d543d20SAndroid Build Coastguard Worker 		 security_class_t tclass, access_vector_t requested,
829*2d543d20SAndroid Build Coastguard Worker 		 struct avc_entry_ref *aeref, void *auditdata)
830*2d543d20SAndroid Build Coastguard Worker {
831*2d543d20SAndroid Build Coastguard Worker 	struct av_decision avd;
832*2d543d20SAndroid Build Coastguard Worker 	int errsave, rc;
833*2d543d20SAndroid Build Coastguard Worker 
834*2d543d20SAndroid Build Coastguard Worker 	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
835*2d543d20SAndroid Build Coastguard Worker 	errsave = errno;
836*2d543d20SAndroid Build Coastguard Worker 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
837*2d543d20SAndroid Build Coastguard Worker 	errno = errsave;
838*2d543d20SAndroid Build Coastguard Worker 	return rc;
839*2d543d20SAndroid Build Coastguard Worker }
840*2d543d20SAndroid Build Coastguard Worker 
avc_compute_create(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)841*2d543d20SAndroid Build Coastguard Worker int avc_compute_create(security_id_t ssid,  security_id_t tsid,
842*2d543d20SAndroid Build Coastguard Worker 		       security_class_t tclass, security_id_t *newsid)
843*2d543d20SAndroid Build Coastguard Worker {
844*2d543d20SAndroid Build Coastguard Worker 	int rc;
845*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry_ref aeref;
846*2d543d20SAndroid Build Coastguard Worker 	struct avc_entry entry;
847*2d543d20SAndroid Build Coastguard Worker 	char * ctx;
848*2d543d20SAndroid Build Coastguard Worker 
849*2d543d20SAndroid Build Coastguard Worker 	*newsid = NULL;
850*2d543d20SAndroid Build Coastguard Worker 	avc_entry_ref_init(&aeref);
851*2d543d20SAndroid Build Coastguard Worker 
852*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
853*2d543d20SAndroid Build Coastguard Worker 
854*2d543d20SAndroid Build Coastguard Worker 	/* check for a cached entry */
855*2d543d20SAndroid Build Coastguard Worker 	rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
856*2d543d20SAndroid Build Coastguard Worker 	if (rc) {
857*2d543d20SAndroid Build Coastguard Worker 		/* need to make a cache entry for this tuple */
858*2d543d20SAndroid Build Coastguard Worker 		rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
859*2d543d20SAndroid Build Coastguard Worker 						   tclass, 0, &entry.avd);
860*2d543d20SAndroid Build Coastguard Worker 		if (rc)
861*2d543d20SAndroid Build Coastguard Worker 			goto out;
862*2d543d20SAndroid Build Coastguard Worker 		rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
863*2d543d20SAndroid Build Coastguard Worker 		if (rc)
864*2d543d20SAndroid Build Coastguard Worker 			goto out;
865*2d543d20SAndroid Build Coastguard Worker 	}
866*2d543d20SAndroid Build Coastguard Worker 
867*2d543d20SAndroid Build Coastguard Worker 	/* check for a saved compute_create value */
868*2d543d20SAndroid Build Coastguard Worker 	if (!aeref.ae->create_sid) {
869*2d543d20SAndroid Build Coastguard Worker 		/* need to query the kernel policy */
870*2d543d20SAndroid Build Coastguard Worker 		rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass,
871*2d543d20SAndroid Build Coastguard Worker 						 &ctx);
872*2d543d20SAndroid Build Coastguard Worker 		if (rc)
873*2d543d20SAndroid Build Coastguard Worker 			goto out;
874*2d543d20SAndroid Build Coastguard Worker 		rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
875*2d543d20SAndroid Build Coastguard Worker 		freecon(ctx);
876*2d543d20SAndroid Build Coastguard Worker 		if (rc)
877*2d543d20SAndroid Build Coastguard Worker 			goto out;
878*2d543d20SAndroid Build Coastguard Worker 
879*2d543d20SAndroid Build Coastguard Worker 		aeref.ae->create_sid = *newsid;
880*2d543d20SAndroid Build Coastguard Worker 	} else {
881*2d543d20SAndroid Build Coastguard Worker 		/* found saved value */
882*2d543d20SAndroid Build Coastguard Worker 		*newsid = aeref.ae->create_sid;
883*2d543d20SAndroid Build Coastguard Worker 	}
884*2d543d20SAndroid Build Coastguard Worker 
885*2d543d20SAndroid Build Coastguard Worker 	rc = 0;
886*2d543d20SAndroid Build Coastguard Worker out:
887*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
888*2d543d20SAndroid Build Coastguard Worker 	return rc;
889*2d543d20SAndroid Build Coastguard Worker }
890*2d543d20SAndroid Build Coastguard Worker 
avc_compute_member(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)891*2d543d20SAndroid Build Coastguard Worker int avc_compute_member(security_id_t ssid,  security_id_t tsid,
892*2d543d20SAndroid Build Coastguard Worker 		       security_class_t tclass, security_id_t *newsid)
893*2d543d20SAndroid Build Coastguard Worker {
894*2d543d20SAndroid Build Coastguard Worker 	int rc;
895*2d543d20SAndroid Build Coastguard Worker 	char * ctx = NULL;
896*2d543d20SAndroid Build Coastguard Worker 	*newsid = NULL;
897*2d543d20SAndroid Build Coastguard Worker 	/* avc_init needs to be called before this function */
898*2d543d20SAndroid Build Coastguard Worker 	assert(avc_running);
899*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
900*2d543d20SAndroid Build Coastguard Worker 
901*2d543d20SAndroid Build Coastguard Worker 	rc = security_compute_member_raw(ssid->ctx, tsid->ctx, tclass, &ctx);
902*2d543d20SAndroid Build Coastguard Worker 	if (rc)
903*2d543d20SAndroid Build Coastguard Worker 		goto out;
904*2d543d20SAndroid Build Coastguard Worker 	rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
905*2d543d20SAndroid Build Coastguard Worker 	freecon(ctx);
906*2d543d20SAndroid Build Coastguard Worker out:
907*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
908*2d543d20SAndroid Build Coastguard Worker 	return rc;
909*2d543d20SAndroid Build Coastguard Worker }
910*2d543d20SAndroid Build Coastguard Worker 
avc_add_callback(int (* callback)(uint32_t event,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,access_vector_t * out_retained),uint32_t events,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms)911*2d543d20SAndroid Build Coastguard Worker int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid,
912*2d543d20SAndroid Build Coastguard Worker 				      security_id_t tsid,
913*2d543d20SAndroid Build Coastguard Worker 				      security_class_t tclass,
914*2d543d20SAndroid Build Coastguard Worker 				      access_vector_t perms,
915*2d543d20SAndroid Build Coastguard Worker 				      access_vector_t * out_retained),
916*2d543d20SAndroid Build Coastguard Worker 		     uint32_t events, security_id_t ssid,
917*2d543d20SAndroid Build Coastguard Worker 		     security_id_t tsid,
918*2d543d20SAndroid Build Coastguard Worker 		     security_class_t tclass, access_vector_t perms)
919*2d543d20SAndroid Build Coastguard Worker {
920*2d543d20SAndroid Build Coastguard Worker 	struct avc_callback_node *c;
921*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
922*2d543d20SAndroid Build Coastguard Worker 
923*2d543d20SAndroid Build Coastguard Worker 	c = avc_malloc(sizeof(*c));
924*2d543d20SAndroid Build Coastguard Worker 	if (!c) {
925*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
926*2d543d20SAndroid Build Coastguard Worker 		goto out;
927*2d543d20SAndroid Build Coastguard Worker 	}
928*2d543d20SAndroid Build Coastguard Worker 
929*2d543d20SAndroid Build Coastguard Worker 	c->callback = callback;
930*2d543d20SAndroid Build Coastguard Worker 	c->events = events;
931*2d543d20SAndroid Build Coastguard Worker 	c->ssid = ssid;
932*2d543d20SAndroid Build Coastguard Worker 	c->tsid = tsid;
933*2d543d20SAndroid Build Coastguard Worker 	c->tclass = tclass;
934*2d543d20SAndroid Build Coastguard Worker 	c->perms = perms;
935*2d543d20SAndroid Build Coastguard Worker 	c->next = avc_callbacks;
936*2d543d20SAndroid Build Coastguard Worker 	avc_callbacks = c;
937*2d543d20SAndroid Build Coastguard Worker       out:
938*2d543d20SAndroid Build Coastguard Worker 	return rc;
939*2d543d20SAndroid Build Coastguard Worker }
940*2d543d20SAndroid Build Coastguard Worker 
avc_sidcmp(security_id_t x,security_id_t y)941*2d543d20SAndroid Build Coastguard Worker static inline int avc_sidcmp(security_id_t x, security_id_t y)
942*2d543d20SAndroid Build Coastguard Worker {
943*2d543d20SAndroid Build Coastguard Worker 	return (x == y || x == SECSID_WILD || y == SECSID_WILD);
944*2d543d20SAndroid Build Coastguard Worker }
945*2d543d20SAndroid Build Coastguard Worker 
avc_update_node(uint32_t event,struct avc_node * node,access_vector_t perms)946*2d543d20SAndroid Build Coastguard Worker static inline void avc_update_node(uint32_t event, struct avc_node *node,
947*2d543d20SAndroid Build Coastguard Worker 				   access_vector_t perms)
948*2d543d20SAndroid Build Coastguard Worker {
949*2d543d20SAndroid Build Coastguard Worker 	switch (event) {
950*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_GRANT:
951*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.allowed |= perms;
952*2d543d20SAndroid Build Coastguard Worker 		break;
953*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_TRY_REVOKE:
954*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_REVOKE:
955*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.allowed &= ~perms;
956*2d543d20SAndroid Build Coastguard Worker 		break;
957*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_AUDITALLOW_ENABLE:
958*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.auditallow |= perms;
959*2d543d20SAndroid Build Coastguard Worker 		break;
960*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_AUDITALLOW_DISABLE:
961*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.auditallow &= ~perms;
962*2d543d20SAndroid Build Coastguard Worker 		break;
963*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_AUDITDENY_ENABLE:
964*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.auditdeny |= perms;
965*2d543d20SAndroid Build Coastguard Worker 		break;
966*2d543d20SAndroid Build Coastguard Worker 	case AVC_CALLBACK_AUDITDENY_DISABLE:
967*2d543d20SAndroid Build Coastguard Worker 		node->ae.avd.auditdeny &= ~perms;
968*2d543d20SAndroid Build Coastguard Worker 		break;
969*2d543d20SAndroid Build Coastguard Worker 	}
970*2d543d20SAndroid Build Coastguard Worker }
971*2d543d20SAndroid Build Coastguard Worker 
avc_update_cache(uint32_t event,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms)972*2d543d20SAndroid Build Coastguard Worker static int avc_update_cache(uint32_t event, security_id_t ssid,
973*2d543d20SAndroid Build Coastguard Worker 			    security_id_t tsid, security_class_t tclass,
974*2d543d20SAndroid Build Coastguard Worker 			    access_vector_t perms)
975*2d543d20SAndroid Build Coastguard Worker {
976*2d543d20SAndroid Build Coastguard Worker 	struct avc_node *node;
977*2d543d20SAndroid Build Coastguard Worker 	int i;
978*2d543d20SAndroid Build Coastguard Worker 
979*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
980*2d543d20SAndroid Build Coastguard Worker 
981*2d543d20SAndroid Build Coastguard Worker 	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
982*2d543d20SAndroid Build Coastguard Worker 		/* apply to all matching nodes */
983*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < AVC_CACHE_SLOTS; i++) {
984*2d543d20SAndroid Build Coastguard Worker 			for (node = avc_cache.slots[i]; node; node = node->next) {
985*2d543d20SAndroid Build Coastguard Worker 				if (avc_sidcmp(ssid, node->ae.ssid) &&
986*2d543d20SAndroid Build Coastguard Worker 				    avc_sidcmp(tsid, node->ae.tsid) &&
987*2d543d20SAndroid Build Coastguard Worker 				    tclass == node->ae.tclass) {
988*2d543d20SAndroid Build Coastguard Worker 					avc_update_node(event, node, perms);
989*2d543d20SAndroid Build Coastguard Worker 				}
990*2d543d20SAndroid Build Coastguard Worker 			}
991*2d543d20SAndroid Build Coastguard Worker 		}
992*2d543d20SAndroid Build Coastguard Worker 	} else {
993*2d543d20SAndroid Build Coastguard Worker 		/* apply to one node */
994*2d543d20SAndroid Build Coastguard Worker 		node = avc_search_node(ssid, tsid, tclass, 0);
995*2d543d20SAndroid Build Coastguard Worker 		if (node) {
996*2d543d20SAndroid Build Coastguard Worker 			avc_update_node(event, node, perms);
997*2d543d20SAndroid Build Coastguard Worker 		}
998*2d543d20SAndroid Build Coastguard Worker 	}
999*2d543d20SAndroid Build Coastguard Worker 
1000*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
1001*2d543d20SAndroid Build Coastguard Worker 
1002*2d543d20SAndroid Build Coastguard Worker 	return 0;
1003*2d543d20SAndroid Build Coastguard Worker }
1004*2d543d20SAndroid Build Coastguard Worker 
1005*2d543d20SAndroid Build Coastguard Worker /* avc_control - update cache and call callbacks
1006*2d543d20SAndroid Build Coastguard Worker  *
1007*2d543d20SAndroid Build Coastguard Worker  * This should not be called directly; use the individual event
1008*2d543d20SAndroid Build Coastguard Worker  * functions instead.
1009*2d543d20SAndroid Build Coastguard Worker  */
avc_control(uint32_t event,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno,access_vector_t * out_retained)1010*2d543d20SAndroid Build Coastguard Worker static int avc_control(uint32_t event, security_id_t ssid,
1011*2d543d20SAndroid Build Coastguard Worker 		       security_id_t tsid, security_class_t tclass,
1012*2d543d20SAndroid Build Coastguard Worker 		       access_vector_t perms,
1013*2d543d20SAndroid Build Coastguard Worker 		       uint32_t seqno, access_vector_t * out_retained)
1014*2d543d20SAndroid Build Coastguard Worker {
1015*2d543d20SAndroid Build Coastguard Worker 	struct avc_callback_node *c;
1016*2d543d20SAndroid Build Coastguard Worker 	access_vector_t tretained = 0, cretained = 0;
1017*2d543d20SAndroid Build Coastguard Worker 	int ret, rc = 0, errsave = 0;
1018*2d543d20SAndroid Build Coastguard Worker 	errno = 0;
1019*2d543d20SAndroid Build Coastguard Worker 
1020*2d543d20SAndroid Build Coastguard Worker 	/*
1021*2d543d20SAndroid Build Coastguard Worker 	 * try_revoke only removes permissions from the cache
1022*2d543d20SAndroid Build Coastguard Worker 	 * state if they are not retained by the object manager.
1023*2d543d20SAndroid Build Coastguard Worker 	 * Hence, try_revoke must wait until after the callbacks have
1024*2d543d20SAndroid Build Coastguard Worker 	 * been invoked to update the cache state.
1025*2d543d20SAndroid Build Coastguard Worker 	 */
1026*2d543d20SAndroid Build Coastguard Worker 	if (event != AVC_CALLBACK_TRY_REVOKE)
1027*2d543d20SAndroid Build Coastguard Worker 		avc_update_cache(event, ssid, tsid, tclass, perms);
1028*2d543d20SAndroid Build Coastguard Worker 
1029*2d543d20SAndroid Build Coastguard Worker 	for (c = avc_callbacks; c; c = c->next) {
1030*2d543d20SAndroid Build Coastguard Worker 		if ((c->events & event) &&
1031*2d543d20SAndroid Build Coastguard Worker 		    avc_sidcmp(c->ssid, ssid) &&
1032*2d543d20SAndroid Build Coastguard Worker 		    avc_sidcmp(c->tsid, tsid) &&
1033*2d543d20SAndroid Build Coastguard Worker 		    c->tclass == tclass && (c->perms & perms)) {
1034*2d543d20SAndroid Build Coastguard Worker 			cretained = 0;
1035*2d543d20SAndroid Build Coastguard Worker 			ret = c->callback(event, ssid, tsid, tclass,
1036*2d543d20SAndroid Build Coastguard Worker 					  (c->perms & perms), &cretained);
1037*2d543d20SAndroid Build Coastguard Worker 			if (ret && !rc) {
1038*2d543d20SAndroid Build Coastguard Worker 				rc = ret;
1039*2d543d20SAndroid Build Coastguard Worker 				errsave = errno;
1040*2d543d20SAndroid Build Coastguard Worker 			}
1041*2d543d20SAndroid Build Coastguard Worker 			if (!ret)
1042*2d543d20SAndroid Build Coastguard Worker 				tretained |= cretained;
1043*2d543d20SAndroid Build Coastguard Worker 		}
1044*2d543d20SAndroid Build Coastguard Worker 	}
1045*2d543d20SAndroid Build Coastguard Worker 
1046*2d543d20SAndroid Build Coastguard Worker 	if (event == AVC_CALLBACK_TRY_REVOKE) {
1047*2d543d20SAndroid Build Coastguard Worker 		/* revoke any unretained permissions */
1048*2d543d20SAndroid Build Coastguard Worker 		perms &= ~tretained;
1049*2d543d20SAndroid Build Coastguard Worker 		avc_update_cache(event, ssid, tsid, tclass, perms);
1050*2d543d20SAndroid Build Coastguard Worker 		*out_retained = tretained;
1051*2d543d20SAndroid Build Coastguard Worker 	}
1052*2d543d20SAndroid Build Coastguard Worker 
1053*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
1054*2d543d20SAndroid Build Coastguard Worker 	if (seqno > avc_cache.latest_notif)
1055*2d543d20SAndroid Build Coastguard Worker 		avc_cache.latest_notif = seqno;
1056*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
1057*2d543d20SAndroid Build Coastguard Worker 
1058*2d543d20SAndroid Build Coastguard Worker 	errno = errsave;
1059*2d543d20SAndroid Build Coastguard Worker 	return rc;
1060*2d543d20SAndroid Build Coastguard Worker }
1061*2d543d20SAndroid Build Coastguard Worker 
1062*2d543d20SAndroid Build Coastguard Worker /**
1063*2d543d20SAndroid Build Coastguard Worker  * avc_ss_grant - Grant previously denied permissions.
1064*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier or %SECSID_WILD
1065*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier or %SECSID_WILD
1066*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
1067*2d543d20SAndroid Build Coastguard Worker  * @perms: permissions to grant
1068*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1069*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_grant(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1070*2d543d20SAndroid Build Coastguard Worker int avc_ss_grant(security_id_t ssid, security_id_t tsid,
1071*2d543d20SAndroid Build Coastguard Worker 		 security_class_t tclass, access_vector_t perms,
1072*2d543d20SAndroid Build Coastguard Worker 		 uint32_t seqno)
1073*2d543d20SAndroid Build Coastguard Worker {
1074*2d543d20SAndroid Build Coastguard Worker 	return avc_control(AVC_CALLBACK_GRANT,
1075*2d543d20SAndroid Build Coastguard Worker 			   ssid, tsid, tclass, perms, seqno, 0);
1076*2d543d20SAndroid Build Coastguard Worker }
1077*2d543d20SAndroid Build Coastguard Worker 
1078*2d543d20SAndroid Build Coastguard Worker /**
1079*2d543d20SAndroid Build Coastguard Worker  * avc_ss_try_revoke - Try to revoke previously granted permissions.
1080*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier or %SECSID_WILD
1081*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier or %SECSID_WILD
1082*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
1083*2d543d20SAndroid Build Coastguard Worker  * @perms: permissions to grant
1084*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1085*2d543d20SAndroid Build Coastguard Worker  * @out_retained: subset of @perms that are retained
1086*2d543d20SAndroid Build Coastguard Worker  *
1087*2d543d20SAndroid Build Coastguard Worker  * Try to revoke previously granted permissions, but
1088*2d543d20SAndroid Build Coastguard Worker  * only if they are not retained as migrated permissions.
1089*2d543d20SAndroid Build Coastguard Worker  * Return the subset of permissions that are retained via @out_retained.
1090*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_try_revoke(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno,access_vector_t * out_retained)1091*2d543d20SAndroid Build Coastguard Worker int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
1092*2d543d20SAndroid Build Coastguard Worker 		      security_class_t tclass,
1093*2d543d20SAndroid Build Coastguard Worker 		      access_vector_t perms, uint32_t seqno,
1094*2d543d20SAndroid Build Coastguard Worker 		      access_vector_t * out_retained)
1095*2d543d20SAndroid Build Coastguard Worker {
1096*2d543d20SAndroid Build Coastguard Worker 	return avc_control(AVC_CALLBACK_TRY_REVOKE,
1097*2d543d20SAndroid Build Coastguard Worker 			   ssid, tsid, tclass, perms, seqno, out_retained);
1098*2d543d20SAndroid Build Coastguard Worker }
1099*2d543d20SAndroid Build Coastguard Worker 
1100*2d543d20SAndroid Build Coastguard Worker /**
1101*2d543d20SAndroid Build Coastguard Worker  * avc_ss_revoke - Revoke previously granted permissions.
1102*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier or %SECSID_WILD
1103*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier or %SECSID_WILD
1104*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
1105*2d543d20SAndroid Build Coastguard Worker  * @perms: permissions to grant
1106*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1107*2d543d20SAndroid Build Coastguard Worker  *
1108*2d543d20SAndroid Build Coastguard Worker  * Revoke previously granted permissions, even if
1109*2d543d20SAndroid Build Coastguard Worker  * they are retained as migrated permissions.
1110*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_revoke(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1111*2d543d20SAndroid Build Coastguard Worker int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
1112*2d543d20SAndroid Build Coastguard Worker 		  security_class_t tclass, access_vector_t perms,
1113*2d543d20SAndroid Build Coastguard Worker 		  uint32_t seqno)
1114*2d543d20SAndroid Build Coastguard Worker {
1115*2d543d20SAndroid Build Coastguard Worker 	return avc_control(AVC_CALLBACK_REVOKE,
1116*2d543d20SAndroid Build Coastguard Worker 			   ssid, tsid, tclass, perms, seqno, 0);
1117*2d543d20SAndroid Build Coastguard Worker }
1118*2d543d20SAndroid Build Coastguard Worker 
1119*2d543d20SAndroid Build Coastguard Worker /**
1120*2d543d20SAndroid Build Coastguard Worker  * avc_ss_reset - Flush the cache and revalidate migrated permissions.
1121*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1122*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_reset(uint32_t seqno)1123*2d543d20SAndroid Build Coastguard Worker int avc_ss_reset(uint32_t seqno)
1124*2d543d20SAndroid Build Coastguard Worker {
1125*2d543d20SAndroid Build Coastguard Worker 	int rc;
1126*2d543d20SAndroid Build Coastguard Worker 
1127*2d543d20SAndroid Build Coastguard Worker 	rc = avc_reset();
1128*2d543d20SAndroid Build Coastguard Worker 
1129*2d543d20SAndroid Build Coastguard Worker 	avc_get_lock(avc_lock);
1130*2d543d20SAndroid Build Coastguard Worker 	if (seqno > avc_cache.latest_notif)
1131*2d543d20SAndroid Build Coastguard Worker 		avc_cache.latest_notif = seqno;
1132*2d543d20SAndroid Build Coastguard Worker 	avc_release_lock(avc_lock);
1133*2d543d20SAndroid Build Coastguard Worker 
1134*2d543d20SAndroid Build Coastguard Worker 	return rc;
1135*2d543d20SAndroid Build Coastguard Worker }
1136*2d543d20SAndroid Build Coastguard Worker 
1137*2d543d20SAndroid Build Coastguard Worker /**
1138*2d543d20SAndroid Build Coastguard Worker  * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
1139*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier or %SECSID_WILD
1140*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier or %SECSID_WILD
1141*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
1142*2d543d20SAndroid Build Coastguard Worker  * @perms: permissions to grant
1143*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1144*2d543d20SAndroid Build Coastguard Worker  * @enable: enable flag.
1145*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_set_auditallow(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno,uint32_t enable)1146*2d543d20SAndroid Build Coastguard Worker int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
1147*2d543d20SAndroid Build Coastguard Worker 			  security_class_t tclass, access_vector_t perms,
1148*2d543d20SAndroid Build Coastguard Worker 			  uint32_t seqno, uint32_t enable)
1149*2d543d20SAndroid Build Coastguard Worker {
1150*2d543d20SAndroid Build Coastguard Worker 	if (enable)
1151*2d543d20SAndroid Build Coastguard Worker 		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
1152*2d543d20SAndroid Build Coastguard Worker 				   ssid, tsid, tclass, perms, seqno, 0);
1153*2d543d20SAndroid Build Coastguard Worker 	else
1154*2d543d20SAndroid Build Coastguard Worker 		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
1155*2d543d20SAndroid Build Coastguard Worker 				   ssid, tsid, tclass, perms, seqno, 0);
1156*2d543d20SAndroid Build Coastguard Worker }
1157*2d543d20SAndroid Build Coastguard Worker 
1158*2d543d20SAndroid Build Coastguard Worker /**
1159*2d543d20SAndroid Build Coastguard Worker  * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
1160*2d543d20SAndroid Build Coastguard Worker  * @ssid: source security identifier or %SECSID_WILD
1161*2d543d20SAndroid Build Coastguard Worker  * @tsid: target security identifier or %SECSID_WILD
1162*2d543d20SAndroid Build Coastguard Worker  * @tclass: target security class
1163*2d543d20SAndroid Build Coastguard Worker  * @perms: permissions to grant
1164*2d543d20SAndroid Build Coastguard Worker  * @seqno: policy sequence number
1165*2d543d20SAndroid Build Coastguard Worker  * @enable: enable flag.
1166*2d543d20SAndroid Build Coastguard Worker  */
avc_ss_set_auditdeny(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno,uint32_t enable)1167*2d543d20SAndroid Build Coastguard Worker int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
1168*2d543d20SAndroid Build Coastguard Worker 			 security_class_t tclass, access_vector_t perms,
1169*2d543d20SAndroid Build Coastguard Worker 			 uint32_t seqno, uint32_t enable)
1170*2d543d20SAndroid Build Coastguard Worker {
1171*2d543d20SAndroid Build Coastguard Worker 	if (enable)
1172*2d543d20SAndroid Build Coastguard Worker 		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
1173*2d543d20SAndroid Build Coastguard Worker 				   ssid, tsid, tclass, perms, seqno, 0);
1174*2d543d20SAndroid Build Coastguard Worker 	else
1175*2d543d20SAndroid Build Coastguard Worker 		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
1176*2d543d20SAndroid Build Coastguard Worker 				   ssid, tsid, tclass, perms, seqno, 0);
1177*2d543d20SAndroid Build Coastguard Worker }
1178