MLSRule: Convert to direct sepol structure access. Add iterator.

This commit is contained in:
Chris PeBenito 2018-02-13 19:28:43 -05:00
parent 3d4b03691d
commit 23d42f162f
5 changed files with 43 additions and 353 deletions

View File

@ -1,276 +0,0 @@
/**
* @file
* Implementation for the public interface for searching and iterating over
* range transition rules.
*
* @author Kevin Carr kcarr@tresys.com
* @author Jeremy A. Mowery jmowery@tresys.com
* @author Jason Tang jtang@tresys.com
*
* Copyright (C) 2006-2007 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 "iterator_internal.h"
#include <qpol/iterator.h>
#include <qpol/policy.h>
#include <qpol/mlsrule_query.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/util.h>
#include <stdlib.h>
#include "qpol_internal.h"
typedef struct range_trans_state
{
unsigned int bucket;
hashtab_ptr_t cur_item;
range_trans_t *cur;
} range_trans_state_t;
static int range_trans_state_end(const qpol_iterator_t * iter)
{
range_trans_state_t *rs = NULL;
if (!iter || !(rs = qpol_iterator_state(iter))) {
errno = EINVAL;
return STATUS_ERR;
}
return rs->cur ? 0 : 1;
}
static void *range_trans_state_get_cur(const qpol_iterator_t * iter)
{
range_trans_state_t *rs = NULL;
const policydb_t *db = NULL;
if (!iter || !(rs = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter))) {
errno = EINVAL;
return NULL;
}
return rs->cur;
}
static int range_trans_state_next(qpol_iterator_t * iter)
{
range_trans_state_t *rs = NULL;
const policydb_t *db = NULL;
if (!iter || !(rs = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter))) {
errno = EINVAL;
return STATUS_ERR;
}
if (range_trans_state_end(iter)) {
errno = EINVAL;
return STATUS_ERR;
}
rs->cur_item = rs->cur_item->next;
while (rs->cur_item == NULL) {
rs->bucket++;
if (rs->bucket >= db->range_tr->size) {
break;
}
rs->cur_item = db->range_tr->htable[rs->bucket];
}
if (rs->cur_item == NULL) {
rs->cur = NULL;
} else {
rs->cur = (range_trans_t*)rs->cur_item->key;
}
return STATUS_SUCCESS;
}
static size_t range_trans_state_size(const qpol_iterator_t * iter)
{
range_trans_state_t *rs = NULL;
const policydb_t *db = NULL;
size_t count = 0;
unsigned int i = 0;
if (!iter || !(rs = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter))) {
errno = EINVAL;
return 0;
}
hashtab_ptr_t cur = NULL;
for (i = 0; i < db->range_tr->size; i++) {
cur = db->range_tr->htable[i];
while (cur != NULL) {
count++;
cur = cur->next;
}
}
return count;
}
int qpol_policy_get_range_trans_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
{
policydb_t *db = NULL;
range_trans_state_t *rs = NULL;
int error = 0;
if (iter)
*iter = NULL;
if (!policy || !iter) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
rs = calloc(1, sizeof(range_trans_state_t));
if (!rs) {
error = errno;
ERR(policy, "%s", strerror(error));
errno = error;
return STATUS_ERR;
}
if (qpol_iterator_create(policy, (void *)rs, range_trans_state_get_cur,
range_trans_state_next, range_trans_state_end, range_trans_state_size, free, iter)) {
error = errno;
free(rs);
errno = error;
return STATUS_ERR;
}
rs->bucket = 0;
rs->cur_item = db->range_tr->htable[0];
rs->cur = NULL;
rs->cur_item = db->range_tr->htable[rs->bucket];
while (rs->cur_item == NULL) {
rs->bucket++;
if (rs->bucket >= db->range_tr->size) {
break;
}
rs->cur_item = db->range_tr->htable[rs->bucket];
}
if (rs->cur_item != NULL) {
rs->cur = (range_trans_t*)rs->cur_item->key;
}
return STATUS_SUCCESS;
}
int qpol_range_trans_get_source_type(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_type_t ** source)
{
policydb_t *db = NULL;
range_trans_t *rt = NULL;
if (source) {
*source = NULL;
}
if (!policy || !rule || !source) {
errno = EINVAL;
ERR(policy, "%s", strerror(EINVAL));
return STATUS_ERR;
}
db = &policy->p->p;
rt = (range_trans_t *) rule;
*source = (qpol_type_t *) db->type_val_to_struct[rt->source_type - 1];
return STATUS_SUCCESS;
}
int qpol_range_trans_get_target_type(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_type_t ** target)
{
policydb_t *db = NULL;
range_trans_t *rt = NULL;
if (target) {
*target = NULL;
}
if (!policy || !rule || !target) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
rt = (range_trans_t *) rule;
*target = (qpol_type_t *) db->type_val_to_struct[rt->target_type - 1];
return STATUS_SUCCESS;
}
int qpol_range_trans_get_target_class(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_class_t ** target)
{
policydb_t *db = NULL;
range_trans_t *rt = NULL;
if (target) {
*target = NULL;
}
if (!policy || !rule || !target) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
db = &policy->p->p;
rt = (range_trans_t *) rule;
*target = (qpol_class_t *) db->class_val_to_struct[rt->target_class - 1];
return STATUS_SUCCESS;
}
int qpol_range_trans_get_range(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_mls_range_t ** range)
{
range_trans_t *rt = NULL;
if (range) {
*range = NULL;
}
if (!policy || !rule || !range) {
ERR(policy, "%s", strerror(EINVAL));
errno = EINVAL;
return STATUS_ERR;
}
policydb_t *db = &policy->p->p;
rt = (range_trans_t *) rule;
mls_range_t *target_range = NULL;
target_range = hashtab_search(db->range_tr, (hashtab_key_t)rt);
if (target_range == NULL) {
return STATUS_ERR;
}
*range = (qpol_mls_range_t *)target_range;
return STATUS_SUCCESS;
}

View File

@ -176,14 +176,6 @@ cdef extern from "include/qpol/constraint_query.h":
int qpol_class_get_constraint_iter(const qpol_policy_t * policy, const qpol_class_t * obj_class, qpol_iterator_t ** constr)
int qpol_class_get_validatetrans_iter(const qpol_policy_t * policy, const qpol_class_t * obj_class, qpol_iterator_t ** vtrans)
cdef extern from "include/qpol/context_query.h":
ctypedef struct qpol_context_t:
pass
int qpol_context_get_user(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_user_t ** user)
int qpol_context_get_role(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_role_t ** role)
int qpol_context_get_type(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_type_t ** type)
int qpol_context_get_range(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_mls_range_t ** range)
cdef extern from "include/qpol/ftrule_query.h":
ctypedef struct qpol_filename_trans_t:
pass
@ -203,27 +195,6 @@ cdef extern from "include/qpol/iterator.h":
int qpol_iterator_end(const qpol_iterator_t * iter)
int qpol_iterator_get_size(const qpol_iterator_t * iter, size_t * size)
cdef extern from "include/qpol/mls_query.h":
ctypedef struct qpol_level_t:
pass
ctypedef struct qpol_cat_t:
pass
ctypedef struct qpol_mls_range_t:
pass
ctypedef struct qpol_mls_level_t:
pass
ctypedef struct qpol_semantic_level_t:
pass
cdef extern from "include/qpol/mlsrule_query.h":
ctypedef struct qpol_range_trans_t:
pass
int qpol_policy_get_range_trans_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
int qpol_range_trans_get_source_type(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_type_t ** source)
int qpol_range_trans_get_target_type(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_type_t ** target)
int qpol_range_trans_get_target_class(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_class_t ** target)
int qpol_range_trans_get_range(const qpol_policy_t * policy, const qpol_range_trans_t * rule, const qpol_mls_range_t ** range)
cdef extern from "qpol_internal.h":
ctypedef struct qpol_policy_t:
sepol.sepol_policydb *p

View File

@ -1,5 +1,5 @@
# Copyright 2014, 2016, Tresys Technology, LLC
# Copyright 2016-2017, Chris PeBenito <pebenito@ieee.org>
# Copyright 2016-2018, Chris PeBenito <pebenito@ieee.org>
#
# This file is part of SETools.
#
@ -19,41 +19,6 @@
#
import itertools
#
# MLS rule factory functions
#
cdef inline MLSRule mls_rule_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
"""Factory function variant for iterating over MLSRule objects."""
return mls_rule_factory(policy, <const qpol_range_trans_t *> symbol.obj)
cdef inline MLSRule mls_rule_factory(SELinuxPolicy policy, const qpol_range_trans_t *symbol):
"""Factory function for creating MLSRule objects."""
r = MLSRule()
r.policy = policy
r.handle = symbol
return r
#
# Expanded MLS rule factory function
#
cdef inline ExpandedMLSRule expanded_mls_rule_factory(MLSRule original, source, target):
"""
Factory function for creating expanded MLS rules.
original The MLS rule the expanded rule originates from.
source The source type of the expanded rule.
target The target type of the expanded rule.
"""
r = ExpandedMLSRule()
r.policy = original.policy
r.handle = original.handle
r.source = source
r.target = target
r.origin = original
return r
class MLSRuletype(PolicyEnum):
@ -68,10 +33,20 @@ cdef class MLSRule(PolicyRule):
cdef:
sepol.range_trans_t *handle
object rng
readonly object ruletype
def __init__(self):
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.range_trans_t *symbol, sepol.mls_range_t *rng):
"""Factory function for creating MLSRule objects."""
r = MLSRule(Range.factory(policy, rng))
r.policy = policy
r.handle = symbol
return r
def __init__(self, rng):
self.ruletype = MLSRuletype.range_transition
self.rng = rng
def __str__(self):
return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default};".format(self)
@ -98,15 +73,18 @@ cdef class MLSRule(PolicyRule):
@property
def default(self):
"""The rule's default range."""
cdef sepol.mls_range_t *default_range
default_range = <sepol.mls_range_t *> hashtab_search(self.policy.handle.p.p.range_tr,
<sepol.hashtab_key_t> self.handle)
return Range.factory(self.policy, default_range)
return self.rng
def expand(self):
"""Expand the rule into an equivalent set of rules without attributes."""
for s, t in itertools.product(self.source.expand(), self.target.expand()):
yield expanded_mls_rule_factory(self, s, t)
r = ExpandedMLSRule(self.rng)
r.policy = self.policy
r.handle = self.handle
r.source = s
r.target = t
r.origin = self
yield r
cdef class ExpandedMLSRule(MLSRule):
@ -131,3 +109,25 @@ cdef class ExpandedMLSRule(MLSRule):
def __lt__(self, other):
return str(self) < str(other)
#
# Iterators
#
cdef class MLSRuleIterator(HashtabIterator):
"""Iterate over MLS rules in the policy."""
@staticmethod
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
"""Factory function for creating MLS rule iterators."""
i = MLSRuleIterator()
i.policy = policy
i.table = table
i.reset()
return i
def __next__(self):
super().__next__()
return MLSRule.factory(self.policy, <sepol.range_trans_t *>self.curr.key,
<sepol.mls_range_t *>self.curr.datum)

View File

@ -608,11 +608,7 @@ cdef class SELinuxPolicy:
def mlsrules(self):
"""Iterator over all MLS rules."""
cdef qpol_iterator_t *iter
if qpol_policy_get_range_trans_iter(self.handle, &iter):
raise MemoryError
return qpol_iterator_factory(self, iter, mls_rule_factory_iter)
return MLSRuleIterator.factory(self, &self.handle.p.p.range_tr)
def rbacrules(self):
"""Iterator over all RBAC rules."""

View File

@ -73,7 +73,6 @@ ext_py_mods = [Extension('setools.policyrep.libpolicyrep',
'libqpol/constraint_query.c',
'libqpol/ftrule_query.c',
'libqpol/iterator.c',
'libqpol/mlsrule_query.c',
'libqpol/policy.c',
'libqpol/policy_extend.c',
'libqpol/rbacrule_query.c',