123 lines
4.2 KiB
Diff
123 lines
4.2 KiB
Diff
|
From 312ff073e117d6207c3ba304ca01532e723d6e54 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <psutter@redhat.com>
|
||
|
Date: Wed, 14 Aug 2024 14:23:33 +0200
|
||
|
Subject: [PATCH] nft: Fix for zeroing non-existent builtin chains
|
||
|
|
||
|
JIRA: https://issues.redhat.com/browse/RHEL-49497
|
||
|
Upstream Status: iptables commit f462975fb8049b9b565cb35cc98302331dbd1548
|
||
|
|
||
|
commit f462975fb8049b9b565cb35cc98302331dbd1548
|
||
|
Author: Phil Sutter <phil@nwl.cc>
|
||
|
Date: Tue Jul 16 21:07:31 2024 +0200
|
||
|
|
||
|
nft: Fix for zeroing non-existent builtin chains
|
||
|
|
||
|
Trying to zero a specific rule in an entirely empty ruleset caused an
|
||
|
error:
|
||
|
|
||
|
| # nft flush ruleset
|
||
|
| # iptables-nft -Z INPUT
|
||
|
| iptables v1.8.10 (nf_tables): CHAIN_ZERO failed (No such file or directory): chain INPUT
|
||
|
|
||
|
To fix this, start by faking any non-existing builtin chains so verbose
|
||
|
mode prints all the would-be-flushed chains. Later set 'skip' flag if
|
||
|
given chain is a fake one (indicated by missing HANDLE attribute).
|
||
|
Finally cover for concurrent ruleset updates by checking whether the
|
||
|
chain exists.
|
||
|
|
||
|
This bug seems to exist for a long time already, Fixes tag identified
|
||
|
via git-bisect. This patch won't apply to such old trees though, but
|
||
|
calling nft_xt_builtin_init() from nft_chain_zero_counters() should work
|
||
|
there.
|
||
|
|
||
|
Fixes: a6ce0c65d3a39 ("xtables: Optimize nft_chain_zero_counters()")
|
||
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||
|
|
||
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||
|
---
|
||
|
iptables/nft.c | 22 +++++++++++++++++--
|
||
|
.../nft-only/0013-zero-non-existent_0 | 17 ++++++++++++++
|
||
|
2 files changed, 37 insertions(+), 2 deletions(-)
|
||
|
create mode 100755 iptables/tests/shell/testcases/nft-only/0013-zero-non-existent_0
|
||
|
|
||
|
diff --git a/iptables/nft.c b/iptables/nft.c
|
||
|
index c4caf29..82eab48 100644
|
||
|
--- a/iptables/nft.c
|
||
|
+++ b/iptables/nft.c
|
||
|
@@ -3109,9 +3109,21 @@ static void nft_refresh_transaction(struct nft_handle *h)
|
||
|
break;
|
||
|
n->skip = !nft_may_delete_chain(n->chain);
|
||
|
break;
|
||
|
+ case NFT_COMPAT_CHAIN_ZERO:
|
||
|
+ tablename = nftnl_chain_get_str(n->chain, NFTNL_CHAIN_TABLE);
|
||
|
+ if (!tablename)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ chainname = nftnl_chain_get_str(n->chain, NFTNL_CHAIN_NAME);
|
||
|
+ if (!chainname)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ n->skip = nftnl_chain_is_set(n->chain,
|
||
|
+ NFTNL_CHAIN_HOOKNUM) &&
|
||
|
+ !nft_chain_find(h, tablename, chainname);
|
||
|
+ break;
|
||
|
case NFT_COMPAT_TABLE_ADD:
|
||
|
case NFT_COMPAT_CHAIN_ADD:
|
||
|
- case NFT_COMPAT_CHAIN_ZERO:
|
||
|
case NFT_COMPAT_CHAIN_USER_FLUSH:
|
||
|
case NFT_COMPAT_CHAIN_UPDATE:
|
||
|
case NFT_COMPAT_CHAIN_RENAME:
|
||
|
@@ -3748,6 +3760,7 @@ static int __nft_chain_zero_counters(struct nft_chain *nc, void *data)
|
||
|
struct nft_handle *h = d->handle;
|
||
|
struct nftnl_rule_iter *iter;
|
||
|
struct nftnl_rule *r;
|
||
|
+ struct obj_update *o;
|
||
|
|
||
|
if (d->verbose)
|
||
|
fprintf(stdout, "Zeroing chain `%s'\n",
|
||
|
@@ -3758,8 +3771,11 @@ static int __nft_chain_zero_counters(struct nft_chain *nc, void *data)
|
||
|
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
|
||
|
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
|
||
|
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
|
||
|
- if (!batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c))
|
||
|
+ o = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c);
|
||
|
+ if (!o)
|
||
|
return -1;
|
||
|
+ /* may skip if it is a fake entry */
|
||
|
+ o->skip = !nftnl_chain_is_set(c, NFTNL_CHAIN_HANDLE);
|
||
|
}
|
||
|
|
||
|
iter = nftnl_rule_iter_create(c);
|
||
|
@@ -3823,6 +3839,8 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
|
||
|
struct nft_chain *c;
|
||
|
int ret = 0;
|
||
|
|
||
|
+ nft_xt_fake_builtin_chains(h, table, chain);
|
||
|
+
|
||
|
if (chain) {
|
||
|
c = nft_chain_find(h, table, chain);
|
||
|
if (!c) {
|
||
|
diff --git a/iptables/tests/shell/testcases/nft-only/0013-zero-non-existent_0 b/iptables/tests/shell/testcases/nft-only/0013-zero-non-existent_0
|
||
|
new file mode 100755
|
||
|
index 0000000..bbf1af7
|
||
|
--- /dev/null
|
||
|
+++ b/iptables/tests/shell/testcases/nft-only/0013-zero-non-existent_0
|
||
|
@@ -0,0 +1,17 @@
|
||
|
+#!/bin/bash
|
||
|
+
|
||
|
+[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
|
||
|
+nft --version >/dev/null 2>&1 || { echo "skip nft"; exit 0; }
|
||
|
+
|
||
|
+set -e
|
||
|
+
|
||
|
+nft flush ruleset
|
||
|
+$XT_MULTI iptables -Z INPUT
|
||
|
+
|
||
|
+EXP="Zeroing chain \`INPUT'"
|
||
|
+diff -u <(echo "$EXP") <($XT_MULTI iptables -v -Z INPUT)
|
||
|
+
|
||
|
+EXP="Zeroing chain \`INPUT'
|
||
|
+Zeroing chain \`FORWARD'
|
||
|
+Zeroing chain \`OUTPUT'"
|
||
|
+diff -u <(echo "$EXP") <($XT_MULTI iptables -v -Z)
|