summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Jallot <ejallot@gmail.com>2019-11-29 15:30:39 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2019-12-02 19:25:22 +0100
commit8a9f48515fb8f9aed0af04e05f4528aa0e32116f (patch)
treec7bf904765079ebef3162d15819b6751b3a495b8
parenta48c1c00b5419fb39af87a22469f77322dc71b31 (diff)
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 <ejallot@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/scanner.l21
-rwxr-xr-xtests/shell/testcases/include/0016maxdepth_08
2 files changed, 17 insertions, 12 deletions
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);
diff --git a/tests/shell/testcases/include/0016maxdepth_0 b/tests/shell/testcases/include/0016maxdepth_0
new file mode 100755
index 00000000..89eb13c4
--- /dev/null
+++ b/tests/shell/testcases/include/0016maxdepth_0
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+
+tmpfile=$(mktemp)
+
+echo 'include "/tmp/rules.nft"' > $tmpfile
+$NFT -f $tmpfile || exit 0