diff mbox series

libsepol/cil: Validate conditional expressions before adding to binary policy

Message ID 20200909194222.263841-1-jwcart2@gmail.com (mailing list archive)
State Superseded
Headers show
Series libsepol/cil: Validate conditional expressions before adding to binary policy | expand

Commit Message

James Carter Sept. 9, 2020, 7:42 p.m. UTC
CIL was not correctly determining the depth of conditional expressions
which prevented it from giving an error when the max depth was exceeded.
This allowed invalid policy binaries to be created.

Validate the conditional expression using the same logic that is used
when evaluating a conditional expression. This includes checking the
depth of the expression.

Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/cil/src/cil_binary.c    | 43 ++++++++++++++++++++++++++++++++
 libsepol/cil/src/cil_build_ast.c | 26 ++++++-------------
 2 files changed, 50 insertions(+), 19 deletions(-)

Comments

Stephen Smalley Sept. 9, 2020, 8:09 p.m. UTC | #1
On Wed, Sep 9, 2020 at 3:43 PM James Carter <jwcart2@gmail.com> wrote:
>
> CIL was not correctly determining the depth of conditional expressions
> which prevented it from giving an error when the max depth was exceeded.
> This allowed invalid policy binaries to be created.
>
> Validate the conditional expression using the same logic that is used
> when evaluating a conditional expression. This includes checking the
> depth of the expression.
>
> Signed-off-by: James Carter <jwcart2@gmail.com>
> ---
>  libsepol/cil/src/cil_binary.c    | 43 ++++++++++++++++++++++++++++++++
>  libsepol/cil/src/cil_build_ast.c | 26 ++++++-------------
>  2 files changed, 50 insertions(+), 19 deletions(-)
>
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index 77266858..d30233c4 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -2176,6 +2176,44 @@ static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_e
>         return SEPOL_OK;
>  }
>
> +int __cil_validate_cond_expr(cond_expr_t *cond_expr)
> +{
> +       cond_expr_t *e;
> +       int depth = -1;
> +
> +       for (e = cond_expr; e != NULL; e = e->next) {
> +               switch (e->expr_type) {
> +               case COND_BOOL:
> +                       if (depth == (COND_EXPR_MAXDEPTH - 1)) {
> +                               cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n");
> +                               return -1;
> +                       }
> +                       depth++;
> +                       break;
> +               case COND_NOT:
> +                       if (depth < 0) {
> +                               cil_log(CIL_ERR,"Invalid conditional expression\n");
> +                               return -1;
> +                       }
> +                       break;
> +               case COND_OR:
> +               case COND_AND:
> +               case COND_XOR:
> +               case COND_EQ:
> +               case COND_NEQ:
> +                       if (depth < 1) {
> +                               cil_log(CIL_ERR,"Invalid conditional expression\n");
> +                               return -1;
> +                       }
> +                       depth--;
> +                       break;
> +               default:
> +                       cil_log(CIL_ERR,"Invalid conditional expression\n");
> +                       return -1;
> +               }
> +       }

Missing a return here.
../cil/src/cil_binary.c: In function ‘__cil_validate_cond_expr’:
../cil/src/cil_binary.c:2215:1: error: control reaches end of non-void
function [-Werror=return-type]
 2215 | }
      | ^
James Carter Sept. 9, 2020, 8:26 p.m. UTC | #2
On Wed, Sep 9, 2020 at 4:09 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Wed, Sep 9, 2020 at 3:43 PM James Carter <jwcart2@gmail.com> wrote:
> >
> > CIL was not correctly determining the depth of conditional expressions
> > which prevented it from giving an error when the max depth was exceeded.
> > This allowed invalid policy binaries to be created.
> >
> > Validate the conditional expression using the same logic that is used
> > when evaluating a conditional expression. This includes checking the
> > depth of the expression.
> >
> > Signed-off-by: James Carter <jwcart2@gmail.com>
> > ---
> >  libsepol/cil/src/cil_binary.c    | 43 ++++++++++++++++++++++++++++++++
> >  libsepol/cil/src/cil_build_ast.c | 26 ++++++-------------
> >  2 files changed, 50 insertions(+), 19 deletions(-)
> >
> > diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> > index 77266858..d30233c4 100644
> > --- a/libsepol/cil/src/cil_binary.c
> > +++ b/libsepol/cil/src/cil_binary.c
> > @@ -2176,6 +2176,44 @@ static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_e
> >         return SEPOL_OK;
> >  }
> >
> > +int __cil_validate_cond_expr(cond_expr_t *cond_expr)
> > +{
> > +       cond_expr_t *e;
> > +       int depth = -1;
> > +
> > +       for (e = cond_expr; e != NULL; e = e->next) {
> > +               switch (e->expr_type) {
> > +               case COND_BOOL:
> > +                       if (depth == (COND_EXPR_MAXDEPTH - 1)) {
> > +                               cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n");
> > +                               return -1;
> > +                       }
> > +                       depth++;
> > +                       break;
> > +               case COND_NOT:
> > +                       if (depth < 0) {
> > +                               cil_log(CIL_ERR,"Invalid conditional expression\n");
> > +                               return -1;
> > +                       }
> > +                       break;
> > +               case COND_OR:
> > +               case COND_AND:
> > +               case COND_XOR:
> > +               case COND_EQ:
> > +               case COND_NEQ:
> > +                       if (depth < 1) {
> > +                               cil_log(CIL_ERR,"Invalid conditional expression\n");
> > +                               return -1;
> > +                       }
> > +                       depth--;
> > +                       break;
> > +               default:
> > +                       cil_log(CIL_ERR,"Invalid conditional expression\n");
> > +                       return -1;
> > +               }
> > +       }
>
> Missing a return here.
> ../cil/src/cil_binary.c: In function ‘__cil_validate_cond_expr’:
> ../cil/src/cil_binary.c:2215:1: error: control reaches end of non-void
> function [-Werror=return-type]
>  2215 | }
>       | ^

