checkpolicy: clean expression on error

The passed expression needs to be transferred into the policy or free'd
by the sink functions define_constraint() and define_validatetrans().

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
Christian Göttsche 2024-01-22 14:54:58 +01:00 committed by James Carter
parent 770ad3ecac
commit 187e75849e
1 changed files with 40 additions and 28 deletions

View File

@ -3428,20 +3428,22 @@ int define_constraint(constraint_expr_t * expr)
return 0; return 0;
} }
ebitmap_init(&classmap);
depth = -1; depth = -1;
for (e = expr; e; e = e->next) { for (e = expr; e; e = e->next) {
switch (e->expr_type) { switch (e->expr_type) {
case CEXPR_NOT: case CEXPR_NOT:
if (depth < 0) { if (depth < 0) {
yyerror("illegal constraint expression"); yyerror("illegal constraint expression");
return -1; goto bad;
} }
break; break;
case CEXPR_AND: case CEXPR_AND:
case CEXPR_OR: case CEXPR_OR:
if (depth < 1) { if (depth < 1) {
yyerror("illegal constraint expression"); yyerror("illegal constraint expression");
return -1; goto bad;
} }
depth--; depth--;
break; break;
@ -3449,51 +3451,48 @@ int define_constraint(constraint_expr_t * expr)
case CEXPR_NAMES: case CEXPR_NAMES:
if (e->attr & CEXPR_XTARGET) { if (e->attr & CEXPR_XTARGET) {
yyerror("illegal constraint expression"); yyerror("illegal constraint expression");
return -1; /* only for validatetrans rules */ goto bad; /* only for validatetrans rules */
} }
if (depth == (CEXPR_MAXDEPTH - 1)) { if (depth == (CEXPR_MAXDEPTH - 1)) {
yyerror("constraint expression is too deep"); yyerror("constraint expression is too deep");
return -1; goto bad;
} }
depth++; depth++;
break; break;
default: default:
yyerror("illegal constraint expression"); yyerror("illegal constraint expression");
return -1; goto bad;
} }
} }
if (depth != 0) { if (depth != 0) {
yyerror("illegal constraint expression"); yyerror("illegal constraint expression");
return -1; goto bad;
} }
ebitmap_init(&classmap);
while ((id = queue_remove(id_queue))) { while ((id = queue_remove(id_queue))) {
if (!is_id_in_scope(SYM_CLASSES, id)) { if (!is_id_in_scope(SYM_CLASSES, id)) {
yyerror2("class %s is not within scope", id); yyerror2("class %s is not within scope", id);
free(id); free(id);
return -1; goto bad;
} }
cladatum = cladatum =
(class_datum_t *) hashtab_search(policydbp->p_classes.table, (class_datum_t *) hashtab_search(policydbp->p_classes.table,
(hashtab_key_t) id); (hashtab_key_t) id);
if (!cladatum) { if (!cladatum) {
yyerror2("class %s is not defined", id); yyerror2("class %s is not defined", id);
ebitmap_destroy(&classmap);
free(id); free(id);
return -1; goto bad;
} }
if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) { if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) {
yyerror("out of memory"); yyerror("out of memory");
ebitmap_destroy(&classmap);
free(id); free(id);
return -1; goto bad;
} }
node = malloc(sizeof(struct constraint_node)); node = malloc(sizeof(struct constraint_node));
if (!node) { if (!node) {
yyerror("out of memory"); yyerror("out of memory");
free(node); free(node);
return -1; goto bad;
} }
memset(node, 0, sizeof(constraint_node_t)); memset(node, 0, sizeof(constraint_node_t));
if (useexpr) { if (useexpr) {
@ -3505,7 +3504,7 @@ int define_constraint(constraint_expr_t * expr)
if (!node->expr) { if (!node->expr) {
yyerror("out of memory"); yyerror("out of memory");
free(node); free(node);
return -1; goto bad;
} }
node->permissions = 0; node->permissions = 0;
@ -3557,8 +3556,7 @@ int define_constraint(constraint_expr_t * expr)
yyerror2("permission %s is not" yyerror2("permission %s is not"
" defined for class %s", id, policydbp->p_class_val_to_name[i]); " defined for class %s", id, policydbp->p_class_val_to_name[i]);
free(id); free(id);
ebitmap_destroy(&classmap); goto bad;
return -1;
} }
} }
node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1)); node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1));
@ -3569,6 +3567,13 @@ int define_constraint(constraint_expr_t * expr)
ebitmap_destroy(&classmap); ebitmap_destroy(&classmap);
return 0; return 0;
bad:
ebitmap_destroy(&classmap);
if (useexpr)
constraint_expr_destroy(expr);
return -1;
} }
int define_validatetrans(constraint_expr_t * expr) int define_validatetrans(constraint_expr_t * expr)
@ -3587,20 +3592,22 @@ int define_validatetrans(constraint_expr_t * expr)
return 0; return 0;
} }
ebitmap_init(&classmap);
depth = -1; depth = -1;
for (e = expr; e; e = e->next) { for (e = expr; e; e = e->next) {
switch (e->expr_type) { switch (e->expr_type) {
case CEXPR_NOT: case CEXPR_NOT:
if (depth < 0) { if (depth < 0) {
yyerror("illegal validatetrans expression"); yyerror("illegal validatetrans expression");
return -1; goto bad;
} }
break; break;
case CEXPR_AND: case CEXPR_AND:
case CEXPR_OR: case CEXPR_OR:
if (depth < 1) { if (depth < 1) {
yyerror("illegal validatetrans expression"); yyerror("illegal validatetrans expression");
return -1; goto bad;
} }
depth--; depth--;
break; break;
@ -3608,47 +3615,45 @@ int define_validatetrans(constraint_expr_t * expr)
case CEXPR_NAMES: case CEXPR_NAMES:
if (depth == (CEXPR_MAXDEPTH - 1)) { if (depth == (CEXPR_MAXDEPTH - 1)) {
yyerror("validatetrans expression is too deep"); yyerror("validatetrans expression is too deep");
return -1; goto bad;
} }
depth++; depth++;
break; break;
default: default:
yyerror("illegal validatetrans expression"); yyerror("illegal validatetrans expression");
return -1; goto bad;
} }
} }
if (depth != 0) { if (depth != 0) {
yyerror("illegal validatetrans expression"); yyerror("illegal validatetrans expression");
return -1; goto bad;
} }
ebitmap_init(&classmap);
while ((id = queue_remove(id_queue))) { while ((id = queue_remove(id_queue))) {
if (!is_id_in_scope(SYM_CLASSES, id)) { if (!is_id_in_scope(SYM_CLASSES, id)) {
yyerror2("class %s is not within scope", id); yyerror2("class %s is not within scope", id);
free(id); free(id);
return -1; goto bad;
} }
cladatum = cladatum =
(class_datum_t *) hashtab_search(policydbp->p_classes.table, (class_datum_t *) hashtab_search(policydbp->p_classes.table,
(hashtab_key_t) id); (hashtab_key_t) id);
if (!cladatum) { if (!cladatum) {
yyerror2("class %s is not defined", id); yyerror2("class %s is not defined", id);
ebitmap_destroy(&classmap);
free(id); free(id);
return -1; goto bad;
} }
if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) { if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) {
yyerror("out of memory"); yyerror("out of memory");
ebitmap_destroy(&classmap);
free(id); free(id);
return -1; goto bad;
} }
node = malloc(sizeof(struct constraint_node)); node = malloc(sizeof(struct constraint_node));
if (!node) { if (!node) {
yyerror("out of memory"); yyerror("out of memory");
return -1; free(id);
goto bad;
} }
memset(node, 0, sizeof(constraint_node_t)); memset(node, 0, sizeof(constraint_node_t));
if (useexpr) { if (useexpr) {
@ -3668,6 +3673,13 @@ int define_validatetrans(constraint_expr_t * expr)
ebitmap_destroy(&classmap); ebitmap_destroy(&classmap);
return 0; return 0;
bad:
ebitmap_destroy(&classmap);
if (useexpr)
constraint_expr_destroy(expr);
return -1;
} }
uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2)