From 1f113a48e43a25d7a078ded97f47bbbd21a1ce8c Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 28 Jul 2020 09:57:58 -0400 Subject: [PATCH] import iptables-1.8.4-14.el8 --- ...e-Fix-for-interface-name-corner-case.patch | 98 +++++ ...0011-xtables-translate-Fix-for-iface.patch | 60 +++ ...shell-Fix-skip-checks-with-host-mode.patch | 366 ++++++++++++++++++ ...tore-fix-for-noflush-and-empty-lines.patch | 78 ++++ .../0014-iptables-test.py-Fix-host-mode.patch | 43 ++ SOURCES/0015-xtables-Review-nft_init.patch | 274 +++++++++++++ ...e-Fix-nft_release_cache-under-stress.patch | 49 +++ ...-iptables-save-segfault-under-stress.patch | 84 ++++ ...Support-mixed-MAC-and-MAC-IP-entries.patch | 127 ++++++ ...gn-effect-of-4-6-options-with-legacy.patch | 157 ++++++++ ...nd-6-support-from-xtables-save-resto.patch | 81 ++++ ...-Fix-broken-conversion-to-nfnl_query.patch | 42 ++ ...0022-nfnl_osf-Improve-error-handling.patch | 80 ++++ ...he-Reset-genid-when-rebuilding-cache.patch | 37 ++ ...0024-nft-Fix-for-F-in-iptables-dumps.patch | 81 ++++ ...025-tests-shell-Test-F-in-dump-files.patch | 37 ++ SOURCES/iptables.service | 5 +- SPECS/iptables.spec | 69 +++- 18 files changed, 1756 insertions(+), 12 deletions(-) create mode 100644 SOURCES/0010-xtables-translate-Fix-for-interface-name-corner-case.patch create mode 100644 SOURCES/0011-xtables-translate-Fix-for-iface.patch create mode 100644 SOURCES/0012-tests-shell-Fix-skip-checks-with-host-mode.patch create mode 100644 SOURCES/0013-xtables-restore-fix-for-noflush-and-empty-lines.patch create mode 100644 SOURCES/0014-iptables-test.py-Fix-host-mode.patch create mode 100644 SOURCES/0015-xtables-Review-nft_init.patch create mode 100644 SOURCES/0016-nft-cache-Fix-nft_release_cache-under-stress.patch create mode 100644 SOURCES/0017-nft-cache-Fix-iptables-save-segfault-under-stress.patch create mode 100644 SOURCES/0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch create mode 100644 SOURCES/0019-xtables-Align-effect-of-4-6-options-with-legacy.patch create mode 100644 SOURCES/0020-xtables-Drop-4-and-6-support-from-xtables-save-resto.patch create mode 100644 SOURCES/0021-nfnl_osf-Fix-broken-conversion-to-nfnl_query.patch create mode 100644 SOURCES/0022-nfnl_osf-Improve-error-handling.patch create mode 100644 SOURCES/0023-nft-cache-Reset-genid-when-rebuilding-cache.patch create mode 100644 SOURCES/0024-nft-Fix-for-F-in-iptables-dumps.patch create mode 100644 SOURCES/0025-tests-shell-Test-F-in-dump-files.patch diff --git a/SOURCES/0010-xtables-translate-Fix-for-interface-name-corner-case.patch b/SOURCES/0010-xtables-translate-Fix-for-interface-name-corner-case.patch new file mode 100644 index 0000000..a1bc86c --- /dev/null +++ b/SOURCES/0010-xtables-translate-Fix-for-interface-name-corner-case.patch @@ -0,0 +1,98 @@ +From da36213a48f6114ab998a5fb37bae61d2a02d5f6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 6 Feb 2020 15:08:41 +0100 +Subject: [PATCH] xtables-translate: Fix for interface name corner-cases + +There are two special situations xlate_ifname() didn't cover for: + +* Interface name containing '*': This went unchanged, creating a command + nft wouldn't accept. Instead translate into '\*' which doesn't change + semantics. + +* Interface name being '+': Can't translate into nft wildcard character + as nft doesn't accept asterisk-only interface names. Instead decide + what to do based on 'invert' value: Skip match creation if false, + match against an invalid interface name if true. + +Also add a test to make sure future changes to this behaviour are +noticed. + +Signed-off-by: Phil Sutter +(cherry picked from commit e179e87a1179e272a9bdabb0220b17d61d099ee3) +Signed-off-by: Phil Sutter +--- + extensions/generic.txlate | 12 ++++++++++++ + iptables/xtables-translate.c | 33 ++++++++++++++++++++++++++++----- + 2 files changed, 40 insertions(+), 5 deletions(-) + +diff --git a/extensions/generic.txlate b/extensions/generic.txlate +index b38fbd1fe113b..c92d082abea78 100644 +--- a/extensions/generic.txlate ++++ b/extensions/generic.txlate +@@ -18,3 +18,15 @@ nft add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oi + + ebtables-translate -I INPUT -p ip -d 1:2:3:4:5:6/ff:ff:ff:ff:00:00 + nft insert rule bridge filter INPUT ether type 0x800 ether daddr 01:02:03:04:00:00 and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter ++ ++# asterisk is not special in iptables and it is even a valid interface name ++iptables-translate -A FORWARD -i '*' -o 'eth*foo' ++nft add rule ip filter FORWARD iifname "\*" oifname "eth\*foo" counter ++ ++# skip for always matching interface names ++iptables-translate -A FORWARD -i '+' ++nft add rule ip filter FORWARD counter ++ ++# match against invalid interface name to simulate never matching rule ++iptables-translate -A FORWARD ! -i '+' ++nft add rule ip filter FORWARD iifname "INVAL/D" counter +diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c +index 77a186b905d73..c4e177c0d63ba 100644 +--- a/iptables/xtables-translate.c ++++ b/iptables/xtables-translate.c +@@ -32,15 +32,38 @@ + void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname, + bool invert) + { +- int ifaclen = strlen(ifname); +- char iface[IFNAMSIZ]; ++ int ifaclen = strlen(ifname), i, j; ++ char iface[IFNAMSIZ * 2]; + + if (ifaclen < 1 || ifaclen >= IFNAMSIZ) + return; + +- strcpy(iface, ifname); +- if (iface[ifaclen - 1] == '+') +- iface[ifaclen - 1] = '*'; ++ for (i = 0, j = 0; i < ifaclen + 1; i++, j++) { ++ switch (ifname[i]) { ++ case '+': ++ iface[j] = '*'; ++ break; ++ case '*': ++ iface[j++] = '\\'; ++ /* fall through */ ++ default: ++ iface[j] = ifname[i]; ++ break; ++ } ++ } ++ ++ if (ifaclen == 1 && ifname[0] == '+') { ++ /* Nftables does not support wildcard only string. Workaround ++ * is easy, given that this will match always or never ++ * depending on 'invert' value. To match always, simply don't ++ * generate an expression. To match never, use an invalid ++ * interface name (kernel doesn't accept '/' in names) to match ++ * against. */ ++ if (!invert) ++ return; ++ strcpy(iface, "INVAL/D"); ++ invert = false; ++ } + + xt_xlate_add(xl, "%s %s\"%s\" ", nftmeta, invert ? "!= " : "", iface); + } +-- +2.24.1 + diff --git a/SOURCES/0011-xtables-translate-Fix-for-iface.patch b/SOURCES/0011-xtables-translate-Fix-for-iface.patch new file mode 100644 index 0000000..5971ec1 --- /dev/null +++ b/SOURCES/0011-xtables-translate-Fix-for-iface.patch @@ -0,0 +1,60 @@ +From 1e1fda9ac0a809c64fd13b4fb759becac824809e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Feb 2020 14:01:50 +0100 +Subject: [PATCH] xtables-translate: Fix for iface++ + +In legacy iptables, only the last plus sign remains special, any +previous ones are taken literally. Therefore xtables-translate must not +replace all of them with asterisk but just the last one. + +Fixes: e179e87a1179e ("xtables-translate: Fix for interface name corner-cases") +Signed-off-by: Phil Sutter +(cherry picked from commit 94488d4eb912f5af4c88d148b39b38eb8a3c1f0b) +Signed-off-by: Phil Sutter +--- + extensions/generic.txlate | 4 ++++ + iptables/xtables-translate.c | 6 +++--- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/extensions/generic.txlate b/extensions/generic.txlate +index c92d082abea78..0e256c3727559 100644 +--- a/extensions/generic.txlate ++++ b/extensions/generic.txlate +@@ -23,6 +23,10 @@ nft insert rule bridge filter INPUT ether type 0x800 ether daddr 01:02:03:04:00: + iptables-translate -A FORWARD -i '*' -o 'eth*foo' + nft add rule ip filter FORWARD iifname "\*" oifname "eth\*foo" counter + ++# escape all asterisks but translate only the first plus character ++iptables-translate -A FORWARD -i 'eth*foo*+' -o 'eth++' ++nft add rule ip filter FORWARD iifname "eth\*foo\**" oifname "eth+*" counter ++ + # skip for always matching interface names + iptables-translate -A FORWARD -i '+' + nft add rule ip filter FORWARD counter +diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c +index c4e177c0d63ba..0f95855b41aa4 100644 +--- a/iptables/xtables-translate.c ++++ b/iptables/xtables-translate.c +@@ -40,9 +40,6 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname, + + for (i = 0, j = 0; i < ifaclen + 1; i++, j++) { + switch (ifname[i]) { +- case '+': +- iface[j] = '*'; +- break; + case '*': + iface[j++] = '\\'; + /* fall through */ +@@ -65,6 +62,9 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname, + invert = false; + } + ++ if (iface[j - 2] == '+') ++ iface[j - 2] = '*'; ++ + xt_xlate_add(xl, "%s %s\"%s\" ", nftmeta, invert ? "!= " : "", iface); + } + +-- +2.24.1 + diff --git a/SOURCES/0012-tests-shell-Fix-skip-checks-with-host-mode.patch b/SOURCES/0012-tests-shell-Fix-skip-checks-with-host-mode.patch new file mode 100644 index 0000000..4501a92 --- /dev/null +++ b/SOURCES/0012-tests-shell-Fix-skip-checks-with-host-mode.patch @@ -0,0 +1,366 @@ +From bbd2dd9ee6db7d11ab5b2b10a63b3dfd8b8acc9d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 21:26:06 +0100 +Subject: [PATCH] tests: shell: Fix skip checks with --host mode + +When testing host binaries, XT_MULTI variable contains just the program +name without path component which most skip checks didn't expect. Fix +them, and while being at it also reduce indenting level in two scripts +by moving the skip check up front with an early exit call. + +Fixes: 416898e335322 ("tests/shell: Support testing host binaries") +Signed-off-by: Phil Sutter +(cherry picked from commit 2b2b7948c1960ba4680677664ff58477be869de6) +Signed-off-by: Phil Sutter +--- + .../arptables/0001-arptables-save-restore_0 | 2 +- + .../0002-arptables-restore-defaults_0 | 2 +- + .../arptables/0003-arptables-verbose-output_0 | 2 +- + .../testcases/ebtables/0001-ebtables-basic_0 | 135 +++++++++--------- + .../ebtables/0002-ebtables-save-restore_0 | 2 +- + .../ebtables/0003-ebtables-restore-defaults_0 | 2 +- + .../testcases/ebtables/0004-save-counters_0 | 2 +- + .../testcases/ebtables/0005-ifnamechecks_0 | 2 +- + .../firewalld-restore/0001-firewalld_0 | 2 +- + .../testcases/ipt-restore/0004-restore-race_0 | 2 +- + .../shell/testcases/nft-only/0001compat_0 | 15 +- + .../shell/testcases/nft-only/0002invflags_0 | 2 +- + .../nft-only/0003delete-with-comment_0 | 2 +- + 13 files changed, 88 insertions(+), 84 deletions(-) + +diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +index bf04dc0a3e15a..e64e9142ee98b 100755 +--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 ++++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +@@ -4,7 +4,7 @@ set -e + #set -x + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + # fill arptables manually + +diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +index 38d387f327ebb..afd0fcb460d85 100755 +--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 ++++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +@@ -3,7 +3,7 @@ + set -e + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + # arptables-restore reuses preloaded targets and matches, make sure defaults + # apply to consecutive rules using the same target/match as a previous one +diff --git a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +index 10c5ec33ada2c..952cfa7898371 100755 +--- a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 ++++ b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +@@ -4,7 +4,7 @@ set -e + set -x + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + $XT_MULTI arptables -N foo + +diff --git a/iptables/tests/shell/testcases/ebtables/0001-ebtables-basic_0 b/iptables/tests/shell/testcases/ebtables/0001-ebtables-basic_0 +index c7f24a383f698..0c1eb4ca66f52 100755 +--- a/iptables/tests/shell/testcases/ebtables/0001-ebtables-basic_0 ++++ b/iptables/tests/shell/testcases/ebtables/0001-ebtables-basic_0 +@@ -1,86 +1,89 @@ + #!/bin/sh + ++case "$XT_MULTI" in ++*xtables-nft-multi) ++ ;; ++*) ++ echo "skip $XT_MULTI" ++ exit 0 ++ ;; ++esac ++ + get_entries_count() { # (chain) + $XT_MULTI ebtables -L $1 | sed -n 's/.*entries: \([0-9]*\).*/\1/p' + } + + set -x +-case "$XT_MULTI" in +-*/xtables-nft-multi) +- for t in filter nat;do +- $XT_MULTI ebtables -t $t -L || exit 1 +- $XT_MULTI ebtables -t $t -X || exit 1 +- $XT_MULTI ebtables -t $t -F || exit 1 +- done +- +- for t in broute foobar ;do +- $XT_MULTI ebtables -t $t -L && +- $XT_MULTI ebtables -t $t -X && +- $XT_MULTI ebtables -t $t -F +- if [ $? -eq 0 ]; then +- echo "Expect nonzero return for unsupported table" +- exit 1 +- fi +- done + ++for t in filter nat;do ++ $XT_MULTI ebtables -t $t -L || exit 1 ++ $XT_MULTI ebtables -t $t -X || exit 1 ++ $XT_MULTI ebtables -t $t -F || exit 1 ++done + +- $XT_MULTI ebtables -t filter -N FOO || exit 1 +- $XT_MULTI ebtables -t filter -N FOO ++for t in broute foobar ;do ++ $XT_MULTI ebtables -t $t -L && ++ $XT_MULTI ebtables -t $t -X && ++ $XT_MULTI ebtables -t $t -F + if [ $? -eq 0 ]; then +- echo "Duplicate chain FOO" +- $XT_MULTI ebtables -t filter -L ++ echo "Expect nonzero return for unsupported table" + exit 1 + fi ++done + +- entries=$(get_entries_count FOO) +- if [ $entries -ne 0 ]; then +- echo "Unexpected entries count in empty unreferenced chain (expected 0, have $entries)" +- $XT_MULTI ebtables -L +- exit 1 +- fi + +- $XT_MULTI ebtables -A FORWARD -j FOO +- entries=$(get_entries_count FORWARD) +- if [ $entries -ne 1 ]; then +- echo "Unexpected entries count in FORWARD chain (expected 1, have $entries)" +- $XT_MULTI ebtables -L +- exit 1 +- fi ++$XT_MULTI ebtables -t filter -N FOO || exit 1 ++$XT_MULTI ebtables -t filter -N FOO ++if [ $? -eq 0 ]; then ++ echo "Duplicate chain FOO" ++ $XT_MULTI ebtables -t filter -L ++ exit 1 ++fi + +- entries=$(get_entries_count FOO) +- if [ $entries -ne 0 ]; then +- echo "Unexpected entries count in empty referenced chain (expected 0, have $entries)" +- $XT_MULTI ebtables -L +- exit 1 +- fi ++entries=$(get_entries_count FOO) ++if [ $entries -ne 0 ]; then ++ echo "Unexpected entries count in empty unreferenced chain (expected 0, have $entries)" ++ $XT_MULTI ebtables -L ++ exit 1 ++fi + +- $XT_MULTI ebtables -A FOO -j ACCEPT +- entries=$(get_entries_count FOO) +- if [ $entries -ne 1 ]; then +- echo "Unexpected entries count in non-empty referenced chain (expected 1, have $entries)" +- $XT_MULTI ebtables -L +- exit 1 +- fi ++$XT_MULTI ebtables -A FORWARD -j FOO ++entries=$(get_entries_count FORWARD) ++if [ $entries -ne 1 ]; then ++ echo "Unexpected entries count in FORWARD chain (expected 1, have $entries)" ++ $XT_MULTI ebtables -L ++ exit 1 ++fi + +- $XT_MULTI ebtables -t filter -N BAR || exit 1 +- $XT_MULTI ebtables -t filter -N BAZ || exit 1 ++entries=$(get_entries_count FOO) ++if [ $entries -ne 0 ]; then ++ echo "Unexpected entries count in empty referenced chain (expected 0, have $entries)" ++ $XT_MULTI ebtables -L ++ exit 1 ++fi + +- $XT_MULTI ebtables -t filter -L | grep -q FOO || exit 1 +- $XT_MULTI ebtables -t filter -L | grep -q BAR || exit 1 +- $XT_MULTI ebtables -t filter -L | grep -q BAZ || exit 1 ++$XT_MULTI ebtables -A FOO -j ACCEPT ++entries=$(get_entries_count FOO) ++if [ $entries -ne 1 ]; then ++ echo "Unexpected entries count in non-empty referenced chain (expected 1, have $entries)" ++ $XT_MULTI ebtables -L ++ exit 1 ++fi + +- $XT_MULTI ebtables -t filter -L BAZ || exit 1 +- $XT_MULTI ebtables -t filter -X BAZ || exit 1 +- $XT_MULTI ebtables -t filter -L BAZ | grep -q BAZ +- if [ $? -eq 0 ]; then +- echo "Deleted chain -L BAZ ok, expected failure" +- $XT_MULTI ebtables -t filter -L +- exit 1 +- fi ++$XT_MULTI ebtables -t filter -N BAR || exit 1 ++$XT_MULTI ebtables -t filter -N BAZ || exit 1 + +- $XT_MULTI ebtables -t $t -F || exit 0 +- ;; +-*) +- echo "skip $XT_MULTI" +- ;; +-esac ++$XT_MULTI ebtables -t filter -L | grep -q FOO || exit 1 ++$XT_MULTI ebtables -t filter -L | grep -q BAR || exit 1 ++$XT_MULTI ebtables -t filter -L | grep -q BAZ || exit 1 ++ ++$XT_MULTI ebtables -t filter -L BAZ || exit 1 ++$XT_MULTI ebtables -t filter -X BAZ || exit 1 ++$XT_MULTI ebtables -t filter -L BAZ | grep -q BAZ ++if [ $? -eq 0 ]; then ++ echo "Deleted chain -L BAZ ok, expected failure" ++ $XT_MULTI ebtables -t filter -L ++ exit 1 ++fi ++ ++$XT_MULTI ebtables -t $t -F || exit 0 +diff --git a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 +index e18d46551509d..b84f63a7c3672 100755 +--- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 ++++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 +@@ -4,7 +4,7 @@ set -e + #set -x + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + # fill ebtables manually + +diff --git a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 +index 62d224134456b..63891c1bb731a 100755 +--- a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 ++++ b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 +@@ -3,7 +3,7 @@ + set -e + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + # ebtables-restore reuses preloaded targets and matches, make sure defaults + # apply to consecutive rules using the same target/match as a previous one +diff --git a/iptables/tests/shell/testcases/ebtables/0004-save-counters_0 b/iptables/tests/shell/testcases/ebtables/0004-save-counters_0 +index 46966f433139a..d52db900604ef 100755 +--- a/iptables/tests/shell/testcases/ebtables/0004-save-counters_0 ++++ b/iptables/tests/shell/testcases/ebtables/0004-save-counters_0 +@@ -3,7 +3,7 @@ + set -e + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + $XT_MULTI ebtables --init-table + $XT_MULTI ebtables -A FORWARD -i nodev123 -o nodev432 -j ACCEPT +diff --git a/iptables/tests/shell/testcases/ebtables/0005-ifnamechecks_0 b/iptables/tests/shell/testcases/ebtables/0005-ifnamechecks_0 +index 2163d364b318b..0b3acfd7613db 100755 +--- a/iptables/tests/shell/testcases/ebtables/0005-ifnamechecks_0 ++++ b/iptables/tests/shell/testcases/ebtables/0005-ifnamechecks_0 +@@ -3,7 +3,7 @@ + set -e + + # there is no legacy backend to test +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + EXPECT='*filter + :INPUT ACCEPT +diff --git a/iptables/tests/shell/testcases/firewalld-restore/0001-firewalld_0 b/iptables/tests/shell/testcases/firewalld-restore/0001-firewalld_0 +index 8bf0c2c6c194e..0174b03f4ebc7 100755 +--- a/iptables/tests/shell/testcases/firewalld-restore/0001-firewalld_0 ++++ b/iptables/tests/shell/testcases/firewalld-restore/0001-firewalld_0 +@@ -231,7 +231,7 @@ for table in nat mangle raw filter;do + done + + case "$XT_MULTI" in +-*/xtables-nft-multi) ++*xtables-nft-multi) + # nft-multi displays chain names in different order, work around this for now + tmpfile2=$(mktemp) + sort "$tmpfile" > "$tmpfile2" +diff --git a/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 b/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 +index 96a5e66d0ab81..9fc50615b8926 100755 +--- a/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 ++++ b/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 +@@ -86,7 +86,7 @@ if [ $LINES1 -ne $LINES2 ]; then + fi + + case "$XT_MULTI" in +-*/xtables-nft-multi) ++*xtables-nft-multi) + attempts=$((RANDOM%10)) + attempts=$((attempts+1)) + ;; +diff --git a/iptables/tests/shell/testcases/nft-only/0001compat_0 b/iptables/tests/shell/testcases/nft-only/0001compat_0 +index 4319ea5a6a797..a617c52f53695 100755 +--- a/iptables/tests/shell/testcases/nft-only/0001compat_0 ++++ b/iptables/tests/shell/testcases/nft-only/0001compat_0 +@@ -5,17 +5,18 @@ + # xtables: avoid bogus 'is incompatible' warning + + case "$XT_MULTI" in +-*/xtables-nft-multi) +- nft -v >/dev/null || exit 0 +- nft 'add table ip nft-test; add chain ip nft-test foobar { type filter hook forward priority 42; }' || exit 1 +- nft 'add table ip6 nft-test; add chain ip6 nft-test foobar { type filter hook forward priority 42; }' || exit 1 +- +- $XT_MULTI iptables -L -t filter || exit 1 +- $XT_MULTI ip6tables -L -t filter || exit 1 ++*xtables-nft-multi) + ;; + *) + echo skip $XT_MULTI ++ exit 0 + ;; + esac + ++nft -v >/dev/null || exit 0 ++nft 'add table ip nft-test; add chain ip nft-test foobar { type filter hook forward priority 42; }' || exit 1 ++nft 'add table ip6 nft-test; add chain ip6 nft-test foobar { type filter hook forward priority 42; }' || exit 1 ++ ++$XT_MULTI iptables -L -t filter || exit 1 ++$XT_MULTI ip6tables -L -t filter || exit 1 + exit 0 +diff --git a/iptables/tests/shell/testcases/nft-only/0002invflags_0 b/iptables/tests/shell/testcases/nft-only/0002invflags_0 +index 406b6081a98a4..fe33874dde7f2 100755 +--- a/iptables/tests/shell/testcases/nft-only/0002invflags_0 ++++ b/iptables/tests/shell/testcases/nft-only/0002invflags_0 +@@ -2,7 +2,7 @@ + + set -e + +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + $XT_MULTI iptables -A INPUT -p tcp --dport 53 ! -s 192.168.0.1 -j ACCEPT + $XT_MULTI ip6tables -A INPUT -p tcp --dport 53 ! -s feed:babe::1 -j ACCEPT +diff --git a/iptables/tests/shell/testcases/nft-only/0003delete-with-comment_0 b/iptables/tests/shell/testcases/nft-only/0003delete-with-comment_0 +index 67af9fd897410..ccb009e469076 100755 +--- a/iptables/tests/shell/testcases/nft-only/0003delete-with-comment_0 ++++ b/iptables/tests/shell/testcases/nft-only/0003delete-with-comment_0 +@@ -2,7 +2,7 @@ + + set -e + +-[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } + + comment1="foo bar" + comment2="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +-- +2.24.1 + diff --git a/SOURCES/0013-xtables-restore-fix-for-noflush-and-empty-lines.patch b/SOURCES/0013-xtables-restore-fix-for-noflush-and-empty-lines.patch new file mode 100644 index 0000000..cb49b21 --- /dev/null +++ b/SOURCES/0013-xtables-restore-fix-for-noflush-and-empty-lines.patch @@ -0,0 +1,78 @@ +From 5ea18ea8c0c99f2c71a5eaf32f4fbf6339ce8cc7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 11 Feb 2020 16:52:59 +0100 +Subject: [PATCH] xtables-restore: fix for --noflush and empty lines + +Lookahead buffer used for cache requirements estimate in restore +--noflush separates individual lines with nul-chars. Two consecutive +nul-chars are interpreted as end of buffer and remaining buffer content +is skipped. + +Sadly, reading an empty line (i.e., one containing a newline character +only) caused double nul-chars to appear in buffer as well, leading to +premature stop when reading cached lines from buffer. + +To fix that, make use of xtables_restore_parse_line() skipping empty +lines without calling strtok() and just leave the newline character in +place. A more intuitive approach, namely skipping empty lines while +buffering, is deliberately not chosen as that would cause wrong values +in 'line' variable. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1400 +Fixes: 09cb517949e69 ("xtables-restore: Improve performance of --noflush operation") +Signed-off-by: Phil Sutter +Acked-by: Arturo Borrero Gonzalez +(cherry picked from commit 8e76391096f12212985c401ee83a67990aa27a29) +Signed-off-by: Phil Sutter +--- + .../ipt-restore/0011-noflush-empty-line_0 | 16 ++++++++++++++++ + iptables/xtables-restore.c | 8 +++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + create mode 100755 iptables/tests/shell/testcases/ipt-restore/0011-noflush-empty-line_0 + +diff --git a/iptables/tests/shell/testcases/ipt-restore/0011-noflush-empty-line_0 b/iptables/tests/shell/testcases/ipt-restore/0011-noflush-empty-line_0 +new file mode 100755 +index 0000000000000..bea1a690bb624 +--- /dev/null ++++ b/iptables/tests/shell/testcases/ipt-restore/0011-noflush-empty-line_0 +@@ -0,0 +1,16 @@ ++#!/bin/bash -e ++ ++# make sure empty lines won't break --noflush ++ ++cat <in)) { + size_t blen = strlen(buffer); + +- /* drop trailing newline; xtables_restore_parse_line() ++ /* Drop trailing newline; xtables_restore_parse_line() + * uses strtok() which replaces them by nul-characters, + * causing unpredictable string delimiting in +- * preload_buffer */ +- if (buffer[blen - 1] == '\n') ++ * preload_buffer. ++ * Unless this is an empty line which would fold into a ++ * spurious EoB indicator (double nul-char). */ ++ if (buffer[blen - 1] == '\n' && blen > 1) + buffer[blen - 1] = '\0'; + else + blen++; +-- +2.24.1 + diff --git a/SOURCES/0014-iptables-test.py-Fix-host-mode.patch b/SOURCES/0014-iptables-test.py-Fix-host-mode.patch new file mode 100644 index 0000000..0387700 --- /dev/null +++ b/SOURCES/0014-iptables-test.py-Fix-host-mode.patch @@ -0,0 +1,43 @@ +From 40e7bc3055f9bc34ccb6327f1f32c2fc524fb693 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 18 Feb 2020 16:43:16 +0100 +Subject: [PATCH] iptables-test.py: Fix --host mode + +In some cases, the script still called repo binaries. Avoid this when in +--host mode to allow testing without the need to compile sources in +beforehand. + +Fixes: 1b5d762c1865e ("iptables-test: Support testing host binaries") +Signed-off-by: Phil Sutter +(cherry picked from commit ba2af278e8836977a8cfb35c54dac60ca9b40000) +Signed-off-by: Phil Sutter +--- + iptables-test.py | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/iptables-test.py b/iptables-test.py +index fdb4e6a3644e4..e986d7a318218 100755 +--- a/iptables-test.py ++++ b/iptables-test.py +@@ -119,8 +119,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns): + elif splitted[0] == EBTABLES: + command = EBTABLES_SAVE + +- path = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE +- command = path + " " + command ++ command = EXECUTEABLE + " " + command + + if netns: + command = "ip netns exec ____iptables-container-test " + command +@@ -165,7 +164,7 @@ def execute_cmd(cmd, filename, lineno): + ''' + global log_file + if cmd.startswith('iptables ') or cmd.startswith('ip6tables ') or cmd.startswith('ebtables ') or cmd.startswith('arptables '): +- cmd = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE + " " + cmd ++ cmd = EXECUTEABLE + " " + cmd + + print("command: {}".format(cmd), file=log_file) + ret = subprocess.call(cmd, shell=True, universal_newlines=True, +-- +2.25.1 + diff --git a/SOURCES/0015-xtables-Review-nft_init.patch b/SOURCES/0015-xtables-Review-nft_init.patch new file mode 100644 index 0000000..2246b84 --- /dev/null +++ b/SOURCES/0015-xtables-Review-nft_init.patch @@ -0,0 +1,274 @@ +From 51f895d54af6e163e0290520e124e9413438ccf4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 21 Feb 2020 14:55:52 +0100 +Subject: [PATCH] xtables: Review nft_init() + +Move common code into nft_init(), such as: + +* initial zeroing nft_handle fields +* family ops lookup and assignment to 'ops' field +* setting of 'family' field + +This requires minor adjustments in xtables_restore_main() so extra field +initialization doesn't happen before nft_init() call. + +As a side-effect, this fixes segfaulting xtables-monitor binary when +printing rules for trace event as in that code-path 'ops' field wasn't +initialized. + +Signed-off-by: Phil Sutter +(cherry picked from commit d0446ab11182f6ca2adc486a124895f09a220c6e) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 9 ++++++++- + iptables/nft.h | 2 +- + iptables/xtables-arp.c | 9 +-------- + iptables/xtables-eb.c | 9 +-------- + iptables/xtables-monitor.c | 2 +- + iptables/xtables-restore.c | 14 +++++++------- + iptables/xtables-save.c | 9 ++------- + iptables/xtables-standalone.c | 6 ++---- + iptables/xtables-translate.c | 2 +- + iptables/xtables.c | 4 ---- + 10 files changed, 24 insertions(+), 42 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 3f2a62ae12c07..0287add3fb21f 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -789,8 +789,10 @@ int nft_restart(struct nft_handle *h) + return 0; + } + +-int nft_init(struct nft_handle *h, const struct builtin_table *t) ++int nft_init(struct nft_handle *h, int family, const struct builtin_table *t) + { ++ memset(h, 0, sizeof(*h)); ++ + h->nl = mnl_socket_open(NETLINK_NETFILTER); + if (h->nl == NULL) + return -1; +@@ -800,9 +802,14 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t) + return -1; + } + ++ h->ops = nft_family_ops_lookup(family); ++ if (!h->ops) ++ xtables_error(PARAMETER_PROBLEM, "Unknown family"); ++ + h->portid = mnl_socket_get_portid(h->nl); + h->tables = t; + h->cache = &h->__cache[0]; ++ h->family = family; + + INIT_LIST_HEAD(&h->obj_list); + INIT_LIST_HEAD(&h->err_list); +diff --git a/iptables/nft.h b/iptables/nft.h +index 51b5660314c0c..5cf260a6d2cd3 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -80,7 +80,7 @@ extern const struct builtin_table xtables_bridge[NFT_TABLE_MAX]; + int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, + int (*cb)(const struct nlmsghdr *nlh, void *data), + void *data); +-int nft_init(struct nft_handle *h, const struct builtin_table *t); ++int nft_init(struct nft_handle *h, int family, const struct builtin_table *t); + void nft_fini(struct nft_handle *h); + int nft_restart(struct nft_handle *h); + +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index 9cfad76263d32..c8196f08baa59 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -500,17 +500,10 @@ int nft_init_arp(struct nft_handle *h, const char *pname) + init_extensionsa(); + #endif + +- memset(h, 0, sizeof(*h)); +- h->family = NFPROTO_ARP; +- +- if (nft_init(h, xtables_arp) < 0) ++ if (nft_init(h, NFPROTO_ARP, xtables_arp) < 0) + xtables_error(OTHER_PROBLEM, + "Could not initialize nftables layer."); + +- h->ops = nft_family_ops_lookup(h->family); +- if (h->ops == NULL) +- xtables_error(PARAMETER_PROBLEM, "Unknown family"); +- + return 0; + } + +diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c +index 15b971da3d425..c006bc95ac681 100644 +--- a/iptables/xtables-eb.c ++++ b/iptables/xtables-eb.c +@@ -739,16 +739,9 @@ int nft_init_eb(struct nft_handle *h, const char *pname) + init_extensionsb(); + #endif + +- memset(h, 0, sizeof(*h)); +- +- h->family = NFPROTO_BRIDGE; +- +- if (nft_init(h, xtables_bridge) < 0) ++ if (nft_init(h, NFPROTO_BRIDGE, xtables_bridge) < 0) + xtables_error(OTHER_PROBLEM, + "Could not initialize nftables layer."); +- h->ops = nft_family_ops_lookup(h->family); +- if (!h->ops) +- xtables_error(PARAMETER_PROBLEM, "Unknown family"); + + /* manually registering ebt matches, given the original ebtables parser + * don't use '-m matchname' and the match can't be loaded dynamically when +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index a5245d1422af9..c2b31dbaa0795 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -615,7 +615,7 @@ int xtables_monitor_main(int argc, char *argv[]) + init_extensions4(); + #endif + +- if (nft_init(&h, xtables_ipv4)) { ++ if (nft_init(&h, AF_INET, xtables_ipv4)) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index fb2ac8b5c12a3..11834c0ea98c5 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -360,15 +360,13 @@ static int + xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + { + const struct builtin_table *tables; +- struct nft_handle h = { +- .family = family, +- .restore = true, +- }; +- int c; + struct nft_xt_restore_parse p = { + .commit = true, + .cb = &restore_cb, + }; ++ bool noflush = false; ++ struct nft_handle h; ++ int c; + + line = 0; + +@@ -402,7 +400,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + print_usage(prog_name, PACKAGE_VERSION); + exit(0); + case 'n': +- h.noflush = 1; ++ noflush = true; + break; + case 'M': + xtables_modprobe_program = optarg; +@@ -464,13 +462,15 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + return 1; + } + +- if (nft_init(&h, tables) < 0) { ++ if (nft_init(&h, family, tables) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, + strerror(errno)); + exit(EXIT_FAILURE); + } ++ h.noflush = noflush; ++ h.restore = true; + + xtables_restore_parse(&h, &p); + +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index 3a52f8c3d8209..228282deaed07 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -139,10 +139,8 @@ xtables_save_main(int family, int argc, char *argv[], + struct do_output_data d = { + .format = FMT_NOCOUNTS, + }; ++ struct nft_handle h; + bool dump = false; +- struct nft_handle h = { +- .family = family, +- }; + FILE *file = NULL; + int ret, c; + +@@ -242,16 +240,13 @@ xtables_save_main(int family, int argc, char *argv[], + return 1; + } + +- if (nft_init(&h, tables) < 0) { ++ if (nft_init(&h, family, tables) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, + strerror(errno)); + exit(EXIT_FAILURE); + } +- h.ops = nft_family_ops_lookup(h.family); +- if (!h.ops) +- xtables_error(PARAMETER_PROBLEM, "Unknown family"); + + ret = do_output(&h, tablename, &d); + nft_fini(&h); +diff --git a/iptables/xtables-standalone.c b/iptables/xtables-standalone.c +index 1a28c5480629f..022d5dd44abbf 100644 +--- a/iptables/xtables-standalone.c ++++ b/iptables/xtables-standalone.c +@@ -44,9 +44,7 @@ xtables_main(int family, const char *progname, int argc, char *argv[]) + { + int ret; + char *table = "filter"; +- struct nft_handle h = { +- .family = family, +- }; ++ struct nft_handle h; + + xtables_globals.program_name = progname; + ret = xtables_init_all(&xtables_globals, family); +@@ -61,7 +59,7 @@ xtables_main(int family, const char *progname, int argc, char *argv[]) + init_extensions4(); + #endif + +- if (nft_init(&h, xtables_ipv4) < 0) { ++ if (nft_init(&h, family, xtables_ipv4) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, +diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c +index 0f95855b41aa4..76ad7eb69eca9 100644 +--- a/iptables/xtables-translate.c ++++ b/iptables/xtables-translate.c +@@ -480,7 +480,7 @@ static int xtables_xlate_main_common(struct nft_handle *h, + return 1; + } + +- if (nft_init(h, tables) < 0) { ++ if (nft_init(h, family, tables) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, +diff --git a/iptables/xtables.c b/iptables/xtables.c +index 8f9dc628d0029..4b24d15c46295 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -571,10 +571,6 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], + demand-load a protocol. */ + opterr = 0; + +- h->ops = nft_family_ops_lookup(h->family); +- if (h->ops == NULL) +- xtables_error(PARAMETER_PROBLEM, "Unknown family"); +- + opts = xt_params->orig_opts; + while ((cs->c = getopt_long(argc, argv, + "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::W::nt:m:xc:g:46", +-- +2.26.2 + diff --git a/SOURCES/0016-nft-cache-Fix-nft_release_cache-under-stress.patch b/SOURCES/0016-nft-cache-Fix-nft_release_cache-under-stress.patch new file mode 100644 index 0000000..ff06e05 --- /dev/null +++ b/SOURCES/0016-nft-cache-Fix-nft_release_cache-under-stress.patch @@ -0,0 +1,49 @@ +From 66b9f92ef41de90fc2b0359247c36bc6d128233d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 28 Feb 2020 20:32:13 +0100 +Subject: [PATCH] nft: cache: Fix nft_release_cache() under stress + +iptables-nft-restore calls nft_action(h, NFT_COMPAT_COMMIT) for each +COMMIT line in input. When restoring a dump containing multiple large +tables, chances are nft_rebuild_cache() has to run multiple times. + +If the above happens, consecutive table contents are added to __cache[1] +which nft_rebuild_cache() then frees, so next commit attempt accesses +invalid memory. + +Fix this by making nft_release_cache() (called after each successful +commit) return things into pre-rebuild state again, but keeping the +fresh cache copy. + +Fixes: f6ad231d698c7 ("nft: keep original cache in case of ERESTART") +Signed-off-by: Phil Sutter +(cherry picked from commit c550c81fd373e5753103d20f7902171f0fa79807) +Signed-off-by: Phil Sutter +--- + iptables/nft-cache.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c +index 7345a27e2894b..6f21f2283e0fb 100644 +--- a/iptables/nft-cache.c ++++ b/iptables/nft-cache.c +@@ -647,8 +647,14 @@ void nft_rebuild_cache(struct nft_handle *h) + + void nft_release_cache(struct nft_handle *h) + { +- if (h->cache_index) +- flush_cache(h, &h->__cache[0], NULL); ++ if (!h->cache_index) ++ return; ++ ++ flush_cache(h, &h->__cache[0], NULL); ++ memcpy(&h->__cache[0], &h->__cache[1], sizeof(h->__cache[0])); ++ memset(&h->__cache[1], 0, sizeof(h->__cache[1])); ++ h->cache_index = 0; ++ h->cache = &h->__cache[0]; + } + + struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) +-- +2.25.1 + diff --git a/SOURCES/0017-nft-cache-Fix-iptables-save-segfault-under-stress.patch b/SOURCES/0017-nft-cache-Fix-iptables-save-segfault-under-stress.patch new file mode 100644 index 0000000..accd32f --- /dev/null +++ b/SOURCES/0017-nft-cache-Fix-iptables-save-segfault-under-stress.patch @@ -0,0 +1,84 @@ +From 38c94a9f5ea03deffe0a34056a0f83a4af4641bb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 13 Mar 2020 13:02:12 +0100 +Subject: [PATCH] nft: cache: Fix iptables-save segfault under stress + +If kernel ruleset is constantly changing, code called by +nft_is_table_compatible() may crash: For each item in table's chain +list, nft_is_chain_compatible() is called. This in turn calls +nft_build_cache() to fetch chain's rules. Though if kernel genid has changed +meanwhile, cache is flushed and rebuilt from scratch, thereby freeing +table's chain list - the foreach loop in nft_is_table_compatible() then +operates on freed memory. + +A simple reproducer (may need a few calls): + +| RULESET='*filter +| :INPUT ACCEPT [10517:1483527] +| :FORWARD ACCEPT [0:0] +| :OUTPUT ACCEPT [1714:105671] +| COMMIT +| ' +| +| for ((i = 0; i < 100; i++)); do +| iptables-nft-restore <<< "$RULESET" & +| done & +| iptables-nft-save + +To fix the problem, basically revert commit ab1cd3b510fa5 ("nft: ensure +cache consistency") so that __nft_build_cache() no longer flushes the +cache. Instead just record kernel's genid when fetching for the first +time. If kernel rule set changes until the changes are committed, the +commit simply fails and local cache is being rebuilt. + +Signed-off-by: Phil Sutter +(cherry picked from commit 200bc399651499f502ac0de45f4d4aa4c9d37ab6) +Signed-off-by: Phil Sutter +--- + iptables/nft-cache.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c +index 6f21f2283e0fb..07265b7795e4f 100644 +--- a/iptables/nft-cache.c ++++ b/iptables/nft-cache.c +@@ -452,15 +452,11 @@ __nft_build_cache(struct nft_handle *h, enum nft_cache_level level, + const struct builtin_table *t, const char *set, + const char *chain) + { +- uint32_t genid_start, genid_stop; +- + if (level <= h->cache_level) + return; +-retry: +- mnl_genid_get(h, &genid_start); + +- if (h->cache_level && genid_start != h->nft_genid) +- flush_chain_cache(h, NULL); ++ if (!h->nft_genid) ++ mnl_genid_get(h, &h->nft_genid); + + switch (h->cache_level) { + case NFT_CL_NONE: +@@ -487,18 +483,10 @@ retry: + break; + } + +- mnl_genid_get(h, &genid_stop); +- if (genid_start != genid_stop) { +- flush_chain_cache(h, NULL); +- goto retry; +- } +- + if (!t && !chain) + h->cache_level = level; + else if (h->cache_level < NFT_CL_TABLES) + h->cache_level = NFT_CL_TABLES; +- +- h->nft_genid = genid_start; + } + + void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c) +-- +2.25.1 + diff --git a/SOURCES/0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch b/SOURCES/0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch new file mode 100644 index 0000000..73d9987 --- /dev/null +++ b/SOURCES/0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch @@ -0,0 +1,127 @@ +From 654b2e2512630df07e3ea57f8d54e851e75b33f1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Feb 2020 17:49:53 +0100 +Subject: [PATCH] ebtables: among: Support mixed MAC and MAC/IP entries + +Powered by Stefano's support for concatenated ranges, a full among match +replacement can be implemented. The trick is to add MAC-only elements as +a concatenation of MAC and zero-length prefix, i.e. a range from +0.0.0.0 till 255.255.255.255. + +Although not quite needed, detection of pure MAC-only matches is left in +place. For those, no implicit 'meta protocol' match is added (which is +required otherwise at least to keep nft output correct) and no concat +type is used for the set. + +Signed-off-by: Phil Sutter +(cherry picked from commit c33bae9c6c7a49c8af16df846e6112fc4727e643) +Signed-off-by: Phil Sutter +--- + extensions/libebt_among.c | 6 +----- + extensions/libebt_among.t | 2 +- + iptables/ebtables-nft.8 | 4 ---- + iptables/nft.c | 20 +++++++++++++++++++- + 4 files changed, 21 insertions(+), 11 deletions(-) + +diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c +index 715d559f432c2..2b9a1b6566684 100644 +--- a/extensions/libebt_among.c ++++ b/extensions/libebt_among.c +@@ -63,10 +63,6 @@ parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip) + char *sep = index(buf, '='); + struct ether_addr *ether; + +- if (have_ip ^ !!sep) +- xtables_error(PARAMETER_PROBLEM, +- "among: Mixed MAC and MAC=IP not allowed."); +- + if (sep) { + *sep = '\0'; + +@@ -205,7 +201,7 @@ static void __bramong_print(struct nft_among_pair *pairs, + isep = ","; + + printf("%s", ether_ntoa(&pairs[i].ether)); +- if (have_ip) ++ if (pairs[i].in.s_addr != INADDR_ANY) + printf("=%s", inet_ntoa(pairs[i].in)); + } + printf(" "); +diff --git a/extensions/libebt_among.t b/extensions/libebt_among.t +index 56b299161ff31..a02206f391cde 100644 +--- a/extensions/libebt_among.t ++++ b/extensions/libebt_among.t +@@ -13,4 +13,4 @@ + --among-src;=;FAIL + --among-src 00:11=10.0.0.1;=;FAIL + --among-src de:ad:0:be:ee:ff=10.256.0.1;=;FAIL +---among-src de:ad:0:be:ee:ff,c0:ff:ee:0:ba:be=192.168.1.1;=;FAIL ++--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff;=;OK +diff --git a/iptables/ebtables-nft.8 b/iptables/ebtables-nft.8 +index a91f0c1aacb0f..1fa5ad9388cc0 100644 +--- a/iptables/ebtables-nft.8 ++++ b/iptables/ebtables-nft.8 +@@ -551,10 +551,6 @@ Same as + .BR "--among-src-file " "[!] \fIfile\fP" + Same as + .BR --among-src " but the list is read in from the specified file." +-.PP +-Note that in this implementation of ebtables, among lists uses must be +-internally homogeneous regarding whether IP addresses are present or not. Mixed +-use of MAC addresses and MAC/IP address pairs is not supported yet. + .SS arp + Specify (R)ARP fields. The protocol must be specified as + .IR ARP " or " RARP . +diff --git a/iptables/nft.c b/iptables/nft.c +index 0287add3fb21f..4930b6de534d8 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1029,19 +1029,28 @@ static int __add_nft_among(struct nft_handle *h, const char *table, + }; + struct nftnl_expr *e; + struct nftnl_set *s; ++ uint32_t flags = 0; + int idx = 0; + + if (ip) { + type = type << CONCAT_TYPE_BITS | NFT_DATATYPE_IPADDR; + len += sizeof(struct in_addr) + NETLINK_ALIGN - 1; + len &= ~(NETLINK_ALIGN - 1); ++ flags = NFT_SET_INTERVAL; + } + +- s = add_anon_set(h, table, 0, type, len, cnt); ++ s = add_anon_set(h, table, flags, type, len, cnt); + if (!s) + return -ENOMEM; + set_id = nftnl_set_get_u32(s, NFTNL_SET_ID); + ++ if (ip) { ++ uint8_t field_len[2] = { ETH_ALEN, sizeof(struct in_addr) }; ++ ++ nftnl_set_set_data(s, NFTNL_SET_DESC_CONCAT, ++ field_len, sizeof(field_len)); ++ } ++ + for (idx = 0; idx < cnt; idx++) { + struct nftnl_set_elem *elem = nftnl_set_elem_alloc(); + +@@ -1049,6 +1058,15 @@ static int __add_nft_among(struct nft_handle *h, const char *table, + return -ENOMEM; + nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY, + &pairs[idx], len); ++ if (ip) { ++ struct in_addr tmp = pairs[idx].in; ++ ++ if (tmp.s_addr == INADDR_ANY) ++ pairs[idx].in.s_addr = INADDR_BROADCAST; ++ nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY_END, ++ &pairs[idx], len); ++ pairs[idx].in = tmp; ++ } + nftnl_set_elem_add(s, elem); + } + +-- +2.26.2 + diff --git a/SOURCES/0019-xtables-Align-effect-of-4-6-options-with-legacy.patch b/SOURCES/0019-xtables-Align-effect-of-4-6-options-with-legacy.patch new file mode 100644 index 0000000..fb77d66 --- /dev/null +++ b/SOURCES/0019-xtables-Align-effect-of-4-6-options-with-legacy.patch @@ -0,0 +1,157 @@ +From aa221d3a7ffc8e3245d9031173b306431ddfaf9f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 21 Feb 2020 13:18:32 +0100 +Subject: [PATCH] xtables: Align effect of -4/-6 options with legacy + +Legacy iptables doesn't accept -4 or -6 if they don't match the +symlink's native family. The only exception to that is iptables-restore +which simply ignores the lines introduced by non-matching options, which +is useful to create combined dump files for feeding into both +iptables-restore and ip6tables-restore. + +Signed-off-by: Phil Sutter +(cherry picked from commit 1639b8ba5105542c73e0e1c35e70f245dab89d81) +Signed-off-by: Phil Sutter +--- + .../shell/testcases/iptables/0006-46-args_0 | 88 +++++++++++++++++++ + iptables/xtables.c | 21 ++--- + 2 files changed, 96 insertions(+), 13 deletions(-) + create mode 100755 iptables/tests/shell/testcases/iptables/0006-46-args_0 + +diff --git a/iptables/tests/shell/testcases/iptables/0006-46-args_0 b/iptables/tests/shell/testcases/iptables/0006-46-args_0 +new file mode 100755 +index 0000000000000..17a0a01829df5 +--- /dev/null ++++ b/iptables/tests/shell/testcases/iptables/0006-46-args_0 +@@ -0,0 +1,88 @@ ++#!/bin/bash ++ ++RC=0 ++ ++$XT_MULTI iptables -6 -A FORWARD -j ACCEPT ++rc=$? ++if [[ $rc -ne 2 ]]; then ++ echo "'iptables -6' returned $rc instead of 2" ++ RC=1 ++fi ++ ++$XT_MULTI ip6tables -4 -A FORWARD -j ACCEPT ++rc=$? ++if [[ $rc -ne 2 ]]; then ++ echo "'ip6tables -4' returned $rc instead of 2" ++ RC=1 ++fi ++ ++RULESET='*filter ++-4 -A FORWARD -d 10.0.0.1 -j ACCEPT ++-6 -A FORWARD -d fec0:10::1 -j ACCEPT ++COMMIT ++' ++EXPECT4='-P FORWARD ACCEPT ++-A FORWARD -d 10.0.0.1/32 -j ACCEPT' ++EXPECT6='-P FORWARD ACCEPT ++-A FORWARD -d fec0:10::1/128 -j ACCEPT' ++EXPECT_EMPTY='-P FORWARD ACCEPT' ++ ++echo "$RULESET" | $XT_MULTI iptables-restore || { ++ echo "iptables-restore failed!" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT4") <($XT_MULTI iptables -S FORWARD) || { ++ echo "unexpected iptables ruleset" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT_EMPTY") <($XT_MULTI ip6tables -S FORWARD) || { ++ echo "unexpected non-empty ip6tables ruleset" ++ RC=1 ++} ++ ++$XT_MULTI iptables -F FORWARD ++ ++echo "$RULESET" | $XT_MULTI ip6tables-restore || { ++ echo "ip6tables-restore failed!" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT6") <($XT_MULTI ip6tables -S FORWARD) || { ++ echo "unexpected ip6tables ruleset" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT_EMPTY") <($XT_MULTI iptables -S FORWARD) || { ++ echo "unexpected non-empty iptables ruleset" ++ RC=1 ++} ++ ++$XT_MULTI ip6tables -F FORWARD ++ ++$XT_MULTI iptables -4 -A FORWARD -d 10.0.0.1 -j ACCEPT || { ++ echo "iptables failed!" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT4") <($XT_MULTI iptables -S FORWARD) || { ++ echo "unexpected iptables ruleset" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT_EMPTY") <($XT_MULTI ip6tables -S FORWARD) || { ++ echo "unexpected non-empty ip6tables ruleset" ++ RC=1 ++} ++ ++$XT_MULTI iptables -F FORWARD ++ ++$XT_MULTI ip6tables -6 -A FORWARD -d fec0:10::1 -j ACCEPT || { ++ echo "ip6tables failed!" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT6") <($XT_MULTI ip6tables -S FORWARD) || { ++ echo "unexpected ip6tables ruleset" ++ RC=1 ++} ++diff -u -Z <(echo -e "$EXPECT_EMPTY") <($XT_MULTI iptables -S FORWARD) || { ++ echo "unexpected non-empty iptables ruleset" ++ RC=1 ++} ++ ++exit $RC +diff --git a/iptables/xtables.c b/iptables/xtables.c +index 4b24d15c46295..8c2d21d42b7d2 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -913,27 +913,22 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], + break; + + case '4': ++ if (args->family == AF_INET) ++ break; ++ + if (p->restore && args->family == AF_INET6) + return; + +- if (args->family != AF_INET) +- exit_tryhelp(2); +- +- h->ops = nft_family_ops_lookup(args->family); +- break; ++ exit_tryhelp(2); + + case '6': ++ if (args->family == AF_INET6) ++ break; ++ + if (p->restore && args->family == AF_INET) + return; + +- args->family = AF_INET6; +- xtables_set_nfproto(AF_INET6); +- +- h->ops = nft_family_ops_lookup(args->family); +- if (h->ops == NULL) +- xtables_error(PARAMETER_PROBLEM, +- "Unknown family"); +- break; ++ exit_tryhelp(2); + + case 1: /* non option */ + if (optarg[0] == '!' && optarg[1] == '\0') { +-- +2.26.2 + diff --git a/SOURCES/0020-xtables-Drop-4-and-6-support-from-xtables-save-resto.patch b/SOURCES/0020-xtables-Drop-4-and-6-support-from-xtables-save-resto.patch new file mode 100644 index 0000000..ccd6b5d --- /dev/null +++ b/SOURCES/0020-xtables-Drop-4-and-6-support-from-xtables-save-resto.patch @@ -0,0 +1,81 @@ +From ea9d40744307d7c49808d8fabfc904d525081055 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 21 Feb 2020 13:29:05 +0100 +Subject: [PATCH] xtables: Drop -4 and -6 support from xtables-{save,restore} + +Legacy tools don't support those options, either. + +Signed-off-by: Phil Sutter +(cherry picked from commit 0f40a8bc49d3f7b815336199931a82f919f37c4e) +Signed-off-by: Phil Sutter +--- + iptables/xtables-restore.c | 9 +-------- + iptables/xtables-save.c | 11 +---------- + 2 files changed, 2 insertions(+), 18 deletions(-) + +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index 11834c0ea98c5..c472ac9bf651b 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -379,7 +379,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + exit(1); + } + +- while ((c = getopt_long(argc, argv, "bcvVthnM:T:46wW", options, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "bcvVthnM:T:wW", options, NULL)) != -1) { + switch (c) { + case 'b': + fprintf(stderr, "-b/--binary option is not implemented\n"); +@@ -408,13 +408,6 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + case 'T': + p.tablename = optarg; + break; +- case '4': +- h.family = AF_INET; +- break; +- case '6': +- h.family = AF_INET6; +- xtables_set_nfproto(AF_INET6); +- break; + case 'w': /* fallthrough. Ignored by xt-restore */ + case 'W': + if (!optarg && xs_has_arg(argc, argv)) +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index 228282deaed07..28f7490275ce5 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -32,7 +32,7 @@ + #define prog_name xtables_globals.program_name + #define prog_vers xtables_globals.program_version + +-static const char *ipt_save_optstring = "bcdt:M:f:46V"; ++static const char *ipt_save_optstring = "bcdt:M:f:V"; + static const struct option ipt_save_options[] = { + {.name = "counters", .has_arg = false, .val = 'c'}, + {.name = "version", .has_arg = false, .val = 'V'}, +@@ -40,8 +40,6 @@ static const struct option ipt_save_options[] = { + {.name = "table", .has_arg = true, .val = 't'}, + {.name = "modprobe", .has_arg = true, .val = 'M'}, + {.name = "file", .has_arg = true, .val = 'f'}, +- {.name = "ipv4", .has_arg = false, .val = '4'}, +- {.name = "ipv6", .has_arg = false, .val = '6'}, + {NULL}, + }; + +@@ -187,13 +185,6 @@ xtables_save_main(int family, int argc, char *argv[], + case 'd': + dump = true; + break; +- case '4': +- h.family = AF_INET; +- break; +- case '6': +- h.family = AF_INET6; +- xtables_set_nfproto(AF_INET6); +- break; + case 'V': + printf("%s v%s (nf_tables)\n", prog_name, prog_vers); + exit(0); +-- +2.26.2 + diff --git a/SOURCES/0021-nfnl_osf-Fix-broken-conversion-to-nfnl_query.patch b/SOURCES/0021-nfnl_osf-Fix-broken-conversion-to-nfnl_query.patch new file mode 100644 index 0000000..0ca025c --- /dev/null +++ b/SOURCES/0021-nfnl_osf-Fix-broken-conversion-to-nfnl_query.patch @@ -0,0 +1,42 @@ +From b29b3a215b9cbec20ea633e6a861accfc48b59bb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sat, 9 May 2020 13:36:49 +0200 +Subject: [PATCH] nfnl_osf: Fix broken conversion to nfnl_query() + +Due to missing NLM_F_ACK flag in request, nfnetlink code in kernel +didn't create an own ACK message but left it upon subsystem to ACK or +not. Since nfnetlink_osf doesn't ACK by itself, nfnl_query() got stuck +waiting for a reply. + +Whoever did the conversion from deprecated nfnl_talk() obviously didn't +even test basic functionality of the tool. + +Fixes: 52aa15098ebd6 ("nfnl_osf: Replace deprecated nfnl_talk() by nfnl_query()") +Signed-off-by: Phil Sutter +(cherry picked from commit c8332553caf48132403895bae750b3cd09a2efd8) +Signed-off-by: Phil Sutter +--- + utils/nfnl_osf.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/utils/nfnl_osf.c b/utils/nfnl_osf.c +index 15d531975e11d..922d90ac135b7 100644 +--- a/utils/nfnl_osf.c ++++ b/utils/nfnl_osf.c +@@ -378,9 +378,11 @@ static int osf_load_line(char *buffer, int len, int del) + memset(buf, 0, sizeof(buf)); + + if (del) +- nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_REMOVE, NLM_F_REQUEST); ++ nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_REMOVE, ++ NLM_F_ACK | NLM_F_REQUEST); + else +- nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_ADD, NLM_F_REQUEST | NLM_F_CREATE); ++ nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_ADD, ++ NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE); + + nfnl_addattr_l(nmh, sizeof(buf), OSF_ATTR_FINGER, &f, sizeof(struct xt_osf_user_finger)); + +-- +2.26.2 + diff --git a/SOURCES/0022-nfnl_osf-Improve-error-handling.patch b/SOURCES/0022-nfnl_osf-Improve-error-handling.patch new file mode 100644 index 0000000..df9cfd3 --- /dev/null +++ b/SOURCES/0022-nfnl_osf-Improve-error-handling.patch @@ -0,0 +1,80 @@ +From acc1fb93b3674f81c9d1daa0e4e855410d2568b0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sat, 9 May 2020 13:42:56 +0200 +Subject: [PATCH] nfnl_osf: Improve error handling + +For some error cases, no log message was created - hence apart from the +return code there was no indication of failing execution. + +If a line load fails, don't abort but continue with the remaining +file contents. The current pf.os file in this repository serves as +proof-of-concept: + +Lines 700 and 701: Duplicates of lines 698 and 699 because 'W*' and 'W0' +parse into the same data. + +Line 704: Duplicate of line 702 because apart from 'W*' and 'W0', only +the first three fields on right-hand side are sent to the kernel. + +When loading, these dups are ignored (they would bounce if NLM_F_EXCL +was given). Upon deletion, they cause ENOENT response from kernel. In +order to align duplicate-tolerance in both modes, just ignore that +ENOENT. + +Signed-off-by: Phil Sutter +(cherry picked from commit 3e09bd1888575cfec136574d2b0e810ba33f1cfb) +Signed-off-by: Phil Sutter +--- + utils/nfnl_osf.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/utils/nfnl_osf.c b/utils/nfnl_osf.c +index 922d90ac135b7..8008e83d8af4b 100644 +--- a/utils/nfnl_osf.c ++++ b/utils/nfnl_osf.c +@@ -392,7 +392,7 @@ static int osf_load_line(char *buffer, int len, int del) + static int osf_load_entries(char *path, int del) + { + FILE *inf; +- int err = 0; ++ int err = 0, lineno = 0; + char buf[1024]; + + inf = fopen(path, "r"); +@@ -402,7 +402,9 @@ static int osf_load_entries(char *path, int del) + } + + while(fgets(buf, sizeof(buf), inf)) { +- int len; ++ int len, rc; ++ ++ lineno++; + + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') + continue; +@@ -414,9 +416,11 @@ static int osf_load_entries(char *path, int del) + + buf[len] = '\0'; + +- err = osf_load_line(buf, len, del); +- if (err) +- break; ++ rc = osf_load_line(buf, len, del); ++ if (rc && (!del || errno != ENOENT)) { ++ ulog_err("Failed to load line %d", lineno); ++ err = rc; ++ } + + memset(buf, 0, sizeof(buf)); + } +@@ -448,6 +452,7 @@ int main(int argc, char *argv[]) + + if (!fingerprints) { + err = -ENOENT; ++ ulog("Missing fingerprints file argument.\n"); + goto err_out_exit; + } + +-- +2.26.2 + diff --git a/SOURCES/0023-nft-cache-Reset-genid-when-rebuilding-cache.patch b/SOURCES/0023-nft-cache-Reset-genid-when-rebuilding-cache.patch new file mode 100644 index 0000000..67f69ea --- /dev/null +++ b/SOURCES/0023-nft-cache-Reset-genid-when-rebuilding-cache.patch @@ -0,0 +1,37 @@ +From 3b98024d952d265d50078c5b7ad04c9c65373733 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 29 May 2020 19:33:22 +0200 +Subject: [PATCH] nft: cache: Reset genid when rebuilding cache + +This is required in order to avoid a cache rebuild loop if +iptables-nft-restore is called with '--test' parameter and a dump +containing more than a single table. + +If non-zero, __nft_build_cache() never updates genid and therefore the +incorrect genid (caused by increment in nft_action()) is never +corrected. + +This is a RHEL-only fix, upstream rewrote the whole cache logic which +implicitly resolved this problem. + +Fixes: 200bc39965149 ("nft: cache: Fix iptables-save segfault under stress") +Signed-off-by: Phil Sutter +--- + iptables/nft-cache.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c +index 07265b7795e4f..bc6e7f7eaebfb 100644 +--- a/iptables/nft-cache.c ++++ b/iptables/nft-cache.c +@@ -629,6 +629,7 @@ void nft_rebuild_cache(struct nft_handle *h) + if (h->cache_level) + __nft_flush_cache(h); + ++ h->nft_genid = 0; + h->cache_level = NFT_CL_NONE; + __nft_build_cache(h, level, NULL, NULL, NULL); + } +-- +2.26.2 + diff --git a/SOURCES/0024-nft-Fix-for-F-in-iptables-dumps.patch b/SOURCES/0024-nft-Fix-for-F-in-iptables-dumps.patch new file mode 100644 index 0000000..cf2c571 --- /dev/null +++ b/SOURCES/0024-nft-Fix-for-F-in-iptables-dumps.patch @@ -0,0 +1,81 @@ +From 8ae56bbaa4119bdcf1d6abc8b78f21490657983c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 24 Apr 2020 11:32:08 +0200 +Subject: [PATCH] nft: Fix for '-F' in iptables dumps + +When restoring a dump which contains an explicit flush command, +previously added rules are removed from cache and the following commit +will try to create netlink messages based on freed memory. + +Fix this by weeding any rule-based commands from obj_list if they +address the same chain. + +Signed-off-by: Phil Sutter +(cherry picked from commit 5bd3ab5c778033877d44a0c619ef6f98f34516af) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 4930b6de534d8..e95e99f1d8d71 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -411,6 +411,38 @@ batch_rule_add(struct nft_handle *h, enum obj_update_type type, + return batch_add(h, type, r); + } + ++static void batch_obj_del(struct nft_handle *h, struct obj_update *o); ++ ++static void batch_chain_flush(struct nft_handle *h, ++ const char *table, const char *chain) ++{ ++ struct obj_update *obj, *tmp; ++ ++ list_for_each_entry_safe(obj, tmp, &h->obj_list, head) { ++ struct nftnl_rule *r = obj->ptr; ++ ++ switch (obj->type) { ++ case NFT_COMPAT_RULE_APPEND: ++ case NFT_COMPAT_RULE_INSERT: ++ case NFT_COMPAT_RULE_REPLACE: ++ case NFT_COMPAT_RULE_DELETE: ++ break; ++ default: ++ continue; ++ } ++ ++ if (table && ++ strcmp(table, nftnl_rule_get_str(r, NFTNL_RULE_TABLE))) ++ continue; ++ ++ if (chain && ++ strcmp(chain, nftnl_rule_get_str(r, NFTNL_RULE_CHAIN))) ++ continue; ++ ++ batch_obj_del(h, obj); ++ } ++} ++ + const struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + [NFT_TABLE_RAW] = { + .name = "raw", +@@ -1671,6 +1703,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + } + + if (chain || !verbose) { ++ batch_chain_flush(h, table, chain); + __nft_rule_flush(h, table, chain, verbose, false); + flush_rule_cache(h, table, c); + return 1; +@@ -1686,6 +1719,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + while (c != NULL) { + chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + ++ batch_chain_flush(h, table, chain); + __nft_rule_flush(h, table, chain, verbose, false); + flush_rule_cache(h, table, c); + c = nftnl_chain_list_iter_next(iter); +-- +2.27.0 + diff --git a/SOURCES/0025-tests-shell-Test-F-in-dump-files.patch b/SOURCES/0025-tests-shell-Test-F-in-dump-files.patch new file mode 100644 index 0000000..628a565 --- /dev/null +++ b/SOURCES/0025-tests-shell-Test-F-in-dump-files.patch @@ -0,0 +1,37 @@ +From dd98af599516806e2eb3e1186d0ad52ce7c6b4b5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 21 Apr 2020 14:10:53 +0200 +Subject: [PATCH] tests: shell: Test -F in dump files + +While not really useful, iptables-nft-restore shouldn't segfault either. +This tests the problem described in nfbz#1407. + +Signed-off-by: Phil Sutter +(cherry picked from commit f2ace0cdf25a5911ac84015829d65d6050a5e82d) +Signed-off-by: Phil Sutter +--- + .../tests/shell/testcases/ipt-restore/0012-dash-F_0 | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + create mode 100755 iptables/tests/shell/testcases/ipt-restore/0012-dash-F_0 + +diff --git a/iptables/tests/shell/testcases/ipt-restore/0012-dash-F_0 b/iptables/tests/shell/testcases/ipt-restore/0012-dash-F_0 +new file mode 100755 +index 0000000000000..fd82afa1bc8ce +--- /dev/null ++++ b/iptables/tests/shell/testcases/ipt-restore/0012-dash-F_0 +@@ -0,0 +1,12 @@ ++#!/bin/bash -e ++ ++# make sure -F lines don't cause segfaults ++ ++RULESET='*nat ++-F PREROUTING ++-A PREROUTING -j ACCEPT ++-F PREROUTING ++COMMIT' ++ ++echo -e "$RULESET" | $XT_MULTI iptables-restore ++echo -e "$RULESET" | $XT_MULTI iptables-restore -n +-- +2.27.0 + diff --git a/SOURCES/iptables.service b/SOURCES/iptables.service index 6722c7a..39f95f9 100644 --- a/SOURCES/iptables.service +++ b/SOURCES/iptables.service @@ -1,7 +1,8 @@ [Unit] Description=IPv4 firewall with iptables -After=syslog.target AssertPathExists=/etc/sysconfig/iptables +Before=network-pre.target +Wants=network-pre.target [Service] Type=oneshot @@ -15,4 +16,4 @@ StandardOutput=syslog StandardError=syslog [Install] -WantedBy=basic.target +WantedBy=multi-user.target diff --git a/SPECS/iptables.spec b/SPECS/iptables.spec index 6168a67..4a37e0a 100644 --- a/SPECS/iptables.spec +++ b/SPECS/iptables.spec @@ -17,7 +17,7 @@ Name: iptables Summary: Tools for managing Linux kernel packet filtering capabilities URL: http://www.netfilter.org/projects/iptables Version: 1.8.4 -Release: 6%{?dist} +Release: 14%{?dist} Source: %{url}/files/%{name}-%{version}.tar.bz2 Source1: iptables.init Source2: iptables-config @@ -34,15 +34,31 @@ Source11: %{url}/files/%{name}-%{version_old}.tar.bz2 Source12: 0003-extensions-format-security-fixes-in-libip-6-t_icmp.patch %endif -Patch1: 0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch -Patch2: 0002-xtables-restore-Fix-parser-feed-from-line-buffer.patch -Patch3: 0003-xtables-restore-Avoid-access-of-uninitialized-data.patch -Patch4: 0004-extensions-time-Avoid-undefined-shift.patch -Patch5: 0005-extensions-cluster-Avoid-undefined-shift.patch -Patch6: 0006-libxtables-Avoid-buffer-overrun-in-xtables_compatibl.patch -Patch7: 0007-xtables-translate-Guard-strcpy-call-in-xlate_ifname.patch -Patch8: 0008-extensions-among-Check-call-to-fstat.patch -Patch9: 0009-uapi-netfilter-Avoid-undefined-left-shift-in-xt_sctp.patch +Patch01: 0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch +Patch02: 0002-xtables-restore-Fix-parser-feed-from-line-buffer.patch +Patch03: 0003-xtables-restore-Avoid-access-of-uninitialized-data.patch +Patch04: 0004-extensions-time-Avoid-undefined-shift.patch +Patch05: 0005-extensions-cluster-Avoid-undefined-shift.patch +Patch06: 0006-libxtables-Avoid-buffer-overrun-in-xtables_compatibl.patch +Patch07: 0007-xtables-translate-Guard-strcpy-call-in-xlate_ifname.patch +Patch08: 0008-extensions-among-Check-call-to-fstat.patch +Patch09: 0009-uapi-netfilter-Avoid-undefined-left-shift-in-xt_sctp.patch +Patch10: 0010-xtables-translate-Fix-for-interface-name-corner-case.patch +Patch11: 0011-xtables-translate-Fix-for-iface.patch +Patch12: 0012-tests-shell-Fix-skip-checks-with-host-mode.patch +Patch13: 0013-xtables-restore-fix-for-noflush-and-empty-lines.patch +Patch14: 0014-iptables-test.py-Fix-host-mode.patch +Patch15: 0015-xtables-Review-nft_init.patch +Patch16: 0016-nft-cache-Fix-nft_release_cache-under-stress.patch +Patch17: 0017-nft-cache-Fix-iptables-save-segfault-under-stress.patch +Patch18: 0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch +Patch19: 0019-xtables-Align-effect-of-4-6-options-with-legacy.patch +Patch20: 0020-xtables-Drop-4-and-6-support-from-xtables-save-resto.patch +Patch21: 0021-nfnl_osf-Fix-broken-conversion-to-nfnl_query.patch +Patch22: 0022-nfnl_osf-Improve-error-handling.patch +Patch23: 0023-nft-cache-Reset-genid-when-rebuilding-cache.patch +Patch24: 0024-nft-Fix-for-F-in-iptables-dumps.patch +Patch25: 0025-tests-shell-Test-F-in-dump-files.patch # pf.os: ISC license # iptables-apply: Artistic Licence 2.0 @@ -451,6 +467,39 @@ done %doc %{_mandir}/man8/ebtables*.8* %changelog +* Wed Jun 24 2020 Phil Sutter - 1.8.4-14 +- nft: Fix for '-F' in iptables dumps +- tests: shell: Test -F in dump files + +* Fri May 29 2020 Phil Sutter - 1.8.4-13 +- Fix for endless loop in iptables-restore --test + +* Tue May 26 2020 Phil Sutter - 1.8.4-12 +- Unbreak nfnl_osf tool + +* Tue May 19 2020 Phil Sutter - 1.8.4-11 +- Complete ebtables-nft among match support +- Replace RHEL-only xtables-monitor fix with upstream solution +- xtables: Align effect of -4/-6 options with legacy +- xtables: Drop -4 and -6 support from xtables-{save,restore} +- Review systemd unit files + +* Tue Mar 17 2020 Phil Sutter - 1.8.4-10 +- Fix for iptables-restore segfault under pressure +- Fix for iptables-save segfault under pressure + +* Mon Feb 24 2020 Phil Sutter - 1.8.4-9 +- iptables-test.py: Fix --host mode +- xtables-monitor: Fix segfault when tracing + +* Sat Feb 15 2020 Phil Sutter - 1.8.4-8 +- xtables-translate: Fix for iface++ +- tests: shell: Fix skip checks with --host mode +- xtables-restore: fix for --noflush and empty lines + +* Wed Feb 12 2020 Phil Sutter - 1.8.4-7 +- xtables-translate: Fix for interface name corner-cases + * Mon Dec 09 2019 Phil Sutter - 1.8.4-6 - Add missing patch in last release, uAPI covscan fix