[PATCH v2 nft] scanner: fix out-of-bound memory write in include_file()

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

 



Before patch:
 # echo 'include "/tmp/rules.nft"' > /tmp/rules.nft
 # nft -f /tmp/rules.nft
 In file included from /tmp/rules.nft:1:1-25:
                  from /tmp/rules.nft:1:1-25:
 [snip]
                  from /tmp/rules.nft:1:1-25:
 /tmp/rules.nft:1:1-25: Error: Include nested too deeply, max 16 levels
 include "/tmp/rules.nft"
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 double free or corruption (out)
 Aborted (core dumped)

valgrind reports:

==8856== Invalid write of size 8
==8856==    at 0x4E8FCAF: include_file (scanner.l:718)
==8856==    by 0x4E8FEF6: include_glob (scanner.l:793)
==8856==    by 0x4E9985D: scanner_include_file (scanner.l:875)
==8856==    by 0x4E89D7A: nft_parse (parser_bison.y:828)
==8856==    by 0x4E765E1: nft_parse_bison_filename (libnftables.c:394)
==8856==    by 0x4E765E1: nft_run_cmd_from_filename (libnftables.c:497)
==8856==    by 0x40172D: main (main.c:340)

So perform bounds checking on MAX_INCLUDE_DEPTH before writing.

After patch:
 # nft -f /tmp/rules.nft
 In file included from /tmp/rules.nft:1:1-25:
                  from /tmp/rules.nft:1:1-25:
 [snip]
                  from /tmp/rules.nft:1:1-25:
 /tmp/rules.nft:1:1-25: Error: Include nested too deeply, max 16 levels
 include "/tmp/rules.nft"
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 # echo $?
 1

Also:
Update scanner_push_file() function definition accordingly.

Fixes: 32325e3c3fab4 ("libnftables: Store top_scope in struct nft_ctx")
Signed-off-by: Eric Jallot <ejallot@xxxxxxxxx>
---
 src/scanner.l | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/scanner.l b/src/scanner.l
index 80b5a5f0dafc..d32adf4897ae 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -672,17 +672,13 @@ static void scanner_pop_buffer(yyscan_t scanner)
 	state->indesc = state->indescs[--state->indesc_idx];
 }
 
-static struct error_record *scanner_push_file(struct nft_ctx *nft, void *scanner,
-					      const char *filename, const struct location *loc)
+static void scanner_push_file(struct nft_ctx *nft, void *scanner,
+			      const char *filename, const struct location *loc)
 {
 	struct parser_state *state = yyget_extra(scanner);
 	struct input_descriptor *indesc;
 	YY_BUFFER_STATE b;
 
-	if (state->indesc_idx == MAX_INCLUDE_DEPTH)
-		return error(loc, "Include nested too deeply, max %u levels",
-			     MAX_INCLUDE_DEPTH);
-
 	b = yy_create_buffer(nft->f[state->indesc_idx], YY_BUF_SIZE, scanner);
 	yypush_buffer_state(b, scanner);
 
@@ -697,8 +693,6 @@ static struct error_record *scanner_push_file(struct nft_ctx *nft, void *scanner
 	state->indescs[state->indesc_idx] = indesc;
 	state->indesc = state->indescs[state->indesc_idx++];
 	list_add_tail(&indesc->list, &state->indesc_list);
-
-	return NULL;
 }
 
 static int include_file(struct nft_ctx *nft, void *scanner,
@@ -708,6 +702,12 @@ static int include_file(struct nft_ctx *nft, void *scanner,
 	struct error_record *erec;
 	FILE *f;
 
+	if (state->indesc_idx == MAX_INCLUDE_DEPTH) {
+		erec = error(loc, "Include nested too deeply, max %u levels",
+			     MAX_INCLUDE_DEPTH);
+		goto err;
+	}
+
 	f = fopen(filename, "r");
 	if (f == NULL) {
 		erec = error(loc, "Could not open file \"%s\": %s\n",
@@ -715,10 +715,7 @@ static int include_file(struct nft_ctx *nft, void *scanner,
 		goto err;
 	}
 	nft->f[state->indesc_idx] = f;
-
-	erec = scanner_push_file(nft, scanner, filename, loc);
-	if (erec != NULL)
-		goto err;
+	scanner_push_file(nft, scanner, filename, loc);
 	return 0;
 err:
 	erec_queue(erec, state->msgs);
-- 
2.11.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux