A recent commit adds base directory of -f/--filename to include paths by default to address a silly use of -I/--include to make this work: # nft -I /path/to -f /path/to/main.nft instead users can simply invoke: # nft -f /path/to/main.nft because /path/to/ is added at the end of the list of include paths. This example above assumes main.nft includes more files that are contained in /path/to/. However, globbing can cause duplicates after this recent update, eg. # cat test/main table inet test { chain test { include "include/*"; } } # nft -I /tmp/test/ -f test/main because /tmp/test and test/ twice refer to the same directory and both are added to the list of include path. Use realpath() to canonicalize include paths. Then, search and skip duplicated include paths. Fixes: 302e9f8b3a13 ("libnftables: add base directory of -f/--filename to include path") Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- src/libnftables.c | 29 +++++++++++++++++-- .../include/dumps/glob_duplicated_include.nft | 6 ++++ .../testcases/include/glob_duplicated_include | 19 ++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 tests/shell/testcases/include/dumps/glob_duplicated_include.nft create mode 100755 tests/shell/testcases/include/glob_duplicated_include diff --git a/src/libnftables.c b/src/libnftables.c index 1df22b3cb57d..c8293f77677f 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -167,8 +167,19 @@ void nft_ctx_clear_vars(struct nft_ctx *ctx) ctx->vars = NULL; } -EXPORT_SYMBOL(nft_ctx_add_include_path); -int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path) +static bool nft_ctx_find_include_path(struct nft_ctx *ctx, const char *path) +{ + unsigned int i; + + for (i = 0; i < ctx->num_include_paths; i++) { + if (!strcmp(ctx->include_paths[i], path)) + return true; + } + + return false; +} + +static int __nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path) { char **tmp; int pcount = ctx->num_include_paths; @@ -184,6 +195,20 @@ int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path) return 0; } +EXPORT_SYMBOL(nft_ctx_add_include_path); +int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path) +{ + char canonical_path[PATH_MAX]; + + if (!realpath(path, canonical_path)) + return -1; + + if (nft_ctx_find_include_path(ctx, canonical_path)) + return 0; + + return __nft_ctx_add_include_path(ctx, canonical_path); +} + EXPORT_SYMBOL(nft_ctx_clear_include_paths); void nft_ctx_clear_include_paths(struct nft_ctx *ctx) { diff --git a/tests/shell/testcases/include/dumps/glob_duplicated_include.nft b/tests/shell/testcases/include/dumps/glob_duplicated_include.nft new file mode 100644 index 000000000000..8e316e9dfa49 --- /dev/null +++ b/tests/shell/testcases/include/dumps/glob_duplicated_include.nft @@ -0,0 +1,6 @@ +table inet test { + chain test { + tcp dport 22 accept + tcp dport 25 accept + } +} diff --git a/tests/shell/testcases/include/glob_duplicated_include b/tests/shell/testcases/include/glob_duplicated_include new file mode 100755 index 000000000000..4507f5d937e0 --- /dev/null +++ b/tests/shell/testcases/include/glob_duplicated_include @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +trap "rm -rf $tmpdir" EXIT + +tmpdir=$(mktemp -d) +mkdir -p $tmpdir/test/include +cat > $tmpdir/test/main << EOF +table inet test { + chain test { + include "include/*"; + } +} +EOF +echo "tcp dport 22 accept;" > $tmpdir/test/include/one +echo "tcp dport 25 accept;" > $tmpdir/test/include/two + +$NFT -I $tmpdir/test/ -f $tmpdir/test/main -- 2.30.2