summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@netfilter.org>2023-09-19 20:04:45 +0200
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2023-10-24 16:42:29 +0000
commit79083beef4e0cff12d93b930dbaf806245fc4eaa (patch)
treecab935d6a44927db759a4e4273d1c394f5e4b71c
parent339eb779339480fdb00d54f35f9db17289db342c (diff)
downloadcommon-79083beef4e0cff12d93b930dbaf806245fc4eaa.tar.gz
UPSTREAM: netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP
[ Upstream commit 7433b6d2afd512d04398c73aa984d1e285be125b ] Kyle Zeng reported that there is a race between IPSET_CMD_ADD and IPSET_CMD_SWAP in netfilter/ip_set, which can lead to the invocation of `__ip_set_put` on a wrong `set`, triggering the `BUG_ON(set->ref == 0);` check in it. The race is caused by using the wrong reference counter, i.e. the ref counter instead of ref_netlink. Bug: 303172721 Fixes: 24e227896bbf ("netfilter: ipset: Add schedule point in call_ad().") Reported-by: Kyle Zeng <zengyhkyle@gmail.com> Closes: https://lore.kernel.org/netfilter-devel/ZPZqetxOmH+w%2Fmyc@westworld/#r Tested-by: Kyle Zeng <zengyhkyle@gmail.com> Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit ea5a61d58886ae875f1b4a371999f2a8b58cf26d) Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I33a6a6234830c600a4ebd62ed1fee3a48876b98d
-rw-r--r--net/netfilter/ipset/ip_set_core.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 55ac0cc12657..26613e3731d0 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -683,6 +683,14 @@ __ip_set_put(struct ip_set *set)
* a separate reference counter
*/
static void
+__ip_set_get_netlink(struct ip_set *set)
+{
+ write_lock_bh(&ip_set_ref_lock);
+ set->ref_netlink++;
+ write_unlock_bh(&ip_set_ref_lock);
+}
+
+static void
__ip_set_put_netlink(struct ip_set *set)
{
write_lock_bh(&ip_set_ref_lock);
@@ -1705,11 +1713,11 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
do {
if (retried) {
- __ip_set_get(set);
+ __ip_set_get_netlink(set);
nfnl_unlock(NFNL_SUBSYS_IPSET);
cond_resched();
nfnl_lock(NFNL_SUBSYS_IPSET);
- __ip_set_put(set);
+ __ip_set_put_netlink(set);
}
ip_set_lock(set);