Skip to content

Commit

Permalink
libsepol/cil: Properly check for loops in sets
Browse files Browse the repository at this point in the history
Commit 61fbdce (ibsepol/cil: Check
for self-referential loops in sets) added checks for self-referential
loops in user, role, type, and category sets. Unfortunately, this
check ends up in an infinite loop if the set with the self-referential
loop is used in a different set that is checked before the bad set.

The problem with the old check is that only the initial datum is used
for the check. Instead, use a stack to track all of the set datums
that are currently involved as the check is made. A self-referential
loop occurs if a duplicate datum is found for any of the datums in the
stack.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
  • Loading branch information
jwcart2 committed Jun 24, 2021
1 parent 67a8dc8 commit c28525a
Showing 1 changed file with 32 additions and 16 deletions.
48 changes: 32 additions & 16 deletions libsepol/cil/src/cil_verify.c
Expand Up @@ -44,6 +44,7 @@
#include "cil_tree.h"
#include "cil_list.h"
#include "cil_find.h"
#include "cil_stack.h"

#include "cil_verify.h"

Expand Down Expand Up @@ -430,9 +431,9 @@ int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, str
return SEPOL_OK;
}

static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig);
static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);

static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_symtab_datum *orig)
static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
{
struct cil_list_item *item;
int rc = SEPOL_OK;
Expand All @@ -444,9 +445,9 @@ static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_
cil_list_for_each(item, expr) {
if (item->flavor == CIL_DATUM) {
struct cil_symtab_datum* datum = item->data;
rc = cil_verify_no_self_reference(FLAVOR(datum), datum, orig);
rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
} else if (item->flavor == CIL_LIST) {
rc = __verify_no_self_reference_in_expr(item->data, orig);
rc = __verify_no_self_reference_in_expr(item->data, stack);
}
if (rc != SEPOL_OK) {
return SEPOL_ERR;
Expand All @@ -456,36 +457,47 @@ static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_
return SEPOL_OK;
}

static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig)
static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
{
struct cil_stack_item *item;
int i = 0;
int rc = SEPOL_OK;

if (datum == orig) {
cil_tree_log(NODE(orig), CIL_ERR, "Self-reference found for %s", orig->name);
return SEPOL_ERR;
} else if (orig == NULL) {
orig = datum;
cil_stack_for_each(stack, i, item) {
struct cil_symtab_datum *prev = item->data;
if (datum == prev) {
cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
return SEPOL_ERR;
}
}

switch (flavor) {
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = (struct cil_userattribute *)datum;
rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
cil_stack_push(stack, CIL_DATUM, datum);
rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
cil_stack_pop(stack);
break;
}
case CIL_ROLEATTRIBUTE: {
struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
cil_stack_push(stack, CIL_DATUM, datum);
rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
cil_stack_pop(stack);
break;
}
case CIL_TYPEATTRIBUTE: {
struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
cil_stack_push(stack, CIL_DATUM, datum);
rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
cil_stack_pop(stack);
break;
}
case CIL_CATSET: {
struct cil_catset *set = (struct cil_catset *)datum;
rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, orig);
cil_stack_push(stack, CIL_DATUM, datum);
rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
cil_stack_pop(stack);
break;
}
default:
Expand Down Expand Up @@ -1826,9 +1838,13 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
case CIL_USERATTRIBUTE:
case CIL_ROLEATTRIBUTE:
case CIL_TYPEATTRIBUTE:
case CIL_CATSET:
rc = cil_verify_no_self_reference(node->flavor, node->data, NULL);
case CIL_CATSET: {
struct cil_stack *stack;
cil_stack_init(&stack);
rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
cil_stack_destroy(&stack);
break;
}
default:
rc = SEPOL_OK;
break;
Expand Down

0 comments on commit c28525a

Please sign in to comment.