/* * cond_evaluate_expr evaluates a conditional expr * in reverse polish notation. It returns true (1), false (0), * or undefined (-1). Undefined occurs when the expression * exceeds the stack depth of COND_EXPR_MAXDEPTH.
*/ staticint cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
{
u32 i; int s[COND_EXPR_MAXDEPTH]; int sp = -1;
if (expr->len == 0) return -1;
for (i = 0; i < expr->len; i++) { struct cond_expr_node *node = &expr->nodes[i];
switch (node->expr_type) { case COND_BOOL: if (sp == (COND_EXPR_MAXDEPTH - 1)) return -1;
sp++;
s[sp] = p->bool_val_to_struct[node->boolean - 1]->state; break; case COND_NOT: if (sp < 0) return -1;
s[sp] = !s[sp]; break; case COND_OR: if (sp < 1) return -1;
sp--;
s[sp] |= s[sp + 1]; break; case COND_AND: if (sp < 1) return -1;
sp--;
s[sp] &= s[sp + 1]; break; case COND_XOR: if (sp < 1) return -1;
sp--;
s[sp] ^= s[sp + 1]; break; case COND_EQ: if (sp < 1) return -1;
sp--;
s[sp] = (s[sp] == s[sp + 1]); break; case COND_NEQ: if (sp < 1) return -1;
sp--;
s[sp] = (s[sp] != s[sp + 1]); break; default: return -1;
}
} return s[0];
}
/* * evaluate_cond_node evaluates the conditional stored in * a struct cond_node and if the result is different than the * current state of the node it sets the rules in the true/false * list appropriately. If the result of the expression is undefined * all of the rules are disabled for safety.
*/ staticvoid evaluate_cond_node(struct policydb *p, struct cond_node *node)
{ struct avtab_node *avnode; int new_state;
u32 i;
new_state = cond_evaluate_expr(p, &node->expr); if (new_state != node->cur_state) {
node->cur_state = new_state; if (new_state == -1)
pr_err("SELinux: expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ for (i = 0; i < node->true_list.len; i++) {
avnode = node->true_list.nodes[i]; if (new_state <= 0)
avnode->key.specified &= ~AVTAB_ENABLED; else
avnode->key.specified |= AVTAB_ENABLED;
}
for (i = 0; i < node->false_list.len; i++) {
avnode = node->false_list.nodes[i]; /* -1 or 1 */ if (new_state)
avnode->key.specified &= ~AVTAB_ENABLED; else
avnode->key.specified |= AVTAB_ENABLED;
}
}
}
staticvoid cond_node_destroy(struct cond_node *node)
{
kfree(node->expr.nodes); /* the avtab_ptr_t nodes are destroyed by the avtab */
kfree(node->true_list.nodes);
kfree(node->false_list.nodes);
}
/* * For type rules we have to make certain there aren't any * conflicting rules by searching the te_avtab and the * cond_te_avtab.
*/ if (k->specified & AVTAB_TYPE) { if (avtab_search_node(&p->te_avtab, k)) {
pr_err("SELinux: type rule already exists outside of a conditional.\n"); return -EINVAL;
} /* * If we are reading the false list other will be a pointer to * the true list. We can have duplicate entries if there is only * 1 other entry and it is in our true list. * * If we are reading the true list (other == NULL) there shouldn't * be any other entries.
*/ if (other) {
node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { if (avtab_search_node_next(node_ptr,
k->specified)) {
pr_err("SELinux: too many conflicting type rules.\n"); return -EINVAL;
}
found = false; for (i = 0; i < other->len; i++) { if (other->nodes[i] == node_ptr) {
found = true; break;
}
} if (!found) {
pr_err("SELinux: conflicting type rules.\n"); return -EINVAL;
}
}
} else { if (avtab_search_node(&p->te_cond_avtab, k)) {
pr_err("SELinux: conflicting type rules when adding type rule for true.\n"); return -EINVAL;
}
}
}
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); if (!node_ptr) {
pr_err("SELinux: could not insert rule.\n"); return -ENOMEM;
}
/* * cond_write_cond_av_list doesn't write out the av_list nodes. * Instead it writes out the key/value pairs from the avtab. This * is necessary because there is no way to uniquely identifying rules * in the avtab so it is not possible to associate individual rules * in the avtab with a conditional without saving them as part of * the conditional. This means that the avtab with the conditional * rules will not be saved but will be rebuilt on policy load.
*/ staticint cond_write_av_list(struct policydb *p, struct cond_av_list *list, struct policy_file *fp)
{
__le32 buf[1];
u32 i; int rc;
for (node = avtab_search_node(ctab, key); node;
node = avtab_search_node_next(node, key->specified)) { if (node->key.specified & AVTAB_ENABLED)
services_compute_xperms_decision(xpermd, node);
}
} /* Determine whether additional permissions are granted by the conditional * av table, and if so, add them to the result
*/ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd, struct extended_perms *xperms)
{ struct avtab_node *node;
if (!ctab || !key || !avd) return;
for (node = avtab_search_node(ctab, key); node;
node = avtab_search_node_next(node, key->specified)) { if ((u16)(AVTAB_ALLOWED | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
avd->allowed |= node->datum.u.data; if ((u16)(AVTAB_AUDITDENY | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) /* Since a '0' in an auditdeny mask represents a * permission we do NOT want to audit (dontaudit), we use * the '&' operand to ensure that all '0's in the mask * are retained (much unlike the allow and auditallow cases).
*/
avd->auditdeny &= node->datum.u.data; if ((u16)(AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
avd->auditallow |= node->datum.u.data; if (xperms && (node->key.specified & AVTAB_ENABLED) &&
(node->key.specified & AVTAB_XPERMS))
services_compute_xperms_drivers(xperms, node);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.