[PATCH] libsepol/cil: Fix integer overflow in the handling of hll line marks

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

 



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




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

  Powered by Linux