selinux: convert cond_av_list to array
Since it is fixed-size after allocation and we know the size beforehand, using a plain old array is simpler and more efficient. Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> Reviewed-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
60abd3181d
commit
2b3a003e15
|
@ -87,8 +87,9 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
|
||||||
*/
|
*/
|
||||||
void evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
void evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
||||||
{
|
{
|
||||||
|
struct avtab_node *avnode;
|
||||||
int new_state;
|
int new_state;
|
||||||
struct cond_av_list *cur;
|
u32 i;
|
||||||
|
|
||||||
new_state = cond_evaluate_expr(p, node->expr);
|
new_state = cond_evaluate_expr(p, node->expr);
|
||||||
if (new_state != node->cur_state) {
|
if (new_state != node->cur_state) {
|
||||||
|
@ -96,19 +97,21 @@ void evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
||||||
if (new_state == -1)
|
if (new_state == -1)
|
||||||
pr_err("SELinux: expression result was undefined - disabling all rules.\n");
|
pr_err("SELinux: expression result was undefined - disabling all rules.\n");
|
||||||
/* turn the rules on or off */
|
/* turn the rules on or off */
|
||||||
for (cur = node->true_list; cur; cur = cur->next) {
|
for (i = 0; i < node->true_list.len; i++) {
|
||||||
|
avnode = node->true_list.nodes[i];
|
||||||
if (new_state <= 0)
|
if (new_state <= 0)
|
||||||
cur->node->key.specified &= ~AVTAB_ENABLED;
|
avnode->key.specified &= ~AVTAB_ENABLED;
|
||||||
else
|
else
|
||||||
cur->node->key.specified |= AVTAB_ENABLED;
|
avnode->key.specified |= AVTAB_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cur = node->false_list; cur; cur = cur->next) {
|
for (i = 0; i < node->false_list.len; i++) {
|
||||||
|
avnode = node->false_list.nodes[i];
|
||||||
/* -1 or 1 */
|
/* -1 or 1 */
|
||||||
if (new_state)
|
if (new_state)
|
||||||
cur->node->key.specified &= ~AVTAB_ENABLED;
|
avnode->key.specified &= ~AVTAB_ENABLED;
|
||||||
else
|
else
|
||||||
cur->node->key.specified |= AVTAB_ENABLED;
|
avnode->key.specified |= AVTAB_ENABLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,16 +131,6 @@ int cond_policydb_init(struct policydb *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cond_av_list_destroy(struct cond_av_list *list)
|
|
||||||
{
|
|
||||||
struct cond_av_list *cur, *next;
|
|
||||||
for (cur = list; cur; cur = next) {
|
|
||||||
next = cur->next;
|
|
||||||
/* the avtab_ptr_t node is destroy by the avtab */
|
|
||||||
kfree(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cond_node_destroy(struct cond_node *node)
|
static void cond_node_destroy(struct cond_node *node)
|
||||||
{
|
{
|
||||||
struct cond_expr *cur_expr, *next_expr;
|
struct cond_expr *cur_expr, *next_expr;
|
||||||
|
@ -146,8 +139,9 @@ static void cond_node_destroy(struct cond_node *node)
|
||||||
next_expr = cur_expr->next;
|
next_expr = cur_expr->next;
|
||||||
kfree(cur_expr);
|
kfree(cur_expr);
|
||||||
}
|
}
|
||||||
cond_av_list_destroy(node->true_list);
|
/* the avtab_ptr_t nodes are destroyed by the avtab */
|
||||||
cond_av_list_destroy(node->false_list);
|
kfree(node->true_list.nodes);
|
||||||
|
kfree(node->false_list.nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cond_list_destroy(struct policydb *p)
|
static void cond_list_destroy(struct policydb *p)
|
||||||
|
@ -255,19 +249,18 @@ err:
|
||||||
|
|
||||||
struct cond_insertf_data {
|
struct cond_insertf_data {
|
||||||
struct policydb *p;
|
struct policydb *p;
|
||||||
|
struct avtab_node **dst;
|
||||||
struct cond_av_list *other;
|
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)
|
static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
|
||||||
{
|
{
|
||||||
struct cond_insertf_data *data = ptr;
|
struct cond_insertf_data *data = ptr;
|
||||||
struct policydb *p = data->p;
|
struct policydb *p = data->p;
|
||||||
struct cond_av_list *other = data->other, *list, *cur;
|
struct cond_av_list *other = data->other;
|
||||||
struct avtab_node *node_ptr;
|
struct avtab_node *node_ptr;
|
||||||
u8 found;
|
u32 i;
|
||||||
int rc = -EINVAL;
|
bool found;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For type rules we have to make certain there aren't any
|
* For type rules we have to make certain there aren't any
|
||||||
|
@ -277,7 +270,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
||||||
if (k->specified & AVTAB_TYPE) {
|
if (k->specified & AVTAB_TYPE) {
|
||||||
if (avtab_search(&p->te_avtab, k)) {
|
if (avtab_search(&p->te_avtab, k)) {
|
||||||
pr_err("SELinux: type rule already exists outside of a conditional.\n");
|
pr_err("SELinux: type rule already exists outside of a conditional.\n");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we are reading the false list other will be a pointer to
|
* If we are reading the false list other will be a pointer to
|
||||||
|
@ -292,24 +285,24 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
||||||
if (node_ptr) {
|
if (node_ptr) {
|
||||||
if (avtab_search_node_next(node_ptr, k->specified)) {
|
if (avtab_search_node_next(node_ptr, k->specified)) {
|
||||||
pr_err("SELinux: too many conflicting type rules.\n");
|
pr_err("SELinux: too many conflicting type rules.\n");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
found = 0;
|
found = false;
|
||||||
for (cur = other; cur; cur = cur->next) {
|
for (i = 0; i < other->len; i++) {
|
||||||
if (cur->node == node_ptr) {
|
if (other->nodes[i] == node_ptr) {
|
||||||
found = 1;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
pr_err("SELinux: conflicting type rules.\n");
|
pr_err("SELinux: conflicting type rules.\n");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (avtab_search(&p->te_cond_avtab, k)) {
|
if (avtab_search(&p->te_cond_avtab, k)) {
|
||||||
pr_err("SELinux: conflicting type rules when adding type rule for true.\n");
|
pr_err("SELinux: conflicting type rules when adding type rule for true.\n");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,39 +310,22 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
||||||
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
|
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
|
||||||
if (!node_ptr) {
|
if (!node_ptr) {
|
||||||
pr_err("SELinux: could not insert rule.\n");
|
pr_err("SELinux: could not insert rule.\n");
|
||||||
rc = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list = kzalloc(sizeof(*list), GFP_KERNEL);
|
*data->dst = node_ptr;
|
||||||
if (!list) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
list->node = node_ptr;
|
|
||||||
if (!data->head)
|
|
||||||
data->head = list;
|
|
||||||
else
|
|
||||||
data->tail->next = list;
|
|
||||||
data->tail = list;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
|
||||||
cond_av_list_destroy(data->head);
|
|
||||||
data->head = NULL;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
|
static int cond_read_av_list(struct policydb *p, void *fp,
|
||||||
|
struct cond_av_list *list,
|
||||||
|
struct cond_av_list *other)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int rc;
|
||||||
__le32 buf[1];
|
__le32 buf[1];
|
||||||
u32 len;
|
u32 i, len;
|
||||||
struct cond_insertf_data data;
|
struct cond_insertf_data data;
|
||||||
|
|
||||||
*ret_list = NULL;
|
|
||||||
|
|
||||||
rc = next_entry(buf, fp, sizeof(u32));
|
rc = next_entry(buf, fp, sizeof(u32));
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -358,18 +334,24 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
list->nodes = kcalloc(len, sizeof(*list->nodes), GFP_KERNEL);
|
||||||
|
if (!list->nodes)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
data.p = p;
|
data.p = p;
|
||||||
data.other = other;
|
data.other = other;
|
||||||
data.head = NULL;
|
|
||||||
data.tail = NULL;
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
|
data.dst = &list->nodes[i];
|
||||||
rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
|
rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
|
||||||
&data);
|
&data);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
kfree(list->nodes);
|
||||||
|
list->nodes = NULL;
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_list = data.head;
|
list->len = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +414,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
|
||||||
rc = cond_read_av_list(p, fp, &node->true_list, NULL);
|
rc = cond_read_av_list(p, fp, &node->true_list, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err;
|
goto err;
|
||||||
rc = cond_read_av_list(p, fp, &node->false_list, node->true_list);
|
rc = cond_read_av_list(p, fp, &node->false_list, &node->true_list);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err;
|
goto err;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -511,24 +493,16 @@ static int cond_write_av_list(struct policydb *p,
|
||||||
struct cond_av_list *list, struct policy_file *fp)
|
struct cond_av_list *list, struct policy_file *fp)
|
||||||
{
|
{
|
||||||
__le32 buf[1];
|
__le32 buf[1];
|
||||||
struct cond_av_list *cur_list;
|
u32 i;
|
||||||
u32 len;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
len = 0;
|
buf[0] = cpu_to_le32(list->len);
|
||||||
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
|
|
||||||
len++;
|
|
||||||
|
|
||||||
buf[0] = cpu_to_le32(len);
|
|
||||||
rc = put_entry(buf, sizeof(u32), 1, fp);
|
rc = put_entry(buf, sizeof(u32), 1, fp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (len == 0)
|
for (i = 0; i < list->len; i++) {
|
||||||
return 0;
|
rc = avtab_write_item(p, list->nodes[i], fp);
|
||||||
|
|
||||||
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
|
|
||||||
rc = avtab_write_item(p, cur_list->node, fp);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -565,10 +539,10 @@ static int cond_write_node(struct policydb *p, struct cond_node *node,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = cond_write_av_list(p, node->true_list, fp);
|
rc = cond_write_av_list(p, &node->true_list, fp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
rc = cond_write_av_list(p, node->false_list, fp);
|
rc = cond_write_av_list(p, &node->false_list, fp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@ struct cond_expr {
|
||||||
* struct is for that list.
|
* struct is for that list.
|
||||||
*/
|
*/
|
||||||
struct cond_av_list {
|
struct cond_av_list {
|
||||||
struct avtab_node *node;
|
struct avtab_node **nodes;
|
||||||
struct cond_av_list *next;
|
u32 len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,8 +53,8 @@ struct cond_av_list {
|
||||||
struct cond_node {
|
struct cond_node {
|
||||||
int cur_state;
|
int cur_state;
|
||||||
struct cond_expr *expr;
|
struct cond_expr *expr;
|
||||||
struct cond_av_list *true_list;
|
struct cond_av_list true_list;
|
||||||
struct cond_av_list *false_list;
|
struct cond_av_list false_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
int cond_policydb_init(struct policydb *p);
|
int cond_policydb_init(struct policydb *p);
|
||||||
|
|
Loading…
Reference in New Issue