1255e72915d4cbddceb435e13d81601755714e9fSE Android/* Authors: Karl MacMillan <kmacmillan@tresys.com> 2255e72915d4cbddceb435e13d81601755714e9fSE Android * Frank Mayer <mayerf@tresys.com> 3255e72915d4cbddceb435e13d81601755714e9fSE Android * David Caplan <dac@tresys.com> 4255e72915d4cbddceb435e13d81601755714e9fSE Android * 5255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2003 - 2005 Tresys Technology, LLC 6255e72915d4cbddceb435e13d81601755714e9fSE Android * 7255e72915d4cbddceb435e13d81601755714e9fSE Android * This library is free software; you can redistribute it and/or 8255e72915d4cbddceb435e13d81601755714e9fSE Android * modify it under the terms of the GNU Lesser General Public 9255e72915d4cbddceb435e13d81601755714e9fSE Android * License as published by the Free Software Foundation; either 10255e72915d4cbddceb435e13d81601755714e9fSE Android * version 2.1 of the License, or (at your option) any later version. 11255e72915d4cbddceb435e13d81601755714e9fSE Android * 12255e72915d4cbddceb435e13d81601755714e9fSE Android * This library is distributed in the hope that it will be useful, 13255e72915d4cbddceb435e13d81601755714e9fSE Android * but WITHOUT ANY WARRANTY; without even the implied warranty of 14255e72915d4cbddceb435e13d81601755714e9fSE Android * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15255e72915d4cbddceb435e13d81601755714e9fSE Android * Lesser General Public License for more details. 16255e72915d4cbddceb435e13d81601755714e9fSE Android * 17255e72915d4cbddceb435e13d81601755714e9fSE Android * You should have received a copy of the GNU Lesser General Public 18255e72915d4cbddceb435e13d81601755714e9fSE Android * License along with this library; if not, write to the Free Software 19255e72915d4cbddceb435e13d81601755714e9fSE Android * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20255e72915d4cbddceb435e13d81601755714e9fSE Android */ 21255e72915d4cbddceb435e13d81601755714e9fSE Android 22255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h> 23255e72915d4cbddceb435e13d81601755714e9fSE Android 24255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/flask_types.h> 25255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/conditional.h> 26255e72915d4cbddceb435e13d81601755714e9fSE Android 27255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h" 28255e72915d4cbddceb435e13d81601755714e9fSE Android 29255e72915d4cbddceb435e13d81601755714e9fSE Android/* move all type rules to top of t/f lists to help kernel on evaluation */ 30255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic void cond_optimize(cond_av_list_t ** l) 31255e72915d4cbddceb435e13d81601755714e9fSE Android{ 32255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *top, *p, *cur; 33255e72915d4cbddceb435e13d81601755714e9fSE Android 34255e72915d4cbddceb435e13d81601755714e9fSE Android top = p = cur = *l; 35255e72915d4cbddceb435e13d81601755714e9fSE Android 36255e72915d4cbddceb435e13d81601755714e9fSE Android while (cur) { 37255e72915d4cbddceb435e13d81601755714e9fSE Android if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) { 38255e72915d4cbddceb435e13d81601755714e9fSE Android p->next = cur->next; 39255e72915d4cbddceb435e13d81601755714e9fSE Android cur->next = top; 40255e72915d4cbddceb435e13d81601755714e9fSE Android top = cur; 41255e72915d4cbddceb435e13d81601755714e9fSE Android cur = p->next; 42255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 43255e72915d4cbddceb435e13d81601755714e9fSE Android p = cur; 44255e72915d4cbddceb435e13d81601755714e9fSE Android cur = cur->next; 45255e72915d4cbddceb435e13d81601755714e9fSE Android } 46255e72915d4cbddceb435e13d81601755714e9fSE Android } 47255e72915d4cbddceb435e13d81601755714e9fSE Android *l = top; 48255e72915d4cbddceb435e13d81601755714e9fSE Android} 49255e72915d4cbddceb435e13d81601755714e9fSE Android 50255e72915d4cbddceb435e13d81601755714e9fSE Android/* reorder t/f lists for kernel */ 51255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_optimize_lists(cond_list_t * cl) 52255e72915d4cbddceb435e13d81601755714e9fSE Android{ 53255e72915d4cbddceb435e13d81601755714e9fSE Android cond_list_t *n; 54255e72915d4cbddceb435e13d81601755714e9fSE Android 55255e72915d4cbddceb435e13d81601755714e9fSE Android for (n = cl; n != NULL; n = n->next) { 56255e72915d4cbddceb435e13d81601755714e9fSE Android cond_optimize(&n->true_list); 57255e72915d4cbddceb435e13d81601755714e9fSE Android cond_optimize(&n->false_list); 58255e72915d4cbddceb435e13d81601755714e9fSE Android } 59255e72915d4cbddceb435e13d81601755714e9fSE Android} 60255e72915d4cbddceb435e13d81601755714e9fSE Android 61255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int bool_present(unsigned int target, unsigned int bools[], 62255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int num_bools) 63255e72915d4cbddceb435e13d81601755714e9fSE Android{ 64255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int i = 0; 65255e72915d4cbddceb435e13d81601755714e9fSE Android int ret = 1; 66255e72915d4cbddceb435e13d81601755714e9fSE Android 67255e72915d4cbddceb435e13d81601755714e9fSE Android if (num_bools > COND_MAX_BOOLS) { 68255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 69255e72915d4cbddceb435e13d81601755714e9fSE Android } 70255e72915d4cbddceb435e13d81601755714e9fSE Android while (i < num_bools && target != bools[i]) 71255e72915d4cbddceb435e13d81601755714e9fSE Android i++; 72255e72915d4cbddceb435e13d81601755714e9fSE Android if (i == num_bools) 73255e72915d4cbddceb435e13d81601755714e9fSE Android ret = 0; /* got to end w/o match */ 74255e72915d4cbddceb435e13d81601755714e9fSE Android return ret; 75255e72915d4cbddceb435e13d81601755714e9fSE Android} 76255e72915d4cbddceb435e13d81601755714e9fSE Android 77255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int same_bools(cond_node_t * a, cond_node_t * b) 78255e72915d4cbddceb435e13d81601755714e9fSE Android{ 79255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int i, x; 80255e72915d4cbddceb435e13d81601755714e9fSE Android 81255e72915d4cbddceb435e13d81601755714e9fSE Android x = a->nbools; 82255e72915d4cbddceb435e13d81601755714e9fSE Android 83255e72915d4cbddceb435e13d81601755714e9fSE Android /* same number of bools? */ 84255e72915d4cbddceb435e13d81601755714e9fSE Android if (x != b->nbools) 85255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 86255e72915d4cbddceb435e13d81601755714e9fSE Android 87255e72915d4cbddceb435e13d81601755714e9fSE Android /* make sure all the bools in a are also in b */ 88255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < x; i++) 89255e72915d4cbddceb435e13d81601755714e9fSE Android if (!bool_present(a->bool_ids[i], b->bool_ids, x)) 90255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 91255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 92255e72915d4cbddceb435e13d81601755714e9fSE Android} 93255e72915d4cbddceb435e13d81601755714e9fSE Android 94255e72915d4cbddceb435e13d81601755714e9fSE Android/* 95255e72915d4cbddceb435e13d81601755714e9fSE Android * Determine if two conditional expressions are equal. 96255e72915d4cbddceb435e13d81601755714e9fSE Android */ 97255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_expr_equal(cond_node_t * a, cond_node_t * b) 98255e72915d4cbddceb435e13d81601755714e9fSE Android{ 99255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *cur_a, *cur_b; 100255e72915d4cbddceb435e13d81601755714e9fSE Android 101255e72915d4cbddceb435e13d81601755714e9fSE Android if (a == NULL || b == NULL) 102255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 103255e72915d4cbddceb435e13d81601755714e9fSE Android 104255e72915d4cbddceb435e13d81601755714e9fSE Android if (a->nbools != b->nbools) 105255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 106255e72915d4cbddceb435e13d81601755714e9fSE Android 107255e72915d4cbddceb435e13d81601755714e9fSE Android /* if exprs have <= COND_MAX_BOOLS we can check the precompute values 108255e72915d4cbddceb435e13d81601755714e9fSE Android * for the expressions. 109255e72915d4cbddceb435e13d81601755714e9fSE Android */ 110255e72915d4cbddceb435e13d81601755714e9fSE Android if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) { 111255e72915d4cbddceb435e13d81601755714e9fSE Android if (!same_bools(a, b)) 112255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 113255e72915d4cbddceb435e13d81601755714e9fSE Android return (a->expr_pre_comp == b->expr_pre_comp); 114255e72915d4cbddceb435e13d81601755714e9fSE Android } 115255e72915d4cbddceb435e13d81601755714e9fSE Android 116255e72915d4cbddceb435e13d81601755714e9fSE Android /* for long expressions we check for exactly the same expression */ 117255e72915d4cbddceb435e13d81601755714e9fSE Android cur_a = a->expr; 118255e72915d4cbddceb435e13d81601755714e9fSE Android cur_b = b->expr; 119255e72915d4cbddceb435e13d81601755714e9fSE Android while (1) { 120255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur_a == NULL && cur_b == NULL) 121255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 122255e72915d4cbddceb435e13d81601755714e9fSE Android else if (cur_a == NULL || cur_b == NULL) 123255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 124255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur_a->expr_type != cur_b->expr_type) 125255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 126255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur_a->expr_type == COND_BOOL) { 127255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur_a->bool != cur_b->bool) 128255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 129255e72915d4cbddceb435e13d81601755714e9fSE Android } 130255e72915d4cbddceb435e13d81601755714e9fSE Android cur_a = cur_a->next; 131255e72915d4cbddceb435e13d81601755714e9fSE Android cur_b = cur_b->next; 132255e72915d4cbddceb435e13d81601755714e9fSE Android } 133255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 134255e72915d4cbddceb435e13d81601755714e9fSE Android} 135255e72915d4cbddceb435e13d81601755714e9fSE Android 136255e72915d4cbddceb435e13d81601755714e9fSE Android/* Create a new conditional node, optionally copying 137255e72915d4cbddceb435e13d81601755714e9fSE Android * the conditional expression from an existing node. 138255e72915d4cbddceb435e13d81601755714e9fSE Android * If node is NULL then a new node will be created 139255e72915d4cbddceb435e13d81601755714e9fSE Android * with no conditional expression. 140255e72915d4cbddceb435e13d81601755714e9fSE Android */ 141255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_create(policydb_t * p, cond_node_t * node) 142255e72915d4cbddceb435e13d81601755714e9fSE Android{ 143255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t *new_node; 144255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int i; 145255e72915d4cbddceb435e13d81601755714e9fSE Android 146255e72915d4cbddceb435e13d81601755714e9fSE Android new_node = (cond_node_t *)malloc(sizeof(cond_node_t)); 147255e72915d4cbddceb435e13d81601755714e9fSE Android if (!new_node) { 148255e72915d4cbddceb435e13d81601755714e9fSE Android return NULL; 149255e72915d4cbddceb435e13d81601755714e9fSE Android } 150255e72915d4cbddceb435e13d81601755714e9fSE Android memset(new_node, 0, sizeof(cond_node_t)); 151255e72915d4cbddceb435e13d81601755714e9fSE Android 152255e72915d4cbddceb435e13d81601755714e9fSE Android if (node) { 153255e72915d4cbddceb435e13d81601755714e9fSE Android new_node->expr = cond_copy_expr(node->expr); 154255e72915d4cbddceb435e13d81601755714e9fSE Android if (!new_node->expr) { 155255e72915d4cbddceb435e13d81601755714e9fSE Android free(new_node); 156255e72915d4cbddceb435e13d81601755714e9fSE Android return NULL; 157255e72915d4cbddceb435e13d81601755714e9fSE Android } 158255e72915d4cbddceb435e13d81601755714e9fSE Android new_node->cur_state = cond_evaluate_expr(p, new_node->expr); 159255e72915d4cbddceb435e13d81601755714e9fSE Android new_node->nbools = node->nbools; 160255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++) 161255e72915d4cbddceb435e13d81601755714e9fSE Android new_node->bool_ids[i] = node->bool_ids[i]; 162255e72915d4cbddceb435e13d81601755714e9fSE Android new_node->expr_pre_comp = node->expr_pre_comp; 163fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley new_node->flags = node->flags; 164255e72915d4cbddceb435e13d81601755714e9fSE Android } 165255e72915d4cbddceb435e13d81601755714e9fSE Android 166255e72915d4cbddceb435e13d81601755714e9fSE Android return new_node; 167255e72915d4cbddceb435e13d81601755714e9fSE Android} 168255e72915d4cbddceb435e13d81601755714e9fSE Android 169255e72915d4cbddceb435e13d81601755714e9fSE Android/* Find a conditional (the needle) within a list of existing ones (the 170255e72915d4cbddceb435e13d81601755714e9fSE Android * haystack) that has a matching expression. If found, return a 171255e72915d4cbddceb435e13d81601755714e9fSE Android * pointer to the existing node, setting 'was_created' to 0. 172255e72915d4cbddceb435e13d81601755714e9fSE Android * Otherwise create a new one and return it, setting 'was_created' to 173255e72915d4cbddceb435e13d81601755714e9fSE Android * 1. */ 174255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_find(policydb_t * p, 175255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t * needle, cond_node_t * haystack, 176255e72915d4cbddceb435e13d81601755714e9fSE Android int *was_created) 177255e72915d4cbddceb435e13d81601755714e9fSE Android{ 178255e72915d4cbddceb435e13d81601755714e9fSE Android while (haystack) { 179255e72915d4cbddceb435e13d81601755714e9fSE Android if (cond_expr_equal(needle, haystack)) { 180255e72915d4cbddceb435e13d81601755714e9fSE Android *was_created = 0; 181255e72915d4cbddceb435e13d81601755714e9fSE Android return haystack; 182255e72915d4cbddceb435e13d81601755714e9fSE Android } 183255e72915d4cbddceb435e13d81601755714e9fSE Android haystack = haystack->next; 184255e72915d4cbddceb435e13d81601755714e9fSE Android } 185255e72915d4cbddceb435e13d81601755714e9fSE Android *was_created = 1; 186255e72915d4cbddceb435e13d81601755714e9fSE Android 187255e72915d4cbddceb435e13d81601755714e9fSE Android return cond_node_create(p, needle); 188255e72915d4cbddceb435e13d81601755714e9fSE Android} 189255e72915d4cbddceb435e13d81601755714e9fSE Android 190255e72915d4cbddceb435e13d81601755714e9fSE Android/* return either a pre-existing matching node or create a new node */ 191255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, 192255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t * cn) 193255e72915d4cbddceb435e13d81601755714e9fSE Android{ 194255e72915d4cbddceb435e13d81601755714e9fSE Android int was_created; 195255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t *result = cond_node_find(p, cn, list, &was_created); 196255e72915d4cbddceb435e13d81601755714e9fSE Android if (result != NULL && was_created) { 197255e72915d4cbddceb435e13d81601755714e9fSE Android /* add conditional node to policy list */ 198255e72915d4cbddceb435e13d81601755714e9fSE Android result->next = p->cond_list; 199255e72915d4cbddceb435e13d81601755714e9fSE Android p->cond_list = result; 200255e72915d4cbddceb435e13d81601755714e9fSE Android } 201255e72915d4cbddceb435e13d81601755714e9fSE Android return result; 202255e72915d4cbddceb435e13d81601755714e9fSE Android} 203255e72915d4cbddceb435e13d81601755714e9fSE Android 204255e72915d4cbddceb435e13d81601755714e9fSE Android/* 205255e72915d4cbddceb435e13d81601755714e9fSE Android * cond_evaluate_expr evaluates a conditional expr 206255e72915d4cbddceb435e13d81601755714e9fSE Android * in reverse polish notation. It returns true (1), false (0), 207255e72915d4cbddceb435e13d81601755714e9fSE Android * or undefined (-1). Undefined occurs when the expression 208255e72915d4cbddceb435e13d81601755714e9fSE Android * exceeds the stack depth of COND_EXPR_MAXDEPTH. 209255e72915d4cbddceb435e13d81601755714e9fSE Android */ 210255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_evaluate_expr(policydb_t * p, cond_expr_t * expr) 211255e72915d4cbddceb435e13d81601755714e9fSE Android{ 212255e72915d4cbddceb435e13d81601755714e9fSE Android 213255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *cur; 214255e72915d4cbddceb435e13d81601755714e9fSE Android int s[COND_EXPR_MAXDEPTH]; 215255e72915d4cbddceb435e13d81601755714e9fSE Android int sp = -1; 216255e72915d4cbddceb435e13d81601755714e9fSE Android 217255e72915d4cbddceb435e13d81601755714e9fSE Android s[0] = -1; 218255e72915d4cbddceb435e13d81601755714e9fSE Android 219255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = expr; cur != NULL; cur = cur->next) { 220255e72915d4cbddceb435e13d81601755714e9fSE Android switch (cur->expr_type) { 221255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_BOOL: 222255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp == (COND_EXPR_MAXDEPTH - 1)) 223255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 224255e72915d4cbddceb435e13d81601755714e9fSE Android sp++; 225255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; 226255e72915d4cbddceb435e13d81601755714e9fSE Android break; 227255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_NOT: 228255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 0) 229255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 230255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] = !s[sp]; 231255e72915d4cbddceb435e13d81601755714e9fSE Android break; 232255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_OR: 233255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 1) 234255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 235255e72915d4cbddceb435e13d81601755714e9fSE Android sp--; 236255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] |= s[sp + 1]; 237255e72915d4cbddceb435e13d81601755714e9fSE Android break; 238255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_AND: 239255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 1) 240255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 241255e72915d4cbddceb435e13d81601755714e9fSE Android sp--; 242255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] &= s[sp + 1]; 243255e72915d4cbddceb435e13d81601755714e9fSE Android break; 244255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_XOR: 245255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 1) 246255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 247255e72915d4cbddceb435e13d81601755714e9fSE Android sp--; 248255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] ^= s[sp + 1]; 249255e72915d4cbddceb435e13d81601755714e9fSE Android break; 250255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_EQ: 251255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 1) 252255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 253255e72915d4cbddceb435e13d81601755714e9fSE Android sp--; 254255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] = (s[sp] == s[sp + 1]); 255255e72915d4cbddceb435e13d81601755714e9fSE Android break; 256255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_NEQ: 257255e72915d4cbddceb435e13d81601755714e9fSE Android if (sp < 1) 258255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 259255e72915d4cbddceb435e13d81601755714e9fSE Android sp--; 260255e72915d4cbddceb435e13d81601755714e9fSE Android s[sp] = (s[sp] != s[sp + 1]); 261255e72915d4cbddceb435e13d81601755714e9fSE Android break; 262255e72915d4cbddceb435e13d81601755714e9fSE Android default: 263255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 264255e72915d4cbddceb435e13d81601755714e9fSE Android } 265255e72915d4cbddceb435e13d81601755714e9fSE Android } 266255e72915d4cbddceb435e13d81601755714e9fSE Android return s[0]; 267255e72915d4cbddceb435e13d81601755714e9fSE Android} 268255e72915d4cbddceb435e13d81601755714e9fSE Android 269255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_expr_t *cond_copy_expr(cond_expr_t * expr) 270255e72915d4cbddceb435e13d81601755714e9fSE Android{ 271255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *cur, *head, *tail, *new_expr; 272255e72915d4cbddceb435e13d81601755714e9fSE Android tail = head = NULL; 273255e72915d4cbddceb435e13d81601755714e9fSE Android cur = expr; 274255e72915d4cbddceb435e13d81601755714e9fSE Android while (cur) { 275255e72915d4cbddceb435e13d81601755714e9fSE Android new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t)); 276255e72915d4cbddceb435e13d81601755714e9fSE Android if (!new_expr) 277255e72915d4cbddceb435e13d81601755714e9fSE Android goto free_head; 278255e72915d4cbddceb435e13d81601755714e9fSE Android memset(new_expr, 0, sizeof(cond_expr_t)); 279255e72915d4cbddceb435e13d81601755714e9fSE Android 280255e72915d4cbddceb435e13d81601755714e9fSE Android new_expr->expr_type = cur->expr_type; 281255e72915d4cbddceb435e13d81601755714e9fSE Android new_expr->bool = cur->bool; 282255e72915d4cbddceb435e13d81601755714e9fSE Android 283255e72915d4cbddceb435e13d81601755714e9fSE Android if (!head) 284255e72915d4cbddceb435e13d81601755714e9fSE Android head = new_expr; 285255e72915d4cbddceb435e13d81601755714e9fSE Android if (tail) 286255e72915d4cbddceb435e13d81601755714e9fSE Android tail->next = new_expr; 287255e72915d4cbddceb435e13d81601755714e9fSE Android tail = new_expr; 288255e72915d4cbddceb435e13d81601755714e9fSE Android cur = cur->next; 289255e72915d4cbddceb435e13d81601755714e9fSE Android } 290255e72915d4cbddceb435e13d81601755714e9fSE Android return head; 291255e72915d4cbddceb435e13d81601755714e9fSE Android 292255e72915d4cbddceb435e13d81601755714e9fSE Android free_head: 293255e72915d4cbddceb435e13d81601755714e9fSE Android while (head) { 294255e72915d4cbddceb435e13d81601755714e9fSE Android tail = head->next; 295255e72915d4cbddceb435e13d81601755714e9fSE Android free(head); 296255e72915d4cbddceb435e13d81601755714e9fSE Android head = tail; 297255e72915d4cbddceb435e13d81601755714e9fSE Android } 298255e72915d4cbddceb435e13d81601755714e9fSE Android return NULL; 299255e72915d4cbddceb435e13d81601755714e9fSE Android} 300255e72915d4cbddceb435e13d81601755714e9fSE Android 301255e72915d4cbddceb435e13d81601755714e9fSE Android/* 302255e72915d4cbddceb435e13d81601755714e9fSE Android * evaluate_cond_node evaluates the conditional stored in 303255e72915d4cbddceb435e13d81601755714e9fSE Android * a cond_node_t and if the result is different than the 304255e72915d4cbddceb435e13d81601755714e9fSE Android * current state of the node it sets the rules in the true/false 305255e72915d4cbddceb435e13d81601755714e9fSE Android * list appropriately. If the result of the expression is undefined 306255e72915d4cbddceb435e13d81601755714e9fSE Android * all of the rules are disabled for safety. 307255e72915d4cbddceb435e13d81601755714e9fSE Android */ 308255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int evaluate_cond_node(policydb_t * p, cond_node_t * node) 309255e72915d4cbddceb435e13d81601755714e9fSE Android{ 310255e72915d4cbddceb435e13d81601755714e9fSE Android int new_state; 311255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *cur; 312255e72915d4cbddceb435e13d81601755714e9fSE Android 313255e72915d4cbddceb435e13d81601755714e9fSE Android new_state = cond_evaluate_expr(p, node->expr); 314255e72915d4cbddceb435e13d81601755714e9fSE Android if (new_state != node->cur_state) { 315255e72915d4cbddceb435e13d81601755714e9fSE Android node->cur_state = new_state; 316255e72915d4cbddceb435e13d81601755714e9fSE Android if (new_state == -1) 317255e72915d4cbddceb435e13d81601755714e9fSE Android printf 318255e72915d4cbddceb435e13d81601755714e9fSE Android ("expression result was undefined - disabling all rules.\n"); 319255e72915d4cbddceb435e13d81601755714e9fSE Android /* turn the rules on or off */ 320255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = node->true_list; cur != NULL; cur = cur->next) { 321255e72915d4cbddceb435e13d81601755714e9fSE Android if (new_state <= 0) { 322255e72915d4cbddceb435e13d81601755714e9fSE Android cur->node->key.specified &= ~AVTAB_ENABLED; 323255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 324255e72915d4cbddceb435e13d81601755714e9fSE Android cur->node->key.specified |= AVTAB_ENABLED; 325255e72915d4cbddceb435e13d81601755714e9fSE Android } 326255e72915d4cbddceb435e13d81601755714e9fSE Android } 327255e72915d4cbddceb435e13d81601755714e9fSE Android 328255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = node->false_list; cur != NULL; cur = cur->next) { 329255e72915d4cbddceb435e13d81601755714e9fSE Android /* -1 or 1 */ 330255e72915d4cbddceb435e13d81601755714e9fSE Android if (new_state) { 331255e72915d4cbddceb435e13d81601755714e9fSE Android cur->node->key.specified &= ~AVTAB_ENABLED; 332255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 333255e72915d4cbddceb435e13d81601755714e9fSE Android cur->node->key.specified |= AVTAB_ENABLED; 334255e72915d4cbddceb435e13d81601755714e9fSE Android } 335255e72915d4cbddceb435e13d81601755714e9fSE Android } 336255e72915d4cbddceb435e13d81601755714e9fSE Android } 337255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 338255e72915d4cbddceb435e13d81601755714e9fSE Android} 339255e72915d4cbddceb435e13d81601755714e9fSE Android 340255e72915d4cbddceb435e13d81601755714e9fSE Android/* precompute and simplify an expression if possible. If left with !expression, change 341255e72915d4cbddceb435e13d81601755714e9fSE Android * to expression and switch t and f. precompute expression for expressions with limited 342255e72915d4cbddceb435e13d81601755714e9fSE Android * number of bools. 343255e72915d4cbddceb435e13d81601755714e9fSE Android */ 344255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_normalize_expr(policydb_t * p, cond_node_t * cn) 345255e72915d4cbddceb435e13d81601755714e9fSE Android{ 346255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *ne, *e; 347255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *tmp; 348255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int i, j, orig_value[COND_MAX_BOOLS]; 349255e72915d4cbddceb435e13d81601755714e9fSE Android int k; 350255e72915d4cbddceb435e13d81601755714e9fSE Android uint32_t test = 0x0; 351255e72915d4cbddceb435e13d81601755714e9fSE Android avrule_t *tmp2; 352255e72915d4cbddceb435e13d81601755714e9fSE Android 353255e72915d4cbddceb435e13d81601755714e9fSE Android cn->nbools = 0; 354255e72915d4cbddceb435e13d81601755714e9fSE Android 355255e72915d4cbddceb435e13d81601755714e9fSE Android memset(cn->bool_ids, 0, sizeof(cn->bool_ids)); 356255e72915d4cbddceb435e13d81601755714e9fSE Android cn->expr_pre_comp = 0x0; 357255e72915d4cbddceb435e13d81601755714e9fSE Android 358255e72915d4cbddceb435e13d81601755714e9fSE Android /* take care of !expr case */ 359255e72915d4cbddceb435e13d81601755714e9fSE Android ne = NULL; 360255e72915d4cbddceb435e13d81601755714e9fSE Android e = cn->expr; 361255e72915d4cbddceb435e13d81601755714e9fSE Android 362255e72915d4cbddceb435e13d81601755714e9fSE Android /* becuase it's RPN look at last element */ 363255e72915d4cbddceb435e13d81601755714e9fSE Android while (e->next != NULL) { 364255e72915d4cbddceb435e13d81601755714e9fSE Android ne = e; 365255e72915d4cbddceb435e13d81601755714e9fSE Android e = e->next; 366255e72915d4cbddceb435e13d81601755714e9fSE Android } 367255e72915d4cbddceb435e13d81601755714e9fSE Android if (e->expr_type == COND_NOT) { 368255e72915d4cbddceb435e13d81601755714e9fSE Android if (ne) { 369255e72915d4cbddceb435e13d81601755714e9fSE Android ne->next = NULL; 370255e72915d4cbddceb435e13d81601755714e9fSE Android } else { /* ne should never be NULL */ 371255e72915d4cbddceb435e13d81601755714e9fSE Android printf 372255e72915d4cbddceb435e13d81601755714e9fSE Android ("Found expr with no bools and only a ! - this should never happen.\n"); 373255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 374255e72915d4cbddceb435e13d81601755714e9fSE Android } 375255e72915d4cbddceb435e13d81601755714e9fSE Android /* swap the true and false lists */ 376255e72915d4cbddceb435e13d81601755714e9fSE Android tmp = cn->true_list; 377255e72915d4cbddceb435e13d81601755714e9fSE Android cn->true_list = cn->false_list; 378255e72915d4cbddceb435e13d81601755714e9fSE Android cn->false_list = tmp; 379255e72915d4cbddceb435e13d81601755714e9fSE Android tmp2 = cn->avtrue_list; 380255e72915d4cbddceb435e13d81601755714e9fSE Android cn->avtrue_list = cn->avfalse_list; 381255e72915d4cbddceb435e13d81601755714e9fSE Android cn->avfalse_list = tmp2; 382255e72915d4cbddceb435e13d81601755714e9fSE Android 383255e72915d4cbddceb435e13d81601755714e9fSE Android /* free the "not" node in the list */ 384255e72915d4cbddceb435e13d81601755714e9fSE Android free(e); 385255e72915d4cbddceb435e13d81601755714e9fSE Android } 386255e72915d4cbddceb435e13d81601755714e9fSE Android 387255e72915d4cbddceb435e13d81601755714e9fSE Android /* find all the bools in the expression */ 388255e72915d4cbddceb435e13d81601755714e9fSE Android for (e = cn->expr; e != NULL; e = e->next) { 389255e72915d4cbddceb435e13d81601755714e9fSE Android switch (e->expr_type) { 390255e72915d4cbddceb435e13d81601755714e9fSE Android case COND_BOOL: 391255e72915d4cbddceb435e13d81601755714e9fSE Android i = 0; 392255e72915d4cbddceb435e13d81601755714e9fSE Android /* see if we've already seen this bool */ 393255e72915d4cbddceb435e13d81601755714e9fSE Android if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) { 394255e72915d4cbddceb435e13d81601755714e9fSE Android /* count em all but only record up to COND_MAX_BOOLS */ 395255e72915d4cbddceb435e13d81601755714e9fSE Android if (cn->nbools < COND_MAX_BOOLS) 396255e72915d4cbddceb435e13d81601755714e9fSE Android cn->bool_ids[cn->nbools++] = e->bool; 397255e72915d4cbddceb435e13d81601755714e9fSE Android else 398255e72915d4cbddceb435e13d81601755714e9fSE Android cn->nbools++; 399255e72915d4cbddceb435e13d81601755714e9fSE Android } 400255e72915d4cbddceb435e13d81601755714e9fSE Android break; 401255e72915d4cbddceb435e13d81601755714e9fSE Android default: 402255e72915d4cbddceb435e13d81601755714e9fSE Android break; 403255e72915d4cbddceb435e13d81601755714e9fSE Android } 404255e72915d4cbddceb435e13d81601755714e9fSE Android } 405255e72915d4cbddceb435e13d81601755714e9fSE Android 406255e72915d4cbddceb435e13d81601755714e9fSE Android /* only precompute for exprs with <= COND_AX_BOOLS */ 407255e72915d4cbddceb435e13d81601755714e9fSE Android if (cn->nbools <= COND_MAX_BOOLS) { 408255e72915d4cbddceb435e13d81601755714e9fSE Android /* save the default values for the bools so we can play with them */ 409255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < cn->nbools; i++) { 410255e72915d4cbddceb435e13d81601755714e9fSE Android orig_value[i] = 411255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct[cn->bool_ids[i] - 1]->state; 412255e72915d4cbddceb435e13d81601755714e9fSE Android } 413255e72915d4cbddceb435e13d81601755714e9fSE Android 414255e72915d4cbddceb435e13d81601755714e9fSE Android /* loop through all possible combinations of values for bools in expression */ 415255e72915d4cbddceb435e13d81601755714e9fSE Android for (test = 0x0; test < (0x1U << cn->nbools); test++) { 416255e72915d4cbddceb435e13d81601755714e9fSE Android /* temporarily set the value for all the bools in the 417255e72915d4cbddceb435e13d81601755714e9fSE Android * expression using the corr. bit in test */ 418255e72915d4cbddceb435e13d81601755714e9fSE Android for (j = 0; j < cn->nbools; j++) { 419255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct[cn->bool_ids[j] - 420255e72915d4cbddceb435e13d81601755714e9fSE Android 1]->state = 421255e72915d4cbddceb435e13d81601755714e9fSE Android (test & (0x1 << j)) ? 1 : 0; 422255e72915d4cbddceb435e13d81601755714e9fSE Android } 423255e72915d4cbddceb435e13d81601755714e9fSE Android k = cond_evaluate_expr(p, cn->expr); 424255e72915d4cbddceb435e13d81601755714e9fSE Android if (k == -1) { 425255e72915d4cbddceb435e13d81601755714e9fSE Android printf 426255e72915d4cbddceb435e13d81601755714e9fSE Android ("While testing expression, expression result " 427255e72915d4cbddceb435e13d81601755714e9fSE Android "was undefined - this should never happen.\n"); 428255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 429255e72915d4cbddceb435e13d81601755714e9fSE Android } 430255e72915d4cbddceb435e13d81601755714e9fSE Android /* set the bit if expression evaluates true */ 431255e72915d4cbddceb435e13d81601755714e9fSE Android if (k) 432255e72915d4cbddceb435e13d81601755714e9fSE Android cn->expr_pre_comp |= 0x1 << test; 433255e72915d4cbddceb435e13d81601755714e9fSE Android } 434255e72915d4cbddceb435e13d81601755714e9fSE Android 435255e72915d4cbddceb435e13d81601755714e9fSE Android /* restore bool default values */ 436255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < cn->nbools; i++) 437255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct[cn->bool_ids[i] - 1]->state = 438255e72915d4cbddceb435e13d81601755714e9fSE Android orig_value[i]; 439255e72915d4cbddceb435e13d81601755714e9fSE Android } 440255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 441255e72915d4cbddceb435e13d81601755714e9fSE Android} 442255e72915d4cbddceb435e13d81601755714e9fSE Android 443255e72915d4cbddceb435e13d81601755714e9fSE Androidint evaluate_conds(policydb_t * p) 444255e72915d4cbddceb435e13d81601755714e9fSE Android{ 445255e72915d4cbddceb435e13d81601755714e9fSE Android int ret; 446255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t *cur; 447255e72915d4cbddceb435e13d81601755714e9fSE Android 448255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = p->cond_list; cur != NULL; cur = cur->next) { 449255e72915d4cbddceb435e13d81601755714e9fSE Android ret = evaluate_cond_node(p, cur); 450255e72915d4cbddceb435e13d81601755714e9fSE Android if (ret) 451255e72915d4cbddceb435e13d81601755714e9fSE Android return ret; 452255e72915d4cbddceb435e13d81601755714e9fSE Android } 453255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 454255e72915d4cbddceb435e13d81601755714e9fSE Android} 455255e72915d4cbddceb435e13d81601755714e9fSE Android 456255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_policydb_init(policydb_t * p) 457255e72915d4cbddceb435e13d81601755714e9fSE Android{ 458255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct = NULL; 459255e72915d4cbddceb435e13d81601755714e9fSE Android p->cond_list = NULL; 460255e72915d4cbddceb435e13d81601755714e9fSE Android if (avtab_init(&p->te_cond_avtab)) 461255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 462255e72915d4cbddceb435e13d81601755714e9fSE Android 463255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 464255e72915d4cbddceb435e13d81601755714e9fSE Android} 465255e72915d4cbddceb435e13d81601755714e9fSE Android 466255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_av_list_destroy(cond_av_list_t * list) 467255e72915d4cbddceb435e13d81601755714e9fSE Android{ 468255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *cur, *next; 469255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = list; cur != NULL; cur = next) { 470255e72915d4cbddceb435e13d81601755714e9fSE Android next = cur->next; 471255e72915d4cbddceb435e13d81601755714e9fSE Android /* the avtab_ptr_t node is destroy by the avtab */ 472255e72915d4cbddceb435e13d81601755714e9fSE Android free(cur); 473255e72915d4cbddceb435e13d81601755714e9fSE Android } 474255e72915d4cbddceb435e13d81601755714e9fSE Android} 475255e72915d4cbddceb435e13d81601755714e9fSE Android 476255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_expr_destroy(cond_expr_t * expr) 477255e72915d4cbddceb435e13d81601755714e9fSE Android{ 478255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *cur_expr, *next_expr; 479255e72915d4cbddceb435e13d81601755714e9fSE Android 480255e72915d4cbddceb435e13d81601755714e9fSE Android if (!expr) 481255e72915d4cbddceb435e13d81601755714e9fSE Android return; 482255e72915d4cbddceb435e13d81601755714e9fSE Android 483255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) { 484255e72915d4cbddceb435e13d81601755714e9fSE Android next_expr = cur_expr->next; 485255e72915d4cbddceb435e13d81601755714e9fSE Android free(cur_expr); 486255e72915d4cbddceb435e13d81601755714e9fSE Android } 487255e72915d4cbddceb435e13d81601755714e9fSE Android} 488255e72915d4cbddceb435e13d81601755714e9fSE Android 489255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_node_destroy(cond_node_t * node) 490255e72915d4cbddceb435e13d81601755714e9fSE Android{ 491255e72915d4cbddceb435e13d81601755714e9fSE Android if (!node) 492255e72915d4cbddceb435e13d81601755714e9fSE Android return; 493255e72915d4cbddceb435e13d81601755714e9fSE Android 494255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_destroy(node->expr); 495255e72915d4cbddceb435e13d81601755714e9fSE Android avrule_list_destroy(node->avtrue_list); 496255e72915d4cbddceb435e13d81601755714e9fSE Android avrule_list_destroy(node->avfalse_list); 497255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_destroy(node->true_list); 498255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_destroy(node->false_list); 499255e72915d4cbddceb435e13d81601755714e9fSE Android} 500255e72915d4cbddceb435e13d81601755714e9fSE Android 501255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_list_destroy(cond_list_t * list) 502255e72915d4cbddceb435e13d81601755714e9fSE Android{ 503255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t *next, *cur; 504255e72915d4cbddceb435e13d81601755714e9fSE Android 505255e72915d4cbddceb435e13d81601755714e9fSE Android if (list == NULL) 506255e72915d4cbddceb435e13d81601755714e9fSE Android return; 507255e72915d4cbddceb435e13d81601755714e9fSE Android 508255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = list; cur != NULL; cur = next) { 509255e72915d4cbddceb435e13d81601755714e9fSE Android next = cur->next; 510255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_destroy(cur); 511255e72915d4cbddceb435e13d81601755714e9fSE Android free(cur); 512255e72915d4cbddceb435e13d81601755714e9fSE Android } 513255e72915d4cbddceb435e13d81601755714e9fSE Android} 514255e72915d4cbddceb435e13d81601755714e9fSE Android 515255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_policydb_destroy(policydb_t * p) 516255e72915d4cbddceb435e13d81601755714e9fSE Android{ 517255e72915d4cbddceb435e13d81601755714e9fSE Android if (p->bool_val_to_struct != NULL) 518255e72915d4cbddceb435e13d81601755714e9fSE Android free(p->bool_val_to_struct); 519255e72915d4cbddceb435e13d81601755714e9fSE Android avtab_destroy(&p->te_cond_avtab); 520255e72915d4cbddceb435e13d81601755714e9fSE Android cond_list_destroy(p->cond_list); 521255e72915d4cbddceb435e13d81601755714e9fSE Android} 522255e72915d4cbddceb435e13d81601755714e9fSE Android 523255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_init_bool_indexes(policydb_t * p) 524255e72915d4cbddceb435e13d81601755714e9fSE Android{ 525255e72915d4cbddceb435e13d81601755714e9fSE Android if (p->bool_val_to_struct) 526255e72915d4cbddceb435e13d81601755714e9fSE Android free(p->bool_val_to_struct); 527255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct = (cond_bool_datum_t **) 528255e72915d4cbddceb435e13d81601755714e9fSE Android malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *)); 529255e72915d4cbddceb435e13d81601755714e9fSE Android if (!p->bool_val_to_struct) 530255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 531255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 532255e72915d4cbddceb435e13d81601755714e9fSE Android} 533255e72915d4cbddceb435e13d81601755714e9fSE Android 534255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p 535255e72915d4cbddceb435e13d81601755714e9fSE Android __attribute__ ((unused))) 536255e72915d4cbddceb435e13d81601755714e9fSE Android{ 537255e72915d4cbddceb435e13d81601755714e9fSE Android if (key) 538255e72915d4cbddceb435e13d81601755714e9fSE Android free(key); 539255e72915d4cbddceb435e13d81601755714e9fSE Android free(datum); 540255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 541255e72915d4cbddceb435e13d81601755714e9fSE Android} 542255e72915d4cbddceb435e13d81601755714e9fSE Android 543255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap) 544255e72915d4cbddceb435e13d81601755714e9fSE Android{ 545255e72915d4cbddceb435e13d81601755714e9fSE Android policydb_t *p; 546255e72915d4cbddceb435e13d81601755714e9fSE Android cond_bool_datum_t *booldatum; 547255e72915d4cbddceb435e13d81601755714e9fSE Android 548255e72915d4cbddceb435e13d81601755714e9fSE Android booldatum = datum; 549255e72915d4cbddceb435e13d81601755714e9fSE Android p = datap; 550255e72915d4cbddceb435e13d81601755714e9fSE Android 551255e72915d4cbddceb435e13d81601755714e9fSE Android if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim) 552255e72915d4cbddceb435e13d81601755714e9fSE Android return -EINVAL; 553255e72915d4cbddceb435e13d81601755714e9fSE Android 554255e72915d4cbddceb435e13d81601755714e9fSE Android p->p_bool_val_to_name[booldatum->s.value - 1] = key; 555255e72915d4cbddceb435e13d81601755714e9fSE Android p->bool_val_to_struct[booldatum->s.value - 1] = booldatum; 556255e72915d4cbddceb435e13d81601755714e9fSE Android 557255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 558255e72915d4cbddceb435e13d81601755714e9fSE Android} 559255e72915d4cbddceb435e13d81601755714e9fSE Android 560255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int bool_isvalid(cond_bool_datum_t * b) 561255e72915d4cbddceb435e13d81601755714e9fSE Android{ 562255e72915d4cbddceb435e13d81601755714e9fSE Android if (!(b->state == 0 || b->state == 1)) 563255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 564255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 565255e72915d4cbddceb435e13d81601755714e9fSE Android} 566255e72915d4cbddceb435e13d81601755714e9fSE Android 567fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalleyint cond_read_bool(policydb_t * p, 568fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley hashtab_t h, 569255e72915d4cbddceb435e13d81601755714e9fSE Android struct policy_file *fp) 570255e72915d4cbddceb435e13d81601755714e9fSE Android{ 571255e72915d4cbddceb435e13d81601755714e9fSE Android char *key = 0; 572255e72915d4cbddceb435e13d81601755714e9fSE Android cond_bool_datum_t *booldatum; 573255e72915d4cbddceb435e13d81601755714e9fSE Android uint32_t buf[3], len; 574255e72915d4cbddceb435e13d81601755714e9fSE Android int rc; 575255e72915d4cbddceb435e13d81601755714e9fSE Android 576255e72915d4cbddceb435e13d81601755714e9fSE Android booldatum = malloc(sizeof(cond_bool_datum_t)); 577255e72915d4cbddceb435e13d81601755714e9fSE Android if (!booldatum) 578255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 579255e72915d4cbddceb435e13d81601755714e9fSE Android memset(booldatum, 0, sizeof(cond_bool_datum_t)); 580255e72915d4cbddceb435e13d81601755714e9fSE Android 581255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t) * 3); 582255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 583255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 584255e72915d4cbddceb435e13d81601755714e9fSE Android 585255e72915d4cbddceb435e13d81601755714e9fSE Android booldatum->s.value = le32_to_cpu(buf[0]); 586255e72915d4cbddceb435e13d81601755714e9fSE Android booldatum->state = le32_to_cpu(buf[1]); 587255e72915d4cbddceb435e13d81601755714e9fSE Android 588255e72915d4cbddceb435e13d81601755714e9fSE Android if (!bool_isvalid(booldatum)) 589255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 590255e72915d4cbddceb435e13d81601755714e9fSE Android 591255e72915d4cbddceb435e13d81601755714e9fSE Android len = le32_to_cpu(buf[2]); 592255e72915d4cbddceb435e13d81601755714e9fSE Android 593255e72915d4cbddceb435e13d81601755714e9fSE Android key = malloc(len + 1); 594255e72915d4cbddceb435e13d81601755714e9fSE Android if (!key) 595255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 596255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(key, fp, len); 597255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 598255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 599255e72915d4cbddceb435e13d81601755714e9fSE Android key[len] = 0; 600fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley 601fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley if (p->policy_type != POLICY_KERN && 602fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 603fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley rc = next_entry(buf, fp, sizeof(uint32_t)); 604fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley if (rc < 0) 605fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley goto err; 606fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley booldatum->flags = le32_to_cpu(buf[0]); 607fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley } 608fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley 609255e72915d4cbddceb435e13d81601755714e9fSE Android if (hashtab_insert(h, key, booldatum)) 610255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 611255e72915d4cbddceb435e13d81601755714e9fSE Android 612255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 613255e72915d4cbddceb435e13d81601755714e9fSE Android err: 614255e72915d4cbddceb435e13d81601755714e9fSE Android cond_destroy_bool(key, booldatum, 0); 615255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 616255e72915d4cbddceb435e13d81601755714e9fSE Android} 617255e72915d4cbddceb435e13d81601755714e9fSE Android 618255e72915d4cbddceb435e13d81601755714e9fSE Androidstruct cond_insertf_data { 619255e72915d4cbddceb435e13d81601755714e9fSE Android struct policydb *p; 620255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *other; 621255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *head; 622255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *tail; 623255e72915d4cbddceb435e13d81601755714e9fSE Android}; 624255e72915d4cbddceb435e13d81601755714e9fSE Android 625255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_insertf(avtab_t * a 626255e72915d4cbddceb435e13d81601755714e9fSE Android __attribute__ ((unused)), avtab_key_t * k, 627255e72915d4cbddceb435e13d81601755714e9fSE Android avtab_datum_t * d, void *ptr) 628255e72915d4cbddceb435e13d81601755714e9fSE Android{ 629255e72915d4cbddceb435e13d81601755714e9fSE Android struct cond_insertf_data *data = ptr; 630255e72915d4cbddceb435e13d81601755714e9fSE Android struct policydb *p = data->p; 631255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *other = data->other, *list, *cur; 632255e72915d4cbddceb435e13d81601755714e9fSE Android avtab_ptr_t node_ptr; 633255e72915d4cbddceb435e13d81601755714e9fSE Android uint8_t found; 634255e72915d4cbddceb435e13d81601755714e9fSE Android 635255e72915d4cbddceb435e13d81601755714e9fSE Android /* 636255e72915d4cbddceb435e13d81601755714e9fSE Android * For type rules we have to make certain there aren't any 637255e72915d4cbddceb435e13d81601755714e9fSE Android * conflicting rules by searching the te_avtab and the 638255e72915d4cbddceb435e13d81601755714e9fSE Android * cond_te_avtab. 639255e72915d4cbddceb435e13d81601755714e9fSE Android */ 640255e72915d4cbddceb435e13d81601755714e9fSE Android if (k->specified & AVTAB_TYPE) { 641255e72915d4cbddceb435e13d81601755714e9fSE Android if (avtab_search(&p->te_avtab, k)) { 642255e72915d4cbddceb435e13d81601755714e9fSE Android printf 643255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: type rule already exists outside of a conditional."); 644255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 645255e72915d4cbddceb435e13d81601755714e9fSE Android } 646255e72915d4cbddceb435e13d81601755714e9fSE Android /* 647255e72915d4cbddceb435e13d81601755714e9fSE Android * If we are reading the false list other will be a pointer to 648255e72915d4cbddceb435e13d81601755714e9fSE Android * the true list. We can have duplicate entries if there is only 649255e72915d4cbddceb435e13d81601755714e9fSE Android * 1 other entry and it is in our true list. 650255e72915d4cbddceb435e13d81601755714e9fSE Android * 651255e72915d4cbddceb435e13d81601755714e9fSE Android * If we are reading the true list (other == NULL) there shouldn't 652255e72915d4cbddceb435e13d81601755714e9fSE Android * be any other entries. 653255e72915d4cbddceb435e13d81601755714e9fSE Android */ 654255e72915d4cbddceb435e13d81601755714e9fSE Android if (other) { 655255e72915d4cbddceb435e13d81601755714e9fSE Android node_ptr = avtab_search_node(&p->te_cond_avtab, k); 656255e72915d4cbddceb435e13d81601755714e9fSE Android if (node_ptr) { 657255e72915d4cbddceb435e13d81601755714e9fSE Android if (avtab_search_node_next 658255e72915d4cbddceb435e13d81601755714e9fSE Android (node_ptr, k->specified)) { 659255e72915d4cbddceb435e13d81601755714e9fSE Android printf 660255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: too many conflicting type rules."); 661255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 662255e72915d4cbddceb435e13d81601755714e9fSE Android } 663255e72915d4cbddceb435e13d81601755714e9fSE Android found = 0; 664255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur = other; cur != NULL; cur = cur->next) { 665255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur->node == node_ptr) { 666255e72915d4cbddceb435e13d81601755714e9fSE Android found = 1; 667255e72915d4cbddceb435e13d81601755714e9fSE Android break; 668255e72915d4cbddceb435e13d81601755714e9fSE Android } 669255e72915d4cbddceb435e13d81601755714e9fSE Android } 670255e72915d4cbddceb435e13d81601755714e9fSE Android if (!found) { 671255e72915d4cbddceb435e13d81601755714e9fSE Android printf 672255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: conflicting type rules.\n"); 673255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 674255e72915d4cbddceb435e13d81601755714e9fSE Android } 675255e72915d4cbddceb435e13d81601755714e9fSE Android } 676255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 677255e72915d4cbddceb435e13d81601755714e9fSE Android if (avtab_search(&p->te_cond_avtab, k)) { 678255e72915d4cbddceb435e13d81601755714e9fSE Android printf 679255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: conflicting type rules when adding type rule for true.\n"); 680255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 681255e72915d4cbddceb435e13d81601755714e9fSE Android } 682255e72915d4cbddceb435e13d81601755714e9fSE Android } 683255e72915d4cbddceb435e13d81601755714e9fSE Android } 684255e72915d4cbddceb435e13d81601755714e9fSE Android 685255e72915d4cbddceb435e13d81601755714e9fSE Android node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 686255e72915d4cbddceb435e13d81601755714e9fSE Android if (!node_ptr) { 687255e72915d4cbddceb435e13d81601755714e9fSE Android printf("security: could not insert rule."); 688255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 689255e72915d4cbddceb435e13d81601755714e9fSE Android } 690255e72915d4cbddceb435e13d81601755714e9fSE Android node_ptr->parse_context = (void *)1; 691255e72915d4cbddceb435e13d81601755714e9fSE Android 692255e72915d4cbddceb435e13d81601755714e9fSE Android list = malloc(sizeof(cond_av_list_t)); 693255e72915d4cbddceb435e13d81601755714e9fSE Android if (!list) 694255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 695255e72915d4cbddceb435e13d81601755714e9fSE Android memset(list, 0, sizeof(cond_av_list_t)); 696255e72915d4cbddceb435e13d81601755714e9fSE Android 697255e72915d4cbddceb435e13d81601755714e9fSE Android list->node = node_ptr; 698255e72915d4cbddceb435e13d81601755714e9fSE Android if (!data->head) 699255e72915d4cbddceb435e13d81601755714e9fSE Android data->head = list; 700255e72915d4cbddceb435e13d81601755714e9fSE Android else 701255e72915d4cbddceb435e13d81601755714e9fSE Android data->tail->next = list; 702255e72915d4cbddceb435e13d81601755714e9fSE Android data->tail = list; 703255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 704255e72915d4cbddceb435e13d81601755714e9fSE Android 705255e72915d4cbddceb435e13d81601755714e9fSE Android err: 706255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_destroy(data->head); 707255e72915d4cbddceb435e13d81601755714e9fSE Android data->head = NULL; 708255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 709255e72915d4cbddceb435e13d81601755714e9fSE Android} 710255e72915d4cbddceb435e13d81601755714e9fSE Android 711255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_read_av_list(policydb_t * p, void *fp, 712255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t ** ret_list, cond_av_list_t * other) 713255e72915d4cbddceb435e13d81601755714e9fSE Android{ 714255e72915d4cbddceb435e13d81601755714e9fSE Android unsigned int i; 715255e72915d4cbddceb435e13d81601755714e9fSE Android int rc; 716255e72915d4cbddceb435e13d81601755714e9fSE Android uint32_t buf[1], len; 717255e72915d4cbddceb435e13d81601755714e9fSE Android struct cond_insertf_data data; 718255e72915d4cbddceb435e13d81601755714e9fSE Android 719255e72915d4cbddceb435e13d81601755714e9fSE Android *ret_list = NULL; 720255e72915d4cbddceb435e13d81601755714e9fSE Android 721255e72915d4cbddceb435e13d81601755714e9fSE Android len = 0; 722255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t)); 723255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 724255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 725255e72915d4cbddceb435e13d81601755714e9fSE Android 726255e72915d4cbddceb435e13d81601755714e9fSE Android len = le32_to_cpu(buf[0]); 727255e72915d4cbddceb435e13d81601755714e9fSE Android if (len == 0) { 728255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 729255e72915d4cbddceb435e13d81601755714e9fSE Android } 730255e72915d4cbddceb435e13d81601755714e9fSE Android 731255e72915d4cbddceb435e13d81601755714e9fSE Android data.p = p; 732255e72915d4cbddceb435e13d81601755714e9fSE Android data.other = other; 733255e72915d4cbddceb435e13d81601755714e9fSE Android data.head = NULL; 734255e72915d4cbddceb435e13d81601755714e9fSE Android data.tail = NULL; 735255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < len; i++) { 736255e72915d4cbddceb435e13d81601755714e9fSE Android rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, 737255e72915d4cbddceb435e13d81601755714e9fSE Android cond_insertf, &data); 738255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc) 739255e72915d4cbddceb435e13d81601755714e9fSE Android return rc; 740255e72915d4cbddceb435e13d81601755714e9fSE Android 741255e72915d4cbddceb435e13d81601755714e9fSE Android } 742255e72915d4cbddceb435e13d81601755714e9fSE Android 743255e72915d4cbddceb435e13d81601755714e9fSE Android *ret_list = data.head; 744255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 745255e72915d4cbddceb435e13d81601755714e9fSE Android} 746255e72915d4cbddceb435e13d81601755714e9fSE Android 747255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int expr_isvalid(policydb_t * p, cond_expr_t * expr) 748255e72915d4cbddceb435e13d81601755714e9fSE Android{ 749255e72915d4cbddceb435e13d81601755714e9fSE Android if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { 750255e72915d4cbddceb435e13d81601755714e9fSE Android printf 751255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: conditional expressions uses unknown operator.\n"); 752255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 753255e72915d4cbddceb435e13d81601755714e9fSE Android } 754255e72915d4cbddceb435e13d81601755714e9fSE Android 755255e72915d4cbddceb435e13d81601755714e9fSE Android if (expr->bool > p->p_bools.nprim) { 756255e72915d4cbddceb435e13d81601755714e9fSE Android printf 757255e72915d4cbddceb435e13d81601755714e9fSE Android ("security: conditional expressions uses unknown bool.\n"); 758255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 759255e72915d4cbddceb435e13d81601755714e9fSE Android } 760255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 761255e72915d4cbddceb435e13d81601755714e9fSE Android} 762255e72915d4cbddceb435e13d81601755714e9fSE Android 763255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) 764255e72915d4cbddceb435e13d81601755714e9fSE Android{ 765255e72915d4cbddceb435e13d81601755714e9fSE Android uint32_t buf[2]; 766255e72915d4cbddceb435e13d81601755714e9fSE Android int len, i, rc; 767255e72915d4cbddceb435e13d81601755714e9fSE Android cond_expr_t *expr = NULL, *last = NULL; 768255e72915d4cbddceb435e13d81601755714e9fSE Android 769255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t)); 770255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 771255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 772255e72915d4cbddceb435e13d81601755714e9fSE Android 773255e72915d4cbddceb435e13d81601755714e9fSE Android node->cur_state = le32_to_cpu(buf[0]); 774255e72915d4cbddceb435e13d81601755714e9fSE Android 775255e72915d4cbddceb435e13d81601755714e9fSE Android len = 0; 776255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t)); 777255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 778255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 779255e72915d4cbddceb435e13d81601755714e9fSE Android 780255e72915d4cbddceb435e13d81601755714e9fSE Android /* expr */ 781255e72915d4cbddceb435e13d81601755714e9fSE Android len = le32_to_cpu(buf[0]); 782255e72915d4cbddceb435e13d81601755714e9fSE Android 783255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < len; i++) { 784255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t) * 2); 785255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 786255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 787255e72915d4cbddceb435e13d81601755714e9fSE Android 788255e72915d4cbddceb435e13d81601755714e9fSE Android expr = malloc(sizeof(cond_expr_t)); 789255e72915d4cbddceb435e13d81601755714e9fSE Android if (!expr) { 790255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 791255e72915d4cbddceb435e13d81601755714e9fSE Android } 792255e72915d4cbddceb435e13d81601755714e9fSE Android memset(expr, 0, sizeof(cond_expr_t)); 793255e72915d4cbddceb435e13d81601755714e9fSE Android 794255e72915d4cbddceb435e13d81601755714e9fSE Android expr->expr_type = le32_to_cpu(buf[0]); 795255e72915d4cbddceb435e13d81601755714e9fSE Android expr->bool = le32_to_cpu(buf[1]); 796255e72915d4cbddceb435e13d81601755714e9fSE Android 797255e72915d4cbddceb435e13d81601755714e9fSE Android if (!expr_isvalid(p, expr)) { 798255e72915d4cbddceb435e13d81601755714e9fSE Android free(expr); 799255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 800255e72915d4cbddceb435e13d81601755714e9fSE Android } 801255e72915d4cbddceb435e13d81601755714e9fSE Android 802255e72915d4cbddceb435e13d81601755714e9fSE Android if (i == 0) { 803255e72915d4cbddceb435e13d81601755714e9fSE Android node->expr = expr; 804255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 805255e72915d4cbddceb435e13d81601755714e9fSE Android last->next = expr; 806255e72915d4cbddceb435e13d81601755714e9fSE Android } 807255e72915d4cbddceb435e13d81601755714e9fSE Android last = expr; 808255e72915d4cbddceb435e13d81601755714e9fSE Android } 809255e72915d4cbddceb435e13d81601755714e9fSE Android 810255e72915d4cbddceb435e13d81601755714e9fSE Android if (p->policy_type == POLICY_KERN) { 811255e72915d4cbddceb435e13d81601755714e9fSE Android if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) 812255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 813255e72915d4cbddceb435e13d81601755714e9fSE Android if (cond_read_av_list(p, fp, &node->false_list, node->true_list) 814255e72915d4cbddceb435e13d81601755714e9fSE Android != 0) 815255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 816255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 817255e72915d4cbddceb435e13d81601755714e9fSE Android if (avrule_read_list(p, &node->avtrue_list, fp)) 818255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 819255e72915d4cbddceb435e13d81601755714e9fSE Android if (avrule_read_list(p, &node->avfalse_list, fp)) 820255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 821255e72915d4cbddceb435e13d81601755714e9fSE Android } 822255e72915d4cbddceb435e13d81601755714e9fSE Android 823fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley if (p->policy_type != POLICY_KERN && 824fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 825fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley rc = next_entry(buf, fp, sizeof(uint32_t)); 826fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley if (rc < 0) 827fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley goto err; 828fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley node->flags = le32_to_cpu(buf[0]); 829fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley } 830fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley 831255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 832255e72915d4cbddceb435e13d81601755714e9fSE Android err: 833255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_destroy(node); 834255e72915d4cbddceb435e13d81601755714e9fSE Android free(node); 835255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 836255e72915d4cbddceb435e13d81601755714e9fSE Android} 837255e72915d4cbddceb435e13d81601755714e9fSE Android 838255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) 839255e72915d4cbddceb435e13d81601755714e9fSE Android{ 840255e72915d4cbddceb435e13d81601755714e9fSE Android cond_node_t *node, *last = NULL; 841255e72915d4cbddceb435e13d81601755714e9fSE Android uint32_t buf[1]; 842255e72915d4cbddceb435e13d81601755714e9fSE Android int i, len, rc; 843255e72915d4cbddceb435e13d81601755714e9fSE Android 844255e72915d4cbddceb435e13d81601755714e9fSE Android rc = next_entry(buf, fp, sizeof(uint32_t)); 845255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc < 0) 846255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 847255e72915d4cbddceb435e13d81601755714e9fSE Android 848255e72915d4cbddceb435e13d81601755714e9fSE Android len = le32_to_cpu(buf[0]); 849255e72915d4cbddceb435e13d81601755714e9fSE Android 850255e72915d4cbddceb435e13d81601755714e9fSE Android rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel); 851255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc) 852255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 853255e72915d4cbddceb435e13d81601755714e9fSE Android 854255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < len; i++) { 855255e72915d4cbddceb435e13d81601755714e9fSE Android node = malloc(sizeof(cond_node_t)); 856255e72915d4cbddceb435e13d81601755714e9fSE Android if (!node) 857255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 858255e72915d4cbddceb435e13d81601755714e9fSE Android memset(node, 0, sizeof(cond_node_t)); 859255e72915d4cbddceb435e13d81601755714e9fSE Android 860255e72915d4cbddceb435e13d81601755714e9fSE Android if (cond_read_node(p, node, fp) != 0) 861255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 862255e72915d4cbddceb435e13d81601755714e9fSE Android 863255e72915d4cbddceb435e13d81601755714e9fSE Android if (i == 0) { 864255e72915d4cbddceb435e13d81601755714e9fSE Android *list = node; 865255e72915d4cbddceb435e13d81601755714e9fSE Android } else { 866255e72915d4cbddceb435e13d81601755714e9fSE Android last->next = node; 867255e72915d4cbddceb435e13d81601755714e9fSE Android } 868255e72915d4cbddceb435e13d81601755714e9fSE Android last = node; 869255e72915d4cbddceb435e13d81601755714e9fSE Android } 870255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 871255e72915d4cbddceb435e13d81601755714e9fSE Android err: 872255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 873255e72915d4cbddceb435e13d81601755714e9fSE Android} 874255e72915d4cbddceb435e13d81601755714e9fSE Android 875255e72915d4cbddceb435e13d81601755714e9fSE Android/* Determine whether additional permissions are granted by the conditional 876255e72915d4cbddceb435e13d81601755714e9fSE Android * av table, and if so, add them to the result 877255e72915d4cbddceb435e13d81601755714e9fSE Android */ 878255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_compute_av(avtab_t * ctab, avtab_key_t * key, 879255e72915d4cbddceb435e13d81601755714e9fSE Android struct sepol_av_decision *avd) 880255e72915d4cbddceb435e13d81601755714e9fSE Android{ 881255e72915d4cbddceb435e13d81601755714e9fSE Android avtab_ptr_t node; 882255e72915d4cbddceb435e13d81601755714e9fSE Android 883255e72915d4cbddceb435e13d81601755714e9fSE Android if (!ctab || !key || !avd) 884255e72915d4cbddceb435e13d81601755714e9fSE Android return; 885255e72915d4cbddceb435e13d81601755714e9fSE Android 886255e72915d4cbddceb435e13d81601755714e9fSE Android for (node = avtab_search_node(ctab, key); node != NULL; 887255e72915d4cbddceb435e13d81601755714e9fSE Android node = avtab_search_node_next(node, key->specified)) { 888255e72915d4cbddceb435e13d81601755714e9fSE Android if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) == 889255e72915d4cbddceb435e13d81601755714e9fSE Android (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) 890255e72915d4cbddceb435e13d81601755714e9fSE Android avd->allowed |= node->datum.data; 891255e72915d4cbddceb435e13d81601755714e9fSE Android if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) == 892255e72915d4cbddceb435e13d81601755714e9fSE Android (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) 893255e72915d4cbddceb435e13d81601755714e9fSE Android /* Since a '0' in an auditdeny mask represents a 894255e72915d4cbddceb435e13d81601755714e9fSE Android * permission we do NOT want to audit (dontaudit), we use 895255e72915d4cbddceb435e13d81601755714e9fSE Android * the '&' operand to ensure that all '0's in the mask 896255e72915d4cbddceb435e13d81601755714e9fSE Android * are retained (much unlike the allow and auditallow cases). 897255e72915d4cbddceb435e13d81601755714e9fSE Android */ 898255e72915d4cbddceb435e13d81601755714e9fSE Android avd->auditdeny &= node->datum.data; 899255e72915d4cbddceb435e13d81601755714e9fSE Android if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) == 900255e72915d4cbddceb435e13d81601755714e9fSE Android (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) 901255e72915d4cbddceb435e13d81601755714e9fSE Android avd->auditallow |= node->datum.data; 902255e72915d4cbddceb435e13d81601755714e9fSE Android } 903255e72915d4cbddceb435e13d81601755714e9fSE Android return; 904255e72915d4cbddceb435e13d81601755714e9fSE Android} 905255e72915d4cbddceb435e13d81601755714e9fSE Android 906255e72915d4cbddceb435e13d81601755714e9fSE Androidavtab_datum_t *cond_av_list_search(avtab_key_t * key, 907255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t * cond_list) 908255e72915d4cbddceb435e13d81601755714e9fSE Android{ 909255e72915d4cbddceb435e13d81601755714e9fSE Android 910255e72915d4cbddceb435e13d81601755714e9fSE Android cond_av_list_t *cur_av; 911255e72915d4cbddceb435e13d81601755714e9fSE Android 912255e72915d4cbddceb435e13d81601755714e9fSE Android for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { 913255e72915d4cbddceb435e13d81601755714e9fSE Android 914255e72915d4cbddceb435e13d81601755714e9fSE Android if (cur_av->node->key.source_type == key->source_type && 915255e72915d4cbddceb435e13d81601755714e9fSE Android cur_av->node->key.target_type == key->target_type && 916255e72915d4cbddceb435e13d81601755714e9fSE Android cur_av->node->key.target_class == key->target_class) 917255e72915d4cbddceb435e13d81601755714e9fSE Android 918255e72915d4cbddceb435e13d81601755714e9fSE Android return &cur_av->node->datum; 919255e72915d4cbddceb435e13d81601755714e9fSE Android 920255e72915d4cbddceb435e13d81601755714e9fSE Android } 921255e72915d4cbddceb435e13d81601755714e9fSE Android return NULL; 922255e72915d4cbddceb435e13d81601755714e9fSE Android 923255e72915d4cbddceb435e13d81601755714e9fSE Android} 924