|
|
8cce6c |
From 9a6553277dc28dc2e4082646e14e49188aa6f096 Mon Sep 17 00:00:00 2001
|
|
|
8cce6c |
From: Phil Sutter <phil@nwl.cc>
|
|
|
8cce6c |
Date: Tue, 15 Jan 2019 23:23:05 +0100
|
|
|
8cce6c |
Subject: [PATCH] xtables: Fix for inserting rule at wrong position
|
|
|
8cce6c |
|
|
|
8cce6c |
iptables-restore allows to insert rules at a certain position which is
|
|
|
8cce6c |
problematic for iptables-nft to realize since rule position is not
|
|
|
8cce6c |
determined by number but handle of previous or following rule and in
|
|
|
8cce6c |
case the rules surrounding the new one are new as well, they don't have
|
|
|
8cce6c |
a handle to refer to yet.
|
|
|
8cce6c |
|
|
|
8cce6c |
Fix this by making use of NFTNL_RULE_POSITION_ID attribute: When
|
|
|
8cce6c |
inserting before a rule which does not have a handle, refer to it using
|
|
|
8cce6c |
its NFTNL_RULE_ID value. If the latter doesn't exist either, assign a
|
|
|
8cce6c |
new one to it.
|
|
|
8cce6c |
|
|
|
8cce6c |
The last used rule ID value is tracked in a new field of struct
|
|
|
8cce6c |
nft_handle which is incremented before each use.
|
|
|
8cce6c |
|
|
|
8cce6c |
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
8cce6c |
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|
|
8cce6c |
(cherry picked from commit 7ea0b7d809229973d950ed99845bdd0b2eb4cbb7)
|
|
|
8cce6c |
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
|
8cce6c |
---
|
|
|
8cce6c |
iptables/nft.c | 30 +++--
|
|
|
8cce6c |
iptables/nft.h | 1 +
|
|
|
8cce6c |
.../ipt-restore/0003-restore-ordering_0 | 117 ++++++++++++++++++
|
|
|
8cce6c |
.../testcases/iptables/0005-rule-replace_0 | 38 ++++++
|
|
|
8cce6c |
4 files changed, 176 insertions(+), 10 deletions(-)
|
|
|
8cce6c |
create mode 100755 iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
|
|
|
8cce6c |
create mode 100755 iptables/tests/shell/testcases/iptables/0005-rule-replace_0
|
|
|
8cce6c |
|
|
|
8cce6c |
diff --git a/iptables/nft.c b/iptables/nft.c
|
|
|
8cce6c |
index 76764fde4e9fb..2fa973cf03975 100644
|
|
|
8cce6c |
--- a/iptables/nft.c
|
|
|
8cce6c |
+++ b/iptables/nft.c
|
|
|
8cce6c |
@@ -2065,16 +2065,30 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
|
|
|
8cce6c |
static struct nftnl_rule *
|
|
|
8cce6c |
nft_rule_add(struct nft_handle *h, const char *chain,
|
|
|
8cce6c |
const char *table, struct iptables_command_state *cs,
|
|
|
8cce6c |
- uint64_t handle, bool verbose)
|
|
|
8cce6c |
+ struct nftnl_rule *ref, bool verbose)
|
|
|
8cce6c |
{
|
|
|
8cce6c |
struct nftnl_rule *r;
|
|
|
8cce6c |
+ uint64_t ref_id;
|
|
|
8cce6c |
|
|
|
8cce6c |
r = nft_rule_new(h, chain, table, cs);
|
|
|
8cce6c |
if (r == NULL)
|
|
|
8cce6c |
return NULL;
|
|
|
8cce6c |
|
|
|
8cce6c |
- if (handle > 0)
|
|
|
8cce6c |
- nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
|
|
|
8cce6c |
+ if (ref) {
|
|
|
8cce6c |
+ ref_id = nftnl_rule_get_u64(ref, NFTNL_RULE_HANDLE);
|
|
|
8cce6c |
+ if (ref_id > 0) {
|
|
|
8cce6c |
+ nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, ref_id);
|
|
|
8cce6c |
+ DEBUGP("adding after rule handle %"PRIu64"\n", ref_id);
|
|
|
8cce6c |
+ } else {
|
|
|
8cce6c |
+ ref_id = nftnl_rule_get_u32(ref, NFTNL_RULE_ID);
|
|
|
8cce6c |
+ if (!ref_id) {
|
|
|
8cce6c |
+ ref_id = ++h->rule_id;
|
|
|
8cce6c |
+ nftnl_rule_set_u32(ref, NFTNL_RULE_ID, ref_id);
|
|
|
8cce6c |
+ }
|
|
|
8cce6c |
+ nftnl_rule_set_u32(r, NFTNL_RULE_POSITION_ID, ref_id);
|
|
|
8cce6c |
+ DEBUGP("adding after rule ID %"PRIu64"\n", ref_id);
|
|
|
8cce6c |
+ }
|
|
|
8cce6c |
+ }
|
|
|
8cce6c |
|
|
|
8cce6c |
if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
|
|
|
8cce6c |
nftnl_rule_free(r);
|
|
|
8cce6c |
@@ -2090,9 +2104,8 @@ nft_rule_add(struct nft_handle *h, const char *chain,
|
|
|
8cce6c |
int nft_rule_insert(struct nft_handle *h, const char *chain,
|
|
|
8cce6c |
const char *table, void *data, int rulenum, bool verbose)
|
|
|
8cce6c |
{
|
|
|
8cce6c |
- struct nftnl_rule *r, *new_rule;
|
|
|
8cce6c |
+ struct nftnl_rule *r = NULL, *new_rule;
|
|
|
8cce6c |
struct nftnl_chain *c;
|
|
|
8cce6c |
- uint64_t handle = 0;
|
|
|
8cce6c |
|
|
|
8cce6c |
/* If built-in chains don't exist for this table, create them */
|
|
|
8cce6c |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
|
8cce6c |
@@ -2120,16 +2133,13 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
|
|
|
8cce6c |
errno = ENOENT;
|
|
|
8cce6c |
goto err;
|
|
|
8cce6c |
}
|
|
|
8cce6c |
-
|
|
|
8cce6c |
- handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
|
|
|
8cce6c |
- DEBUGP("adding after rule handle %"PRIu64"\n", handle);
|
|
|
8cce6c |
}
|
|
|
8cce6c |
|
|
|
8cce6c |
- new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
|
|
|
8cce6c |
+ new_rule = nft_rule_add(h, chain, table, data, r, verbose);
|
|
|
8cce6c |
if (!new_rule)
|
|
|
8cce6c |
goto err;
|
|
|
8cce6c |
|
|
|
8cce6c |
- if (handle)
|
|
|
8cce6c |
+ if (r)
|
|
|
8cce6c |
nftnl_chain_rule_insert_at(new_rule, r);
|
|
|
8cce6c |
else
|
|
|
8cce6c |
nftnl_chain_rule_add(new_rule, c);
|
|
|
8cce6c |
diff --git a/iptables/nft.h b/iptables/nft.h
|
|
|
8cce6c |
index 97d73c8b534be..0726923a63dd4 100644
|
|
|
8cce6c |
--- a/iptables/nft.h
|
|
|
8cce6c |
+++ b/iptables/nft.h
|
|
|
8cce6c |
@@ -32,6 +32,7 @@ struct nft_handle {
|
|
|
8cce6c |
struct mnl_socket *nl;
|
|
|
8cce6c |
uint32_t portid;
|
|
|
8cce6c |
uint32_t seq;
|
|
|
8cce6c |
+ uint32_t rule_id;
|
|
|
8cce6c |
struct list_head obj_list;
|
|
|
8cce6c |
int obj_list_num;
|
|
|
8cce6c |
struct nftnl_batch *batch;
|
|
|
8cce6c |
diff --git a/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
|
|
|
8cce6c |
new file mode 100755
|
|
|
8cce6c |
index 0000000000000..51f2422e15259
|
|
|
8cce6c |
--- /dev/null
|
|
|
8cce6c |
+++ b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
|
|
|
8cce6c |
@@ -0,0 +1,117 @@
|
|
|
8cce6c |
+#!/bin/bash
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# Make sure iptables-restore does the right thing
|
|
|
8cce6c |
+# when encountering INSERT rules with index.
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+set -e
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# show rules, drop uninteresting policy settings
|
|
|
8cce6c |
+ipt_show() {
|
|
|
8cce6c |
+ $XT_MULTI iptables -S | grep -v '^-P'
|
|
|
8cce6c |
+}
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# basic issue reproducer
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 2 -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 3 -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# insert rules into existing ruleset
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore --noflush <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-I FORWARD 1 -m comment --comment "rule 0.5" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 3 -m comment --comment "rule 1.5" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 5 -m comment --comment "rule 2.5" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 7 -m comment --comment "rule 3.5" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 9 -m comment --comment "appended rule 2" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 0.5" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 1.5" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 2.5" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3.5" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# insert rules in between added ones
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 3 -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 5 -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# test rule deletion in dump files
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore --noflush <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-D FORWARD -m comment --comment "appended rule 1" -j ACCEPT
|
|
|
8cce6c |
+-D FORWARD 3
|
|
|
8cce6c |
+-I FORWARD 3 -m comment --comment "manually replaced rule 2" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "manually replaced rule 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# test rule replacement in dump files
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule to be replaced" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables-restore --noflush <
|
|
|
8cce6c |
+*filter
|
|
|
8cce6c |
+-R FORWARD 2 -m comment --comment "replacement" -j ACCEPT
|
|
|
8cce6c |
+-I FORWARD 2 -m comment --comment "insert referencing replaced rule" -j ACCEPT
|
|
|
8cce6c |
+COMMIT
|
|
|
8cce6c |
+EOF
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "insert referencing replaced rule" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment replacement -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
diff --git a/iptables/tests/shell/testcases/iptables/0005-rule-replace_0 b/iptables/tests/shell/testcases/iptables/0005-rule-replace_0
|
|
|
8cce6c |
new file mode 100755
|
|
|
8cce6c |
index 0000000000000..5a3e922e50672
|
|
|
8cce6c |
--- /dev/null
|
|
|
8cce6c |
+++ b/iptables/tests/shell/testcases/iptables/0005-rule-replace_0
|
|
|
8cce6c |
@@ -0,0 +1,38 @@
|
|
|
8cce6c |
+#!/bin/bash
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# test rule replacement
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+set -e
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+# show rules, drop uninteresting policy settings
|
|
|
8cce6c |
+ipt_show() {
|
|
|
8cce6c |
+ $XT_MULTI iptables -S | grep -v '^-P'
|
|
|
8cce6c |
+}
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 2" -j ACCEPT
|
|
|
8cce6c |
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 3" -j ACCEPT
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables -R FORWARD 2 -m comment --comment "replaced 2" -j ACCEPT
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables -R FORWARD 1 -m comment --comment "replaced 1" -j ACCEPT
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "replaced 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+$XT_MULTI iptables -R FORWARD 3 -m comment --comment "replaced 3" -j ACCEPT
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+EXPECT='-A FORWARD -m comment --comment "replaced 1" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
|
|
|
8cce6c |
+-A FORWARD -m comment --comment "replaced 3" -j ACCEPT'
|
|
|
8cce6c |
+
|
|
|
8cce6c |
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
|
|
|
8cce6c |
--
|
|
|
8cce6c |
2.20.1
|
|
|
8cce6c |
|