Thanks, V2 coming up.
Jim
diff mbox series

Patch

diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 77266858..d30233c4 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -2176,6 +2176,44 @@  static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_e
 	return SEPOL_OK;
 }
 
+int __cil_validate_cond_expr(cond_expr_t *cond_expr)
+{
+	cond_expr_t *e;
+	int depth = -1;
+
+	for (e = cond_expr; e != NULL; e = e->next) {
+		switch (e->expr_type) {
+		case COND_BOOL:
+			if (depth == (COND_EXPR_MAXDEPTH - 1)) {
+				cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n");
+				return -1;
+			}
+			depth++;
+			break;
+		case COND_NOT:
+			if (depth < 0) {
+				cil_log(CIL_ERR,"Invalid conditional expression\n");
+				return -1;
+			}
+			break;
+		case COND_OR:
+		case COND_AND:
+		case COND_XOR:
+		case COND_EQ:
+		case COND_NEQ:
+			if (depth < 1) {
+				cil_log(CIL_ERR,"Invalid conditional expression\n");
+				return -1;
+			}
+			depth--;
+			break;
+		default:
+			cil_log(CIL_ERR,"Invalid conditional expression\n");
+			return -1;
+		}
+	}
+}
+
 int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node)
 {
 	int rc = SEPOL_ERR;
@@ -2204,6 +2242,11 @@  int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
 		goto exit;
 	}
 
+	rc = __cil_validate_cond_expr(tmp_cond->expr);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
 	tmp_cond->true_list = &tmp_cl;
 
 	rc = cond_normalize_expr(pdb, tmp_cond);
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 60ecaaff..f1d5dcca 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -2548,18 +2548,13 @@  static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
 	else return CIL_NONE;
 }
 
-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth);
+static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr);
 
-static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
+static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
 {
 	int rc = SEPOL_ERR;
 	enum cil_flavor op;
 
-	if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) {
-		cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH);
-		goto exit;
-	}
-
 	op = __cil_get_expr_operator_flavor(current->data);
 
 	rc = cil_verify_expr_syntax(current, op, flavor);
@@ -2572,26 +2567,20 @@  static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor
 		current = current->next;
 	}
 
-	if (op == CIL_NONE || op == CIL_ALL) {
-		(*depth)++;
-	}
-
 	for (;current != NULL; current = current->next) {
-		rc = __cil_fill_expr(current, flavor, expr, depth);
+		rc = __cil_fill_expr(current, flavor, expr);
 		if (rc != SEPOL_OK) {
 			goto exit;
 		}
 	}
 
-	(*depth)--;
-
 	return SEPOL_OK;
 
 exit:
 	return rc;
 }
 
-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
+static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
 {
 	int rc = SEPOL_ERR;
 
@@ -2605,7 +2594,7 @@  static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor
 	} else {
 		struct cil_list *sub_expr;
 		cil_list_init(&sub_expr, flavor);
-		rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth);
+		rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
 		if (rc != SEPOL_OK) {
 			cil_list_destroy(&sub_expr, CIL_TRUE);
 			goto exit;
@@ -2623,14 +2612,13 @@  exit:
 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
 {
 	int rc = SEPOL_ERR;
-	int depth = 0;
 
 	cil_list_init(expr, flavor);
 
 	if (current->cl_head == NULL) {
-		rc = __cil_fill_expr(current, flavor, *expr, &depth);
+		rc = __cil_fill_expr(current, flavor, *expr);
 	} else {
-		rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth);
+		rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
 	}
 
 	if (rc != SEPOL_OK) {