Re: [PATCH] libsepol/cil: Allow duplicate optional blocks in most cases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jun 23, 2021 at 4:05 PM Nicolas Iooss <nicolas.iooss@xxxxxxx> wrote:
>
> On Thu, Jun 17, 2021 at 7:43 PM James Carter <jwcart2@xxxxxxxxx> wrote:
> >
> > The commit d155b410d4bbc90d28f361b966f0429598da8188 (libsepol/cil:
> > Check for duplicate blocks, optionals, and macros) fixed a bug
> > that allowed duplicate blocks, optionals, and macros with the same
> > name in the same namespace. For blocks and macros, a duplicate
> > is always a problem, but optional block names are only used for
> > in-statement resolution. If no in-statement refers to an optional
> > block, then it does not matter if more than one with same name
> > exists.
> >
> > One easy way to generate multiple optional blocks with the same
> > name declaration is to call a macro with an optional block multiple
> > times in the same namespace.
> >
> > As an example, here is a portion of CIL policy
> >   (macro m1 ((type t))
> >     (optional op1
> >       (allow t self (CLASS (PERM)))
> >     )
> >   )
> >   (type t1)
> >   (call m1 (t1))
> >   (type t2)
> >   (call m1 (t2))
> > This will result in two optional blocks with the name op1.
> >
> > There are three parts to allowing multiple optional blocks with
> > the same name declaration.
> >
> > 1) Track an optional block's enabled status in a different way.
> >
> >    One hinderance to allowing multiple optional blocks with the same
> >    name declaration is that they cannot share the same datum. This is
> >    because the datum is used to get the struct cil_optional which has
> >    the enabled field and each block's enabled status is independent of
> >    the others.
> >
> >    Remove the enabled field from struct cil_optional, so it only contains
> >    the datum. Use a stack to track which optional blocks are being
> >    disabled, so they can be deleted in the right order.
> >
> > 2) Allow multiple declarations of optional blocks.
> >
> >    Update cil_allow_multiple_decls() so that a flavor of CIL_OPTIONAL
> >    will return CIL_TRUE. Also remove the check in cil_copy_optional().
> >
> > 3) Check if an in-statement refers to an optional with multiple
> >    declarations and exit with an error if it does.
> >
> > Signed-off-by: James Carter <jwcart2@xxxxxxxxx>
>
> Hello,
>
> This patch looks good to me, even though it conflicts with the pending
> patch "libsepol/cil: Improve degenerate inheritance check" in
> libsepol/cil/src/cil_resolve_ast.c:
>
> ++<<<<<<< HEAD
>  +      struct cil_stack *disabled_optionals;
> ++=======
> +       int *inheritance_check;
> ++>>>>>>> c8dde7093e4a (libsepol/cil: Improve degenerate inheritance check)
> ...
> ++<<<<<<< HEAD
>  +      extra_args.disabled_optionals = NULL;
> ++=======
> +       extra_args.inheritance_check = &inheritance_check;
> ++>>>>>>> c8dde7093e4a (libsepol/cil: Improve degenerate inheritance check)
>
> I guess both additions need to be kept when merging both patches
>
> Acked-by: Nicolas Iooss <nicolas.iooss@xxxxxxx>
>

Yes, I will have to resolve that conflict when I merge them.
Thanks for the review,
Jim

