Re: [PATCH 7/8] libsepol/cil: Report correct high-level language line numbers

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

 



On Tue, Aug 10, 2021 at 8:22 PM James Carter <jwcart2@xxxxxxxxx> wrote:
>
> CIL supports specifiying the original high-level language file and
> line numbers when reporting errors. This is done through line marks
> and is mostly used to report the original Refpolicy file and line
> number for neverallow rules that have been converted to CIL.
>
> As long as the line mark remain simple, everything works fine, but
> the wrong line numbers will be reported with more complex nextings
> of line marks.
>
> Example:
> ;;* lms 100 file01.hll
> (type t1a)
> (allow t1a self (CLASS (PERM)))
> ;;* lmx 200 file02.hll
> (type t2a)
> (allow t2a self (CLASS (PERM)))
> ;;* lme
> (type t1b)
> (allow t1b self (CLASS (PERM)))
> (allow bad1b self (CLASS (PERM))) ; file01.hll:101 (Should be 106)
> ;;* lme
>
> The primary problem is that the tree nodes can only store one hll
> line number. Instead a number is needed that can be used by any
> number of stacked line mark sections. This number would increment
> line a normal line number except when in lmx sections (that have
> the same line number throughout the section because they represent
> an expansion of a line -- like the expansion of a macro call. This
> number can go backwards when exiting a lms section within a lmx
> section, because line number will increase in the lms section, but
> outside the lmx section, the line number did not advance.
>
> This number is called the hll_offset and this is the value that is
> now stored in tree nodes instead of the hll line number. To calculate
> the hll line number for a rule, a search is made for an ancestor of
> the node that is a line mark and the line number for a lms section
> is the hll line number stored in the line mark, plus the hll offset
> of the rule, minus the hll offset of the line mark node, minus one.
> (hll_lineno + hll_offset_rule - hll_offset_lm - 1)
>
> Signed-off-by: James Carter <jwcart2@xxxxxxxxx>
> ---
>  libsepol/cil/src/cil_binary.c    |  9 ++--
>  libsepol/cil/src/cil_build_ast.c |  4 +-
>  libsepol/cil/src/cil_copy_ast.c  |  2 +-
>  libsepol/cil/src/cil_parser.c    | 74 +++++++++++++++++++-------------
>  libsepol/cil/src/cil_tree.c      | 53 +++++++++++++++--------
>  libsepol/cil/src/cil_tree.h      |  4 +-
>  6 files changed, 90 insertions(+), 56 deletions(-)
>
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index 2b65c622..43c37fc2 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -4480,7 +4480,8 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
>         avrule_t *avrule;
>         struct cil_tree_node *source_node;
>         char *source_path;
> -       int is_cil;
> +       char *lm_kind;
> +       uint32_t hll_line;
>
>         avrule = cil_malloc(sizeof(avrule_t));
>         avrule->specified = kind;
> @@ -4492,11 +4493,11 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
>
>         avrule->source_filename = NULL;
>         avrule->source_line = node->line;
> -       source_node = cil_tree_get_next_path(node, &source_path, &is_cil);
> +       source_node = cil_tree_get_next_path(node, &lm_kind, &hll_line, &source_path);
>         if (source_node) {
>                 avrule->source_filename = source_path;
> -               if (!is_cil) {
> -                       avrule->source_line = node->hll_line;
> +               if (lm_kind != CIL_KEY_SRC_CIL) {
> +                       avrule->source_line = hll_line + node->hll_offset - source_node->hll_offset - 1;
>                 }
>         }
>
> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> index a0f58b1e..a5afc267 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -619,7 +619,7 @@ int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, st
>                 cil_tree_node_init(&new_ast);
>                 new_ast->parent = ast_node;
>                 new_ast->line = current_perm->line;
> -               new_ast->hll_line = current_perm->hll_line;
> +               new_ast->hll_offset = current_perm->hll_offset;
>
>                 rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
>                 if (rc != SEPOL_OK) {
> @@ -6203,7 +6203,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
>
>         ast_node->parent = ast_current;
>         ast_node->line = parse_current->line;
> -       ast_node->hll_line = parse_current->hll_line;
> +       ast_node->hll_offset = parse_current->hll_offset;
>
>         if (parse_current->data == CIL_KEY_BLOCK) {
>                 rc = cil_gen_block(db, parse_current, ast_node, 0);
> diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
> index 02b9828f..34282a92 100644
> --- a/libsepol/cil/src/cil_copy_ast.c
> +++ b/libsepol/cil/src/cil_copy_ast.c
> @@ -2010,7 +2010,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
>
>                 new->parent = parent;
>                 new->line = orig->line;
> -               new->hll_line = orig->hll_line;
> +               new->hll_offset = orig->hll_offset;
>                 new->flavor = orig->flavor;
>                 new->data = data;
>
> diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c
> index 842c327c..3ccef5d7 100644
> --- a/libsepol/cil/src/cil_parser.c
> +++ b/libsepol/cil/src/cil_parser.c
> @@ -45,21 +45,21 @@
>  #define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12)
>
>  struct hll_info {
> -       uint32_t hll_lineno;
> +       uint32_t hll_offset;
>         uint32_t hll_expand;
>  };
>
> -static void push_hll_info(struct cil_stack *stack, uint32_t hll_lineno, uint32_t hll_expand)
> +static void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand)
>  {
>         struct hll_info *new = cil_malloc(sizeof(*new));
>
> -       new->hll_lineno = hll_lineno;
> +       new->hll_offset = hll_offset;
>         new->hll_expand = hll_expand;
>
>         cil_stack_push(stack, CIL_NONE, new);
>  }
>
> -static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_lineno, uint32_t *hll_expand)
> +static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand)
>  {
>         struct cil_stack_item *curr = cil_stack_pop(stack);
>         struct hll_info *info;
> @@ -69,17 +69,17 @@ static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_lineno, uint32_t
>         }
>         info = curr->data;
>         *hll_expand = info->hll_expand;
> -       *hll_lineno = info->hll_lineno;
> +       *hll_offset = info->hll_offset;
>         free(curr->data);
>  }
>
> -static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_line, void *value)
> +static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value)
>  {
>         cil_tree_node_init(node);
>         (*node)->parent = current;
>         (*node)->flavor = CIL_NODE;
>         (*node)->line = line;
> -       (*node)->hll_line = hll_line;
> +       (*node)->hll_offset = hll_offset;
>         (*node)->data = value;
>  }
>
> @@ -93,12 +93,12 @@ static void insert_node(struct cil_tree_node *node, struct cil_tree_node *curren
>         current->cl_tail = node;
>  }
>
> -static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno, uint32_t *hll_expand, struct cil_stack *stack, char *path)
> +static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path)
>  {
>         char *hll_type;
>         struct cil_tree_node *node;
>         struct token tok;
> -       int rc;
> +       uint32_t prev_hll_expand, prev_hll_offset;

In this function, gcc (in GitHub Actions CI) reports:

  ../cil/src/cil_parser.c: In function ‘cil_parser’:
  ../cil/src/cil_parser.c:181:16: error: ‘hll_offset’ may be used
uninitialized in this function [-Werror=maybe-uninitialized]
    181 |   (*hll_offset)++;
        |   ~~~~~~~~~~~~~^~
  ../cil/src/cil_parser.c:222:11: note: ‘hll_offset’ was declared here
    222 |  uint32_t hll_offset = 1;
        |           ^~~~~~~~~~

In fact the warning is misleading because it comes from
prev_hll_offset not being initialized and gcc having trouble figuring
out it is initialized in calls to pop_hll_info.

To silence this warning, could you initialize prev_hll_offset to some value?

>
>         cil_lexer_next(&tok);
>         if (tok.type != SYMBOL) {
> @@ -115,19 +115,33 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
>                         cil_log(CIL_ERR, "Line mark end without start\n");
>                         goto exit;
>                 }
> -               pop_hll_info(stack, hll_lineno, hll_expand);
> +               prev_hll_expand = *hll_expand;
> +               pop_hll_info(stack, &prev_hll_offset, hll_expand);
> +               if (*hll_expand) {
> +                       /* This is needed when exiting an lms section within an lmx section.
> +                        * In the lms section, hll_offset will increment and then revert
> +                        * back to its previous value when going back into the lmx section.
> +                        */
> +                       *hll_offset = prev_hll_offset;
> +               }
> +               if (prev_hll_expand && !*hll_expand) {
> +                       /* This is needed to count the lme at the end of an lmx section
> +                        * within an lms section (or within no hll section).
> +                        */
> +                       (*hll_offset)++;
> +               }
>                 *current = (*current)->parent;
>         } else {
> -               push_hll_info(stack, *hll_lineno, *hll_expand);
> +               push_hll_info(stack, *hll_offset, *hll_expand);
>
> -               create_node(&node, *current, tok.line, *hll_lineno, NULL);
> +               create_node(&node, *current, tok.line, *hll_offset, NULL);
>                 insert_node(node, *current);
>                 *current = node;
>
> -               create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO);
> +               create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO);
>                 insert_node(node, *current);
>
> -               create_node(&node, *current, tok.line, *hll_lineno, hll_type);
> +               create_node(&node, *current, tok.line, *hll_offset, hll_type);
>                 insert_node(node, *current);
>
>                 cil_lexer_next(&tok);
> @@ -136,16 +150,9 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
>                         goto exit;
>                 }
>
> -               create_node(&node, *current, tok.line, *hll_lineno, cil_strpool_add(tok.value));
> +               create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
>                 insert_node(node, *current);
>
> -               rc = cil_string_to_uint32(tok.value, hll_lineno, 10);
> -               if (rc != SEPOL_OK) {
> -                       goto exit;
> -               }
> -
> -               *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0;
> -
>                 cil_lexer_next(&tok);
>                 if (tok.type != SYMBOL && tok.type != QSTRING) {
>                         cil_log(CIL_ERR, "Invalid line mark syntax\n");
> @@ -157,8 +164,10 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
>                         tok.value = tok.value+1;
>                 }
>
> -               create_node(&node, *current, tok.line, *hll_lineno, cil_strpool_add(tok.value));
> +               create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
>                 insert_node(node, *current);
> +
> +               *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0;
>         }
>
>         cil_lexer_next(&tok);
> @@ -167,6 +176,11 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
>                 goto exit;
>         }
>
> +       if (!*hll_expand) {
> +               /* Need to increment because of the NEWLINE */
> +               (*hll_offset)++;
> +       }
> +
>         return SEPOL_OK;
>
>  exit:
> @@ -205,7 +219,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>         struct cil_tree_node *current = NULL;
>         char *path = cil_strpool_add(_path);
>         struct cil_stack *stack;
> -       uint32_t hll_lineno = 0;
> +       uint32_t hll_offset = 1;
>         uint32_t hll_expand = 0;
>         struct token tok;
>         int rc = SEPOL_OK;
> @@ -223,7 +237,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>                 cil_lexer_next(&tok);
>                 switch (tok.type) {
>                 case HLL_LINEMARK:
> -                       rc = add_hll_linemark(&current, &hll_lineno, &hll_expand, stack, path);
> +                       rc = add_hll_linemark(&current, &hll_offset, &hll_expand, stack, path);
>                         if (rc != SEPOL_OK) {
>                                 goto exit;
>                         }
> @@ -234,7 +248,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>                                 cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path);
>                                 goto exit;
>                         }
> -                       create_node(&node, current, tok.line, hll_lineno, NULL);
> +                       create_node(&node, current, tok.line, hll_offset, NULL);
>                         insert_node(node, current);
>                         current = node;
>                         break;
> @@ -256,12 +270,12 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>                                 goto exit;
>                         }
>
> -                       create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value));
> +                       create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value));
>                         insert_node(node, current);
>                         break;
>                 case NEWLINE :
>                         if (!hll_expand) {
> -                               hll_lineno++;
> +                               hll_offset++;
>                         }
>                         break;
>                 case COMMENT:
> @@ -269,7 +283,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>                                 cil_lexer_next(&tok);
>                         }
>                         if (!hll_expand) {
> -                               hll_lineno++;
> +                               hll_offset++;
>                         }
>                         if (tok.type != END_OF_FILE) {
>                                 break;
> @@ -306,7 +320,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
>
>  exit:
>         while (!cil_stack_is_empty(stack)) {
> -               pop_hll_info(stack, &hll_lineno, &hll_expand);
> +               pop_hll_info(stack, &hll_offset, &hll_expand);
>         }
>         cil_lexer_destroy();
>         cil_stack_destroy(&stack);
> diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
> index 52b28999..4fdf339d 100644
> --- a/libsepol/cil/src/cil_tree.c
> +++ b/libsepol/cil/src/cil_tree.c
> @@ -50,10 +50,12 @@ __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_e
>         exit(1);
>  }
>
> -struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil)
> +struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path)
>  {
> +       int rc;
> +
>         if (!node) {
> -               return NULL;
> +               goto exit;
>         }
>
>         node = node->parent;
> @@ -62,16 +64,21 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
>                 if (node->flavor == CIL_NODE && node->data == NULL) {
>                         if (node->cl_head->data == CIL_KEY_SRC_INFO && node->cl_head->next != NULL && node->cl_head->next->next != NULL) {
>                                 /* Parse Tree */
> -                               *path = node->cl_head->next->next->data;
> -                               *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
> +                               *info_kind = node->cl_head->next->data;
> +                               rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10);
> +                               if (rc != SEPOL_OK) {
> +                                       goto exit;
> +                               }
> +                               *path = node->cl_head->next->next->next->data;
>                                 return node;
>                         }
>                         node = node->parent;
>                 } else if (node->flavor == CIL_SRC_INFO) {
>                                 /* AST */
>                                 struct cil_src_info *info = node->data;
> +                               *info_kind = info->kind;
> +                               *hll_line = info->hll_line;
>                                 *path = info->path;
> -                               *is_cil = (info->kind == CIL_KEY_SRC_CIL);
>                                 return node;
>                 } else {
>                         if (node->flavor == CIL_CALL) {
> @@ -86,17 +93,22 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
>                 }
>         }
>
> +exit:
> +       *info_kind = NULL;
> +       *hll_line = 0;
> +       *path = NULL;
>         return NULL;
>  }
>
>  char *cil_tree_get_cil_path(struct cil_tree_node *node)
>  {
> -       char *path = NULL;
> -       int is_cil;
> +       char *info_kind;
> +       uint32_t hll_line;
> +       char *path;
>
>         while (node) {
> -               node = cil_tree_get_next_path(node, &path, &is_cil);
> -               if (node && is_cil) {
> +               node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
> +               if (node && info_kind == CIL_KEY_SRC_CIL) {
>                         return path;
>                 }
>         }
> @@ -114,8 +126,7 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n
>
>         if (node) {
>                 char *path = NULL;
> -               int is_cil;
> -               unsigned hll_line = node->hll_line;
> +               uint32_t hll_offset = node->hll_offset;
>
>                 path = cil_tree_get_cil_path(node);
>
> @@ -124,12 +135,20 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n
>                 }
>
>                 while (node) {
> -                       node = cil_tree_get_next_path(node, &path, &is_cil);
> -                       if (node && !is_cil) {
> +                       do {
> +                               char *info_kind;
> +                               uint32_t hll_line;
> +
> +                               node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
> +                               if (!node || info_kind == CIL_KEY_SRC_CIL) {
> +                                       break;
> +                               }
> +                               if (info_kind == CIL_KEY_SRC_HLL_LMS) {
> +                                       hll_line += hll_offset - node->hll_offset - 1;
> +                               }
> +
>                                 cil_log(lvl," from %s:%d", path, hll_line);

While modifying this code, it would be nice if this "%d" was modified
to "%u", as hll_line should never be negative.

> -                               path = NULL;
> -                               hll_line = node->hll_line;
> -                       }
> +                       } while (1);
>                 }
>         }
>
> @@ -222,7 +241,7 @@ void cil_tree_node_init(struct cil_tree_node **node)
>         new_node->next = NULL;
>         new_node->flavor = CIL_ROOT;
>         new_node->line = 0;
> -       new_node->hll_line = 0;
> +       new_node->hll_offset = 0;
>
>         *node = new_node;
>  }
> diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h
> index f4d22071..5a98da55 100644
> --- a/libsepol/cil/src/cil_tree.h
> +++ b/libsepol/cil/src/cil_tree.h
> @@ -46,11 +46,11 @@ struct cil_tree_node {
>         struct cil_tree_node *next;             //Each element in the list points to the next element
>         enum cil_flavor flavor;
>         uint32_t line;
> -       uint32_t hll_line;
> +       uint32_t hll_offset;
>         void *data;
>  };
>
> -struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil);
> +struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path);
>  char *cil_tree_get_cil_path(struct cil_tree_node *node);
>  __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...);
>
> --
> 2.31.1
>




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

  Powered by Linux