aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2018-10-30 17:43:42 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2018-11-03 08:28:01 -0400
commit8a02bdd50b2ecb6d62121d2958d3ea186cc88ce7 (patch)
treeda24e01ea80e6ecccc657fe8891ae5925874d58c
parent54451f60c8fa061af9051a53be9786393947367c (diff)
netfilter: ipset: Fix calling ip_set() macro at dumping
The ip_set() macro is called when either ip_set_ref_lock held only or no lock/nfnl mutex is held at dumping. Take this into account properly. Also, use Pablo's suggestion to use rcu_dereference_raw(), the ref_netlink protects the set. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/ipset/ip_set_core.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 68db946df151..1577f2f76060 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -55,11 +55,15 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
55MODULE_DESCRIPTION("core IP set support"); 55MODULE_DESCRIPTION("core IP set support");
56MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); 56MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
57 57
58/* When the nfnl mutex is held: */ 58/* When the nfnl mutex or ip_set_ref_lock is held: */
59#define ip_set_dereference(p) \ 59#define ip_set_dereference(p) \
60 rcu_dereference_protected(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) 60 rcu_dereference_protected(p, \
61 lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
62 lockdep_is_held(&ip_set_ref_lock))
61#define ip_set(inst, id) \ 63#define ip_set(inst, id) \
62 ip_set_dereference((inst)->ip_set_list)[id] 64 ip_set_dereference((inst)->ip_set_list)[id]
65#define ip_set_ref_netlink(inst,id) \
66 rcu_dereference_raw((inst)->ip_set_list)[id]
63 67
64/* The set types are implemented in modules and registered set types 68/* The set types are implemented in modules and registered set types
65 * can be found in ip_set_type_list. Adding/deleting types is 69 * can be found in ip_set_type_list. Adding/deleting types is
@@ -1251,7 +1255,7 @@ ip_set_dump_done(struct netlink_callback *cb)
1251 struct ip_set_net *inst = 1255 struct ip_set_net *inst =
1252 (struct ip_set_net *)cb->args[IPSET_CB_NET]; 1256 (struct ip_set_net *)cb->args[IPSET_CB_NET];
1253 ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX]; 1257 ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
1254 struct ip_set *set = ip_set(inst, index); 1258 struct ip_set *set = ip_set_ref_netlink(inst, index);
1255 1259
1256 if (set->variant->uref) 1260 if (set->variant->uref)
1257 set->variant->uref(set, cb, false); 1261 set->variant->uref(set, cb, false);
@@ -1440,7 +1444,7 @@ next_set:
1440release_refcount: 1444release_refcount:
1441 /* If there was an error or set is done, release set */ 1445 /* If there was an error or set is done, release set */
1442 if (ret || !cb->args[IPSET_CB_ARG0]) { 1446 if (ret || !cb->args[IPSET_CB_ARG0]) {
1443 set = ip_set(inst, index); 1447 set = ip_set_ref_netlink(inst, index);
1444 if (set->variant->uref) 1448 if (set->variant->uref)
1445 set->variant->uref(set, cb, false); 1449 set->variant->uref(set, cb, false);
1446 pr_debug("release set %s\n", set->name); 1450 pr_debug("release set %s\n", set->name);