/* Authors: Karl MacMillan <kmacmillan@tresys.com>
- * Frank Mayer <mayerf@tresys.com>
+ * Frank Mayer <mayerf@tresys.com>
*
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
+ * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*/
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/spinlock.h>
-#include <asm/semaphore.h>
#include <linux/slab.h>
#include "security.h"
int evaluate_cond_node(struct policydb *p, struct cond_node *node)
{
int new_state;
- struct cond_av_list* cur;
+ struct cond_av_list *cur;
new_state = cond_evaluate_expr(p, node->expr);
if (new_state != node->cur_state) {
node->cur_state = new_state;
if (new_state == -1)
- printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
+ printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
/* turn the rules on or off */
for (cur = node->true_list; cur != NULL; cur = cur->next) {
- if (new_state <= 0) {
- cur->node->datum.specified &= ~AVTAB_ENABLED;
- } else {
- cur->node->datum.specified |= AVTAB_ENABLED;
- }
+ if (new_state <= 0)
+ cur->node->key.specified &= ~AVTAB_ENABLED;
+ else
+ cur->node->key.specified |= AVTAB_ENABLED;
}
for (cur = node->false_list; cur != NULL; cur = cur->next) {
/* -1 or 1 */
- if (new_state) {
- cur->node->datum.specified &= ~AVTAB_ENABLED;
- } else {
- cur->node->datum.specified |= AVTAB_ENABLED;
- }
+ if (new_state)
+ cur->node->key.specified &= ~AVTAB_ENABLED;
+ else
+ cur->node->key.specified |= AVTAB_ENABLED;
}
}
return 0;
int cond_init_bool_indexes(struct policydb *p)
{
kfree(p->bool_val_to_struct);
- p->bool_val_to_struct = (struct cond_bool_datum**)
- kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
+ p->bool_val_to_struct = (struct cond_bool_datum **)
+ kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL);
if (!p->bool_val_to_struct)
return -1;
return 0;
return -EINVAL;
p->p_bool_val_to_name[booldatum->value - 1] = key;
- p->bool_val_to_struct[booldatum->value -1] = booldatum;
+ p->bool_val_to_struct[booldatum->value - 1] = booldatum;
return 0;
}
{
char *key = NULL;
struct cond_bool_datum *booldatum;
- u32 buf[3], len;
+ __le32 buf[3];
+ u32 len;
int rc;
- booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
+ booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
if (!booldatum)
return -1;
- memset(booldatum, 0, sizeof(struct cond_bool_datum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
return -1;
}
-static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list,
- struct cond_av_list *other)
+struct cond_insertf_data {
+ struct policydb *p;
+ struct cond_av_list *other;
+ struct cond_av_list *head;
+ struct cond_av_list *tail;
+};
+
+static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
{
- struct cond_av_list *list, *last = NULL, *cur;
- struct avtab_key key;
- struct avtab_datum datum;
+ struct cond_insertf_data *data = ptr;
+ struct policydb *p = data->p;
+ struct cond_av_list *other = data->other, *list, *cur;
struct avtab_node *node_ptr;
- int rc;
- u32 buf[1], i, len;
u8 found;
- *ret_list = NULL;
- len = 0;
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- return -1;
-
- len = le32_to_cpu(buf[0]);
- if (len == 0) {
- return 0;
- }
-
- for (i = 0; i < len; i++) {
- if (avtab_read_item(fp, &datum, &key))
+ /*
+ * 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(&p->te_avtab, k)) {
+ printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n");
goto err;
-
+ }
/*
- * 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 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 (datum.specified & AVTAB_TYPE) {
- if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
- printk("security: type rule already exists outside of a conditional.");
- goto err;
- }
- /*
- * 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, &key, AVTAB_TYPE);
- if (node_ptr) {
- if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
- printk("security: too many conflicting type rules.");
- goto err;
- }
- found = 0;
- for (cur = other; cur != NULL; cur = cur->next) {
- if (cur->node == node_ptr) {
- found = 1;
- break;
- }
- }
- if (!found) {
- printk("security: conflicting type rules.");
- goto err;
+ if (other) {
+ node_ptr = avtab_search_node(&p->te_cond_avtab, k);
+ if (node_ptr) {
+ if (avtab_search_node_next(node_ptr, k->specified)) {
+ printk(KERN_ERR "SELinux: too many conflicting type rules.\n");
+ goto err;
+ }
+ found = 0;
+ for (cur = other; cur != NULL; cur = cur->next) {
+ if (cur->node == node_ptr) {
+ found = 1;
+ break;
}
}
- } else {
- if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
- printk("security: conflicting type rules when adding type rule for true.");
+ if (!found) {
+ printk(KERN_ERR "SELinux: conflicting type rules.\n");
goto err;
}
}
+ } else {
+ if (avtab_search(&p->te_cond_avtab, k)) {
+ printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n");
+ goto err;
+ }
}
- node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
- if (!node_ptr) {
- printk("security: could not insert rule.");
- goto err;
- }
-
- list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
- if (!list)
- goto err;
- memset(list, 0, sizeof(struct cond_av_list));
-
- list->node = node_ptr;
- if (i == 0)
- *ret_list = list;
- else
- last->next = list;
- last = list;
+ }
+ node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
+ if (!node_ptr) {
+ printk(KERN_ERR "SELinux: could not insert rule.\n");
+ goto err;
}
+ list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+ if (!list)
+ goto err;
+
+ list->node = node_ptr;
+ if (!data->head)
+ data->head = list;
+ else
+ data->tail->next = list;
+ data->tail = list;
return 0;
+
err:
- cond_av_list_destroy(*ret_list);
- *ret_list = NULL;
+ cond_av_list_destroy(data->head);
+ data->head = NULL;
return -1;
}
+static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
+{
+ int i, rc;
+ __le32 buf[1];
+ u32 len;
+ struct cond_insertf_data data;
+
+ *ret_list = NULL;
+
+ len = 0;
+ rc = next_entry(buf, fp, sizeof(u32));
+ if (rc < 0)
+ return -1;
+
+ len = le32_to_cpu(buf[0]);
+ if (len == 0)
+ return 0;
+
+ data.p = p;
+ data.other = other;
+ data.head = NULL;
+ data.tail = NULL;
+ for (i = 0; i < len; i++) {
+ rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
+ &data);
+ if (rc)
+ return rc;
+
+ }
+
+ *ret_list = data.head;
+ return 0;
+}
+
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
{
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
- printk("security: conditional expressions uses unknown operator.\n");
+ printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n");
return 0;
}
if (expr->bool > p->p_bools.nprim) {
- printk("security: conditional expressions uses unknown bool.\n");
+ printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n");
return 0;
}
return 1;
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
{
- u32 buf[2], len, i;
+ __le32 buf[2];
+ u32 len, i;
int rc;
struct cond_expr *expr = NULL, *last = NULL;
/* expr */
len = le32_to_cpu(buf[0]);
- for (i = 0; i < len; i++ ) {
+ for (i = 0; i < len; i++) {
rc = next_entry(buf, fp, sizeof(u32) * 2);
if (rc < 0)
goto err;
- expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
- if (!expr) {
+ expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
+ if (!expr)
goto err;
- }
- memset(expr, 0, sizeof(struct cond_expr));
expr->expr_type = le32_to_cpu(buf[0]);
expr->bool = le32_to_cpu(buf[1]);
goto err;
}
- if (i == 0) {
+ if (i == 0)
node->expr = expr;
- } else {
+ else
last->next = expr;
- }
last = expr;
}
int cond_read_list(struct policydb *p, void *fp)
{
struct cond_node *node, *last = NULL;
- u32 buf[1], i, len;
+ __le32 buf[1];
+ u32 i, len;
int rc;
rc = next_entry(buf, fp, sizeof buf);
len = le32_to_cpu(buf[0]);
+ rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
+ if (rc)
+ goto err;
+
for (i = 0; i < len; i++) {
- node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
+ node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
if (!node)
goto err;
- memset(node, 0, sizeof(struct cond_node));
if (cond_read_node(p, node, fp) != 0)
goto err;
- if (i == 0) {
+ if (i == 0)
p->cond_list = node;
- } else {
+ else
last->next = node;
- }
last = node;
}
return 0;
err:
cond_list_destroy(p->cond_list);
+ p->cond_list = NULL;
return -1;
}
{
struct avtab_node *node;
- if(!ctab || !key || !avd)
+ if (!ctab || !key || !avd)
return;
- for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
- node = avtab_search_node_next(node, AVTAB_AV)) {
- if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
- avd->allowed |= avtab_allowed(&node->datum);
- if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
+ for (node = avtab_search_node(ctab, key); node != NULL;
+ 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.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 &= avtab_auditdeny(&node->datum);
- if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
- avd->auditallow |= avtab_auditallow(&node->datum);
+ avd->auditdeny &= node->datum.data;
+ if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
+ (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
+ avd->auditallow |= node->datum.data;
}
return;
}