libsepol/cil: Verify users prior to evaluating users

If a userlevel or userrange statement is missing from a policy,
evaluate_level_expression() and evaluate_levelrange_expression, respectively
will have a NULL pointer dereference caused by a missing level in a user.

Add cil_pre_verify() which verifies users have a valid level. Also, move loop
checking in classpermissions into cil_pre_verify().

This fixes https://github.com/SELinuxProject/cil/issues/1.

Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
This commit is contained in:
Yuli Khodorkovskiy 2015-05-05 15:19:59 -04:00 committed by James Carter
parent 34e196c3c2
commit c3345c58a4
3 changed files with 40 additions and 19 deletions

View File

@ -1691,12 +1691,30 @@ exit:
return rc;
}
static int cil_pre_verify(struct cil_db *db)
{
int rc = SEPOL_ERR;
struct cil_args_verify extra_args;
extra_args.db = db;
rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify cil database\n");
goto exit;
}
exit:
return rc;
}
int cil_post_process(struct cil_db *db)
{
int rc = SEPOL_ERR;
rc = cil_verify_no_classperms_loop(db);
rc = cil_pre_verify(db);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify cil database\n");
goto exit;
}

View File

@ -601,7 +601,7 @@ exit:
return rc;
}
int __cil_verify_user(struct cil_db *db, struct cil_tree_node *node)
static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
{
int rc = SEPOL_ERR;
struct cil_user *user = node->data;
@ -635,6 +635,17 @@ int __cil_verify_user(struct cil_db *db, struct cil_tree_node *node)
}
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path);
return rc;
}
static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
{
int rc = SEPOL_ERR;
struct cil_user *user = node->data;
/* Verify user range only if anonymous */
if (user->range->datum.name == NULL) {
rc = __cil_verify_levelrange(db, user->range);
@ -1318,7 +1329,7 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex
case 0: {
switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user(db, node);
rc = __cil_verify_user_post_eval(db, node);
break;
case CIL_SELINUXUSERDEFAULT:
(*nseuserdflt)++;
@ -1531,7 +1542,7 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
return SEPOL_OK;
}
static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
{
int rc = SEPOL_ERR;
@ -1549,6 +1560,12 @@ static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, ui
}
switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user_pre_eval(node);
if (rc != SEPOL_OK) {
goto exit;
}
break;
case CIL_MAP_CLASS:
rc = __cil_verify_map_class(node);
break;
@ -1563,17 +1580,3 @@ static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, ui
exit:
return rc;
}
int cil_verify_no_classperms_loop(struct cil_db *db)
{
int rc = SEPOL_ERR;
rc = cil_tree_walk(db->ast->root, __cil_verify_no_classperms_loop_helper, NULL, NULL, NULL);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify no loops in class permissions\n");
goto exit;
}
exit:
return rc;
}

View File

@ -68,6 +68,6 @@ int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
int __cil_verify_initsids(struct cil_list *sids);
int __cil_verify_senscat(struct cil_sens *sens, struct cil_cat *cat);
int __cil_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args);
int cil_verify_no_classperms_loop(struct cil_db *db);
int __cil_pre_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args);
#endif