diff --git a/backport-libiptc-Fix-for-another-segfault-due-to-chain-index-NULL-pointer.patch b/backport-libiptc-Fix-for-another-segfault-due-to-chain-index-NULL-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..f9115e0ffc1cc5f7f53b6c0142a91f24aeb7546d --- /dev/null +++ b/backport-libiptc-Fix-for-another-segfault-due-to-chain-index-NULL-pointer.patch @@ -0,0 +1,82 @@ +From e2d7ee9c49b582f399ad4ba2da2ee1b3e1f89620 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 12 Oct 2023 17:27:42 +0200 +Subject: libiptc: Fix for another segfault due to chain index NULL pointer + +Chain rename code missed to adjust the num_chains value which is used to +calculate the number of chain index buckets to allocate during an index +rebuild. So with the right number of chains present, the last chain in a +middle bucket being renamed (and ending up in another bucket) triggers +an index rebuild based on false data. The resulting NULL pointer index +bucket then causes a segfault upon reinsertion. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1713 +Fixes: 64ff47cde38e4 ("libiptc: fix chain rename bug in libiptc") +--- + .../shell/testcases/chain/0008rename-segfault2_0 | 32 ++++++++++++++++++++++ + libiptc/libiptc.c | 4 +++ + 2 files changed, 36 insertions(+) + create mode 100755 iptables/tests/shell/testcases/chain/0008rename-segfault2_0 + +diff --git a/iptables/tests/shell/testcases/chain/0008rename-segfault2_0 b/iptables/tests/shell/testcases/chain/0008rename-segfault2_0 +new file mode 100755 +index 00000000..bc473d25 +--- /dev/null ++++ b/iptables/tests/shell/testcases/chain/0008rename-segfault2_0 +@@ -0,0 +1,32 @@ ++#!/bin/bash ++# ++# Another funny rename bug in libiptc: ++# If there is a chain index bucket with only a single chain in it and it is not ++# the last one and that chain is renamed, a chain index rebuild is triggered. ++# Since TC_RENAME_CHAIN missed to temporarily decrement num_chains value, an ++# extra index is allocated and remains NULL. The following insert of renamed ++# chain then segfaults. ++ ++( ++ echo "*filter" ++ # first bucket ++ for ((i = 0; i < 40; i++)); do ++ echo ":chain-a-$i - [0:0]" ++ done ++ # second bucket ++ for ((i = 0; i < 40; i++)); do ++ echo ":chain-b-$i - [0:0]" ++ done ++ # third bucket, just make sure it exists ++ echo ":chain-c-0 - [0:0]" ++ echo "COMMIT" ++) | $XT_MULTI iptables-restore ++ ++# rename all chains of the middle bucket ++( ++ echo "*filter" ++ for ((i = 0; i < 40; i++)); do ++ echo "-E chain-b-$i chain-d-$i" ++ done ++ echo "COMMIT" ++) | $XT_MULTI iptables-restore --noflush +diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c +index e4750633..9712a363 100644 +--- a/libiptc/libiptc.c ++++ b/libiptc/libiptc.c +@@ -2384,12 +2384,16 @@ int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, + return 0; + } + ++ handle->num_chains--; ++ + /* This only unlinks "c" from the list, thus no free(c) */ + iptcc_chain_index_delete_chain(c, handle); + + /* Change the name of the chain */ + strncpy(c->name, newname, sizeof(IPT_CHAINLABEL) - 1); + ++ handle->num_chains++; ++ + /* Insert sorted into to list again */ + iptc_insert_chain(handle, c); + +-- +cgit v1.2.3 + diff --git a/backport-libiptc-Fix-for-segfault-when-renaming-a-chain.patch b/backport-libiptc-Fix-for-segfault-when-renaming-a-chain.patch new file mode 100644 index 0000000000000000000000000000000000000000..aebc516703fb6343a02ec8541444252fd3767433 --- /dev/null +++ b/backport-libiptc-Fix-for-segfault-when-renaming-a-chain.patch @@ -0,0 +1,66 @@ +From 97bf4e68fc0794adba3243fd96f40f4568e7216f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 7 Oct 2022 18:29:07 +0200 +Subject: libiptc: Fix for segfault when renaming a chain + +This is an odd bug: If the number of chains is right and one renames the +last one in the list, libiptc dereferences a NULL pointer. Add fix and +test case for it. + +Fixes: 64ff47cde38e4 ("libiptc: fix chain rename bug in libiptc") +Reported-by: Julien Castets +Signed-off-by: Phil Sutter +--- + .../tests/shell/testcases/chain/0006rename-segfault_0 | 19 +++++++++++++++++++ + libiptc/libiptc.c | 9 +++++++++ + 2 files changed, 28 insertions(+) + create mode 100755 iptables/tests/shell/testcases/chain/0006rename-segfault_0 + +diff --git a/iptables/tests/shell/testcases/chain/0006rename-segfault_0 b/iptables/tests/shell/testcases/chain/0006rename-segfault_0 +new file mode 100755 +index 00000000..c10a8006 +--- /dev/null ++++ b/iptables/tests/shell/testcases/chain/0006rename-segfault_0 +@@ -0,0 +1,19 @@ ++#!/bin/bash ++# ++# Cover for a bug in libiptc: ++# - the chain 'node-98-tmp' is the last in the list sorted by name ++# - there are 81 chains in total, so three chain index buckets ++# - the last index bucket contains only the 'node-98-tmp' chain ++# => rename temporarily removes it from the bucket, leaving a NULL bucket ++# behind which is dereferenced later when inserting the chain again with new ++# name again ++ ++( ++ echo "*filter" ++ for chain in node-1 node-10 node-101 node-102 node-104 node-107 node-11 node-12 node-13 node-14 node-15 node-16 node-17 node-18 node-19 node-2 node-20 node-21 node-22 node-23 node-25 node-26 node-27 node-28 node-29 node-3 node-30 node-31 node-32 node-33 node-34 node-36 node-37 node-39 node-4 node-40 node-41 node-42 node-43 node-44 node-45 node-46 node-47 node-48 node-49 node-5 node-50 node-51 node-53 node-54 node-55 node-56 node-57 node-58 node-59 node-6 node-60 node-61 node-62 node-63 node-64 node-65 node-66 node-68 node-69 node-7 node-70 node-71 node-74 node-75 node-76 node-8 node-80 node-81 node-86 node-89 node-9 node-92 node-93 node-95 node-98-tmp; do ++ echo ":$chain - [0:0]" ++ done ++ echo "COMMIT" ++) | $XT_MULTI iptables-restore ++$XT_MULTI iptables -E node-98-tmp node-98 ++exit $? +diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c +index ceeb017b..97823f93 100644 +--- a/libiptc/libiptc.c ++++ b/libiptc/libiptc.c +@@ -606,6 +606,15 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handl + + if (index_ptr == &c->list) { /* Chain used as index ptr */ + ++ /* If this is the last chain in the list, its index bucket just ++ * became empty. Adjust the size to avoid a NULL-pointer deref ++ * later. ++ */ ++ if (next == &h->chains) { ++ h->chain_index_sz--; ++ return 0; ++ } ++ + /* See if its possible to avoid a rebuild, by shifting + * to next pointer. Its possible if the next pointer + * is located in the same index bucket. +-- +cgit v1.2.3 + diff --git a/iptables.spec b/iptables.spec index fd917e15518297491e99282ac7b6270c71c14d4b..e9a3a8aba12dbc3d38c4b3da008eef520f288c93 100644 --- a/iptables.spec +++ b/iptables.spec @@ -2,7 +2,7 @@ %global legacy_actions %{_libexecdir}/initscripts/legacy-actions Name: iptables Version: 1.8.7 -Release: 14 +Release: 15 Summary: IP packet filter administration utilities License: GPLv2 and Artistic Licence 2.0 and ISC URL: https://www.netfilter.org/ @@ -32,6 +32,8 @@ Patch14: backport-iptables-Plug-memleaks-in-print_firewall.patch Patch15: backport-ebtables-translate-Print-flush-command-after-parsing-is-finished.patch Patch16: backport-xtables-eb-fix-crash-when-opts-isn-t-reallocated.patch Patch17: backport-iptables-Fix-handling-of-non-existent-chains.patch +Patch18: backport-libiptc-Fix-for-segfault-when-renaming-a-chain.patch +Patch19: backport-libiptc-Fix-for-another-segfault-due-to-chain-index-NULL-pointer.patch BuildRequires: bison flex gcc kernel-headers libpcap-devel libselinux-devel systemd BuildRequires: libmnl-devel libnetfilter_conntrack-devel libnfnetlink-devel libnftnl-devel @@ -340,6 +342,13 @@ fi %{_mandir}/man8/xtables-legacy* %changelog +* Mon Apr 15 2024 liweigang - 1.8.7-15 +- Type: bugfix +- CVE: NA +- SUG: NA +- DESC: libiptc: Fix for segfault when renaming a chain +- DESC: libiptc: Fix for another segfault due to chain index NULL pointer + * Mon Aug 14 2023 zhanghao - 1.8.7-14 - Type:bugfix - CVE:NA