Home | History | Annotate | Download | only in src
      1 /* Authors: Joshua Brindle <jbrindle (at) tresys.com>
      2  *
      3  * Assertion checker for avtab entries, taken from
      4  * checkpolicy.c by Stephen Smalley <sds (at) 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 
     31 struct 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 
     39 static 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 
     65 static 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 
     78 static 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 
     88 static 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 */
    110 static 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 */
    140 static 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 
    211 static 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) == 0)
    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 
    292 oom:
    293 	ERR(NULL, "Out of memory - unable to check neverallows");
    294 
    295 exit:
    296 	ebitmap_destroy(&src_matches);
    297 	ebitmap_destroy(&tgt_matches);
    298 	ebitmap_destroy(&self_matches);
    299 	ebitmap_destroy(&matches);
    300 	return rc;
    301 }
    302 
    303 int 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 
    323 oom:
    324 	return rc;
    325 }
    326 
    327 /*
    328  * Look up the extended permissions in avtab and verify that neverallowed
    329  * permissions are not granted.
    330  */
    331 static 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  */
    390 static 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 
    456 oom:
    457 	ERR(NULL, "Out of memory - unable to check neverallows");
    458 
    459 exit:
    460 	ebitmap_destroy(&src_matches);
    461 	ebitmap_destroy(&tgt_matches);
    462 	ebitmap_destroy(&matches);
    463 	return ret;
    464 }
    465 
    466 static 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) == 0)
    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 
    512 exit:
    513 	return 0;
    514 
    515 oom:
    516 	ERR(NULL, "Out of memory - unable to check neverallows");
    517 	return rc;
    518 }
    519 
    520 int 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 
    541 int 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