From: James Carter <jwcart2@xxxxxxxxxxxxx> Nicolass Iooss reports: OSS-Fuzz found an integer overflow when compiling the following (empty) CIL policy: ;;*lms 2147483647 a ; (empty line) Change hll_lineno to uint32_t which is the type of the field hll_line in struct cil_tree_node where the line number will be stored eventually. Read the line number into an unsigned long variable using strtoul() instead of strtol(). On systems where ULONG_MAX > UINT32_MAX, set the value to 0 and print a warning if it is larger than UINT32_MAX before storing it in hll_lineno. Also change hll_expand to uint32_t, since its value will be either 0 or 1 and there is no need for it to be signed. Reported-by: Nicolass Iooss <nicolas.iooss@xxxxxxx> Signed-off-by: James Carter <jwcart2@xxxxxxxxx> --- libsepol/cil/src/cil_parser.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c index b62043b9..9d3bd580 100644 --- a/libsepol/cil/src/cil_parser.c +++ b/libsepol/cil/src/cil_parser.c @@ -46,11 +46,11 @@ char *CIL_KEY_HLL_LMX; char *CIL_KEY_HLL_LME; struct hll_info { - int hll_lineno; - int hll_expand; + uint32_t hll_lineno; + uint32_t hll_expand; }; -static void push_hll_info(struct cil_stack *stack, int hll_lineno, int hll_expand) +static void push_hll_info(struct cil_stack *stack, uint32_t hll_lineno, uint32_t hll_expand) { struct hll_info *new = cil_malloc(sizeof(*new)); @@ -60,7 +60,7 @@ static void push_hll_info(struct cil_stack *stack, int hll_lineno, int hll_expan cil_stack_push(stack, CIL_NONE, new); } -static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expand) +static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_lineno, uint32_t *hll_expand) { struct cil_stack_item *curr = cil_stack_pop(stack); struct cil_stack_item *prev = cil_stack_peek(stack); @@ -69,8 +69,8 @@ static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expa free(curr->data); if (!prev) { - *hll_lineno = -1; - *hll_expand = -1; + *hll_lineno = 0; + *hll_expand = 0; } else { old = prev->data; *hll_lineno = old->hll_lineno; @@ -78,7 +78,7 @@ static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expa } } -static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, int line, int hll_line, void *value) +static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_line, void *value) { cil_tree_node_init(node); (*node)->parent = current; @@ -98,13 +98,14 @@ 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, int *hll_lineno, int *hll_expand, struct cil_stack *stack, char *path) +static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno, uint32_t *hll_expand, struct cil_stack *stack, char *path) { char *hll_type; struct cil_tree_node *node; struct token tok; char *hll_file; char *end = NULL; + unsigned long val; cil_lexer_next(&tok); hll_type = cil_strpool_add(tok.value); @@ -140,11 +141,19 @@ static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } - *hll_lineno = strtol(tok.value, &end, 10); + + val = strtoul(tok.value, &end, 10); if (errno == ERANGE || *end != '\0') { cil_log(CIL_ERR, "Problem parsing line number for line mark\n"); goto exit; } +#if ULONG_MAX > UINT32_MAX + if (val > UINT32_MAX) { + cil_log(CIL_WARN, "Line mark line number > UINT32_MAX\n"); + val = 0; + } +#endif + *hll_lineno = val; push_hll_info(stack, *hll_lineno, *hll_expand); @@ -206,8 +215,8 @@ 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; - int hll_lineno = -1; - int hll_expand = -1; + uint32_t hll_lineno = 0; + uint32_t hll_expand = 0; struct token tok; int rc = SEPOL_OK; -- 2.26.2