libsepol/cil: Verify neither child nor parent in a bounds is an attribute
Nicolas Iooss found while fuzzing secilc with AFL that using an attribute as a child in a typebounds statement will cause a segfault. This happens because the child datum is assumed to be part of a cil_type struct when it is really part of a cil_typeattribute struct. The check to verify that it is a type and not an attribute comes after it is used. This bug effects user and role bounds as well because they do not check whether a datum refers to an attribute or not. Add checks to verify that neither the child nor the parent datum refer to an attribute before using them in user, role, and type bounds. Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
This commit is contained in:
parent
0fcc430add
commit
410634d650
|
@ -2468,7 +2468,7 @@ exit:
|
|||
}
|
||||
|
||||
|
||||
int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor)
|
||||
int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor)
|
||||
{
|
||||
int rc = SEPOL_ERR;
|
||||
struct cil_bounds *bounds = current->data;
|
||||
|
@ -2485,19 +2485,29 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
|
|||
if (rc != SEPOL_OK) {
|
||||
goto exit;
|
||||
}
|
||||
if (NODE(parent_datum)->flavor == attr_flavor) {
|
||||
cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
|
||||
if (rc != SEPOL_OK) {
|
||||
goto exit;
|
||||
}
|
||||
if (NODE(child_datum)->flavor == attr_flavor) {
|
||||
cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (flavor) {
|
||||
case CIL_USER: {
|
||||
struct cil_user *user = (struct cil_user *)child_datum;
|
||||
|
||||
if (user->bounds != NULL) {
|
||||
struct cil_tree_node *node = user->bounds->datum.nodes->head->data;
|
||||
cil_tree_log(node, CIL_ERR, "User %s already bound by parent", bounds->child_str);
|
||||
cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -2509,8 +2519,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
|
|||
struct cil_role *role = (struct cil_role *)child_datum;
|
||||
|
||||
if (role->bounds != NULL) {
|
||||
struct cil_tree_node *node = role->bounds->datum.nodes->head->data;
|
||||
cil_tree_log(node, CIL_ERR, "Role %s already bound by parent", bounds->child_str);
|
||||
cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -2520,26 +2529,9 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
|
|||
}
|
||||
case CIL_TYPE: {
|
||||
struct cil_type *type = (struct cil_type *)child_datum;
|
||||
struct cil_tree_node *node = NULL;
|
||||
|
||||
if (type->bounds != NULL) {
|
||||
node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data;
|
||||
cil_tree_log(node, CIL_ERR, "Type %s already bound by parent", bounds->child_str);
|
||||
cil_tree_log(current, CIL_ERR, "Now being bound to parent %s", bounds->parent_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
node = parent_datum->nodes->head->data;
|
||||
if (node->flavor == CIL_TYPEATTRIBUTE) {
|
||||
cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
node = child_datum->nodes->head->data;
|
||||
if (node->flavor == CIL_TYPEATTRIBUTE) {
|
||||
cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
|
||||
cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str);
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3445,7 +3437,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
|
|||
rc = cil_resolve_typeattributeset(node, args);
|
||||
break;
|
||||
case CIL_TYPEBOUNDS:
|
||||
rc = cil_resolve_bounds(node, args, CIL_TYPE);
|
||||
rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE);
|
||||
break;
|
||||
case CIL_TYPEPERMISSIVE:
|
||||
rc = cil_resolve_typepermissive(node, args);
|
||||
|
@ -3482,7 +3474,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
|
|||
rc = cil_resolve_userrange(node, args);
|
||||
break;
|
||||
case CIL_USERBOUNDS:
|
||||
rc = cil_resolve_bounds(node, args, CIL_USER);
|
||||
rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE);
|
||||
break;
|
||||
case CIL_USERPREFIX:
|
||||
rc = cil_resolve_userprefix(node, args);
|
||||
|
@ -3504,7 +3496,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
|
|||
rc = cil_resolve_roleallow(node, args);
|
||||
break;
|
||||
case CIL_ROLEBOUNDS:
|
||||
rc = cil_resolve_bounds(node, args, CIL_ROLE);
|
||||
rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE);
|
||||
break;
|
||||
case CIL_LEVEL:
|
||||
rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
|
||||
|
|
Loading…
Reference in New Issue