1255e72915d4cbddceb435e13d81601755714e9fSE Android/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
2255e72915d4cbddceb435e13d81601755714e9fSE Android/*
3255e72915d4cbddceb435e13d81601755714e9fSE Android * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
4255e72915d4cbddceb435e13d81601755714e9fSE Android *
5255e72915d4cbddceb435e13d81601755714e9fSE Android *	Support for enhanced MLS infrastructure.
6255e72915d4cbddceb435e13d81601755714e9fSE Android *
7255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
8255e72915d4cbddceb435e13d81601755714e9fSE Android *
9255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is free software; you can redistribute it and/or
10255e72915d4cbddceb435e13d81601755714e9fSE Android *  modify it under the terms of the GNU Lesser General Public
11255e72915d4cbddceb435e13d81601755714e9fSE Android *  License as published by the Free Software Foundation; either
12255e72915d4cbddceb435e13d81601755714e9fSE Android *  version 2.1 of the License, or (at your option) any later version.
13255e72915d4cbddceb435e13d81601755714e9fSE Android *
14255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is distributed in the hope that it will be useful,
15255e72915d4cbddceb435e13d81601755714e9fSE Android *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16255e72915d4cbddceb435e13d81601755714e9fSE Android *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17255e72915d4cbddceb435e13d81601755714e9fSE Android *  Lesser General Public License for more details.
18255e72915d4cbddceb435e13d81601755714e9fSE Android *
19255e72915d4cbddceb435e13d81601755714e9fSE Android *  You should have received a copy of the GNU Lesser General Public
20255e72915d4cbddceb435e13d81601755714e9fSE Android *  License along with this library; if not, write to the Free Software
21255e72915d4cbddceb435e13d81601755714e9fSE Android *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22255e72915d4cbddceb435e13d81601755714e9fSE Android */
23255e72915d4cbddceb435e13d81601755714e9fSE Android
24255e72915d4cbddceb435e13d81601755714e9fSE Android/* FLASK */
25255e72915d4cbddceb435e13d81601755714e9fSE Android
26255e72915d4cbddceb435e13d81601755714e9fSE Android/*
27255e72915d4cbddceb435e13d81601755714e9fSE Android * Implementation of the multi-level security (MLS) policy.
28255e72915d4cbddceb435e13d81601755714e9fSE Android */
29255e72915d4cbddceb435e13d81601755714e9fSE Android
30255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h>
31255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/services.h>
32255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/flask.h>
33255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/context.h>
34255e72915d4cbddceb435e13d81601755714e9fSE Android
35255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
36255e72915d4cbddceb435e13d81601755714e9fSE Android
37255e72915d4cbddceb435e13d81601755714e9fSE Android#include "handle.h"
38255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
39255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h"
40255e72915d4cbddceb435e13d81601755714e9fSE Android#include "mls.h"
41255e72915d4cbddceb435e13d81601755714e9fSE Android
42255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_to_string(sepol_handle_t * handle,
43255e72915d4cbddceb435e13d81601755714e9fSE Android		  const policydb_t * policydb,
44255e72915d4cbddceb435e13d81601755714e9fSE Android		  const context_struct_t * mls, char **str)
45255e72915d4cbddceb435e13d81601755714e9fSE Android{
46255e72915d4cbddceb435e13d81601755714e9fSE Android
47255e72915d4cbddceb435e13d81601755714e9fSE Android	char *ptr = NULL, *ptr2 = NULL;
48255e72915d4cbddceb435e13d81601755714e9fSE Android
49255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Temporary buffer - length + NULL terminator */
50255e72915d4cbddceb435e13d81601755714e9fSE Android	int len = mls_compute_context_len(policydb, mls) + 1;
51255e72915d4cbddceb435e13d81601755714e9fSE Android
52255e72915d4cbddceb435e13d81601755714e9fSE Android	ptr = (char *)malloc(len);
53255e72915d4cbddceb435e13d81601755714e9fSE Android	if (ptr == NULL)
54255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
55255e72915d4cbddceb435e13d81601755714e9fSE Android
56255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Final string w/ ':' cut off */
57255e72915d4cbddceb435e13d81601755714e9fSE Android	ptr2 = (char *)malloc(len - 1);
58255e72915d4cbddceb435e13d81601755714e9fSE Android	if (ptr2 == NULL)
59255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
60255e72915d4cbddceb435e13d81601755714e9fSE Android
61255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_sid_to_context(policydb, mls, &ptr);
62255e72915d4cbddceb435e13d81601755714e9fSE Android	ptr -= len - 1;
63255e72915d4cbddceb435e13d81601755714e9fSE Android	strcpy(ptr2, ptr + 1);
64255e72915d4cbddceb435e13d81601755714e9fSE Android
65255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ptr);
66255e72915d4cbddceb435e13d81601755714e9fSE Android	*str = ptr2;
67255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
68255e72915d4cbddceb435e13d81601755714e9fSE Android
69255e72915d4cbddceb435e13d81601755714e9fSE Android      omem:
70255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "out of memory, could not convert mls context to string");
71255e72915d4cbddceb435e13d81601755714e9fSE Android
72255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ptr);
73255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ptr2);
74255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
75255e72915d4cbddceb435e13d81601755714e9fSE Android
76255e72915d4cbddceb435e13d81601755714e9fSE Android}
77255e72915d4cbddceb435e13d81601755714e9fSE Android
78255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_from_string(sepol_handle_t * handle,
79255e72915d4cbddceb435e13d81601755714e9fSE Android		    const policydb_t * policydb,
80255e72915d4cbddceb435e13d81601755714e9fSE Android		    const char *str, context_struct_t * mls)
81255e72915d4cbddceb435e13d81601755714e9fSE Android{
82255e72915d4cbddceb435e13d81601755714e9fSE Android
83255e72915d4cbddceb435e13d81601755714e9fSE Android	char *tmp = strdup(str);
84255e72915d4cbddceb435e13d81601755714e9fSE Android	char *tmp_cp = tmp;
85255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tmp)
86255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
87255e72915d4cbddceb435e13d81601755714e9fSE Android
88255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls_context_to_sid(policydb, '$', &tmp_cp, mls) < 0) {
89255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "invalid MLS context %s", str);
90255e72915d4cbddceb435e13d81601755714e9fSE Android		free(tmp);
91255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
92255e72915d4cbddceb435e13d81601755714e9fSE Android	}
93255e72915d4cbddceb435e13d81601755714e9fSE Android
94255e72915d4cbddceb435e13d81601755714e9fSE Android	free(tmp);
95255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
96255e72915d4cbddceb435e13d81601755714e9fSE Android
97255e72915d4cbddceb435e13d81601755714e9fSE Android      omem:
98255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "out of memory");
99255e72915d4cbddceb435e13d81601755714e9fSE Android
100255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
101255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not construct mls context structure");
102255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
103255e72915d4cbddceb435e13d81601755714e9fSE Android}
104255e72915d4cbddceb435e13d81601755714e9fSE Android
105255e72915d4cbddceb435e13d81601755714e9fSE Android/*
106255e72915d4cbddceb435e13d81601755714e9fSE Android * Return the length in bytes for the MLS fields of the
107255e72915d4cbddceb435e13d81601755714e9fSE Android * security context string representation of `context'.
108255e72915d4cbddceb435e13d81601755714e9fSE Android */
109255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_compute_context_len(const policydb_t * policydb,
110255e72915d4cbddceb435e13d81601755714e9fSE Android			    const context_struct_t * context)
111255e72915d4cbddceb435e13d81601755714e9fSE Android{
112255e72915d4cbddceb435e13d81601755714e9fSE Android
113255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, l, len, range;
114255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *cnode;
115255e72915d4cbddceb435e13d81601755714e9fSE Android
116255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb->mls)
117255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
118255e72915d4cbddceb435e13d81601755714e9fSE Android
119255e72915d4cbddceb435e13d81601755714e9fSE Android	len = 1;		/* for the beginning ":" */
120255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
121255e72915d4cbddceb435e13d81601755714e9fSE Android		range = 0;
122255e72915d4cbddceb435e13d81601755714e9fSE Android		len +=
123255e72915d4cbddceb435e13d81601755714e9fSE Android		    strlen(policydb->
124255e72915d4cbddceb435e13d81601755714e9fSE Android			   p_sens_val_to_name[context->range.level[l].sens -
125255e72915d4cbddceb435e13d81601755714e9fSE Android					      1]);
126255e72915d4cbddceb435e13d81601755714e9fSE Android
127255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) {
128255e72915d4cbddceb435e13d81601755714e9fSE Android			if (ebitmap_node_get_bit(cnode, i)) {
129255e72915d4cbddceb435e13d81601755714e9fSE Android				if (range) {
130255e72915d4cbddceb435e13d81601755714e9fSE Android					range++;
131255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
132255e72915d4cbddceb435e13d81601755714e9fSE Android				}
133255e72915d4cbddceb435e13d81601755714e9fSE Android
134255e72915d4cbddceb435e13d81601755714e9fSE Android				len +=
135255e72915d4cbddceb435e13d81601755714e9fSE Android				    strlen(policydb->p_cat_val_to_name[i]) + 1;
136255e72915d4cbddceb435e13d81601755714e9fSE Android				range++;
137255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
138255e72915d4cbddceb435e13d81601755714e9fSE Android				if (range > 1)
139255e72915d4cbddceb435e13d81601755714e9fSE Android					len +=
140255e72915d4cbddceb435e13d81601755714e9fSE Android					    strlen(policydb->
141255e72915d4cbddceb435e13d81601755714e9fSE Android						   p_cat_val_to_name[i - 1]) +
142255e72915d4cbddceb435e13d81601755714e9fSE Android					    1;
143255e72915d4cbddceb435e13d81601755714e9fSE Android				range = 0;
144255e72915d4cbddceb435e13d81601755714e9fSE Android			}
145255e72915d4cbddceb435e13d81601755714e9fSE Android		}
146255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Handle case where last category is the end of range */
147255e72915d4cbddceb435e13d81601755714e9fSE Android		if (range > 1)
148255e72915d4cbddceb435e13d81601755714e9fSE Android			len += strlen(policydb->p_cat_val_to_name[i - 1]) + 1;
149255e72915d4cbddceb435e13d81601755714e9fSE Android
150255e72915d4cbddceb435e13d81601755714e9fSE Android		if (l == 0) {
151255e72915d4cbddceb435e13d81601755714e9fSE Android			if (mls_level_eq(&context->range.level[0],
152255e72915d4cbddceb435e13d81601755714e9fSE Android					 &context->range.level[1]))
153255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
154255e72915d4cbddceb435e13d81601755714e9fSE Android			else
155255e72915d4cbddceb435e13d81601755714e9fSE Android				len++;
156255e72915d4cbddceb435e13d81601755714e9fSE Android		}
157255e72915d4cbddceb435e13d81601755714e9fSE Android	}
158255e72915d4cbddceb435e13d81601755714e9fSE Android
159255e72915d4cbddceb435e13d81601755714e9fSE Android	return len;
160255e72915d4cbddceb435e13d81601755714e9fSE Android}
161255e72915d4cbddceb435e13d81601755714e9fSE Android
162255e72915d4cbddceb435e13d81601755714e9fSE Android/*
163255e72915d4cbddceb435e13d81601755714e9fSE Android * Write the security context string representation of
164255e72915d4cbddceb435e13d81601755714e9fSE Android * the MLS fields of `context' into the string `*scontext'.
165255e72915d4cbddceb435e13d81601755714e9fSE Android * Update `*scontext' to point to the end of the MLS fields.
166255e72915d4cbddceb435e13d81601755714e9fSE Android */
167255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_sid_to_context(const policydb_t * policydb,
168255e72915d4cbddceb435e13d81601755714e9fSE Android			const context_struct_t * context, char **scontext)
169255e72915d4cbddceb435e13d81601755714e9fSE Android{
170255e72915d4cbddceb435e13d81601755714e9fSE Android
171255e72915d4cbddceb435e13d81601755714e9fSE Android	char *scontextp;
172255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, l, range, wrote_sep;
173255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *cnode;
174255e72915d4cbddceb435e13d81601755714e9fSE Android
175255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb->mls)
176255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
177255e72915d4cbddceb435e13d81601755714e9fSE Android
178255e72915d4cbddceb435e13d81601755714e9fSE Android	scontextp = *scontext;
179255e72915d4cbddceb435e13d81601755714e9fSE Android
180255e72915d4cbddceb435e13d81601755714e9fSE Android	*scontextp = ':';
181255e72915d4cbddceb435e13d81601755714e9fSE Android	scontextp++;
182255e72915d4cbddceb435e13d81601755714e9fSE Android
183255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
184255e72915d4cbddceb435e13d81601755714e9fSE Android		range = 0;
185255e72915d4cbddceb435e13d81601755714e9fSE Android		wrote_sep = 0;
186255e72915d4cbddceb435e13d81601755714e9fSE Android		strcpy(scontextp,
187255e72915d4cbddceb435e13d81601755714e9fSE Android		       policydb->p_sens_val_to_name[context->range.level[l].
188255e72915d4cbddceb435e13d81601755714e9fSE Android						    sens - 1]);
189255e72915d4cbddceb435e13d81601755714e9fSE Android		scontextp +=
190255e72915d4cbddceb435e13d81601755714e9fSE Android		    strlen(policydb->
191255e72915d4cbddceb435e13d81601755714e9fSE Android			   p_sens_val_to_name[context->range.level[l].sens -
192255e72915d4cbddceb435e13d81601755714e9fSE Android					      1]);
193255e72915d4cbddceb435e13d81601755714e9fSE Android		/* categories */
194255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) {
195255e72915d4cbddceb435e13d81601755714e9fSE Android			if (ebitmap_node_get_bit(cnode, i)) {
196255e72915d4cbddceb435e13d81601755714e9fSE Android				if (range) {
197255e72915d4cbddceb435e13d81601755714e9fSE Android					range++;
198255e72915d4cbddceb435e13d81601755714e9fSE Android					continue;
199255e72915d4cbddceb435e13d81601755714e9fSE Android				}
200255e72915d4cbddceb435e13d81601755714e9fSE Android
201255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!wrote_sep) {
202255e72915d4cbddceb435e13d81601755714e9fSE Android					*scontextp++ = ':';
203255e72915d4cbddceb435e13d81601755714e9fSE Android					wrote_sep = 1;
204255e72915d4cbddceb435e13d81601755714e9fSE Android				} else
205255e72915d4cbddceb435e13d81601755714e9fSE Android					*scontextp++ = ',';
206255e72915d4cbddceb435e13d81601755714e9fSE Android				strcpy(scontextp,
207255e72915d4cbddceb435e13d81601755714e9fSE Android				       policydb->p_cat_val_to_name[i]);
208255e72915d4cbddceb435e13d81601755714e9fSE Android				scontextp +=
209255e72915d4cbddceb435e13d81601755714e9fSE Android				    strlen(policydb->p_cat_val_to_name[i]);
210255e72915d4cbddceb435e13d81601755714e9fSE Android				range++;
211255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
212255e72915d4cbddceb435e13d81601755714e9fSE Android				if (range > 1) {
213255e72915d4cbddceb435e13d81601755714e9fSE Android					if (range > 2)
214255e72915d4cbddceb435e13d81601755714e9fSE Android						*scontextp++ = '.';
215255e72915d4cbddceb435e13d81601755714e9fSE Android					else
216255e72915d4cbddceb435e13d81601755714e9fSE Android						*scontextp++ = ',';
217255e72915d4cbddceb435e13d81601755714e9fSE Android
218255e72915d4cbddceb435e13d81601755714e9fSE Android					strcpy(scontextp,
219255e72915d4cbddceb435e13d81601755714e9fSE Android					       policydb->p_cat_val_to_name[i -
220255e72915d4cbddceb435e13d81601755714e9fSE Android									   1]);
221255e72915d4cbddceb435e13d81601755714e9fSE Android					scontextp +=
222255e72915d4cbddceb435e13d81601755714e9fSE Android					    strlen(policydb->
223255e72915d4cbddceb435e13d81601755714e9fSE Android						   p_cat_val_to_name[i - 1]);
224255e72915d4cbddceb435e13d81601755714e9fSE Android				}
225255e72915d4cbddceb435e13d81601755714e9fSE Android				range = 0;
226255e72915d4cbddceb435e13d81601755714e9fSE Android			}
227255e72915d4cbddceb435e13d81601755714e9fSE Android		}
228255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Handle case where last category is the end of range */
229255e72915d4cbddceb435e13d81601755714e9fSE Android		if (range > 1) {
230255e72915d4cbddceb435e13d81601755714e9fSE Android			if (range > 2)
231255e72915d4cbddceb435e13d81601755714e9fSE Android				*scontextp++ = '.';
232255e72915d4cbddceb435e13d81601755714e9fSE Android			else
233255e72915d4cbddceb435e13d81601755714e9fSE Android				*scontextp++ = ',';
234255e72915d4cbddceb435e13d81601755714e9fSE Android
235255e72915d4cbddceb435e13d81601755714e9fSE Android			strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]);
236255e72915d4cbddceb435e13d81601755714e9fSE Android			scontextp += strlen(policydb->p_cat_val_to_name[i - 1]);
237255e72915d4cbddceb435e13d81601755714e9fSE Android		}
238255e72915d4cbddceb435e13d81601755714e9fSE Android
239255e72915d4cbddceb435e13d81601755714e9fSE Android		if (l == 0) {
240255e72915d4cbddceb435e13d81601755714e9fSE Android			if (mls_level_eq(&context->range.level[0],
241255e72915d4cbddceb435e13d81601755714e9fSE Android					 &context->range.level[1]))
242255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
243255e72915d4cbddceb435e13d81601755714e9fSE Android			else {
244255e72915d4cbddceb435e13d81601755714e9fSE Android				*scontextp = '-';
245255e72915d4cbddceb435e13d81601755714e9fSE Android				scontextp++;
246255e72915d4cbddceb435e13d81601755714e9fSE Android			}
247255e72915d4cbddceb435e13d81601755714e9fSE Android		}
248255e72915d4cbddceb435e13d81601755714e9fSE Android	}
249255e72915d4cbddceb435e13d81601755714e9fSE Android
250255e72915d4cbddceb435e13d81601755714e9fSE Android	*scontext = scontextp;
251255e72915d4cbddceb435e13d81601755714e9fSE Android	return;
252255e72915d4cbddceb435e13d81601755714e9fSE Android}
253255e72915d4cbddceb435e13d81601755714e9fSE Android
254255e72915d4cbddceb435e13d81601755714e9fSE Android/*
255255e72915d4cbddceb435e13d81601755714e9fSE Android * Return 1 if the MLS fields in the security context
256255e72915d4cbddceb435e13d81601755714e9fSE Android * structure `c' are valid.  Return 0 otherwise.
257255e72915d4cbddceb435e13d81601755714e9fSE Android */
258255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_context_isvalid(const policydb_t * p, const context_struct_t * c)
259255e72915d4cbddceb435e13d81601755714e9fSE Android{
260255e72915d4cbddceb435e13d81601755714e9fSE Android
261255e72915d4cbddceb435e13d81601755714e9fSE Android	level_datum_t *levdatum;
262255e72915d4cbddceb435e13d81601755714e9fSE Android	user_datum_t *usrdatum;
263255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, l;
264255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *cnode;
265255e72915d4cbddceb435e13d81601755714e9fSE Android
266255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!p->mls)
267255e72915d4cbddceb435e13d81601755714e9fSE Android		return 1;
268255e72915d4cbddceb435e13d81601755714e9fSE Android
269255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
270255e72915d4cbddceb435e13d81601755714e9fSE Android	 * MLS range validity checks: high must dominate low, low level must
271255e72915d4cbddceb435e13d81601755714e9fSE Android	 * be valid (category set <-> sensitivity check), and high level must
272255e72915d4cbddceb435e13d81601755714e9fSE Android	 * be valid (category set <-> sensitivity check)
273255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
274255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
275255e72915d4cbddceb435e13d81601755714e9fSE Android		/* High does not dominate low. */
276255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
277255e72915d4cbddceb435e13d81601755714e9fSE Android
278255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
279255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!c->range.level[l].sens
280255e72915d4cbddceb435e13d81601755714e9fSE Android		    || c->range.level[l].sens > p->p_levels.nprim)
281255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
282255e72915d4cbddceb435e13d81601755714e9fSE Android		levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
283255e72915d4cbddceb435e13d81601755714e9fSE Android							    p->
284255e72915d4cbddceb435e13d81601755714e9fSE Android							    p_sens_val_to_name
285255e72915d4cbddceb435e13d81601755714e9fSE Android							    [c->range.level[l].
286255e72915d4cbddceb435e13d81601755714e9fSE Android							     sens - 1]);
287255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!levdatum)
288255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
289255e72915d4cbddceb435e13d81601755714e9fSE Android
290255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(&c->range.level[l].cat, cnode, i) {
291255e72915d4cbddceb435e13d81601755714e9fSE Android			if (ebitmap_node_get_bit(cnode, i)) {
292255e72915d4cbddceb435e13d81601755714e9fSE Android				if (i > p->p_cats.nprim)
293255e72915d4cbddceb435e13d81601755714e9fSE Android					return 0;
294255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!ebitmap_get_bit(&levdatum->level->cat, i))
295255e72915d4cbddceb435e13d81601755714e9fSE Android					/*
296255e72915d4cbddceb435e13d81601755714e9fSE Android					 * Category may not be associated with
297255e72915d4cbddceb435e13d81601755714e9fSE Android					 * sensitivity in low level.
298255e72915d4cbddceb435e13d81601755714e9fSE Android					 */
299255e72915d4cbddceb435e13d81601755714e9fSE Android					return 0;
300255e72915d4cbddceb435e13d81601755714e9fSE Android			}
301255e72915d4cbddceb435e13d81601755714e9fSE Android		}
302255e72915d4cbddceb435e13d81601755714e9fSE Android	}
303255e72915d4cbddceb435e13d81601755714e9fSE Android
304255e72915d4cbddceb435e13d81601755714e9fSE Android	if (c->role == OBJECT_R_VAL)
305255e72915d4cbddceb435e13d81601755714e9fSE Android		return 1;
306255e72915d4cbddceb435e13d81601755714e9fSE Android
307255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
308255e72915d4cbddceb435e13d81601755714e9fSE Android	 * User must be authorized for the MLS range.
309255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
310255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!c->user || c->user > p->p_users.nprim)
311255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
312255e72915d4cbddceb435e13d81601755714e9fSE Android	usrdatum = p->user_val_to_struct[c->user - 1];
313255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!mls_range_contains(usrdatum->exp_range, c->range))
314255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;	/* user may not be associated with range */
315255e72915d4cbddceb435e13d81601755714e9fSE Android
316255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
317255e72915d4cbddceb435e13d81601755714e9fSE Android}
318255e72915d4cbddceb435e13d81601755714e9fSE Android
319255e72915d4cbddceb435e13d81601755714e9fSE Android/*
320255e72915d4cbddceb435e13d81601755714e9fSE Android * Set the MLS fields in the security context structure
321255e72915d4cbddceb435e13d81601755714e9fSE Android * `context' based on the string representation in
322255e72915d4cbddceb435e13d81601755714e9fSE Android * the string `*scontext'.  Update `*scontext' to
323255e72915d4cbddceb435e13d81601755714e9fSE Android * point to the end of the string representation of
324255e72915d4cbddceb435e13d81601755714e9fSE Android * the MLS fields.
325255e72915d4cbddceb435e13d81601755714e9fSE Android *
326255e72915d4cbddceb435e13d81601755714e9fSE Android * This function modifies the string in place, inserting
327255e72915d4cbddceb435e13d81601755714e9fSE Android * NULL characters to terminate the MLS fields.
328255e72915d4cbddceb435e13d81601755714e9fSE Android */
329255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_context_to_sid(const policydb_t * policydb,
330255e72915d4cbddceb435e13d81601755714e9fSE Android		       char oldc, char **scontext, context_struct_t * context)
331255e72915d4cbddceb435e13d81601755714e9fSE Android{
332255e72915d4cbddceb435e13d81601755714e9fSE Android
333255e72915d4cbddceb435e13d81601755714e9fSE Android	char delim;
334255e72915d4cbddceb435e13d81601755714e9fSE Android	char *scontextp, *p, *rngptr;
335255e72915d4cbddceb435e13d81601755714e9fSE Android	level_datum_t *levdatum;
336255e72915d4cbddceb435e13d81601755714e9fSE Android	cat_datum_t *catdatum, *rngdatum;
337255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int l;
338255e72915d4cbddceb435e13d81601755714e9fSE Android
339255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb->mls)
340255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
341255e72915d4cbddceb435e13d81601755714e9fSE Android
342255e72915d4cbddceb435e13d81601755714e9fSE Android	/* No MLS component to the security context */
343255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!oldc)
344255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
345255e72915d4cbddceb435e13d81601755714e9fSE Android
346255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Extract low sensitivity. */
347255e72915d4cbddceb435e13d81601755714e9fSE Android	scontextp = p = *scontext;
348255e72915d4cbddceb435e13d81601755714e9fSE Android	while (*p && *p != ':' && *p != '-')
349255e72915d4cbddceb435e13d81601755714e9fSE Android		p++;
350255e72915d4cbddceb435e13d81601755714e9fSE Android
351255e72915d4cbddceb435e13d81601755714e9fSE Android	delim = *p;
352255e72915d4cbddceb435e13d81601755714e9fSE Android	if (delim != 0)
353255e72915d4cbddceb435e13d81601755714e9fSE Android		*p++ = 0;
354255e72915d4cbddceb435e13d81601755714e9fSE Android
355255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
356255e72915d4cbddceb435e13d81601755714e9fSE Android		levdatum =
357255e72915d4cbddceb435e13d81601755714e9fSE Android		    (level_datum_t *) hashtab_search(policydb->p_levels.table,
358255e72915d4cbddceb435e13d81601755714e9fSE Android						     (hashtab_key_t) scontextp);
359255e72915d4cbddceb435e13d81601755714e9fSE Android
360255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!levdatum)
361255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
362255e72915d4cbddceb435e13d81601755714e9fSE Android
363255e72915d4cbddceb435e13d81601755714e9fSE Android		context->range.level[l].sens = levdatum->level->sens;
364255e72915d4cbddceb435e13d81601755714e9fSE Android
365255e72915d4cbddceb435e13d81601755714e9fSE Android		if (delim == ':') {
366255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Extract category set. */
367255e72915d4cbddceb435e13d81601755714e9fSE Android			while (1) {
368255e72915d4cbddceb435e13d81601755714e9fSE Android				scontextp = p;
369255e72915d4cbddceb435e13d81601755714e9fSE Android				while (*p && *p != ',' && *p != '-')
370255e72915d4cbddceb435e13d81601755714e9fSE Android					p++;
371255e72915d4cbddceb435e13d81601755714e9fSE Android				delim = *p;
372255e72915d4cbddceb435e13d81601755714e9fSE Android				if (delim != 0)
373255e72915d4cbddceb435e13d81601755714e9fSE Android					*p++ = 0;
374255e72915d4cbddceb435e13d81601755714e9fSE Android
375255e72915d4cbddceb435e13d81601755714e9fSE Android				/* Separate into range if exists */
376255e72915d4cbddceb435e13d81601755714e9fSE Android				if ((rngptr = strchr(scontextp, '.')) != NULL) {
377255e72915d4cbddceb435e13d81601755714e9fSE Android					/* Remove '.' */
378255e72915d4cbddceb435e13d81601755714e9fSE Android					*rngptr++ = 0;
379255e72915d4cbddceb435e13d81601755714e9fSE Android				}
380255e72915d4cbddceb435e13d81601755714e9fSE Android
381255e72915d4cbddceb435e13d81601755714e9fSE Android				catdatum =
382255e72915d4cbddceb435e13d81601755714e9fSE Android				    (cat_datum_t *) hashtab_search(policydb->
383255e72915d4cbddceb435e13d81601755714e9fSE Android								   p_cats.table,
384255e72915d4cbddceb435e13d81601755714e9fSE Android								   (hashtab_key_t)
385255e72915d4cbddceb435e13d81601755714e9fSE Android								   scontextp);
386255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!catdatum)
387255e72915d4cbddceb435e13d81601755714e9fSE Android					goto err;
388255e72915d4cbddceb435e13d81601755714e9fSE Android
389255e72915d4cbddceb435e13d81601755714e9fSE Android				if (ebitmap_set_bit
390255e72915d4cbddceb435e13d81601755714e9fSE Android				    (&context->range.level[l].cat,
391255e72915d4cbddceb435e13d81601755714e9fSE Android				     catdatum->s.value - 1, 1))
392255e72915d4cbddceb435e13d81601755714e9fSE Android					goto err;
393255e72915d4cbddceb435e13d81601755714e9fSE Android
394255e72915d4cbddceb435e13d81601755714e9fSE Android				/* If range, set all categories in range */
395255e72915d4cbddceb435e13d81601755714e9fSE Android				if (rngptr) {
396255e72915d4cbddceb435e13d81601755714e9fSE Android					unsigned int i;
397255e72915d4cbddceb435e13d81601755714e9fSE Android
398255e72915d4cbddceb435e13d81601755714e9fSE Android					rngdatum = (cat_datum_t *)
399255e72915d4cbddceb435e13d81601755714e9fSE Android					    hashtab_search(policydb->p_cats.
400255e72915d4cbddceb435e13d81601755714e9fSE Android							   table,
401255e72915d4cbddceb435e13d81601755714e9fSE Android							   (hashtab_key_t)
402255e72915d4cbddceb435e13d81601755714e9fSE Android							   rngptr);
403255e72915d4cbddceb435e13d81601755714e9fSE Android					if (!rngdatum)
404255e72915d4cbddceb435e13d81601755714e9fSE Android						goto err;
405255e72915d4cbddceb435e13d81601755714e9fSE Android
406255e72915d4cbddceb435e13d81601755714e9fSE Android					if (catdatum->s.value >=
407255e72915d4cbddceb435e13d81601755714e9fSE Android					    rngdatum->s.value)
408255e72915d4cbddceb435e13d81601755714e9fSE Android						goto err;
409255e72915d4cbddceb435e13d81601755714e9fSE Android
410255e72915d4cbddceb435e13d81601755714e9fSE Android					for (i = catdatum->s.value;
411255e72915d4cbddceb435e13d81601755714e9fSE Android					     i < rngdatum->s.value; i++) {
412255e72915d4cbddceb435e13d81601755714e9fSE Android						if (ebitmap_set_bit
413255e72915d4cbddceb435e13d81601755714e9fSE Android						    (&context->range.level[l].
414255e72915d4cbddceb435e13d81601755714e9fSE Android						     cat, i, 1))
415255e72915d4cbddceb435e13d81601755714e9fSE Android							goto err;
416255e72915d4cbddceb435e13d81601755714e9fSE Android					}
417255e72915d4cbddceb435e13d81601755714e9fSE Android				}
418255e72915d4cbddceb435e13d81601755714e9fSE Android
419255e72915d4cbddceb435e13d81601755714e9fSE Android				if (delim != ',')
420255e72915d4cbddceb435e13d81601755714e9fSE Android					break;
421255e72915d4cbddceb435e13d81601755714e9fSE Android			}
422255e72915d4cbddceb435e13d81601755714e9fSE Android		}
423255e72915d4cbddceb435e13d81601755714e9fSE Android		if (delim == '-') {
424255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Extract high sensitivity. */
425255e72915d4cbddceb435e13d81601755714e9fSE Android			scontextp = p;
426255e72915d4cbddceb435e13d81601755714e9fSE Android			while (*p && *p != ':')
427255e72915d4cbddceb435e13d81601755714e9fSE Android				p++;
428255e72915d4cbddceb435e13d81601755714e9fSE Android
429255e72915d4cbddceb435e13d81601755714e9fSE Android			delim = *p;
430255e72915d4cbddceb435e13d81601755714e9fSE Android			if (delim != 0)
431255e72915d4cbddceb435e13d81601755714e9fSE Android				*p++ = 0;
432255e72915d4cbddceb435e13d81601755714e9fSE Android		} else
433255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
434255e72915d4cbddceb435e13d81601755714e9fSE Android	}
435255e72915d4cbddceb435e13d81601755714e9fSE Android
436255e72915d4cbddceb435e13d81601755714e9fSE Android	/* High level is missing, copy low level */
437255e72915d4cbddceb435e13d81601755714e9fSE Android	if (l == 0) {
438255e72915d4cbddceb435e13d81601755714e9fSE Android		if (mls_level_cpy(&context->range.level[1],
439255e72915d4cbddceb435e13d81601755714e9fSE Android				  &context->range.level[0]) < 0)
440255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
441255e72915d4cbddceb435e13d81601755714e9fSE Android	}
442255e72915d4cbddceb435e13d81601755714e9fSE Android	*scontext = ++p;
443255e72915d4cbddceb435e13d81601755714e9fSE Android
444255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
445255e72915d4cbddceb435e13d81601755714e9fSE Android
446255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
447255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
448255e72915d4cbddceb435e13d81601755714e9fSE Android}
449255e72915d4cbddceb435e13d81601755714e9fSE Android
450255e72915d4cbddceb435e13d81601755714e9fSE Android/*
451255e72915d4cbddceb435e13d81601755714e9fSE Android * Copies the MLS range from `src' into `dst'.
452255e72915d4cbddceb435e13d81601755714e9fSE Android */
453255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int mls_copy_context(context_struct_t * dst,
454255e72915d4cbddceb435e13d81601755714e9fSE Android				   context_struct_t * src)
455255e72915d4cbddceb435e13d81601755714e9fSE Android{
456255e72915d4cbddceb435e13d81601755714e9fSE Android	int l, rc = 0;
457255e72915d4cbddceb435e13d81601755714e9fSE Android
458255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Copy the MLS range from the source context */
459255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
460255e72915d4cbddceb435e13d81601755714e9fSE Android		dst->range.level[l].sens = src->range.level[l].sens;
461255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = ebitmap_cpy(&dst->range.level[l].cat,
462255e72915d4cbddceb435e13d81601755714e9fSE Android				 &src->range.level[l].cat);
463255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
464255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
465255e72915d4cbddceb435e13d81601755714e9fSE Android	}
466255e72915d4cbddceb435e13d81601755714e9fSE Android
467255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
468255e72915d4cbddceb435e13d81601755714e9fSE Android}
469255e72915d4cbddceb435e13d81601755714e9fSE Android
470255e72915d4cbddceb435e13d81601755714e9fSE Android/*
471255e72915d4cbddceb435e13d81601755714e9fSE Android * Copies the effective MLS range from `src' into `dst'.
472255e72915d4cbddceb435e13d81601755714e9fSE Android */
473255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int mls_scopy_context(context_struct_t * dst,
474255e72915d4cbddceb435e13d81601755714e9fSE Android				    context_struct_t * src)
475255e72915d4cbddceb435e13d81601755714e9fSE Android{
476255e72915d4cbddceb435e13d81601755714e9fSE Android	int l, rc = 0;
477255e72915d4cbddceb435e13d81601755714e9fSE Android
478255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Copy the MLS range from the source context */
479255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
480255e72915d4cbddceb435e13d81601755714e9fSE Android		dst->range.level[l].sens = src->range.level[0].sens;
481255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = ebitmap_cpy(&dst->range.level[l].cat,
482255e72915d4cbddceb435e13d81601755714e9fSE Android				 &src->range.level[0].cat);
483255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
484255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
485255e72915d4cbddceb435e13d81601755714e9fSE Android	}
486255e72915d4cbddceb435e13d81601755714e9fSE Android
487255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
488255e72915d4cbddceb435e13d81601755714e9fSE Android}
489255e72915d4cbddceb435e13d81601755714e9fSE Android
490255e72915d4cbddceb435e13d81601755714e9fSE Android/*
491255e72915d4cbddceb435e13d81601755714e9fSE Android * Copies the MLS range `range' into `context'.
492255e72915d4cbddceb435e13d81601755714e9fSE Android */
493255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int mls_range_set(context_struct_t * context, mls_range_t * range)
494255e72915d4cbddceb435e13d81601755714e9fSE Android{
495255e72915d4cbddceb435e13d81601755714e9fSE Android	int l, rc = 0;
496255e72915d4cbddceb435e13d81601755714e9fSE Android
497255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Copy the MLS range into the  context */
498255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
499255e72915d4cbddceb435e13d81601755714e9fSE Android		context->range.level[l].sens = range->level[l].sens;
500255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = ebitmap_cpy(&context->range.level[l].cat,
501255e72915d4cbddceb435e13d81601755714e9fSE Android				 &range->level[l].cat);
502255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
503255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
504255e72915d4cbddceb435e13d81601755714e9fSE Android	}
505255e72915d4cbddceb435e13d81601755714e9fSE Android
506255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
507255e72915d4cbddceb435e13d81601755714e9fSE Android}
508255e72915d4cbddceb435e13d81601755714e9fSE Android
509255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user,
510255e72915d4cbddceb435e13d81601755714e9fSE Android			 context_struct_t * usercon, int mls)
511255e72915d4cbddceb435e13d81601755714e9fSE Android{
512255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls) {
513255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
514255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);
515255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *user_low = &(user->exp_range.level[0]);
516255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *user_clr = &(user->exp_range.level[1]);
517255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *user_def = &(user->exp_dfltlevel);
518255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *usercon_sen = &(usercon->range.level[0]);
519255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_level_t *usercon_clr = &(usercon->range.level[1]);
520255e72915d4cbddceb435e13d81601755714e9fSE Android
521255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Honor the user's default level if we can */
522255e72915d4cbddceb435e13d81601755714e9fSE Android		if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
523255e72915d4cbddceb435e13d81601755714e9fSE Android			*usercon_sen = *user_def;
524255e72915d4cbddceb435e13d81601755714e9fSE Android		} else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
525255e72915d4cbddceb435e13d81601755714e9fSE Android			*usercon_sen = *fromcon_sen;
526255e72915d4cbddceb435e13d81601755714e9fSE Android		} else if (mls_level_between(fromcon_clr, user_low, user_def)) {
527255e72915d4cbddceb435e13d81601755714e9fSE Android			*usercon_sen = *user_low;
528255e72915d4cbddceb435e13d81601755714e9fSE Android		} else
529255e72915d4cbddceb435e13d81601755714e9fSE Android			return -EINVAL;
530255e72915d4cbddceb435e13d81601755714e9fSE Android
531255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Lower the clearance of available contexts
532255e72915d4cbddceb435e13d81601755714e9fSE Android		   if the clearance of "fromcon" is lower than
533255e72915d4cbddceb435e13d81601755714e9fSE Android		   that of the user's default clearance (but
534255e72915d4cbddceb435e13d81601755714e9fSE Android		   only if the "fromcon" clearance dominates
535255e72915d4cbddceb435e13d81601755714e9fSE Android		   the user's computed sensitivity level) */
536255e72915d4cbddceb435e13d81601755714e9fSE Android		if (mls_level_dom(user_clr, fromcon_clr)) {
537255e72915d4cbddceb435e13d81601755714e9fSE Android			*usercon_clr = *fromcon_clr;
538255e72915d4cbddceb435e13d81601755714e9fSE Android		} else if (mls_level_dom(fromcon_clr, user_clr)) {
539255e72915d4cbddceb435e13d81601755714e9fSE Android			*usercon_clr = *user_clr;
540255e72915d4cbddceb435e13d81601755714e9fSE Android		} else
541255e72915d4cbddceb435e13d81601755714e9fSE Android			return -EINVAL;
542255e72915d4cbddceb435e13d81601755714e9fSE Android	}
543255e72915d4cbddceb435e13d81601755714e9fSE Android
544255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
545255e72915d4cbddceb435e13d81601755714e9fSE Android}
546255e72915d4cbddceb435e13d81601755714e9fSE Android
547255e72915d4cbddceb435e13d81601755714e9fSE Android/*
548255e72915d4cbddceb435e13d81601755714e9fSE Android * Convert the MLS fields in the security context
549255e72915d4cbddceb435e13d81601755714e9fSE Android * structure `c' from the values specified in the
550255e72915d4cbddceb435e13d81601755714e9fSE Android * policy `oldp' to the values specified in the policy `newp'.
551255e72915d4cbddceb435e13d81601755714e9fSE Android */
552255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_convert_context(policydb_t * oldp,
553255e72915d4cbddceb435e13d81601755714e9fSE Android			policydb_t * newp, context_struct_t * c)
554255e72915d4cbddceb435e13d81601755714e9fSE Android{
555255e72915d4cbddceb435e13d81601755714e9fSE Android	level_datum_t *levdatum;
556255e72915d4cbddceb435e13d81601755714e9fSE Android	cat_datum_t *catdatum;
557255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_t bitmap;
558255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int l, i;
559255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *cnode;
560255e72915d4cbddceb435e13d81601755714e9fSE Android
561255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!oldp->mls)
562255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
563255e72915d4cbddceb435e13d81601755714e9fSE Android
564255e72915d4cbddceb435e13d81601755714e9fSE Android	for (l = 0; l < 2; l++) {
565255e72915d4cbddceb435e13d81601755714e9fSE Android		levdatum =
566255e72915d4cbddceb435e13d81601755714e9fSE Android		    (level_datum_t *) hashtab_search(newp->p_levels.table,
567255e72915d4cbddceb435e13d81601755714e9fSE Android						     oldp->
568255e72915d4cbddceb435e13d81601755714e9fSE Android						     p_sens_val_to_name[c->
569255e72915d4cbddceb435e13d81601755714e9fSE Android									range.
570255e72915d4cbddceb435e13d81601755714e9fSE Android									level
571255e72915d4cbddceb435e13d81601755714e9fSE Android									[l].
572255e72915d4cbddceb435e13d81601755714e9fSE Android									sens -
573255e72915d4cbddceb435e13d81601755714e9fSE Android									1]);
574255e72915d4cbddceb435e13d81601755714e9fSE Android
575255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!levdatum)
576255e72915d4cbddceb435e13d81601755714e9fSE Android			return -EINVAL;
577255e72915d4cbddceb435e13d81601755714e9fSE Android		c->range.level[l].sens = levdatum->level->sens;
578255e72915d4cbddceb435e13d81601755714e9fSE Android
579255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_init(&bitmap);
580255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_for_each_bit(&c->range.level[l].cat, cnode, i) {
581255e72915d4cbddceb435e13d81601755714e9fSE Android			if (ebitmap_node_get_bit(cnode, i)) {
582255e72915d4cbddceb435e13d81601755714e9fSE Android				int rc;
583255e72915d4cbddceb435e13d81601755714e9fSE Android
584255e72915d4cbddceb435e13d81601755714e9fSE Android				catdatum =
585255e72915d4cbddceb435e13d81601755714e9fSE Android				    (cat_datum_t *) hashtab_search(newp->p_cats.
586255e72915d4cbddceb435e13d81601755714e9fSE Android								   table,
587255e72915d4cbddceb435e13d81601755714e9fSE Android								   oldp->
588255e72915d4cbddceb435e13d81601755714e9fSE Android								   p_cat_val_to_name
589255e72915d4cbddceb435e13d81601755714e9fSE Android								   [i]);
590255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!catdatum)
591255e72915d4cbddceb435e13d81601755714e9fSE Android					return -EINVAL;
592255e72915d4cbddceb435e13d81601755714e9fSE Android				rc = ebitmap_set_bit(&bitmap,
593255e72915d4cbddceb435e13d81601755714e9fSE Android						     catdatum->s.value - 1, 1);
594255e72915d4cbddceb435e13d81601755714e9fSE Android				if (rc)
595255e72915d4cbddceb435e13d81601755714e9fSE Android					return rc;
596255e72915d4cbddceb435e13d81601755714e9fSE Android			}
597255e72915d4cbddceb435e13d81601755714e9fSE Android		}
598255e72915d4cbddceb435e13d81601755714e9fSE Android		ebitmap_destroy(&c->range.level[l].cat);
599255e72915d4cbddceb435e13d81601755714e9fSE Android		c->range.level[l].cat = bitmap;
600255e72915d4cbddceb435e13d81601755714e9fSE Android	}
601255e72915d4cbddceb435e13d81601755714e9fSE Android
602255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
603255e72915d4cbddceb435e13d81601755714e9fSE Android}
604255e72915d4cbddceb435e13d81601755714e9fSE Android
605255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_compute_sid(policydb_t * policydb,
606255e72915d4cbddceb435e13d81601755714e9fSE Android		    context_struct_t * scontext,
607255e72915d4cbddceb435e13d81601755714e9fSE Android		    context_struct_t * tcontext,
608255e72915d4cbddceb435e13d81601755714e9fSE Android		    sepol_security_class_t tclass,
609255e72915d4cbddceb435e13d81601755714e9fSE Android		    uint32_t specified, context_struct_t * newcontext)
610255e72915d4cbddceb435e13d81601755714e9fSE Android{
611255e72915d4cbddceb435e13d81601755714e9fSE Android	range_trans_t *rtr;
612255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!policydb->mls)
613255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
614255e72915d4cbddceb435e13d81601755714e9fSE Android
615255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (specified) {
616255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_TRANSITION:
617255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Look for a range transition rule. */
618255e72915d4cbddceb435e13d81601755714e9fSE Android		for (rtr = policydb->range_tr; rtr; rtr = rtr->next) {
619255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rtr->source_type == scontext->type &&
620255e72915d4cbddceb435e13d81601755714e9fSE Android			    rtr->target_type == tcontext->type &&
621255e72915d4cbddceb435e13d81601755714e9fSE Android			    rtr->target_class == tclass) {
622255e72915d4cbddceb435e13d81601755714e9fSE Android				/* Set the range from the rule */
623255e72915d4cbddceb435e13d81601755714e9fSE Android				return mls_range_set(newcontext,
624255e72915d4cbddceb435e13d81601755714e9fSE Android						     &rtr->target_range);
625255e72915d4cbddceb435e13d81601755714e9fSE Android			}
626255e72915d4cbddceb435e13d81601755714e9fSE Android		}
627255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Fallthrough */
628255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_CHANGE:
629255e72915d4cbddceb435e13d81601755714e9fSE Android		if (tclass == SECCLASS_PROCESS)
630255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Use the process MLS attributes. */
631255e72915d4cbddceb435e13d81601755714e9fSE Android			return mls_copy_context(newcontext, scontext);
632255e72915d4cbddceb435e13d81601755714e9fSE Android		else
633255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Use the process effective MLS attributes. */
634255e72915d4cbddceb435e13d81601755714e9fSE Android			return mls_scopy_context(newcontext, scontext);
635255e72915d4cbddceb435e13d81601755714e9fSE Android	case AVTAB_MEMBER:
636255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Only polyinstantiate the MLS attributes if
637255e72915d4cbddceb435e13d81601755714e9fSE Android		   the type is being polyinstantiated */
638255e72915d4cbddceb435e13d81601755714e9fSE Android		if (newcontext->type != tcontext->type) {
639255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Use the process effective MLS attributes. */
640255e72915d4cbddceb435e13d81601755714e9fSE Android			return mls_scopy_context(newcontext, scontext);
641255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
642255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Use the related object MLS attributes. */
643255e72915d4cbddceb435e13d81601755714e9fSE Android			return mls_copy_context(newcontext, tcontext);
644255e72915d4cbddceb435e13d81601755714e9fSE Android		}
645255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
646255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
647255e72915d4cbddceb435e13d81601755714e9fSE Android	}
648255e72915d4cbddceb435e13d81601755714e9fSE Android	return -EINVAL;
649255e72915d4cbddceb435e13d81601755714e9fSE Android}
650255e72915d4cbddceb435e13d81601755714e9fSE Android
651255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_mls_contains(sepol_handle_t * handle,
652255e72915d4cbddceb435e13d81601755714e9fSE Android		       sepol_policydb_t * policydb,
653255e72915d4cbddceb435e13d81601755714e9fSE Android		       const char *mls1, const char *mls2, int *response)
654255e72915d4cbddceb435e13d81601755714e9fSE Android{
655255e72915d4cbddceb435e13d81601755714e9fSE Android
656255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *ctx1 = NULL, *ctx2 = NULL;
657255e72915d4cbddceb435e13d81601755714e9fSE Android	ctx1 = malloc(sizeof(context_struct_t));
658255e72915d4cbddceb435e13d81601755714e9fSE Android	ctx2 = malloc(sizeof(context_struct_t));
659255e72915d4cbddceb435e13d81601755714e9fSE Android	if (ctx1 == NULL || ctx2 == NULL)
660255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
661255e72915d4cbddceb435e13d81601755714e9fSE Android	context_init(ctx1);
662255e72915d4cbddceb435e13d81601755714e9fSE Android	context_init(ctx2);
663255e72915d4cbddceb435e13d81601755714e9fSE Android
664255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls_from_string(handle, &policydb->p, mls1, ctx1) < 0)
665255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
666255e72915d4cbddceb435e13d81601755714e9fSE Android
667255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls_from_string(handle, &policydb->p, mls2, ctx2) < 0)
668255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
669255e72915d4cbddceb435e13d81601755714e9fSE Android
670255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = mls_range_contains(ctx1->range, ctx2->range);
671255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(ctx1);
672255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(ctx2);
673255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ctx1);
674255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ctx2);
675255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
676255e72915d4cbddceb435e13d81601755714e9fSE Android
677255e72915d4cbddceb435e13d81601755714e9fSE Android      omem:
678255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "out of memory");
679255e72915d4cbddceb435e13d81601755714e9fSE Android
680255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
681255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not check if mls context %s contains %s",
682255e72915d4cbddceb435e13d81601755714e9fSE Android	    mls1, mls2);
683255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(ctx1);
684255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(ctx2);
685255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ctx1);
686255e72915d4cbddceb435e13d81601755714e9fSE Android	free(ctx2);
687255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
688255e72915d4cbddceb435e13d81601755714e9fSE Android}
689255e72915d4cbddceb435e13d81601755714e9fSE Android
690255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_mls_check(sepol_handle_t * handle,
691255e72915d4cbddceb435e13d81601755714e9fSE Android		    sepol_policydb_t * policydb, const char *mls)
692255e72915d4cbddceb435e13d81601755714e9fSE Android{
693255e72915d4cbddceb435e13d81601755714e9fSE Android
694255e72915d4cbddceb435e13d81601755714e9fSE Android	int ret;
695255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *con = malloc(sizeof(context_struct_t));
696255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!con) {
697255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "out of memory, could not check if "
698255e72915d4cbddceb435e13d81601755714e9fSE Android		    "mls context %s is valid", mls);
699255e72915d4cbddceb435e13d81601755714e9fSE Android		return STATUS_ERR;
700255e72915d4cbddceb435e13d81601755714e9fSE Android	}
701255e72915d4cbddceb435e13d81601755714e9fSE Android	context_init(con);
702255e72915d4cbddceb435e13d81601755714e9fSE Android
703255e72915d4cbddceb435e13d81601755714e9fSE Android	ret = mls_from_string(handle, &policydb->p, mls, con);
704255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(con);
705255e72915d4cbddceb435e13d81601755714e9fSE Android	free(con);
706255e72915d4cbddceb435e13d81601755714e9fSE Android	return ret;
707255e72915d4cbddceb435e13d81601755714e9fSE Android}
708255e72915d4cbddceb435e13d81601755714e9fSE Android
709255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_cat_init(mls_semantic_cat_t * c)
710255e72915d4cbddceb435e13d81601755714e9fSE Android{
711255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(c, 0, sizeof(mls_semantic_cat_t));
712255e72915d4cbddceb435e13d81601755714e9fSE Android}
713255e72915d4cbddceb435e13d81601755714e9fSE Android
714255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_cat_destroy(mls_semantic_cat_t * c __attribute__ ((unused)))
715255e72915d4cbddceb435e13d81601755714e9fSE Android{
716255e72915d4cbddceb435e13d81601755714e9fSE Android	/* it's currently a simple struct - really nothing to destroy */
717255e72915d4cbddceb435e13d81601755714e9fSE Android	return;
718255e72915d4cbddceb435e13d81601755714e9fSE Android}
719255e72915d4cbddceb435e13d81601755714e9fSE Android
720255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_level_init(mls_semantic_level_t * l)
721255e72915d4cbddceb435e13d81601755714e9fSE Android{
722255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(l, 0, sizeof(mls_semantic_level_t));
723255e72915d4cbddceb435e13d81601755714e9fSE Android}
724255e72915d4cbddceb435e13d81601755714e9fSE Android
725255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_level_destroy(mls_semantic_level_t * l)
726255e72915d4cbddceb435e13d81601755714e9fSE Android{
727255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_cat_t *cur, *next;
728255e72915d4cbddceb435e13d81601755714e9fSE Android
729255e72915d4cbddceb435e13d81601755714e9fSE Android	if (l == NULL)
730255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
731255e72915d4cbddceb435e13d81601755714e9fSE Android
732255e72915d4cbddceb435e13d81601755714e9fSE Android	next = l->cat;
733255e72915d4cbddceb435e13d81601755714e9fSE Android	while (next) {
734255e72915d4cbddceb435e13d81601755714e9fSE Android		cur = next;
735255e72915d4cbddceb435e13d81601755714e9fSE Android		next = cur->next;
736255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_semantic_cat_destroy(cur);
737255e72915d4cbddceb435e13d81601755714e9fSE Android		free(cur);
738255e72915d4cbddceb435e13d81601755714e9fSE Android	}
739255e72915d4cbddceb435e13d81601755714e9fSE Android}
740255e72915d4cbddceb435e13d81601755714e9fSE Android
741255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_semantic_level_cpy(mls_semantic_level_t * dst,
742255e72915d4cbddceb435e13d81601755714e9fSE Android			   mls_semantic_level_t * src)
743255e72915d4cbddceb435e13d81601755714e9fSE Android{
744255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_cat_t *cat, *newcat, *lnewcat = NULL;
745255e72915d4cbddceb435e13d81601755714e9fSE Android
746255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_init(dst);
747255e72915d4cbddceb435e13d81601755714e9fSE Android	dst->sens = src->sens;
748255e72915d4cbddceb435e13d81601755714e9fSE Android	cat = src->cat;
749255e72915d4cbddceb435e13d81601755714e9fSE Android	while (cat) {
750255e72915d4cbddceb435e13d81601755714e9fSE Android		newcat =
751255e72915d4cbddceb435e13d81601755714e9fSE Android		    (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
752255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!newcat)
753255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
754255e72915d4cbddceb435e13d81601755714e9fSE Android
755255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_semantic_cat_init(newcat);
756255e72915d4cbddceb435e13d81601755714e9fSE Android		if (lnewcat)
757255e72915d4cbddceb435e13d81601755714e9fSE Android			lnewcat->next = newcat;
758255e72915d4cbddceb435e13d81601755714e9fSE Android		else
759255e72915d4cbddceb435e13d81601755714e9fSE Android			dst->cat = newcat;
760255e72915d4cbddceb435e13d81601755714e9fSE Android
761255e72915d4cbddceb435e13d81601755714e9fSE Android		newcat->low = cat->low;
762255e72915d4cbddceb435e13d81601755714e9fSE Android		newcat->high = cat->high;
763255e72915d4cbddceb435e13d81601755714e9fSE Android
764255e72915d4cbddceb435e13d81601755714e9fSE Android		lnewcat = newcat;
765255e72915d4cbddceb435e13d81601755714e9fSE Android		cat = cat->next;
766255e72915d4cbddceb435e13d81601755714e9fSE Android	}
767255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
768255e72915d4cbddceb435e13d81601755714e9fSE Android
769255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
770255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_destroy(dst);
771255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
772255e72915d4cbddceb435e13d81601755714e9fSE Android}
773255e72915d4cbddceb435e13d81601755714e9fSE Android
774255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_range_init(mls_semantic_range_t * r)
775255e72915d4cbddceb435e13d81601755714e9fSE Android{
776255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_init(&r->level[0]);
777255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_init(&r->level[1]);
778255e72915d4cbddceb435e13d81601755714e9fSE Android}
779255e72915d4cbddceb435e13d81601755714e9fSE Android
780255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid mls_semantic_range_destroy(mls_semantic_range_t * r)
781255e72915d4cbddceb435e13d81601755714e9fSE Android{
782255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_destroy(&r->level[0]);
783255e72915d4cbddceb435e13d81601755714e9fSE Android	mls_semantic_level_destroy(&r->level[1]);
784255e72915d4cbddceb435e13d81601755714e9fSE Android}
785255e72915d4cbddceb435e13d81601755714e9fSE Android
786255e72915d4cbddceb435e13d81601755714e9fSE Androidint mls_semantic_range_cpy(mls_semantic_range_t * dst,
787255e72915d4cbddceb435e13d81601755714e9fSE Android			   mls_semantic_range_t * src)
788255e72915d4cbddceb435e13d81601755714e9fSE Android{
789255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls_semantic_level_cpy(&dst->level[0], &src->level[0]) < 0)
790255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
791255e72915d4cbddceb435e13d81601755714e9fSE Android
792255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mls_semantic_level_cpy(&dst->level[1], &src->level[1]) < 0) {
793255e72915d4cbddceb435e13d81601755714e9fSE Android		mls_semantic_level_destroy(&dst->level[0]);
794255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
795255e72915d4cbddceb435e13d81601755714e9fSE Android	}
796255e72915d4cbddceb435e13d81601755714e9fSE Android
797255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
798255e72915d4cbddceb435e13d81601755714e9fSE Android}
799