> > ---
> >  libsepol/cil/src/cil.c             |  1 -
> >  libsepol/cil/src/cil_build_ast.c   |  3 ++
> >  libsepol/cil/src/cil_copy_ast.c    | 11 +-----
> >  libsepol/cil/src/cil_internal.h    |  1 -
> >  libsepol/cil/src/cil_resolve_ast.c | 55 ++++++++++++++++++------------
> >  5 files changed, 37 insertions(+), 34 deletions(-)
> >
> > diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> > index 0d351b49..671b5ec6 100644
> > --- a/libsepol/cil/src/cil.c
> > +++ b/libsepol/cil/src/cil.c
> > @@ -2752,7 +2752,6 @@ void cil_call_init(struct cil_call **call)
> >  void cil_optional_init(struct cil_optional **optional)
> >  {
> >         *optional = cil_malloc(sizeof(**optional));
> > -       (*optional)->enabled = CIL_TRUE;
> >         cil_symtab_datum_init(&(*optional)->datum);
> >  }
> >
> > diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> > index 71f14e20..2c72accc 100644
> > --- a/libsepol/cil/src/cil_build_ast.c
> > +++ b/libsepol/cil/src/cil_build_ast.c
> > @@ -96,6 +96,9 @@ static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, en
> >                         return CIL_TRUE;
> >                 }
> >                 break;
> > +       case CIL_OPTIONAL:
> > +               return CIL_TRUE;
> > +               break;
> >         default:
> >                 break;
> >         }
> > diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
> > index 954eab33..9c0231f2 100644
> > --- a/libsepol/cil/src/cil_copy_ast.c
> > +++ b/libsepol/cil/src/cil_copy_ast.c
> > @@ -1529,19 +1529,10 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void *
> >         return SEPOL_OK;
> >  }
> >
> > -int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
> > +int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
> >  {
> > -       struct cil_optional *orig = data;
> > -       char *key = orig->datum.name;
> > -       struct cil_symtab_datum *datum = NULL;
> >         struct cil_optional *new;
> >
> > -       cil_symtab_get_datum(symtab, key, &datum);
> > -       if (datum != NULL) {
> > -               cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key);
> > -               return SEPOL_ERR;
> > -       }
> > -
> >         cil_optional_init(&new);
> >         *copy = new;
> >
> > diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> > index a77c9520..24be09aa 100644
> > --- a/libsepol/cil/src/cil_internal.h
> > +++ b/libsepol/cil/src/cil_internal.h
> > @@ -358,7 +358,6 @@ struct cil_in {
> >
> >  struct cil_optional {
> >         struct cil_symtab_datum datum;
> > -       int enabled;
> >  };
> >
> >  struct cil_perm {
> > diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> > index 77ffe0ff..62e0e013 100644
> > --- a/libsepol/cil/src/cil_resolve_ast.c
> > +++ b/libsepol/cil/src/cil_resolve_ast.c
> > @@ -46,12 +46,13 @@
> >  #include "cil_verify.h"
> >  #include "cil_strpool.h"
> >  #include "cil_symtab.h"
> > +#include "cil_stack.h"
> >
> >  struct cil_args_resolve {
> >         struct cil_db *db;
> >         enum cil_pass pass;
> >         uint32_t *changed;
> > -       struct cil_list *disabled_optionals;
> > +       struct cil_list *to_destroy;
> >         struct cil_tree_node *block;
> >         struct cil_tree_node *macro;
> >         struct cil_tree_node *optional;
> > @@ -62,6 +63,7 @@ struct cil_args_resolve {
> >         struct cil_list *catorder_lists;
> >         struct cil_list *sensitivityorder_lists;
> >         struct cil_list *in_list;
> > +       struct cil_stack *disabled_optionals;
> >  };
> >
> >  static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
> > @@ -2552,6 +2554,15 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args)
> >
> >         block_node = NODE(block_datum);
> >
> > +       if (block_node->flavor == CIL_OPTIONAL) {
> > +               if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) {
> > +                       cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement");
> > +                       cil_tree_log(block_node, CIL_ERR, "First optional block");
> > +                       rc = SEPOL_ERR;
> > +                       goto exit;
> > +               }
> > +       }
> > +
> >         rc = cil_copy_ast(db, current, block_node);
> >         if (rc != SEPOL_OK) {
> >                 cil_tree_log(current, CIL_ERR, "Failed to copy in-statement");
> > @@ -3867,6 +3878,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
> >         struct cil_tree_node *macro = args->macro;
> >         struct cil_tree_node *optional = args->optional;
> >         struct cil_tree_node *boolif = args->boolif;
> > +       struct cil_stack *disabled_optionals = args->disabled_optionals;
> >
> >         if (node == NULL) {
> >                 goto exit;
> > @@ -3946,22 +3958,14 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
> >
> >         rc = __cil_resolve_ast_node(node, extra_args);
> >         if (rc == SEPOL_ENOENT) {
> > -               enum cil_log_level lvl = CIL_ERR;
> > -
> > -               if (optional != NULL) {
> > -                       lvl = CIL_INFO;
> > -
> > -                       struct cil_optional *opt = (struct cil_optional *)optional->data;
> > -                       struct cil_tree_node *opt_node = NODE(opt);;
> > -                       /* disable an optional if something failed to resolve */
> > -                       opt->enabled = CIL_FALSE;
> > -                       cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
> > -                       cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name);
> > +               if (optional == NULL) {
> > +                       cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node));
> > +               } else {
> > +                       cil_stack_push(disabled_optionals, CIL_NODE, optional);
> > +                       cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node));
> > +                       cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name);
> >                         rc = SEPOL_OK;
> > -                       goto exit;
> >                 }
> > -
> > -               cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
> >                 goto exit;
> >         }
> >
> > @@ -4004,6 +4008,7 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
> >  {
> >         int rc = SEPOL_ERR;
> >         struct cil_args_resolve *args = extra_args;
> > +       struct cil_stack *disabled_optionals = args->disabled_optionals;
> >         struct cil_tree_node *parent = NULL;
> >
> >         if (current == NULL ||  extra_args == NULL) {
> > @@ -4026,9 +4031,11 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
> >                 args->macro = NULL;
> >         } else if (parent->flavor == CIL_OPTIONAL) {
> >                 struct cil_tree_node *n = parent->parent;
> > -               if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
> > +               struct cil_stack_item *item = cil_stack_peek(disabled_optionals);
> > +               if (item && item->data == parent) {
> > +                       cil_stack_pop(disabled_optionals);
> >                         *(args->changed) = CIL_TRUE;
> > -                       cil_list_append(args->disabled_optionals, CIL_NODE, parent);
> > +                       cil_list_append(args->to_destroy, CIL_NODE, parent);
> >                 }
> >                 args->optional = NULL;
> >                 while (n && n->flavor != CIL_ROOT) {
> > @@ -4072,14 +4079,17 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
> >         extra_args.catorder_lists = NULL;
> >         extra_args.sensitivityorder_lists = NULL;
> >         extra_args.in_list = NULL;
> > +       extra_args.disabled_optionals = NULL;
> >
> > -       cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
> > +       cil_list_init(&extra_args.to_destroy, CIL_NODE);
> >         cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
> >         cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
> >         cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
> >         cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
> >         cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
> >         cil_list_init(&extra_args.in_list, CIL_IN);
> > +       cil_stack_init(&extra_args.disabled_optionals);
> > +
> >         for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) {
> >                 extra_args.pass = pass;
> >                 rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args);
> > @@ -4172,11 +4182,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
> >                                         goto exit;
> >                                 }
> >                         }
> > -                       cil_list_for_each(item, extra_args.disabled_optionals) {
> > +                       cil_list_for_each(item, extra_args.to_destroy) {
> >                                 cil_tree_children_destroy(item->data);
> >                         }
> > -                       cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
> > -                       cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
> > +                       cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
> > +                       cil_list_init(&extra_args.to_destroy, CIL_NODE);
> >                         changed = 0;
> >                 }
> >         }
> > @@ -4193,8 +4203,9 @@ exit:
> >         __cil_ordered_lists_destroy(&extra_args.catorder_lists);
> >         __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
> >         __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists);
> > -       cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
> > +       cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
> >         cil_list_destroy(&extra_args.in_list, CIL_FALSE);
> > +       cil_stack_destroy(&extra_args.disabled_optionals);
> >
> >         return rc;
> >  }
> > --
> > 2.26.3
> >
>



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux