hackedteam/core-android-native

View on GitHub
selinux_native/jni/libsepol/src/avrule_block.c

Summary

Maintainability
Test Coverage
/* Authors: Jason Tang <jtang@tresys.com>
 *
 * Functions that manipulate a logical block (conditional, optional,
 * or global scope) for a policy module.
 *
 * Copyright (C) 2005 Tresys Technology, LLC
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <sepol/policydb/policydb.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/avrule_block.h>

#include <assert.h>
#include <stdlib.h>

/* It is anticipated that there be less declarations within an avrule
 * block than the global policy.  Thus the symbol table sizes are
 * smaller than those listed in policydb.c */
static unsigned int symtab_sizes[SYM_NUM] = {
    2,
    4,
    8,
    32,
    16,
    4,
    2,
    2,
};

avrule_block_t *avrule_block_create(void)
{
    avrule_block_t *block;
    if ((block = calloc(1, sizeof(*block))) == NULL) {
        return NULL;
    }
    return block;
}

avrule_decl_t *avrule_decl_create(uint32_t decl_id)
{
    avrule_decl_t *decl;
    int i;
    if ((decl = calloc(1, sizeof(*decl))) == NULL) {
        return NULL;
    }
    decl->decl_id = decl_id;
    for (i = 0; i < SYM_NUM; i++) {
        if (symtab_init(&decl->symtab[i], symtab_sizes[i])) {
            avrule_decl_destroy(decl);
            return NULL;
        }
    }

    for (i = 0; i < SYM_NUM; i++) {
        ebitmap_init(&decl->required.scope[i]);
        ebitmap_init(&decl->declared.scope[i]);
    }
    return decl;
}

/* note that unlike the other destroy functions, this one does /NOT/
 * destroy the pointer itself */
static void scope_index_destroy(scope_index_t * scope)
{
    unsigned int i;
    if (scope == NULL) {
        return;
    }
    for (i = 0; i < SYM_NUM; i++) {
        ebitmap_destroy(scope->scope + i);
    }
    for (i = 0; i < scope->class_perms_len; i++) {
        ebitmap_destroy(scope->class_perms_map + i);
    }
    free(scope->class_perms_map);
}

void avrule_decl_destroy(avrule_decl_t * x)
{
    if (x == NULL) {
        return;
    }
    cond_list_destroy(x->cond_list);
    avrule_list_destroy(x->avrules);
    role_trans_rule_list_destroy(x->role_tr_rules);
    filename_trans_rule_list_destroy(x->filename_trans_rules);
    role_allow_rule_list_destroy(x->role_allow_rules);
    range_trans_rule_list_destroy(x->range_tr_rules);
    scope_index_destroy(&x->required);
    scope_index_destroy(&x->declared);
    symtabs_destroy(x->symtab);
    free(x->module_name);
    free(x);
}

void avrule_block_destroy(avrule_block_t * x)
{
    avrule_decl_t *decl;
    if (x == NULL) {
        return;
    }
    decl = x->branch_list;
    while (decl != NULL) {
        avrule_decl_t *next_decl = decl->next;
        avrule_decl_destroy(decl);
        decl = next_decl;
    }
    free(x);
}

void avrule_block_list_destroy(avrule_block_t * x)
{
    while (x != NULL) {
        avrule_block_t *next = x->next;
        avrule_block_destroy(x);
        x = next;
    }
}

/* Get a conditional node from a avrule_decl with the same expression.
 * If that expression does not exist then create one. */
cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl,
                cond_list_t * cond)
{
    cond_list_t *result;
    int was_created;
    result = cond_node_find(p, cond, decl->cond_list, &was_created);
    if (result != NULL && was_created) {
        result->next = decl->cond_list;
        decl->cond_list = result;
    }
    return result;
}

/* Look up an identifier in a policy's scoping table.  If it is there,
 * marked as SCOPE_DECL, and any of its declaring block has been enabled,
 * then return 1.  Otherwise return 0. Can only be called after the 
 * decl_val_to_struct index has been created */
int is_id_enabled(char *id, policydb_t * p, int symbol_table)
{
    scope_datum_t *scope =
        (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id);
    uint32_t i;
    if (scope == NULL) {
        return 0;
    }
    if (scope->scope != SCOPE_DECL) {
        return 0;
    }
    for (i = 0; i < scope->decl_ids_len; i++) {
        avrule_decl_t *decl =
            p->decl_val_to_struct[scope->decl_ids[i] - 1];
        if (decl != NULL && decl->enabled) {
            return 1;
        }
    }
    return 0;
}

/* Check if a particular permission is present within the given class,
 * and that the class is enabled.  Returns 1 if both conditions are
 * true, 0 if neither could be found or if the class id disabled. */
int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p)
{
    class_datum_t *cladatum;
    perm_datum_t *perm;
    if (!is_id_enabled(class_id, p, SYM_CLASSES)) {
        return 0;
    }
    cladatum =
        (class_datum_t *) hashtab_search(p->p_classes.table, class_id);
    if (cladatum == NULL) {
        return 0;
    }
    perm = hashtab_search(cladatum->permissions.table, perm_id);
    if (perm == NULL && cladatum->comdatum != 0) {
        /* permission was not in this class.  before giving
         * up, check the class's parent */
        perm =
            hashtab_search(cladatum->comdatum->permissions.table,
                   perm_id);
    }
    if (perm == NULL) {
        return 0;
    }
    return 1;
}