Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
netfilter: ipset: Fix for recursive locking warning
Browse files Browse the repository at this point in the history
[ Upstream commit 70b6f46 ]

With CONFIG_PROVE_LOCKING, when creating a set of type bitmap:ip, adding
it to a set of type list:set and populating it from iptables SET target
triggers a kernel warning:

| WARNING: possible recursive locking detected
| 6.12.0-rc7-01692-g5e9a28f41134-dirty torvalds#594 Not tainted
| --------------------------------------------
| ping/4018 is trying to acquire lock:
| ffff8881094a6848 (&set->lock){+.-.}-{2:2}, at: ip_set_add+0x28c/0x360 [ip_set]
|
| but task is already holding lock:
| ffff88811034c048 (&set->lock){+.-.}-{2:2}, at: ip_set_add+0x28c/0x360 [ip_set]

This is a false alarm: ipset does not allow nested list:set type, so the
loop in list_set_kadd() can never encounter the outer set itself. No
other set type supports embedded sets, so this is the only case to
consider.

To avoid the false report, create a distinct lock class for list:set
type ipset locks.

Fixes: f830837 ("netfilter: ipset: list:set set type support")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Phil Sutter authored and gregkh committed Dec 23, 2024
1 parent b8d964e commit 6882bff
Showing 1 changed file with 3 additions and 0 deletions.
3 changes: 3 additions & 0 deletions net/netfilter/ipset/ip_set_list_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,8 @@ init_list_set(struct net *net, struct ip_set *set, u32 size)
return true;
}

static struct lock_class_key list_set_lockdep_key;

static int
list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
u32 flags)
Expand All @@ -627,6 +629,7 @@ list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (size < IP_SET_LIST_MIN_SIZE)
size = IP_SET_LIST_MIN_SIZE;

lockdep_set_class(&set->lock, &list_set_lockdep_key);
set->variant = &set_variant;
set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem),
__alignof__(struct set_elem));
Expand Down

0 comments on commit 6882bff

Please sign in to comment.