⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conditional.c

📁 xen 3.2.2 源码
💻 C
字号:
/* Authors: Karl MacMillan <kmacmillan@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 *    the Free Software Foundation, version 2. *//* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */#include <asm/byteorder.h>#include <xen/lib.h>#include <xen/types.h>#include <xen/errno.h>#include <xen/string.h>#include <xen/spinlock.h>#include <xen/xmalloc.h>#include "security.h"#include "conditional.h"/* * 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. */static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr){    struct cond_expr *cur;    int s[COND_EXPR_MAXDEPTH];    int sp = -1;    for ( cur = expr; cur != NULL; cur = cur->next )    {        switch ( cur->expr_type )        {            case COND_BOOL:                if ( sp == (COND_EXPR_MAXDEPTH - 1) )                    return -1;                sp++;                s[sp] = p->bool_val_to_struct[cur->bool - 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. */int evaluate_cond_node(struct policydb *p, struct cond_node *node){    int new_state;    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");        /* turn the rules on or off */        for ( cur = node->true_list; cur != NULL; cur = cur->next )        {            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->key.specified &= ~AVTAB_ENABLED;            else                cur->node->key.specified |= AVTAB_ENABLED;        }    }    return 0;}int cond_policydb_init(struct policydb *p){    p->bool_val_to_struct = NULL;    p->cond_list = NULL;    if ( avtab_init(&p->te_cond_avtab) )        return -1;    return 0;}static void cond_av_list_destroy(struct cond_av_list *list){    struct cond_av_list *cur, *next;    for ( cur = list; cur != NULL; cur = next )    {        next = cur->next;        /* the avtab_ptr_t node is destroy by the avtab */        xfree(cur);    }}static void cond_node_destroy(struct cond_node *node){    struct cond_expr *cur_expr, *next_expr;    for ( cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr )    {        next_expr = cur_expr->next;        xfree(cur_expr);    }    cond_av_list_destroy(node->true_list);    cond_av_list_destroy(node->false_list);    xfree(node);}static void cond_list_destroy(struct cond_node *list){    struct cond_node *next, *cur;    if ( list == NULL )        return;    for ( cur = list; cur != NULL; cur = next )    {        next = cur->next;        cond_node_destroy(cur);    }}void cond_policydb_destroy(struct policydb *p){    xfree(p->bool_val_to_struct);    avtab_destroy(&p->te_cond_avtab);    cond_list_destroy(p->cond_list);}int cond_init_bool_indexes(struct policydb *p){    xfree(p->bool_val_to_struct);    p->bool_val_to_struct = (struct cond_bool_datum**)        xmalloc_array(struct cond_bool_datum*, p->p_bools.nprim);    if ( !p->bool_val_to_struct )        return -1;    return 0;}int cond_destroy_bool(void *key, void *datum, void *p){    xfree(key);    xfree(datum);    return 0;}int cond_index_bool(void *key, void *datum, void *datap){    struct policydb *p;    struct cond_bool_datum *booldatum;    booldatum = datum;    p = datap;    if ( !booldatum->value || booldatum->value > p->p_bools.nprim )        return -EINVAL;    p->p_bool_val_to_name[booldatum->value - 1] = key;    p->bool_val_to_struct[booldatum->value -1] = booldatum;    return 0;}static int bool_isvalid(struct cond_bool_datum *b){    if ( !(b->state == 0 || b->state == 1) )        return 0;    return 1;}int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp){    char *key = NULL;    struct cond_bool_datum *booldatum;    __le32 buf[3];    u32 len;    int rc;    booldatum = xmalloc(struct cond_bool_datum);    if ( !booldatum )        return -1;    memset(booldatum, 0, sizeof(struct cond_bool_datum));    rc = next_entry(buf, fp, sizeof buf);    if ( rc < 0 )        goto err;    booldatum->value = le32_to_cpu(buf[0]);    booldatum->state = le32_to_cpu(buf[1]);    if ( !bool_isvalid(booldatum) )        goto err;    len = le32_to_cpu(buf[2]);    key = xmalloc_array(char, len + 1);    if ( !key )        goto err;    rc = next_entry(key, fp, len);    if ( rc < 0 )        goto err;    key[len] = 0;    if ( hashtab_insert(h, key, booldatum) )        goto err;    return 0;err:    cond_destroy_bool(key, booldatum, NULL);    return -1;}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_insertf_data *data = ptr;    struct policydb *p = data->p;    struct cond_av_list *other = data->other, *list, *cur;    struct avtab_node *node_ptr;    u8 found;    /*     * 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("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, k);            if ( node_ptr )            {                if ( avtab_search_node_next(node_ptr, k->specified) )                {                    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.\n");                    goto err;                }            }        }        else        {            if ( avtab_search(&p->te_cond_avtab, k) )            {                printk("security: conflicting type rules when adding type rule "                                                                "for true.\n");                goto err;            }        }    }    node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);    if ( !node_ptr )    {        printk("security: could not insert rule.");        goto err;    }    list = xmalloc(struct cond_av_list);    if ( !list )        goto err;    memset(list, 0, sizeof(*list));    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(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(fp, p->policyvers, &p->te_cond_avtab, 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");        return 0;    }    if ( expr->bool > p->p_bools.nprim )    {        printk("security: conditional expressions uses unknown bool.\n");        return 0;    }    return 1;}static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp){    __le32 buf[2];    u32 len, i;    int rc;    struct cond_expr *expr = NULL, *last = NULL;    rc = next_entry(buf, fp, sizeof(u32));    if ( rc < 0 )        return -1;    node->cur_state = le32_to_cpu(buf[0]);    len = 0;    rc = next_entry(buf, fp, sizeof(u32));    if ( rc < 0 )        return -1;    /* expr */    len = le32_to_cpu(buf[0]);    for ( i = 0; i < len; i++ )    {        rc = next_entry(buf, fp, sizeof(u32) * 2);        if ( rc < 0 )            goto err;        expr = xmalloc(struct cond_expr);        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]);        if ( !expr_isvalid(p, expr) )        {            xfree(expr);            goto err;        }        if ( i == 0 )             node->expr = expr;        else            last->next = expr;        last = expr;    }    if ( cond_read_av_list(p, fp, &node->true_list, NULL) != 0 )        goto err;    if ( cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0 )        goto err;    return 0;err:    cond_node_destroy(node);    return -1;}int cond_read_list(struct policydb *p, void *fp){    struct cond_node *node, *last = NULL;    __le32 buf[1];    u32 i, len;    int rc;    rc = next_entry(buf, fp, sizeof buf);    if ( rc < 0 )        return -1;    len = le32_to_cpu(buf[0]);    for ( i = 0; i < len; i++ )    {        node = xmalloc(struct cond_node);        if ( !node )            goto err;        memset(node, 0, sizeof(struct cond_node));        if ( cond_read_node(p, node, fp) != 0 )            goto err;        if ( i == 0 )            p->cond_list = node;        else            last->next = node;        last = node;    }    return 0;err:    cond_list_destroy(p->cond_list);    p->cond_list = NULL;    return -1;}/* 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 avtab_node *node;    if( !ctab || !key || !avd )        return;    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 &= node->datum.data;        if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==             (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)) )            avd->auditallow |= node->datum.data;    }    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -