From 8a9f48515fb8f9aed0af04e05f4528aa0e32116f Mon Sep 17 00:00:00 2001 From: Eric Jallot Date: Fri, 29 Nov 2019 15:30:39 +0100 Subject: scanner: fix out-of-bound memory write in include_file() 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 Signed-off-by: Pablo Neira Ayuso --- src/scanner.l | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'src/scanner.l') diff --git a/src/scanner.l b/src/scanner.l index 80b5a5f0..d32adf48 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); -- cgit v1.2.3