From patchwork Wed Jan 16 18:46:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 1026115 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nwl.cc Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43fx4d1lKdz9s2P for ; Thu, 17 Jan 2019 05:46:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728989AbfAPSqY (ORCPT ); Wed, 16 Jan 2019 13:46:24 -0500 Received: from orbyte.nwl.cc ([151.80.46.58]:55680 "EHLO orbyte.nwl.cc" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728621AbfAPSqY (ORCPT ); Wed, 16 Jan 2019 13:46:24 -0500 Received: from localhost ([::1]:40538 helo=tatos) by orbyte.nwl.cc with esmtp (Exim 4.91) (envelope-from ) id 1gjqCk-00018y-AR; Wed, 16 Jan 2019 19:46:22 +0100 From: Phil Sutter To: Pablo Neira Ayuso Cc: netfilter-devel@vger.kernel.org Subject: [nft PATCH] src: Quote user-defined names Date: Wed, 16 Jan 2019 19:46:13 +0100 Message-Id: <20190116184613.31698-1-phil@nwl.cc> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Nftables claims to allow arbitrary names for ruleset elements (tables, chains, objects) but suffers from the known problem of lex/yacc trying to interpret those as keywords. As a workaround, users may quote their names. Sadly this wasn't supported in most cases and this patch lifts this restriction. In order to not print rulesets which are not accepted anymore by 'nft -f' command, unconditionally quote all names on output. Note that the same problem existed for interface names. I've tested for those to work in both netdev family chains and flowtable definitions, though automatic testing is troublesome since they must exist (and I'm not sure if test scripts should call iproute2 to add an interface with a crafted name). Signed-off-by: Phil Sutter Acked-by: Florian Westphal --- src/parser_bison.y | 3 +- src/rule.c | 28 +++++++++---------- .../shell/testcases/nft-f/0018quoted-names_0 | 19 +++++++++++++ 3 files changed, 35 insertions(+), 15 deletions(-) create mode 100755 tests/shell/testcases/nft-f/0018quoted-names_0 diff --git a/src/parser_bison.y b/src/parser_bison.y index 02a373cb2289a..fb9b0fcf89baf 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1782,7 +1782,7 @@ flowtable_list_expr : flowtable_expr_member | flowtable_list_expr COMMA opt_newline ; -flowtable_expr_member : STRING +flowtable_expr_member : string { $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE, current_scope(state), @@ -1989,6 +1989,7 @@ chain_policy : ACCEPT { $$ = NF_ACCEPT; } ; identifier : STRING + | QUOTED_STRING ; string : STRING diff --git a/src/rule.c b/src/rule.c index 73b78c75a267a..f845b5d097c3a 100644 --- a/src/rule.c +++ b/src/rule.c @@ -433,9 +433,9 @@ static void set_print_declaration(const struct set *set, nft_print(octx, " %s", opts->family); if (opts->table != NULL) - nft_print(octx, " %s", opts->table); + nft_print(octx, " \"%s\"", opts->table); - nft_print(octx, " %s {", set->handle.set.name); + nft_print(octx, " \"%s\" {", set->handle.set.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, set->handle.handle.id); @@ -1062,7 +1062,7 @@ static void chain_print_declaration(const struct chain *chain, { char priobuf[STD_PRIO_BUFSIZE]; - nft_print(octx, "\tchain %s {", chain->handle.chain.name); + nft_print(octx, "\tchain \"%s\" {", chain->handle.chain.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, chain->handle.handle.id); nft_print(octx, "\n"); @@ -1222,7 +1222,7 @@ static void table_print(const struct table *table, struct output_ctx *octx) const char *delim = ""; const char *family = family2str(table->handle.family); - nft_print(octx, "table %s %s {", family, table->handle.table.name); + nft_print(octx, "table %s \"%s\" {", family, table->handle.table.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, table->handle.handle.id); nft_print(octx, "\n"); @@ -1748,7 +1748,7 @@ static void obj_print_data(const struct obj *obj, { switch (obj->type) { case NFT_OBJECT_COUNTER: - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); @@ -1763,7 +1763,7 @@ static void obj_print_data(const struct obj *obj, const char *data_unit; uint64_t bytes; - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); @@ -1780,14 +1780,14 @@ static void obj_print_data(const struct obj *obj, } break; case NFT_OBJECT_SECMARK: - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); nft_print(octx, "%s", obj->secmark.ctx); break; case NFT_OBJECT_CT_HELPER: - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s", opts->nl); @@ -1801,7 +1801,7 @@ static void obj_print_data(const struct obj *obj, opts->stmt_separator); break; case NFT_OBJECT_CT_TIMEOUT: - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s", opts->nl); @@ -1820,7 +1820,7 @@ static void obj_print_data(const struct obj *obj, const char *data_unit; uint64_t rate; - nft_print(octx, " %s {", obj->handle.obj.name); + nft_print(octx, " \"%s\" {", obj->handle.obj.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); @@ -1899,7 +1899,7 @@ static void obj_print_declaration(const struct obj *obj, nft_print(octx, " %s", opts->family); if (opts->table != NULL) - nft_print(octx, " %s", opts->table); + nft_print(octx, " \"%s\"", opts->table); obj_print_data(obj, opts, octx); @@ -2015,9 +2015,9 @@ static void flowtable_print_declaration(const struct flowtable *flowtable, nft_print(octx, " %s", opts->family); if (opts->table != NULL) - nft_print(octx, " %s", opts->table); + nft_print(octx, " \"%s\"", opts->table); - nft_print(octx, " %s {%s", flowtable->handle.flowtable, opts->nl); + nft_print(octx, " \"%s\" {%s", flowtable->handle.flowtable, opts->nl); nft_print(octx, "%s%shook %s priority %s%s", opts->tab, opts->tab, @@ -2028,7 +2028,7 @@ static void flowtable_print_declaration(const struct flowtable *flowtable, nft_print(octx, "%s%sdevices = { ", opts->tab, opts->tab); for (i = 0; i < flowtable->dev_array_len; i++) { - nft_print(octx, "%s", flowtable->dev_array[i]); + nft_print(octx, "\"%s\"", flowtable->dev_array[i]); if (i + 1 != flowtable->dev_array_len) nft_print(octx, ", "); } diff --git a/tests/shell/testcases/nft-f/0018quoted-names_0 b/tests/shell/testcases/nft-f/0018quoted-names_0 new file mode 100755 index 0000000000000..9655a48d492c0 --- /dev/null +++ b/tests/shell/testcases/nft-f/0018quoted-names_0 @@ -0,0 +1,19 @@ +#!/bin/bash + +# Test if keywords are allowed as names if quoted + +set -e + +# XXX: interface names are arbitrary, too (flowtable, chain) +RULESET=' +table inet "day" { + chain "minute" {} + set "hour" { type inet_service; } + flowtable "second" { hook ingress priority 0; devices = { lo }; } + counter "table" { packets 0 bytes 0 } + quota "chain" { 10 bytes } +}' + +$NFT -f - <<< "$RULESET" +OUTPUT=$($NFT list ruleset) +$NFT -f - <<< "$OUTPUT"