mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-11 07:18:15 +00:00
policyrep: Convert MLS symbols and levels/ranges to direct sepol structure access.
Add iterators.
This commit is contained in:
parent
8260b9b166
commit
d476f22055
@ -571,42 +571,6 @@ void *ebitmap_state_get_cur_role(const qpol_iterator_t * iter)
|
||||
return db->role_val_to_struct[es->cur];
|
||||
}
|
||||
|
||||
void *ebitmap_state_get_cur_cat(const qpol_iterator_t * iter)
|
||||
{
|
||||
ebitmap_state_t *es = NULL;
|
||||
const policydb_t *db = NULL;
|
||||
const qpol_cat_t *cat = NULL;
|
||||
sepol_policydb_t sp;
|
||||
qpol_policy_t qp;
|
||||
|
||||
if (iter == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
es = qpol_iterator_state(iter);
|
||||
if (es == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
db = qpol_iterator_policy(iter);
|
||||
if (db == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* shallow copy is safe here */
|
||||
sp.p = *db;
|
||||
qp.p = &sp;
|
||||
qp.fn = NULL;
|
||||
|
||||
qpol_policy_get_cat_by_name(&qp, db->p_cat_val_to_name[es->cur], &cat);
|
||||
|
||||
/* There is no val_to_struct for categories; this requires that qpol
|
||||
* search for the struct, but it can't be returned as const here so
|
||||
* cast it to void* explicitly. */
|
||||
return (void *)cat;
|
||||
}
|
||||
|
||||
void *ebitmap_state_get_cur_permissive(const qpol_iterator_t * iter)
|
||||
{
|
||||
ebitmap_state_t *es = NULL;
|
||||
|
@ -1,836 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Implementation of the interface for searching and iterating over
|
||||
* policy MLS components.
|
||||
*
|
||||
* @author Jeremy A. Mowery jmowery@tresys.com
|
||||
* @author Jason Tang jtang@tresys.com
|
||||
*
|
||||
* Copyright (C) 2006-2007. 2015 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <qpol/iterator.h>
|
||||
#include <sepol/policydb/policydb.h>
|
||||
#include <sepol/policydb/expand.h>
|
||||
#include "iterator_internal.h"
|
||||
#include <qpol/mls_query.h>
|
||||
#include "qpol_internal.h"
|
||||
|
||||
/* level */
|
||||
int qpol_policy_get_level_by_name(const qpol_policy_t * policy, const char *name, const qpol_level_t ** datum)
|
||||
{
|
||||
policydb_t *db = NULL;
|
||||
hashtab_datum_t internal_datum = NULL;
|
||||
|
||||
if (policy == NULL || name == NULL || datum == NULL) {
|
||||
if (datum != NULL)
|
||||
*datum = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
db = &policy->p->p;
|
||||
internal_datum = hashtab_search(db->p_levels.table, (hashtab_key_t)name);
|
||||
if (internal_datum == NULL) {
|
||||
ERR(policy, "could not find datum for level %s", name);
|
||||
errno = EINVAL;
|
||||
*datum = NULL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
*datum = (qpol_level_t *) internal_datum;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_policy_get_level_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
|
||||
{
|
||||
policydb_t *db;
|
||||
int error = 0;
|
||||
hash_state_t *hs = NULL;
|
||||
|
||||
if (policy == NULL || iter == NULL) {
|
||||
if (iter != NULL)
|
||||
*iter = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
|
||||
hs = calloc(1, sizeof(hash_state_t));
|
||||
if (hs == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs->table = &db->p_levels.table;
|
||||
hs->node = (*(hs->table))->htable[0];
|
||||
|
||||
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur,
|
||||
hash_state_next, hash_state_end, hash_state_size, free, iter)) {
|
||||
free(hs);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->node == NULL)
|
||||
hash_state_next(*iter);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_level_get_isalias(const qpol_policy_t * policy, const qpol_level_t * datum, unsigned char *isalias)
|
||||
{
|
||||
level_datum_t *internal_datum;
|
||||
|
||||
if (policy == NULL || datum == NULL || isalias == NULL) {
|
||||
if (isalias != NULL)
|
||||
*isalias = 0;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_datum = (level_datum_t *) datum;
|
||||
*isalias = internal_datum->isalias;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_level_get_value(const qpol_policy_t * policy, const qpol_level_t * datum, uint32_t * value)
|
||||
{
|
||||
level_datum_t *internal_datum = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || value == NULL) {
|
||||
if (value != NULL)
|
||||
*value = 0;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_datum = (level_datum_t *) datum;
|
||||
*value = internal_datum->level->sens;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_level_get_cat_iter(const qpol_policy_t * policy, const qpol_level_t * datum, qpol_iterator_t ** cats)
|
||||
{
|
||||
level_datum_t *internal_datum = NULL;
|
||||
ebitmap_state_t *es = NULL;
|
||||
int error = 0;
|
||||
|
||||
if (policy == NULL || datum == NULL || cats == NULL) {
|
||||
if (cats != NULL)
|
||||
*cats = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_datum = (level_datum_t *) datum;
|
||||
|
||||
es = calloc(1, sizeof(ebitmap_state_t));
|
||||
if (es == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
es->bmap = &(internal_datum->level->cat);
|
||||
es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
|
||||
|
||||
if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_cat,
|
||||
ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, cats)) {
|
||||
free(es);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
|
||||
ebitmap_state_next(*cats);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_level_get_name(const qpol_policy_t * policy, const qpol_level_t * datum, const char **name)
|
||||
{
|
||||
level_datum_t *internal_datum = NULL;
|
||||
policydb_t *db = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || name == NULL) {
|
||||
if (name != NULL)
|
||||
*name = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = (level_datum_t *) datum;
|
||||
|
||||
*name = db->p_sens_val_to_name[internal_datum->level->sens - 1];
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct level_alias_hash_state
|
||||
{
|
||||
unsigned int bucket;
|
||||
hashtab_node_t *node;
|
||||
hashtab_t *table;
|
||||
uint32_t val;
|
||||
} level_alias_hash_state_t;
|
||||
|
||||
static int hash_state_next_level_alias(qpol_iterator_t * iter)
|
||||
{
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
level_datum_t *datum = NULL;
|
||||
|
||||
if (iter == NULL) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs = (level_alias_hash_state_t *) qpol_iterator_state(iter);
|
||||
if (hs == NULL) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->bucket >= (*(hs->table))->size) {
|
||||
errno = ERANGE;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
do {
|
||||
hash_state_next(iter);
|
||||
datum = hs->node ? (level_datum_t *) hs->node->datum : NULL;
|
||||
} while (datum != NULL && (datum->level->sens != hs->val || !datum->isalias));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void *hash_state_get_cur_alias(const qpol_iterator_t * iter)
|
||||
{
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
|
||||
if (iter == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
hs = (level_alias_hash_state_t *) qpol_iterator_state(iter);
|
||||
if (hs == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hs->bucket >= (*(hs->table))->size) {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hs->node->key;
|
||||
}
|
||||
|
||||
static size_t hash_state_level_alias_size(const qpol_iterator_t * iter)
|
||||
{
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
hashtab_node_t *tmp_node;
|
||||
level_datum_t *tmp_lvl_datum;
|
||||
uint32_t tmp_bucket = 0;
|
||||
size_t count = 0;
|
||||
if (iter == NULL || qpol_iterator_state(iter) == NULL) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
hs = (level_alias_hash_state_t *) qpol_iterator_state(iter);
|
||||
if (!hs) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
for (tmp_bucket = 0; tmp_bucket < (*(hs->table))->size; tmp_bucket++) {
|
||||
for (tmp_node = (*(hs->table))->htable[tmp_bucket]; tmp_node; tmp_node = tmp_node->next) {
|
||||
tmp_lvl_datum = tmp_node ? tmp_node->datum : NULL;
|
||||
if (tmp_lvl_datum) {
|
||||
if (tmp_lvl_datum->isalias && tmp_lvl_datum->level->sens == hs->val)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int qpol_level_get_alias_iter(const qpol_policy_t * policy, const qpol_level_t * datum, qpol_iterator_t ** aliases)
|
||||
{
|
||||
level_datum_t *internal_datum = NULL;
|
||||
policydb_t *db = NULL;
|
||||
int error;
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || aliases == NULL) {
|
||||
if (aliases != NULL)
|
||||
*aliases = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = (level_datum_t *) datum;
|
||||
|
||||
hs = calloc(1, sizeof(level_alias_hash_state_t));
|
||||
if (hs == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs->table = &db->p_levels.table;
|
||||
hs->node = (*(hs->table))->htable[0];
|
||||
hs->val = internal_datum->level->sens;
|
||||
|
||||
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur_alias,
|
||||
hash_state_next_level_alias, hash_state_end, hash_state_level_alias_size, free, aliases)) {
|
||||
free(hs);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->node == NULL || !((level_datum_t *) hs->node->datum)->isalias
|
||||
|| ((level_datum_t *) (hs->node->datum))->level->sens != hs->val)
|
||||
hash_state_next_level_alias(*aliases);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* cat */
|
||||
int qpol_policy_get_cat_by_name(const qpol_policy_t * policy, const char *name, const qpol_cat_t ** datum)
|
||||
{
|
||||
hashtab_datum_t internal_datum;
|
||||
policydb_t *db;
|
||||
|
||||
if (policy == NULL || name == NULL || datum == NULL) {
|
||||
if (datum != NULL)
|
||||
*datum = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = hashtab_search(db->p_cats.table, (hashtab_key_t)name);
|
||||
if (internal_datum == NULL) {
|
||||
*datum = NULL;
|
||||
ERR(policy, "could not find datum for cat %s", name);
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
*datum = (qpol_cat_t *) internal_datum;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_policy_get_cat_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
|
||||
{
|
||||
policydb_t *db;
|
||||
int error = 0;
|
||||
hash_state_t *hs = NULL;
|
||||
|
||||
if (policy == NULL || iter == NULL) {
|
||||
if (iter != NULL)
|
||||
*iter = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
|
||||
hs = calloc(1, sizeof(hash_state_t));
|
||||
if (hs == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs->table = &db->p_cats.table;
|
||||
hs->node = (*(hs->table))->htable[0];
|
||||
|
||||
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur,
|
||||
hash_state_next, hash_state_end, hash_state_size, free, iter)) {
|
||||
free(hs);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->node == NULL)
|
||||
hash_state_next(*iter);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_cat_get_value(const qpol_policy_t * policy, const qpol_cat_t * datum, uint32_t * value)
|
||||
{
|
||||
cat_datum_t *internal_datum = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || value == NULL) {
|
||||
if (value != NULL)
|
||||
*value = 0;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_datum = (cat_datum_t *) datum;
|
||||
*value = internal_datum->s.value;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_cat_get_isalias(const qpol_policy_t * policy, const qpol_cat_t * datum, unsigned char *isalias)
|
||||
{
|
||||
cat_datum_t *internal_datum;
|
||||
|
||||
if (policy == NULL || datum == NULL || isalias == NULL) {
|
||||
if (isalias != NULL)
|
||||
*isalias = 0;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_datum = (cat_datum_t *) datum;
|
||||
*isalias = internal_datum->isalias;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_cat_get_name(const qpol_policy_t * policy, const qpol_cat_t * datum, const char **name)
|
||||
{
|
||||
cat_datum_t *internal_datum = NULL;
|
||||
policydb_t *db = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || name == NULL) {
|
||||
if (name != NULL)
|
||||
*name = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = (cat_datum_t *) datum;
|
||||
|
||||
*name = db->p_cat_val_to_name[internal_datum->s.value - 1];
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int hash_state_next_cat_alias(qpol_iterator_t * iter)
|
||||
{
|
||||
/* using level alias state datum since data needed is identical */
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
cat_datum_t *datum = NULL;
|
||||
|
||||
if (iter == NULL) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs = (level_alias_hash_state_t *) qpol_iterator_state(iter);
|
||||
if (hs == NULL) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->bucket >= (*(hs->table))->size) {
|
||||
errno = ERANGE;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
do {
|
||||
hash_state_next(iter);
|
||||
datum = hs->node ? (cat_datum_t *) hs->node->datum : NULL;
|
||||
} while (datum != NULL && (datum->s.value != hs->val || !datum->isalias));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static size_t hash_state_cat_alias_size(const qpol_iterator_t * iter)
|
||||
{
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
hashtab_node_t *tmp_node;
|
||||
cat_datum_t *tmp_cat_datum;
|
||||
uint32_t tmp_bucket = 0;
|
||||
size_t count = 0;
|
||||
if (iter == NULL || qpol_iterator_state(iter) == NULL) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
hs = (level_alias_hash_state_t *) qpol_iterator_state(iter);
|
||||
if (!hs) {
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
for (tmp_bucket = 0; tmp_bucket < (*(hs->table))->size; tmp_bucket++) {
|
||||
for (tmp_node = (*(hs->table))->htable[tmp_bucket]; tmp_node; tmp_node = tmp_node->next) {
|
||||
tmp_cat_datum = tmp_node ? tmp_node->datum : NULL;
|
||||
if (tmp_cat_datum) {
|
||||
if (tmp_cat_datum->isalias && tmp_cat_datum->s.value == hs->val)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int qpol_cat_get_alias_iter(const qpol_policy_t * policy, const qpol_cat_t * datum, qpol_iterator_t ** aliases)
|
||||
{
|
||||
cat_datum_t *internal_datum = NULL;
|
||||
policydb_t *db = NULL;
|
||||
int error;
|
||||
level_alias_hash_state_t *hs = NULL;
|
||||
|
||||
if (policy == NULL || datum == NULL || aliases == NULL) {
|
||||
if (aliases != NULL)
|
||||
*aliases = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = (cat_datum_t *) datum;
|
||||
|
||||
hs = calloc(1, sizeof(level_alias_hash_state_t));
|
||||
if (hs == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
hs->table = &db->p_cats.table;
|
||||
hs->node = (*(hs->table))->htable[0];
|
||||
hs->val = internal_datum->s.value;
|
||||
|
||||
if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur_alias,
|
||||
hash_state_next_cat_alias, hash_state_end, hash_state_cat_alias_size, free, aliases)) {
|
||||
free(hs);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (hs->node == NULL || ((cat_datum_t *) (hs->node->datum))->s.value != hs->val)
|
||||
hash_state_next_cat_alias(*aliases);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* mls range */
|
||||
int qpol_policy_get_mls_range_from_mls_levels(const qpol_policy_t * policy, const qpol_mls_level_t *low, const qpol_mls_level_t *high, qpol_mls_range_t **dest)
|
||||
{
|
||||
mls_range_t *internal_range = NULL;
|
||||
mls_level_t *internal_low = NULL, *internal_high = NULL;
|
||||
|
||||
if (policy == NULL || low == NULL || high == NULL || dest == NULL) {
|
||||
if (dest != NULL)
|
||||
*dest = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
*dest = NULL;
|
||||
internal_low = (mls_level_t*)low;
|
||||
internal_high = (mls_level_t*)high;
|
||||
|
||||
if (!mls_level_dom(internal_high, internal_low)) {
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_range = malloc(sizeof(mls_range_t));
|
||||
if (!internal_range) {
|
||||
ERR(policy, "%s", strerror(errno));
|
||||
return STATUS_ERR;
|
||||
}
|
||||
mls_range_init(internal_range);
|
||||
|
||||
if (mls_level_cpy(&internal_range->level[0], internal_low) < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mls_level_cpy(&internal_range->level[1], internal_high) < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
*dest = (qpol_mls_range_t*) internal_range;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
mls_range_destroy(internal_range);
|
||||
free(internal_range);
|
||||
errno = ENOMEM;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
int qpol_mls_range_get_low_level(const qpol_policy_t * policy, const qpol_mls_range_t * range, const qpol_mls_level_t ** level)
|
||||
{
|
||||
mls_range_t *internal_range = NULL;
|
||||
|
||||
if (policy == NULL || range == NULL || level == NULL) {
|
||||
if (level != NULL)
|
||||
*level = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_range = (mls_range_t *) range;
|
||||
*level = (qpol_mls_level_t *) & (internal_range->level[0]);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_mls_range_get_high_level(const qpol_policy_t * policy, const qpol_mls_range_t * range, const qpol_mls_level_t ** level)
|
||||
{
|
||||
mls_range_t *internal_range = NULL;
|
||||
|
||||
if (policy == NULL || range == NULL || level == NULL) {
|
||||
if (level != NULL)
|
||||
*level = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_range = (mls_range_t *) range;
|
||||
*level = (qpol_mls_level_t *) & (internal_range->level[1]);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* mls_level */
|
||||
int qpol_mls_level_get_sens_name(const qpol_policy_t * policy, const qpol_mls_level_t * level, const char **name)
|
||||
{
|
||||
policydb_t *db = NULL;
|
||||
mls_level_t *internal_level = NULL;
|
||||
|
||||
if (policy == NULL || level == NULL || name == NULL) {
|
||||
if (name != NULL)
|
||||
*name = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_level = (mls_level_t *) level;
|
||||
db = &policy->p->p;
|
||||
|
||||
*name = db->p_sens_val_to_name[internal_level->sens - 1];
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_mls_level_get_cat_iter(const qpol_policy_t * policy, const qpol_mls_level_t * level, qpol_iterator_t ** cats)
|
||||
{
|
||||
mls_level_t *internal_level = NULL;
|
||||
ebitmap_state_t *es = NULL;
|
||||
int error = 0;
|
||||
|
||||
if (policy == NULL || level == NULL || cats == NULL) {
|
||||
if (cats != NULL)
|
||||
*cats = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_level = (mls_level_t *) level;
|
||||
|
||||
es = calloc(1, sizeof(ebitmap_state_t));
|
||||
if (es == NULL) {
|
||||
error = errno;
|
||||
ERR(policy, "%s", strerror(ENOMEM));
|
||||
errno = error;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
es->bmap = &(internal_level->cat);
|
||||
es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
|
||||
|
||||
if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_cat,
|
||||
ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, cats)) {
|
||||
free(es);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
|
||||
ebitmap_state_next(*cats);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_mls_level_from_semantic_level(const qpol_policy_t * policy, const qpol_semantic_level_t * src, qpol_mls_level_t **dest)
|
||||
{
|
||||
policydb_t *db = NULL;
|
||||
mls_semantic_level_t *internal_semantic = NULL;
|
||||
mls_level_t *internal_level = NULL;
|
||||
|
||||
if (policy == NULL || src == NULL || dest == NULL) {
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
*dest = NULL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_semantic = (mls_semantic_level_t*) src;
|
||||
db = &policy->p->p;
|
||||
|
||||
internal_level = malloc(sizeof(mls_level_t));
|
||||
if (!internal_level) {
|
||||
return STATUS_ERR;
|
||||
}
|
||||
mls_level_init(internal_level);
|
||||
|
||||
if(mls_semantic_level_expand(internal_semantic, internal_level, db, policy->sh) < 0) {
|
||||
mls_level_destroy(internal_level);
|
||||
free(internal_level);
|
||||
errno = EINVAL;
|
||||
*dest = NULL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
*dest = (qpol_mls_level_t*) internal_level;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* semantic level */
|
||||
int qpol_policy_get_semantic_level_by_name(const qpol_policy_t * policy, const char *name, qpol_semantic_level_t ** datum)
|
||||
{
|
||||
policydb_t *db = NULL;
|
||||
hashtab_datum_t internal_datum = NULL;
|
||||
mls_semantic_level_t *internal_semantic = NULL;
|
||||
|
||||
if (policy == NULL || name == NULL || datum == NULL) {
|
||||
if (datum != NULL)
|
||||
*datum = NULL;
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_semantic = malloc(sizeof(mls_semantic_level_t));
|
||||
if (!internal_semantic) {
|
||||
return STATUS_ERR;
|
||||
}
|
||||
mls_semantic_level_init(internal_semantic);
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_datum = hashtab_search(db->p_levels.table, (hashtab_key_t)name);
|
||||
if (internal_datum == NULL) {
|
||||
mls_semantic_level_destroy(internal_semantic);
|
||||
free(internal_semantic);
|
||||
*datum = NULL;
|
||||
ERR(policy, "could not find datum for level %s", name);
|
||||
errno = ENOENT;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_semantic->sens = ((level_datum_t*)internal_datum)->level->sens;
|
||||
|
||||
*datum = (qpol_semantic_level_t *) internal_semantic;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int qpol_semantic_level_add_cats_by_name(const qpol_policy_t * policy, const qpol_semantic_level_t * level, const char *low, const char *high)
|
||||
{
|
||||
hashtab_datum_t internal_datum;
|
||||
policydb_t *db = NULL;
|
||||
mls_semantic_level_t *internal_level = NULL;
|
||||
mls_semantic_cat_t *internal_cat = NULL;
|
||||
|
||||
if (policy == NULL || level == NULL || low == NULL || high == NULL) {
|
||||
ERR(policy, "%s", strerror(EINVAL));
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
internal_cat = malloc(sizeof(mls_semantic_cat_t));
|
||||
if (!internal_cat) {
|
||||
return STATUS_ERR;
|
||||
}
|
||||
mls_semantic_cat_init(internal_cat);
|
||||
|
||||
db = &policy->p->p;
|
||||
internal_level = (mls_semantic_level_t*) level;
|
||||
|
||||
internal_datum = hashtab_search(db->p_cats.table, (hashtab_key_t)low);
|
||||
if (internal_datum == NULL) {
|
||||
ERR(policy, "could not find datum for cat %s", low);
|
||||
goto err;
|
||||
}
|
||||
internal_cat->low = ((cat_datum_t*)internal_datum)->s.value;
|
||||
|
||||
internal_datum = hashtab_search(db->p_cats.table, (hashtab_key_t)high);
|
||||
if (internal_datum == NULL) {
|
||||
ERR(policy, "could not find datum for cat %s", high);
|
||||
goto err;
|
||||
}
|
||||
internal_cat->high = ((cat_datum_t*)internal_datum)->s.value;
|
||||
|
||||
if (internal_cat->low > internal_cat->high) {
|
||||
ERR(policy, "invalid semantic category range: %s.%s", low, high);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(internal_level->cat)) {
|
||||
internal_level->cat = internal_cat;
|
||||
} else {
|
||||
mls_semantic_cat_t *curr = internal_level->cat;
|
||||
|
||||
while(curr->next) {
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
curr->next = internal_cat;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
mls_semantic_cat_destroy(internal_cat);
|
||||
free(internal_cat);
|
||||
errno = ENOENT;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
void qpol_semantic_level_destroy(qpol_semantic_level_t * level)
|
||||
{
|
||||
|
||||
if (level == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mls_semantic_level_destroy((mls_semantic_level_t*) level);
|
||||
free(level);
|
||||
}
|
@ -72,11 +72,10 @@ cdef class Context(PolicySymbol):
|
||||
@property
|
||||
def range_(self):
|
||||
"""The MLS range of the context."""
|
||||
cdef const qpol_mls_range_t *r
|
||||
if qpol_context_get_range(self.policy.handle, self.handle, &r):
|
||||
raise RuntimeError("Could not get range from context")
|
||||
if not self.policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
return range_factory(self.policy, r)
|
||||
return Range.factory(self.policy, &self.handle.range)
|
||||
|
||||
def statement(self):
|
||||
raise NoStatement
|
||||
|
@ -224,34 +224,6 @@ cdef extern from "include/qpol/mls_query.h":
|
||||
pass
|
||||
ctypedef struct qpol_semantic_level_t:
|
||||
pass
|
||||
# level
|
||||
int qpol_policy_get_level_by_name(const qpol_policy_t * policy, const char *name, const qpol_level_t ** datum)
|
||||
int qpol_policy_get_level_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
|
||||
int qpol_level_get_isalias(const qpol_policy_t * policy, const qpol_level_t * datum, unsigned char *isalias)
|
||||
int qpol_level_get_value(const qpol_policy_t * policy, const qpol_level_t * datum, uint32_t * value)
|
||||
int qpol_level_get_cat_iter(const qpol_policy_t * policy, const qpol_level_t * datum, qpol_iterator_t ** cats)
|
||||
int qpol_level_get_name(const qpol_policy_t * policy, const qpol_level_t * datum, const char **name)
|
||||
int qpol_level_get_alias_iter(const qpol_policy_t * policy, const qpol_level_t * datum, qpol_iterator_t ** aliases)
|
||||
# category
|
||||
int qpol_policy_get_cat_by_name(const qpol_policy_t * policy, const char *name, const qpol_cat_t ** datum)
|
||||
int qpol_policy_get_cat_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
|
||||
int qpol_cat_get_value(const qpol_policy_t * policy, const qpol_cat_t * datum, uint32_t * value)
|
||||
int qpol_cat_get_isalias(const qpol_policy_t * policy, const qpol_cat_t * datum, unsigned char *isalias)
|
||||
int qpol_cat_get_name(const qpol_policy_t * policy, const qpol_cat_t * datum, const char **name)
|
||||
int qpol_cat_get_alias_iter(const qpol_policy_t * policy, const qpol_cat_t * datum, qpol_iterator_t ** aliases)
|
||||
# MLS range
|
||||
int qpol_mls_range_get_low_level(const qpol_policy_t * policy, const qpol_mls_range_t * range, const qpol_mls_level_t ** level)
|
||||
int qpol_mls_range_get_high_level(const qpol_policy_t * policy, const qpol_mls_range_t * range, const qpol_mls_level_t ** level)
|
||||
# MLS level
|
||||
int qpol_mls_level_get_sens_name(const qpol_policy_t * policy, const qpol_mls_level_t * level, const char **name)
|
||||
int qpol_mls_level_get_cat_iter(const qpol_policy_t * policy, const qpol_mls_level_t * level, qpol_iterator_t ** cats)
|
||||
# Semantic levels
|
||||
int qpol_policy_get_semantic_level_by_name(const qpol_policy_t * policy, const char *name, qpol_semantic_level_t ** datum)
|
||||
int qpol_semantic_level_add_cats_by_name(const qpol_policy_t * policy, const qpol_semantic_level_t * level, const char *low, const char *high)
|
||||
int qpol_mls_level_from_semantic_level(const qpol_policy_t * policy, qpol_semantic_level_t * src, qpol_mls_level_t **dest)
|
||||
void qpol_semantic_level_destroy(qpol_semantic_level_t * level)
|
||||
# Semantic ranges
|
||||
int qpol_policy_get_mls_range_from_mls_levels(const qpol_policy_t * policy, const qpol_mls_level_t * low, const qpol_mls_level_t *high, qpol_mls_range_t **dest)
|
||||
|
||||
cdef extern from "include/qpol/mlsrule_query.h":
|
||||
ctypedef struct qpol_range_trans_t:
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Copyright 2014-2016, Tresys Technology, LLC
|
||||
# Copyright 2017, Chris PeBenito <pebenito@ieee.org>
|
||||
# Copyright 2017-2018, Chris PeBenito <pebenito@ieee.org>
|
||||
#
|
||||
# This file is part of SETools.
|
||||
#
|
||||
@ -20,281 +20,52 @@
|
||||
# pylint: disable=protected-access
|
||||
import itertools
|
||||
|
||||
# qpol does not expose an equivalent of a sensitivity declaration.
|
||||
# qpol_level_t is equivalent to the level declaration:
|
||||
# level s0:c0.c1023;
|
||||
|
||||
# qpol_mls_level_t represents a level as used in contexts,
|
||||
# such as range_transitions or labeling statements such as
|
||||
# portcon and nodecon.
|
||||
|
||||
# Here qpol_level_t is also used for MLSSensitivity
|
||||
# since it has the sensitivity name, dominance, and there
|
||||
# is a 1:1 correspondence between the sensitivity declarations
|
||||
# and level declarations.
|
||||
|
||||
# Hashing has to be handled below because the qpol references,
|
||||
# normally used for a hash key, are not the same for multiple
|
||||
# instances of the same object (except for level decl).
|
||||
|
||||
|
||||
#
|
||||
# Category factory functions
|
||||
#
|
||||
cdef inline Category category_factory_lookup(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Category objects by name."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
cdef const qpol_cat_t *symbol
|
||||
if qpol_policy_get_cat_by_name(policy.handle, name, &symbol):
|
||||
raise InvalidCategory("{0} is not a valid category".format(name))
|
||||
|
||||
return category_factory(policy, symbol)
|
||||
|
||||
|
||||
cdef inline Category category_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
|
||||
"""Factory function variant for iterating over Category objects."""
|
||||
return category_factory(policy, <const qpol_cat_t *> symbol.obj)
|
||||
|
||||
|
||||
cdef inline Category category_factory(SELinuxPolicy policy, const qpol_cat_t *symbol):
|
||||
"""Factory function for creating Category objects."""
|
||||
cdef unsigned char isalias
|
||||
cdef const char *name
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
if qpol_cat_get_isalias(policy.handle, symbol, &isalias):
|
||||
ex = LowLevelPolicyError("Error determining category alias status: {}".format(
|
||||
strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
if isalias:
|
||||
if qpol_cat_get_name(policy.handle, symbol, &name):
|
||||
raise ValueError("The category is an alias")
|
||||
|
||||
raise ValueError("{0} is an alias".format(name))
|
||||
|
||||
r = Category()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
|
||||
|
||||
#
|
||||
# Sensitivity factory functions
|
||||
#
|
||||
cdef inline Sensitivity sensitivity_factory_lookup(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Sensitivity objects by name."""
|
||||
cdef const qpol_level_t *symbol
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
if qpol_policy_get_level_by_name(policy.handle, name, &symbol):
|
||||
raise InvalidSensitivity("{0} is not a valid sensitivity".format(name))
|
||||
|
||||
return sensitivity_factory(policy, symbol)
|
||||
|
||||
|
||||
cdef inline Sensitivity sensitivity_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
|
||||
"""Factory function variant for iterating over Sensitivity objects."""
|
||||
return sensitivity_factory(policy, <const qpol_level_t *> symbol.obj)
|
||||
|
||||
|
||||
cdef inline Sensitivity sensitivity_factory(SELinuxPolicy policy, const qpol_level_t *symbol):
|
||||
"""Factory function for creating Sensitivity objects."""
|
||||
cdef unsigned char isalias
|
||||
cdef const char *name
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
if qpol_level_get_isalias(policy.handle, symbol, &isalias):
|
||||
ex = LowLevelPolicyError("Error determining sensitivity alias status: {}".format(
|
||||
strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
if isalias:
|
||||
if qpol_level_get_name(policy.handle, symbol, &name):
|
||||
raise ValueError("The sensitivity is an alias")
|
||||
|
||||
raise ValueError("{0} is an alias".format(name))
|
||||
|
||||
r = Sensitivity()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
|
||||
|
||||
#
|
||||
# Level declaration factory functions
|
||||
#
|
||||
cdef inline LevelDecl level_decl_factory_iter(SELinuxPolicy policy, QpolIteratorItem symbol):
|
||||
"""Factory function variant for iterating over LevelDecl objects."""
|
||||
return level_decl_factory(policy, <const qpol_level_t *> symbol.obj)
|
||||
|
||||
|
||||
cdef inline LevelDecl level_decl_factory(SELinuxPolicy policy, const qpol_level_t *symbol):
|
||||
"""Factory function for creating LevelDecl objects."""
|
||||
cdef unsigned char isalias
|
||||
cdef const char *name
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
if qpol_level_get_isalias(policy.handle, symbol, &isalias):
|
||||
ex = LowLevelPolicyError("Error determining level alias status: {}".format(
|
||||
strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
if isalias:
|
||||
if qpol_level_get_name(policy.handle, symbol, &name):
|
||||
raise ValueError("The level decl is an alias")
|
||||
|
||||
raise ValueError("{0} is an alias".format(name))
|
||||
|
||||
r = LevelDecl()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
|
||||
|
||||
#
|
||||
# Level factory functions
|
||||
#
|
||||
cdef inline Level level_factory_lookup(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Level objects by name."""
|
||||
cdef qpol_semantic_level_t *l
|
||||
cdef qpol_mls_level_t *level
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
sens_split = name.split(":")
|
||||
sens = sens_split[0]
|
||||
|
||||
if qpol_policy_get_semantic_level_by_name(policy.handle, sens, &l):
|
||||
raise InvalidLevel("{0} is not a valid level ({1} is not a valid sensitivity)". \
|
||||
format(name, sens))
|
||||
|
||||
try:
|
||||
cats = sens_split[1]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
for group in cats.split(","):
|
||||
catrange = group.split(".")
|
||||
|
||||
if len(catrange) == 2:
|
||||
if qpol_semantic_level_add_cats_by_name(policy.handle, l, catrange[0], catrange[1]):
|
||||
|
||||
raise InvalidLevel(
|
||||
"{0} is not a valid level ({1} is not a valid category range)".
|
||||
format(name, group))
|
||||
|
||||
elif len(catrange) == 1:
|
||||
if qpol_semantic_level_add_cats_by_name(policy.handle, l, catrange[0], catrange[0]):
|
||||
|
||||
raise InvalidLevel("{0} is not a valid level ({1} is not a valid category)".
|
||||
format(name, group))
|
||||
|
||||
else:
|
||||
raise InvalidLevel("{0} is not a valid level (level parsing error)".format(name))
|
||||
|
||||
# convert to level symbol
|
||||
if qpol_mls_level_from_semantic_level(policy.handle, l, &level):
|
||||
raise InvalidLevel(
|
||||
"{0} is not a valid level (one or more categories are not associated with the "
|
||||
"sensitivity)".format(name))
|
||||
|
||||
qpol_semantic_level_destroy(l)
|
||||
|
||||
# TODO: since this is user-generated, the level will need a destructor
|
||||
return level_factory(policy, level)
|
||||
|
||||
|
||||
cdef inline Level level_factory(SELinuxPolicy policy, const qpol_mls_level_t *symbol):
|
||||
"""Factory function for creating Level objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
r = Level()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
|
||||
|
||||
#
|
||||
# Range factory functions
|
||||
#
|
||||
cdef inline Range range_factory_lookup(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Range objects by name."""
|
||||
cdef qpol_mls_range_t *range
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
# build range:
|
||||
levels = name.split("-")
|
||||
|
||||
# strip() levels to handle ranges with spaces in them,
|
||||
# e.g. s0:c1 - s0:c0.c255
|
||||
try:
|
||||
low = level_factory_lookup(policy, levels[0].strip())
|
||||
except InvalidLevel as ex:
|
||||
raise InvalidRange("{0} is not a valid range ({1}).".format(name, ex)) from ex
|
||||
|
||||
try:
|
||||
high = level_factory_lookup(policy, levels[1].strip())
|
||||
except InvalidLevel as ex:
|
||||
raise InvalidRange("{0} is not a valid range ({1}).".format(name, ex)) from ex
|
||||
except IndexError:
|
||||
high = low
|
||||
|
||||
# convert to range object
|
||||
if qpol_policy_get_mls_range_from_mls_levels(policy.handle, low.handle, high.handle, &range):
|
||||
raise InvalidRange("{0} is not a valid range ({1} is not dominated by {2})".
|
||||
format(name, low, high))
|
||||
|
||||
# TODO: since this is user-generated, the range will need a destructor
|
||||
return range_factory(policy, range)
|
||||
|
||||
|
||||
cdef inline Range range_factory(SELinuxPolicy policy, const qpol_mls_range_t *symbol):
|
||||
"""Factory function for creating Range objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
r = Range()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
cdef dict _cat_cache = {}
|
||||
cdef dict _sens_cache = {}
|
||||
cdef dict _leveldecl_cache = {}
|
||||
|
||||
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
cdef list expand_cat_range(SELinuxPolicy policy, Category low, Category high):
|
||||
"""
|
||||
Helper function to expand a category range, e.g. c0.c1023
|
||||
into the full set of categories by using the low and high
|
||||
categories of the set.
|
||||
"""
|
||||
|
||||
cdef list expanded
|
||||
expanded = [low, high]
|
||||
for value in range(low._value, high._value):
|
||||
expanded.append(Category.factory(policy, policy.cat_val_to_struct[value]))
|
||||
|
||||
return expanded
|
||||
|
||||
|
||||
cdef class Category(PolicySymbol):
|
||||
|
||||
"""An MLS category."""
|
||||
|
||||
cdef const qpol_cat_t *handle
|
||||
cdef sepol.cat_datum_t *handle
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.cat_datum_t *symbol):
|
||||
"""Factory function for creating Category objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
try:
|
||||
return _cat_cache[<uintptr_t>symbol]
|
||||
except KeyError:
|
||||
c = Category()
|
||||
c.policy = policy
|
||||
c.handle = symbol
|
||||
_cat_cache[<uintptr_t>symbol] = c
|
||||
return c
|
||||
|
||||
def __str__(self):
|
||||
cdef const char *name
|
||||
|
||||
if qpol_cat_get_name(self.policy.handle, self.handle, &name):
|
||||
ex = LowLevelPolicyError("Error reading category name: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return intern(name)
|
||||
return intern(self.policy.handle.p.p.sym_val_to_name[sepol.SYM_CATS][self.handle.s.value - 1])
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
@ -310,25 +81,15 @@ cdef class Category(PolicySymbol):
|
||||
@property
|
||||
def _value(self):
|
||||
"""
|
||||
The value of the component.
|
||||
The value of the category.
|
||||
|
||||
This is a low-level policy detail exposed for internal use only.
|
||||
"""
|
||||
cdef uint32_t v
|
||||
if qpol_cat_get_value(self.policy.handle, self.handle, &v):
|
||||
ex = LowLevelPolicyError("Error reading category value: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return v
|
||||
return self.handle.s.value
|
||||
|
||||
def aliases(self):
|
||||
"""Generator that yields all aliases for this category."""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_cat_get_alias_iter(self.policy.handle, self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self.policy, iter, string_factory_iter)
|
||||
return CategoryAliasHashtabIterator.factory(self.policy, &self.policy.handle.p.p.symtab[sepol.SYM_CATS].table, self)
|
||||
|
||||
def statement(self):
|
||||
aliases = list(self.aliases())
|
||||
@ -346,17 +107,25 @@ cdef class Sensitivity(PolicySymbol):
|
||||
|
||||
"""An MLS sensitivity"""
|
||||
|
||||
cdef const qpol_level_t *handle
|
||||
cdef sepol.level_datum_t *handle
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.level_datum_t *symbol):
|
||||
"""Factory function for creating Sensitivity objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
try:
|
||||
return _sens_cache[<uintptr_t>symbol]
|
||||
except KeyError:
|
||||
s = Sensitivity()
|
||||
s.policy = policy
|
||||
s.handle = symbol
|
||||
_sens_cache[<uintptr_t>symbol] = s
|
||||
return s
|
||||
|
||||
def __str__(self):
|
||||
cdef const char *name
|
||||
|
||||
if qpol_level_get_name(self.policy.handle, self.handle, &name):
|
||||
ex = LowLevelPolicyError("Error reading sensitivity name: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return intern(name)
|
||||
return intern(self.policy.handle.p.p.sym_val_to_name[sepol.SYM_LEVELS][self.handle.level.sens - 1])
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
@ -384,21 +153,15 @@ cdef class Sensitivity(PolicySymbol):
|
||||
|
||||
This is a low-level policy detail exposed for internal use only.
|
||||
"""
|
||||
cdef uint32_t v
|
||||
if qpol_level_get_value(self.policy.handle, self.handle, &v):
|
||||
ex = LowLevelPolicyError("Error reading sensitivity value: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return v
|
||||
return self.handle.level.sens
|
||||
|
||||
def aliases(self):
|
||||
"""Generator that yields all aliases for this sensitivity."""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_level_get_alias_iter(self.policy.handle, self.handle, &iter):
|
||||
raise MemoryError
|
||||
return SensitivityAliasHashtabIterator.factory(self.policy, &self.policy.handle.p.p.symtab[sepol.SYM_LEVELS].table, self)
|
||||
|
||||
return qpol_iterator_factory(self.policy, iter, string_factory_iter)
|
||||
def level_decl(self):
|
||||
"""Get the level declaration corresponding to this sensitivity."""
|
||||
return LevelDecl.factory(self.policy, self.handle)
|
||||
|
||||
def statement(self):
|
||||
aliases = list(self.aliases())
|
||||
@ -458,7 +221,22 @@ cdef class LevelDecl(BaseMLSLevel):
|
||||
level s7:c0.c1023;
|
||||
"""
|
||||
|
||||
cdef const qpol_level_t *handle
|
||||
cdef sepol.level_datum_t *handle
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.level_datum_t *symbol):
|
||||
"""Factory function for creating LevelDecl objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
try:
|
||||
return _leveldecl_cache[<uintptr_t>symbol]
|
||||
except KeyError:
|
||||
l = LevelDecl()
|
||||
l.policy = policy
|
||||
l.handle = symbol
|
||||
_leveldecl_cache[<uintptr_t>symbol] = l
|
||||
return l
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.sensitivity)
|
||||
@ -503,18 +281,14 @@ cdef class LevelDecl(BaseMLSLevel):
|
||||
All categories are yielded, not a compact notation such as
|
||||
c0.c255
|
||||
"""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_level_get_cat_iter(self.policy.handle, self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self.policy, iter, category_factory_iter)
|
||||
return CategoryEbitmapIterator.factory(self.policy, &self.handle.level.cat)
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""The sensitivity of the level."""
|
||||
# since the qpol symbol for levels is also used for
|
||||
# MLSSensitivity objects, use self's qpol symbol
|
||||
return sensitivity_factory(self.policy, self.handle)
|
||||
# since the datum for levels is also used for
|
||||
# Sensitivity objects, use self's datum
|
||||
return Sensitivity.factory(self.policy, self.handle)
|
||||
|
||||
def statement(self):
|
||||
return "level {0};".format(self)
|
||||
@ -522,9 +296,88 @@ cdef class LevelDecl(BaseMLSLevel):
|
||||
|
||||
cdef class Level(BaseMLSLevel):
|
||||
|
||||
"""An MLS level used in contexts."""
|
||||
"""
|
||||
An MLS level used in contexts.
|
||||
|
||||
cdef const qpol_mls_level_t *handle
|
||||
The _sensitivity and _categories attributes are only populated
|
||||
if the level is user-generated.
|
||||
"""
|
||||
|
||||
cdef:
|
||||
sepol.mls_level_t *handle
|
||||
list _categories
|
||||
Sensitivity _sensitivity
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.mls_level_t *symbol):
|
||||
"""Factory function for creating Level objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
l = Level()
|
||||
l.policy = policy
|
||||
l.handle = symbol
|
||||
return l
|
||||
|
||||
@staticmethod
|
||||
cdef factory_from_string(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Level objects by a string."""
|
||||
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
sens_split = name.split(":")
|
||||
sens = sens_split[0]
|
||||
|
||||
try:
|
||||
s = policy.lookup_sensitivity(sens)
|
||||
except InvalidSensitivity as ex:
|
||||
raise InvalidLevel("{0} is not a valid level ({1} is not a valid sensitivity)". \
|
||||
format(name, sens)) from ex
|
||||
|
||||
c = []
|
||||
|
||||
try:
|
||||
cats = sens_split[1]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
for group in cats.split(","):
|
||||
catrange = group.split(".")
|
||||
if len(catrange) == 2:
|
||||
try:
|
||||
c.extend(expand_cat_range(policy,
|
||||
policy.lookup_category(catrange[0]),
|
||||
policy.lookup_category(catrange[1])))
|
||||
except InvalidCategory as ex:
|
||||
raise InvalidLevel(
|
||||
"{0} is not a valid level ({1} is not a valid category range)".
|
||||
format(name, group)) from ex
|
||||
|
||||
elif len(catrange) == 1:
|
||||
try:
|
||||
c.append(policy.lookup_category(catrange[0]))
|
||||
except InvalidCategory as ex:
|
||||
raise InvalidLevel("{0} is not a valid level ({1} is not a valid category)".
|
||||
format(name, group)) from ex
|
||||
|
||||
else:
|
||||
raise InvalidLevel("{0} is not a valid level (level parsing error)".format(name))
|
||||
|
||||
# build object
|
||||
l = Level()
|
||||
l.policy = policy
|
||||
l.handle = NULL
|
||||
l._sensitivity = s
|
||||
l._categories = c
|
||||
|
||||
# verify level is valid
|
||||
if not l <= s.level_decl():
|
||||
raise InvalidLevel(
|
||||
"{0} is not a valid level (one or more categories are not associated with the "
|
||||
"sensitivity)".format(name))
|
||||
|
||||
return l
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
@ -576,23 +429,18 @@ cdef class Level(BaseMLSLevel):
|
||||
All categories are yielded, not a compact notation such as
|
||||
c0.c255
|
||||
"""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_mls_level_get_cat_iter(self.policy.handle, self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self.policy, iter, category_factory_iter)
|
||||
if self.handle == NULL:
|
||||
return iter(self._categories)
|
||||
else:
|
||||
return CategoryEbitmapIterator.factory(self.policy, &self.handle.cat)
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""The sensitivity of the level."""
|
||||
cdef const char *name
|
||||
if qpol_mls_level_get_sens_name(self.policy.handle, self.handle, &name):
|
||||
ex = LowLevelPolicyError("Error reading level sensitivity name: {}".format(
|
||||
strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return sensitivity_factory_lookup(self.policy, name)
|
||||
if self.handle == NULL:
|
||||
return self._sensitivity
|
||||
else:
|
||||
return Sensitivity.factory(self.policy, self.policy.level_val_to_struct[self.handle.sens - 1])
|
||||
|
||||
def statement(self):
|
||||
raise NoStatement
|
||||
@ -602,7 +450,56 @@ cdef class Range(PolicySymbol):
|
||||
|
||||
"""An MLS range"""
|
||||
|
||||
cdef const qpol_mls_range_t *handle
|
||||
cdef:
|
||||
sepol.mls_range_t *handle
|
||||
Level _low
|
||||
Level _high
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.mls_range_t *symbol):
|
||||
"""Factory function for creating Range objects."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
r = Range()
|
||||
r.policy = policy
|
||||
r.handle = symbol
|
||||
return r
|
||||
|
||||
@staticmethod
|
||||
cdef factory_from_string(SELinuxPolicy policy, str name):
|
||||
"""Factory function variant for constructing Range objects by name."""
|
||||
if not policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
# build range:
|
||||
levels = name.split("-")
|
||||
|
||||
# strip() levels to handle ranges with spaces in them,
|
||||
# e.g. s0:c1 - s0:c0.c255
|
||||
try:
|
||||
low = Level.factory_from_string(policy, levels[0].strip())
|
||||
except InvalidLevel as ex:
|
||||
raise InvalidRange("{0} is not a valid range ({1}).".format(name, ex)) from ex
|
||||
|
||||
try:
|
||||
high = Level.factory_from_string(policy, levels[1].strip())
|
||||
except InvalidLevel as ex:
|
||||
raise InvalidRange("{0} is not a valid range ({1}).".format(name, ex)) from ex
|
||||
except IndexError:
|
||||
high = low
|
||||
|
||||
# verify high level dominates low range
|
||||
if not high >= low:
|
||||
raise InvalidRange("{0} is not a valid range ({1} is not dominated by {2})".
|
||||
format(name, low, high))
|
||||
|
||||
r = Range()
|
||||
r.policy = policy
|
||||
r.handle = NULL
|
||||
r._low = low
|
||||
r._high = high
|
||||
return r
|
||||
|
||||
def __str__(self):
|
||||
high = self.high
|
||||
@ -636,24 +533,333 @@ cdef class Range(PolicySymbol):
|
||||
@property
|
||||
def high(self):
|
||||
"""The high end/clearance level of this range."""
|
||||
cdef const qpol_mls_level_t *l
|
||||
if qpol_mls_range_get_high_level(self.policy.handle, self.handle, &l):
|
||||
ex = LowLevelPolicyError("Error reading range high level: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return level_factory(self.policy, l)
|
||||
if self.handle == NULL:
|
||||
return self._high
|
||||
else:
|
||||
return Level.factory(self.policy, &self.handle.level[1])
|
||||
|
||||
@property
|
||||
def low(self):
|
||||
"""The low end/current level of this range."""
|
||||
cdef const qpol_mls_level_t *l
|
||||
if qpol_mls_range_get_low_level(self.policy.handle, self.handle, &l):
|
||||
ex = LowLevelPolicyError("Error reading range low level: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return level_factory(self.policy, l)
|
||||
if self.handle == NULL:
|
||||
return self._low
|
||||
else:
|
||||
return Level.factory(self.policy, &self.handle.level[0])
|
||||
|
||||
def statement(self):
|
||||
raise NoStatement
|
||||
|
||||
|
||||
#
|
||||
# Hash Table Iterators
|
||||
#
|
||||
cdef class CategoryHashtabIterator(HashtabIterator):
|
||||
|
||||
"""Iterate over categories in the policy."""
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
|
||||
"""Factory function for creating category iterators."""
|
||||
i = CategoryHashtabIterator()
|
||||
i.policy = policy
|
||||
i.table = table
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
datum = <sepol.cat_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
while datum != NULL and datum.isalias:
|
||||
super().__next__()
|
||||
datum = <sepol.cat_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
return Category.factory(self.policy, datum)
|
||||
|
||||
def __len__(self):
|
||||
cdef sepol.cat_datum_t *datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
cdef size_t count = 0
|
||||
|
||||
while bucket < self.table[0].size:
|
||||
node = self.table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
datum = <sepol.cat_datum_t *>node.datum if node else NULL
|
||||
if datum != NULL and not datum.isalias:
|
||||
count += 1
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
return count
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
|
||||
cdef sepol.cat_datum_t *datum = <sepol.cat_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
# advance over any attributes or aliases
|
||||
while datum != NULL and datum.isalias:
|
||||
self._next_node()
|
||||
|
||||
if self.node == NULL or self.bucket >= self.table[0].size:
|
||||
break
|
||||
|
||||
datum = <sepol.cat_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
|
||||
cdef class CategoryAliasHashtabIterator(HashtabIterator):
|
||||
|
||||
"""Iterate over category aliases in the policy."""
|
||||
|
||||
cdef uint32_t primary
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table, Category primary):
|
||||
"""Factory function for creating category alias iterators."""
|
||||
i = CategoryAliasHashtabIterator()
|
||||
i.policy = policy
|
||||
i.table = table
|
||||
i.primary = primary._value
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
datum = <sepol.cat_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
while datum != NULL and (not datum.isalias or datum.s.value != self.primary):
|
||||
super().__next__()
|
||||
datum = <sepol.cat_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
return intern(self.curr.key)
|
||||
|
||||
def __len__(self):
|
||||
cdef sepol.cat_datum_t *datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
cdef size_t count = 0
|
||||
|
||||
while bucket < self.table[0].size:
|
||||
node = self.table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
datum = <sepol.cat_datum_t *>node.datum if node else NULL
|
||||
if datum != NULL and self.primary == datum.s.value and datum.isalias:
|
||||
count += 1
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
return count
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
|
||||
cdef sepol.cat_datum_t *datum = <sepol.cat_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
# advance over any attributes or aliases
|
||||
while datum != NULL and (not datum.isalias and self.primary != datum.s.value):
|
||||
self._next_node()
|
||||
|
||||
if self.node == NULL or self.bucket >= self.table[0].size:
|
||||
break
|
||||
|
||||
datum = <sepol.cat_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
|
||||
cdef class SensitivityHashtabIterator(HashtabIterator):
|
||||
|
||||
"""Iterate over sensitivity in the policy."""
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
|
||||
"""Factory function for creating category iterators."""
|
||||
i = SensitivityHashtabIterator()
|
||||
i.policy = policy
|
||||
i.table = table
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
while datum != NULL and datum.isalias:
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
return Sensitivity.factory(self.policy, datum)
|
||||
|
||||
def __len__(self):
|
||||
cdef sepol.level_datum_t *datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
cdef size_t count = 0
|
||||
|
||||
while bucket < self.table[0].size:
|
||||
node = self.table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
datum = <sepol.level_datum_t *>node.datum if node else NULL
|
||||
if datum != NULL and not datum.isalias:
|
||||
count += 1
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
return count
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
|
||||
cdef sepol.level_datum_t *datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
# advance over any attributes or aliases
|
||||
while datum != NULL and datum.isalias:
|
||||
self._next_node()
|
||||
|
||||
if self.node == NULL or self.bucket >= self.table[0].size:
|
||||
break
|
||||
|
||||
datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
|
||||
cdef class SensitivityAliasHashtabIterator(HashtabIterator):
|
||||
|
||||
"""Iterate over sensitivity aliases in the policy."""
|
||||
|
||||
cdef uint32_t primary
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table, Sensitivity primary):
|
||||
"""Factory function for creating Sensitivity alias iterators."""
|
||||
i = SensitivityAliasHashtabIterator()
|
||||
i.policy = policy
|
||||
i.table = table
|
||||
i.primary = primary._value
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
while datum != NULL and (not datum.isalias or datum.level.sens != self.primary):
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
return intern(self.curr.key)
|
||||
|
||||
def __len__(self):
|
||||
cdef sepol.level_datum_t *datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
cdef size_t count = 0
|
||||
|
||||
while bucket < self.table[0].size:
|
||||
node = self.table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
datum = <sepol.level_datum_t *>node.datum if node else NULL
|
||||
if datum != NULL and self.primary == datum.level.sens and datum.isalias:
|
||||
count += 1
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
return count
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
|
||||
cdef sepol.level_datum_t *datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
# advance over any attributes or aliases
|
||||
while datum != NULL and (not datum.isalias and self.primary != datum.level.sens):
|
||||
self._next_node()
|
||||
|
||||
if self.node == NULL or self.bucket >= self.table[0].size:
|
||||
break
|
||||
|
||||
datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
|
||||
cdef class LevelDeclHashtabIterator(HashtabIterator):
|
||||
|
||||
"""Iterate over level declarations in the policy."""
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.hashtab_t *table):
|
||||
"""Factory function for creating level declarations iterators."""
|
||||
i = LevelDeclHashtabIterator()
|
||||
i.policy = policy
|
||||
i.table = table
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
while datum != NULL and datum.isalias:
|
||||
super().__next__()
|
||||
datum = <sepol.level_datum_t *> self.curr.datum if self.curr else NULL
|
||||
|
||||
return LevelDecl.factory(self.policy, datum)
|
||||
|
||||
def __len__(self):
|
||||
cdef sepol.level_datum_t *datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
cdef size_t count = 0
|
||||
|
||||
while bucket < self.table[0].size:
|
||||
node = self.table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
datum = <sepol.level_datum_t *>node.datum if node else NULL
|
||||
if datum != NULL and not datum.isalias:
|
||||
count += 1
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
return count
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
|
||||
cdef sepol.level_datum_t *datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
# advance over any attributes or aliases
|
||||
while datum != NULL and datum.isalias:
|
||||
self._next_node()
|
||||
|
||||
if self.node == NULL or self.bucket >= self.table[0].size:
|
||||
break
|
||||
|
||||
datum = <sepol.level_datum_t *> self.node.datum if self.node else NULL
|
||||
|
||||
|
||||
#
|
||||
# Ebitmap Iterators
|
||||
#
|
||||
cdef class CategoryEbitmapIterator(EbitmapIterator):
|
||||
|
||||
"""Iterate over a category ebitmap."""
|
||||
|
||||
@staticmethod
|
||||
cdef factory(SELinuxPolicy policy, sepol.ebitmap_t *symbol):
|
||||
"""Factory function for creating CategoryEbitmapIterator."""
|
||||
i = CategoryEbitmapIterator()
|
||||
i.policy = policy
|
||||
i.bmap = symbol
|
||||
i.reset()
|
||||
return i
|
||||
|
||||
def __next__(self):
|
||||
super().__next__()
|
||||
return Category.factory(self.policy, self.policy.cat_val_to_struct[self.bit])
|
||||
|
@ -67,7 +67,7 @@ cdef class MLSRule(PolicyRule):
|
||||
"""An MLS rule."""
|
||||
|
||||
cdef:
|
||||
const qpol_range_trans_t *handle
|
||||
sepol.range_trans_t *handle
|
||||
readonly object ruletype
|
||||
|
||||
def __init__(self):
|
||||
@ -119,14 +119,10 @@ cdef class MLSRule(PolicyRule):
|
||||
@property
|
||||
def default(self):
|
||||
"""The rule's default range."""
|
||||
cdef const qpol_mls_range_t *r
|
||||
if qpol_range_trans_get_range(self.policy.handle, self.handle, &r):
|
||||
ex = LowLevelPolicyError("Error reading range for range_transition rule: {}".format(
|
||||
strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
|
||||
return range_factory(self.policy, r)
|
||||
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)
|
||||
|
||||
def expand(self):
|
||||
"""Expand the rule into an equivalent set of rules without attributes."""
|
||||
|
@ -53,6 +53,8 @@ cdef void qpol_log_callback(void *varg, const qpol_policy_t *p, int level, const
|
||||
cdef class SELinuxPolicy:
|
||||
cdef:
|
||||
qpol_policy_t *handle
|
||||
sepol.cat_datum_t **cat_val_to_struct
|
||||
sepol.level_datum_t **level_val_to_struct
|
||||
readonly str path
|
||||
object log
|
||||
|
||||
@ -72,7 +74,17 @@ cdef class SELinuxPolicy:
|
||||
except NameError:
|
||||
raise RuntimeError("Loading the running policy requires libselinux Python bindings")
|
||||
|
||||
self._policy_extend()
|
||||
|
||||
def __cinit__(self):
|
||||
self.handle = NULL
|
||||
self.cat_val_to_struct = NULL
|
||||
self.level_val_to_struct = NULL
|
||||
|
||||
def __dealloc__(self):
|
||||
PyMem_Free(self.cat_val_to_struct)
|
||||
PyMem_Free(self.level_val_to_struct)
|
||||
|
||||
if self.handle:
|
||||
qpol_policy_destroy(&self.handle)
|
||||
|
||||
@ -435,6 +447,14 @@ cdef class SELinuxPolicy:
|
||||
|
||||
raise InvalidBoolean("{0} is not a valid Boolean".format(name))
|
||||
|
||||
def lookup_category(self, name):
|
||||
"""Look up a category."""
|
||||
for c in self.categories():
|
||||
if c == name:
|
||||
return c
|
||||
|
||||
raise InvalidCategory("{0} is not a valid category".format(name))
|
||||
|
||||
def lookup_class(self, name):
|
||||
"""Look up an object class."""
|
||||
return class_factory_lookup(self, name)
|
||||
@ -453,15 +473,19 @@ cdef class SELinuxPolicy:
|
||||
|
||||
def lookup_level(self, level):
|
||||
"""Look up a MLS level."""
|
||||
return level_factory_lookup(self, level)
|
||||
return Level.factory_from_string(self, level)
|
||||
|
||||
def lookup_sensitivity(self, name):
|
||||
"""Look up a MLS sensitivity by name."""
|
||||
return sensitivity_factory_lookup(self, name)
|
||||
for s in self.sensitivities():
|
||||
if s == name:
|
||||
return s
|
||||
|
||||
raise InvalidSensitivity("{0} is not a valid sensitivity".format(name))
|
||||
|
||||
def lookup_range(self, range_):
|
||||
"""Look up a MLS range."""
|
||||
return range_factory_lookup(self, range_)
|
||||
return Range.factory_from_string(self, range_)
|
||||
|
||||
def lookup_role(self, name):
|
||||
"""Look up a role by name."""
|
||||
@ -500,11 +524,7 @@ cdef class SELinuxPolicy:
|
||||
|
||||
def categories(self):
|
||||
"""Iterator which yields all MLS categories."""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_policy_get_cat_iter(self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self, iter, category_factory_iter, ValueError)
|
||||
return CategoryHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_CATS].table)
|
||||
|
||||
def classes(self):
|
||||
"""Iterator which yields all object classes."""
|
||||
@ -532,11 +552,7 @@ cdef class SELinuxPolicy:
|
||||
|
||||
def levels(self):
|
||||
"""Iterator which yields all level declarations."""
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_policy_get_level_iter(self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self, iter, level_decl_factory_iter, ValueError)
|
||||
return LevelDeclHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_LEVELS].table)
|
||||
|
||||
def polcaps(self):
|
||||
"""Iterator which yields all policy capabilities."""
|
||||
@ -552,12 +568,7 @@ cdef class SELinuxPolicy:
|
||||
|
||||
def sensitivities(self):
|
||||
"""Iterator over all sensitivities."""
|
||||
# see mls.pxi for more info on why level_iter is used here.
|
||||
cdef qpol_iterator_t *iter
|
||||
if qpol_policy_get_level_iter(self.handle, &iter):
|
||||
raise MemoryError
|
||||
|
||||
return qpol_iterator_factory(self, iter, sensitivity_factory_iter, ValueError)
|
||||
return SensitivityHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_LEVELS].table)
|
||||
|
||||
def types(self):
|
||||
"""Iterator over all types."""
|
||||
@ -712,3 +723,63 @@ cdef class SELinuxPolicy:
|
||||
def pirqcons(self):
|
||||
"""Iterator over all pirqcon statements."""
|
||||
return PirqconIterator.factory(self, self.handle.p.p.ocontexts[sepol.OCON_XEN_PIRQ])
|
||||
|
||||
#
|
||||
# Internal methods
|
||||
#
|
||||
cdef _policy_extend(self):
|
||||
"""Create supplementary data structures (linkages) from the policydb."""
|
||||
cdef sepol.cat_datum_t *cat_datum
|
||||
cdef sepol.hashtab_node_t *node
|
||||
cdef uint32_t bucket = 0
|
||||
|
||||
cdef size_t bucket_len
|
||||
cdef size_t map_len
|
||||
|
||||
if self.mls:
|
||||
#
|
||||
# Create cat_val_to_struct (indexed by value -1)
|
||||
#
|
||||
map_len = self.handle.p.p.symtab[sepol.SYM_CATS].table.nel
|
||||
bucket_len = self.handle.p.p.symtab[sepol.SYM_CATS].table[0].size
|
||||
|
||||
self.cat_val_to_struct = <sepol.cat_datum_t**>PyMem_Malloc(
|
||||
map_len * sizeof(sepol.cat_datum_t*))
|
||||
|
||||
if self.cat_val_to_struct == NULL:
|
||||
raise MemoryError
|
||||
|
||||
while bucket < bucket_len:
|
||||
node = self.handle.p.p.symtab[sepol.SYM_CATS].table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
cat_datum = <sepol.cat_datum_t *>node.datum
|
||||
if cat_datum != NULL:
|
||||
self.cat_val_to_struct[cat_datum.s.value - 1] = cat_datum
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
||||
#
|
||||
# Create level_val_to_struct (indexed by value -1)
|
||||
#
|
||||
map_len = self.handle.p.p.symtab[sepol.SYM_LEVELS].table.nel
|
||||
bucket_len = self.handle.p.p.symtab[sepol.SYM_LEVELS].table[0].size
|
||||
bucket = 0
|
||||
|
||||
self.level_val_to_struct = <sepol.level_datum_t**>PyMem_Malloc(
|
||||
map_len * sizeof(sepol.level_datum_t*))
|
||||
|
||||
if self.level_val_to_struct == NULL:
|
||||
raise MemoryError
|
||||
|
||||
while bucket < bucket_len:
|
||||
node = self.handle.p.p.symtab[sepol.SYM_LEVELS].table[0].htable[bucket]
|
||||
while node != NULL:
|
||||
level_datum = <sepol.level_datum_t *>node.datum
|
||||
if level_datum != NULL:
|
||||
self.level_val_to_struct[level_datum.level.sens - 1] = level_datum
|
||||
|
||||
node = node.next
|
||||
|
||||
bucket += 1
|
||||
|
@ -77,24 +77,18 @@ cdef class User(PolicySymbol):
|
||||
@property
|
||||
def mls_level(self):
|
||||
"""The user's default MLS level."""
|
||||
cdef const qpol_mls_level_t *l
|
||||
if qpol_user_get_dfltlevel(self.policy.handle, self.handle, &l):
|
||||
ex = LowLevelPolicyError("Error reading user default level: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
if not self.policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
return level_factory(self.policy, l)
|
||||
return Level.factory(self.policy, &self.handle.exp_dfltlevel)
|
||||
|
||||
@property
|
||||
def mls_range(self):
|
||||
"""The user's MLS range."""
|
||||
cdef const qpol_mls_range_t *r
|
||||
if qpol_user_get_range(self.policy.handle, self.handle, &r):
|
||||
ex = LowLevelPolicyError("Error reading user range: {}".format(strerror(errno)))
|
||||
ex.errno = errno
|
||||
raise ex
|
||||
if not self.policy.mls:
|
||||
raise MLSDisabled
|
||||
|
||||
return range_factory(self.policy, r)
|
||||
return Range.factory(self.policy, &self.handle.exp_range)
|
||||
|
||||
def statement(self):
|
||||
roles = list(str(r) for r in self.roles)
|
||||
|
Loading…
Reference in New Issue
Block a user