1/* Authors: Joshua Brindle <jbrindle@tresys.com>
2 *
3 * Assertion checker for avtab entries, taken from
4 * checkpolicy.c by Stephen Smalley <sds@tycho.nsa.gov>
5 *
6 * Copyright (C) 2005 Tresys Technology, LLC
7 *
8 *  This library is free software; you can redistribute it and/or
9 *  modify it under the terms of the GNU Lesser General Public
10 *  License as published by the Free Software Foundation; either
11 *  version 2.1 of the License, or (at your option) any later version.
12 *
13 *  This library is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *  Lesser General Public License for more details.
17 *
18 *  You should have received a copy of the GNU Lesser General Public
19 *  License along with this library; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 */
22
23#include <sepol/policydb/avtab.h>
24#include <sepol/policydb/policydb.h>
25#include <sepol/policydb/expand.h>
26#include <sepol/policydb/util.h>
27
28#include "private.h"
29#include "debug.h"
30
31struct avtab_match_args {
32	sepol_handle_t *handle;
33	policydb_t *p;
34	avrule_t *avrule;
35	avtab_t *avtab;
36	unsigned long errors;
37};
38
39static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule,
40			   unsigned int stype, unsigned int ttype,
41			   const class_perm_node_t *curperm, uint32_t perms)
42{
43	if (avrule->source_filename) {
44		ERR(handle, "neverallow on line %lu of %s (or line %lu of policy.conf) violated by allow %s %s:%s {%s };",
45		    avrule->source_line, avrule->source_filename, avrule->line,
46		    p->p_type_val_to_name[stype],
47		    p->p_type_val_to_name[ttype],
48		    p->p_class_val_to_name[curperm->tclass - 1],
49		    sepol_av_to_string(p, curperm->tclass, perms));
50	} else if (avrule->line) {
51		ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };",
52		    avrule->line, p->p_type_val_to_name[stype],
53		    p->p_type_val_to_name[ttype],
54		    p->p_class_val_to_name[curperm->tclass - 1],
55		    sepol_av_to_string(p, curperm->tclass, perms));
56	} else {
57		ERR(handle, "neverallow violated by allow %s %s:%s {%s };",
58		    p->p_type_val_to_name[stype],
59		    p->p_type_val_to_name[ttype],
60		    p->p_class_val_to_name[curperm->tclass - 1],
61		    sepol_av_to_string(p, curperm->tclass, perms));
62	}
63}
64
65static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data)
66{
67	for (; cp; cp = cp->next) {
68		if ((cp->tclass == class) && (cp->data & data)) {
69			break;
70		}
71	}
72	if (!cp)
73		return 0;
74
75	return 1;
76}
77
78static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) {
79	size_t i;
80	for (i = 0; i < EXTENDED_PERMS_LEN; i++) {
81		if (perms1[i] & perms2[i])
82			return 1;
83	}
84
85	return 0;
86}
87
88static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow)
89{
90	int rc = 0;
91	if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
92			&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
93		if (neverallow->driver == allow->driver)
94			rc = extended_permissions_and(neverallow->perms, allow->perms);
95	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
96			&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
97		rc = xperm_test(neverallow->driver, allow->perms);
98	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
99			&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
100		rc = xperm_test(allow->driver, neverallow->perms);
101	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
102			&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
103		rc = extended_permissions_and(neverallow->perms, allow->perms);
104	}
105
106	return rc;
107}
108
109/* Compute which allowed extended permissions violate the neverallow rule */
110static void extended_permissions_violated(avtab_extended_perms_t *result,
111					av_extended_perms_t *neverallow,
112					avtab_extended_perms_t *allow)
113{
114	size_t i;
115	if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
116			&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
117		result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
118		result->driver = allow->driver;
119		for (i = 0; i < EXTENDED_PERMS_LEN; i++)
120			result->perms[i] = neverallow->perms[i] & allow->perms[i];
121	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
122			&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
123		result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
124		result->driver = neverallow->driver;
125		memcpy(result->perms, neverallow->perms, sizeof(result->perms));
126	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
127			&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
128		result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
129		result->driver = allow->driver;
130		memcpy(result->perms, allow->perms, sizeof(result->perms));
131	} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
132			&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
133		result->specified = AVTAB_XPERMS_IOCTLDRIVER;
134		for (i = 0; i < EXTENDED_PERMS_LEN; i++)
135			result->perms[i] = neverallow->perms[i] & allow->perms[i];
136	}
137}
138
139/* Same scenarios of interest as check_assertion_extended_permissions */
140static int report_assertion_extended_permissions(sepol_handle_t *handle,
141				policydb_t *p, const avrule_t *avrule,
142				unsigned int stype, unsigned int ttype,
143				const class_perm_node_t *curperm, uint32_t perms,
144				avtab_key_t *k, avtab_t *avtab)
145{
146	avtab_ptr_t node;
147	avtab_key_t tmp_key;
148	avtab_extended_perms_t *xperms;
149	avtab_extended_perms_t error;
150	ebitmap_t *sattr = &p->type_attr_map[stype];
151	ebitmap_t *tattr = &p->type_attr_map[ttype];
152	ebitmap_node_t *snode, *tnode;
153	unsigned int i, j;
154	int rc = 1;
155	int ret = 0;
156
157	memcpy(&tmp_key, k, sizeof(avtab_key_t));
158	tmp_key.specified = AVTAB_XPERMS_ALLOWED;
159
160	ebitmap_for_each_bit(sattr, snode, i) {
161		if (!ebitmap_node_get_bit(snode, i))
162			continue;
163		ebitmap_for_each_bit(tattr, tnode, j) {
164			if (!ebitmap_node_get_bit(tnode, j))
165				continue;
166			tmp_key.source_type = i + 1;
167			tmp_key.target_type = j + 1;
168			for (node = avtab_search_node(avtab, &tmp_key);
169			     node;
170			     node = avtab_search_node_next(node, tmp_key.specified)) {
171				xperms = node->datum.xperms;
172				if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
173						&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
174					continue;
175
176				rc = check_extended_permissions(avrule->xperms, xperms);
177				/* failure on the extended permission check_extended_permissions */
178				if (rc) {
179					extended_permissions_violated(&error, avrule->xperms, xperms);
180					ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
181							"allowxperm %s %s:%s %s;",
182							avrule->source_line, avrule->source_filename, avrule->line,
183							p->p_type_val_to_name[i],
184							p->p_type_val_to_name[j],
185							p->p_class_val_to_name[curperm->tclass - 1],
186							sepol_extended_perms_to_string(&error));
187
188					rc = 0;
189					ret++;
190				}
191			}
192		}
193	}
194
195	/* failure on the regular permissions */
196	if (rc) {
197		ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
198				"allow %s %s:%s {%s };",
199				avrule->source_line, avrule->source_filename, avrule->line,
200				p->p_type_val_to_name[stype],
201				p->p_type_val_to_name[ttype],
202				p->p_class_val_to_name[curperm->tclass - 1],
203				sepol_av_to_string(p, curperm->tclass, perms));
204		ret++;
205
206	}
207
208	return ret;
209}
210
211static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
212{
213	int rc = 0;
214	struct avtab_match_args *a = (struct avtab_match_args *)args;
215	sepol_handle_t *handle = a->handle;
216	policydb_t *p = a->p;
217	avtab_t *avtab = a->avtab;
218	avrule_t *avrule = a->avrule;
219	class_perm_node_t *cp;
220	uint32_t perms;
221	ebitmap_t src_matches, tgt_matches, self_matches, matches;
222	ebitmap_node_t *snode, *tnode;
223	unsigned int i, j;
224
225	if (k->specified != AVTAB_ALLOWED)
226		return 0;
227
228	if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
229		return 0;
230
231	ebitmap_init(&src_matches);
232	ebitmap_init(&tgt_matches);
233	ebitmap_init(&self_matches);
234	ebitmap_init(&matches);
235
236	rc = ebitmap_and(&src_matches, &avrule->stypes.types,
237			 &p->attr_type_map[k->source_type - 1]);
238	if (rc)
239		goto oom;
240
241	if (ebitmap_length(&src_matches) == 0)
242		goto exit;
243
244	rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
245	if (rc)
246		goto oom;
247
248	if (avrule->flags == RULE_SELF) {
249		rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]);
250		if (rc)
251			goto oom;
252		rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
253		if (rc)
254			goto oom;
255
256		if (ebitmap_length(&self_matches) > 0) {
257			rc = ebitmap_union(&tgt_matches, &self_matches);
258			if (rc)
259				goto oom;
260		}
261	}
262
263	if (ebitmap_length(&tgt_matches) == 0)
264		goto exit;
265
266	for (cp = avrule->perms; cp; cp = cp->next) {
267
268		perms = cp->data & d->data;
269		if ((cp->tclass != k->target_class) || !perms) {
270			continue;
271		}
272
273		ebitmap_for_each_bit(&src_matches, snode, i) {
274			if (!ebitmap_node_get_bit(snode, i))
275				continue;
276			ebitmap_for_each_bit(&tgt_matches, tnode, j) {
277				if (!ebitmap_node_get_bit(tnode, j))
278					continue;
279
280				if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
281					a->errors += report_assertion_extended_permissions(handle,p, avrule,
282											i, j, cp, perms, k, avtab);
283				} else {
284					a->errors++;
285					report_failure(handle, p, avrule, i, j, cp, perms);
286				}
287			}
288		}
289	}
290	goto exit;
291
292oom:
293	ERR(NULL, "Out of memory - unable to check neverallows");
294
295exit:
296	ebitmap_destroy(&src_matches);
297	ebitmap_destroy(&tgt_matches);
298	ebitmap_destroy(&self_matches);
299	ebitmap_destroy(&matches);
300	return rc;
301}
302
303int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
304{
305	int rc;
306	struct avtab_match_args args;
307
308	args.handle = handle;
309	args.p = p;
310	args.avrule = avrule;
311	args.errors = 0;
312
313	rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
314	if (rc)
315		goto oom;
316
317	rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
318	if (rc)
319		goto oom;
320
321	return args.errors;
322
323oom:
324	return rc;
325}
326
327/*
328 * Look up the extended permissions in avtab and verify that neverallowed
329 * permissions are not granted.
330 */
331static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab,
332						unsigned int stype, unsigned int ttype,
333						avtab_key_t *k, policydb_t *p)
334{
335	avtab_ptr_t node;
336	avtab_key_t tmp_key;
337	avtab_extended_perms_t *xperms;
338	av_extended_perms_t *neverallow_xperms = avrule->xperms;
339	ebitmap_t *sattr = &p->type_attr_map[stype];
340	ebitmap_t *tattr = &p->type_attr_map[ttype];
341	ebitmap_node_t *snode, *tnode;
342	unsigned int i, j;
343	int rc = 1;
344
345	memcpy(&tmp_key, k, sizeof(avtab_key_t));
346	tmp_key.specified = AVTAB_XPERMS_ALLOWED;
347
348	ebitmap_for_each_bit(sattr, snode, i) {
349		if (!ebitmap_node_get_bit(snode, i))
350			continue;
351		ebitmap_for_each_bit(tattr, tnode, j) {
352			if (!ebitmap_node_get_bit(tnode, j))
353				continue;
354			tmp_key.source_type = i + 1;
355			tmp_key.target_type = j + 1;
356			for (node = avtab_search_node(avtab, &tmp_key);
357			     node;
358			     node = avtab_search_node_next(node, tmp_key.specified)) {
359				xperms = node->datum.xperms;
360
361				if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
362						&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
363					continue;
364				rc = check_extended_permissions(neverallow_xperms, xperms);
365				if (rc)
366					break;
367			}
368		}
369	}
370
371	return rc;
372}
373
374/*
375 * When the ioctl permission is granted on an avtab entry that matches an
376 * avrule neverallowxperm entry, enumerate over the matching
377 * source/target/class sets to determine if the extended permissions exist
378 * and if the neverallowed ioctls are granted.
379 *
380 * Four scenarios of interest:
381 * 1. PASS - the ioctl permission is not granted for this source/target/class
382 *    This case is handled in check_assertion_avtab_match
383 * 2. PASS - The ioctl permission is granted AND the extended permission
384 *    is NOT granted
385 * 3. FAIL - The ioctl permission is granted AND no extended permissions
386 *    exist
387 * 4. FAIL - The ioctl permission is granted AND the extended permission is
388 *    granted
389 */
390static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
391						avtab_key_t *k, policydb_t *p)
392{
393	ebitmap_t src_matches, tgt_matches, self_matches, matches;
394	unsigned int i, j;
395	ebitmap_node_t *snode, *tnode;
396	class_perm_node_t *cp;
397	int rc;
398	int ret = 1;
399
400	ebitmap_init(&src_matches);
401	ebitmap_init(&tgt_matches);
402	ebitmap_init(&self_matches);
403	ebitmap_init(&matches);
404
405	rc = ebitmap_and(&src_matches, &avrule->stypes.types,
406			 &p->attr_type_map[k->source_type - 1]);
407	if (rc)
408		goto oom;
409
410	if (ebitmap_length(&src_matches) == 0)
411		goto exit;
412
413	rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
414			 &p->attr_type_map[k->target_type -1]);
415	if (rc)
416		goto oom;
417
418	if (avrule->flags == RULE_SELF) {
419		rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1],
420				&p->attr_type_map[k->target_type - 1]);
421		if (rc)
422			goto oom;
423		rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
424		if (rc)
425			goto oom;
426
427		if (ebitmap_length(&self_matches) > 0) {
428			rc = ebitmap_union(&tgt_matches, &self_matches);
429			if (rc)
430				goto oom;
431		}
432	}
433
434	if (ebitmap_length(&tgt_matches) == 0)
435		goto exit;
436
437	for (cp = avrule->perms; cp; cp = cp->next) {
438		if (cp->tclass != k->target_class)
439			continue;
440		ebitmap_for_each_bit(&src_matches, snode, i) {
441			if (!ebitmap_node_get_bit(snode, i))
442				continue;
443			ebitmap_for_each_bit(&tgt_matches, tnode, j) {
444				if (!ebitmap_node_get_bit(tnode, j))
445					continue;
446
447				ret = check_assertion_extended_permissions_avtab(
448						avrule, avtab, i, j, k, p);
449				if (ret)
450					goto exit;
451			}
452		}
453	}
454	goto exit;
455
456oom:
457	ERR(NULL, "Out of memory - unable to check neverallows");
458
459exit:
460	ebitmap_destroy(&src_matches);
461	ebitmap_destroy(&tgt_matches);
462	ebitmap_destroy(&matches);
463	return ret;
464}
465
466static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
467{
468	int rc, rc2 = 0;
469	struct avtab_match_args *a = (struct avtab_match_args *)args;
470	policydb_t *p = a->p;
471	avrule_t *avrule = a->avrule;
472	avtab_t *avtab = a->avtab;
473
474	if (k->specified != AVTAB_ALLOWED)
475		goto exit;
476
477	if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
478		goto exit;
479
480	rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
481	if (rc == 0)
482		goto exit;
483
484	if (avrule->flags == RULE_SELF) {
485		/* If the neverallow uses SELF, then it is not enough that the
486		 * neverallow's source matches the src and tgt of the rule being checked.
487		 * It must match the same thing in the src and tgt, so AND the source
488		 * and target together and check for a match on the result.
489		 */
490		ebitmap_t match;
491		rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] );
492		if (rc) {
493			ebitmap_destroy(&match);
494			goto oom;
495		}
496		rc2 = ebitmap_match_any(&avrule->stypes.types, &match);
497		ebitmap_destroy(&match);
498	}
499
500	/* neverallow may have tgts even if it uses SELF */
501	rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
502	if (rc == 0 && rc2 == 0)
503		goto exit;
504
505	if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
506		rc = check_assertion_extended_permissions(avrule, avtab, k, p);
507		if (rc == 0)
508			goto exit;
509	}
510	return 1;
511
512exit:
513	return 0;
514
515oom:
516	ERR(NULL, "Out of memory - unable to check neverallows");
517	return rc;
518}
519
520int check_assertion(policydb_t *p, avrule_t *avrule)
521{
522	int rc;
523	struct avtab_match_args args;
524
525	args.handle = NULL;
526	args.p = p;
527	args.avrule = avrule;
528	args.errors = 0;
529	args.avtab = &p->te_avtab;
530
531	rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
532
533	if (rc == 0) {
534		args.avtab = &p->te_cond_avtab;
535		rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
536	}
537
538	return rc;
539}
540
541int check_assertions(sepol_handle_t * handle, policydb_t * p,
542		     avrule_t * avrules)
543{
544	int rc;
545	avrule_t *a;
546	unsigned long errors = 0;
547
548	if (!avrules) {
549		/* Since assertions are stored in avrules, if it is NULL
550		   there won't be any to check. This also prevents an invalid
551		   free if the avtabs are never initialized */
552		return 0;
553	}
554
555	for (a = avrules; a != NULL; a = a->next) {
556		if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
557			continue;
558		rc = check_assertion(p, a);
559		if (rc) {
560			rc = report_assertion_failures(handle, p, a);
561			if (rc < 0) {
562				ERR(handle, "Error occurred while checking neverallows");
563				return -1;
564			}
565			errors += rc;
566		}
567	}
568
569	if (errors)
570		ERR(handle, "%lu neverallow failures occurred", errors);
571
572	return errors ? -1 : 0;
573}
574