]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: ipset: do not update comments from kernel-side hash adds
authorDavid Lee <david.lee@trailofbits.com>
Mon, 13 Jul 2026 09:59:15 +0000 (09:59 +0000)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 23 Jul 2026 15:58:46 +0000 (17:58 +0200)
mtype_resize() copies comment pointers with memcpy(), not the comment
objects themselves. During the window after an entry has been copied but
before the table swap and backlog replay, the old table is still
published for packet-side updates while the replacement-table entry
already holds the same ip_set_comment_rcu pointer.

If xt_SET --add-set ... --exist hits that old entry in this window,
mtype_add() calls ip_set_init_comment() even though packet-side adds
carry no comment payload. That call frees the shared comment through the
old entry, so the replacement-table entry now holds a stale pointer.
When the queued add is replayed on the new table, mtype_add() calls
ip_set_init_comment() again and strlen() dereferences the stale pointer.

Fix this in mtype_add() by skipping ip_set_init_comment() when
ext->target marks a packet-side add. Userspace adds still update
comments, while packet-side adds can no longer free comment storage
shared with a resize copy.

Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
Cc: stable@vger.kernel.org
Signed-off-by: David Lee <david.lee@trailofbits.com>
Assisted-by: Codex:gpt-5.5
Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/ipset/ip_set_hash_gen.h

index 8231317b0f1f4bf145923756c287faccb839aebf..b2d77973272d25e1bfe10043b2f373ee46a3a617 100644 (file)
@@ -1005,7 +1005,7 @@ overwrite_extensions:
 #endif
        if (SET_WITH_COUNTER(set))
                ip_set_init_counter(ext_counter(data, set), ext);
-       if (SET_WITH_COMMENT(set))
+       if (SET_WITH_COMMENT(set) && !ext->target)
                ip_set_init_comment(set, ext_comment(data, set), ext);
        if (SET_WITH_SKBINFO(set))
                ip_set_init_skbinfo(ext_skbinfo(data, set), ext);