/* Authors: Joshua Brindle <jbrindle@tresys.com> * * Assertion checker for avtab entries, taken from * checkpolicy.c by Stephen Smalley <sds@tycho.nsa.gov> * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <sepol/policydb/avtab.h> #include <sepol/policydb/policydb.h> #include <sepol/policydb/expand.h> #include <sepol/policydb/util.h> #include "debug.h" static int check_assertion_helper(sepol_handle_t * handle, policydb_t * p, avtab_t * te_avtab, avtab_t * te_cond_avtab, unsigned int stype, unsigned int ttype, class_perm_node_t * perm, unsigned long line) { avtab_key_t avkey; avtab_ptr_t node; class_perm_node_t *curperm; for (curperm = perm; curperm != NULL; curperm = curperm->next) { avkey.source_type = stype + 1; avkey.target_type = ttype + 1; avkey.target_class = curperm->class; avkey.specified = AVTAB_ALLOWED; for (node = avtab_search_node(te_avtab, &avkey); node != NULL; node = avtab_search_node_next(node, avkey.specified)) { if (node->datum.data & curperm->data) goto err; } for (node = avtab_search_node(te_cond_avtab, &avkey); node != NULL; node = avtab_search_node_next(node, avkey.specified)) { if (node->datum.data & curperm->data) goto err; } } return 0; err: if (line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->class - 1], sepol_av_to_string(p, curperm->class, node->datum.data & curperm->data)); } else { ERR(handle, "neverallow violated by allow %s %s:%s {%s };", p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->class - 1], sepol_av_to_string(p, curperm->class, node->datum.data & curperm->data)); } return -1; } int check_assertions(sepol_handle_t * handle, policydb_t * p, avrule_t * avrules) { avrule_t *a; avtab_t te_avtab, te_cond_avtab; ebitmap_node_t *snode, *tnode; unsigned int i, j; int rc; if (!avrules) { /* Since assertions are stored in avrules, if it is NULL there won't be any to check. This also prevents an invalid free if the avtabs are never initialized */ return 0; } if (avrules) { if (avtab_init(&te_avtab)) goto oom; if (avtab_init(&te_cond_avtab)) { avtab_destroy(&te_avtab); goto oom; } if (expand_avtab(p, &p->te_avtab, &te_avtab) || expand_avtab(p, &p->te_cond_avtab, &te_cond_avtab)) { avtab_destroy(&te_avtab); avtab_destroy(&te_cond_avtab); goto oom; } } for (a = avrules; a != NULL; a = a->next) { ebitmap_t *stypes = &a->stypes.types; ebitmap_t *ttypes = &a->ttypes.types; if (!(a->specified & AVRULE_NEVERALLOW)) continue; ebitmap_for_each_bit(stypes, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; if (a->flags & RULE_SELF) { if (check_assertion_helper (handle, p, &te_avtab, &te_cond_avtab, i, i, a->perms, a->line)) { rc = -1; goto out; } } ebitmap_for_each_bit(ttypes, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; if (check_assertion_helper (handle, p, &te_avtab, &te_cond_avtab, i, j, a->perms, a->line)) { rc = -1; goto out; } } } } rc = 0; out: avtab_destroy(&te_avtab); avtab_destroy(&te_cond_avtab); return rc; oom: ERR(handle, "Out of memory - unable to check neverallows"); return -1; }