Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_conntrack: don't send destroy events from iterator

Let nf_ct_delete handle delivery of the DESTROY event.

Based on earlier patch from Pablo Neira.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
c655bc68 54e35cc5

+14 -40
+3 -1
include/net/netfilter/nf_conntrack.h
··· 248 248 249 249 /* Iterate over all conntracks: if iter returns true, it's deleted. */ 250 250 extern void 251 - nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data); 251 + nf_ct_iterate_cleanup(struct net *net, 252 + int (*iter)(struct nf_conn *i, void *data), 253 + void *data, u32 portid, int report); 252 254 extern void nf_conntrack_free(struct nf_conn *ct); 253 255 extern struct nf_conn * 254 256 nf_conntrack_alloc(struct net *net, u16 zone,
+1 -1
net/ipv4/netfilter/ipt_MASQUERADE.c
··· 118 118 NF_CT_ASSERT(dev->ifindex != 0); 119 119 120 120 nf_ct_iterate_cleanup(net, device_cmp, 121 - (void *)(long)dev->ifindex); 121 + (void *)(long)dev->ifindex, 0, 0); 122 122 } 123 123 124 124 return NOTIFY_DONE;
+1 -1
net/ipv6/netfilter/ip6t_MASQUERADE.c
··· 76 76 77 77 if (event == NETDEV_DOWN) 78 78 nf_ct_iterate_cleanup(net, device_cmp, 79 - (void *)(long)dev->ifindex); 79 + (void *)(long)dev->ifindex, 0, 0); 80 80 81 81 return NOTIFY_DONE; 82 82 }
+4 -32
net/netfilter/nf_conntrack_core.c
··· 1246 1246 1247 1247 void nf_ct_iterate_cleanup(struct net *net, 1248 1248 int (*iter)(struct nf_conn *i, void *data), 1249 - void *data) 1249 + void *data, u32 portid, int report) 1250 1250 { 1251 1251 struct nf_conn *ct; 1252 1252 unsigned int bucket = 0; ··· 1254 1254 while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) { 1255 1255 /* Time to push up daises... */ 1256 1256 if (del_timer(&ct->timeout)) 1257 - death_by_timeout((unsigned long)ct); 1257 + nf_ct_delete(ct, portid, report); 1258 1258 1259 1259 /* ... else the timer will get him soon. */ 1260 1260 ··· 1262 1262 } 1263 1263 } 1264 1264 EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); 1265 - 1266 - struct __nf_ct_flush_report { 1267 - u32 portid; 1268 - int report; 1269 - }; 1270 - 1271 - static int kill_report(struct nf_conn *i, void *data) 1272 - { 1273 - struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data; 1274 - struct nf_conn_tstamp *tstamp; 1275 - 1276 - tstamp = nf_conn_tstamp_find(i); 1277 - if (tstamp && tstamp->stop == 0) 1278 - tstamp->stop = ktime_to_ns(ktime_get_real()); 1279 - 1280 - /* If we fail to deliver the event, death_by_timeout() will retry */ 1281 - if (nf_conntrack_event_report(IPCT_DESTROY, i, 1282 - fr->portid, fr->report) < 0) 1283 - return 1; 1284 - 1285 - /* Avoid the delivery of the destroy event in death_by_timeout(). */ 1286 - set_bit(IPS_DYING_BIT, &i->status); 1287 - return 1; 1288 - } 1289 1265 1290 1266 static int kill_all(struct nf_conn *i, void *data) 1291 1267 { ··· 1280 1304 1281 1305 void nf_conntrack_flush_report(struct net *net, u32 portid, int report) 1282 1306 { 1283 - struct __nf_ct_flush_report fr = { 1284 - .portid = portid, 1285 - .report = report, 1286 - }; 1287 - nf_ct_iterate_cleanup(net, kill_report, &fr); 1307 + nf_ct_iterate_cleanup(net, kill_all, NULL, portid, report); 1288 1308 } 1289 1309 EXPORT_SYMBOL_GPL(nf_conntrack_flush_report); 1290 1310 ··· 1361 1389 i_see_dead_people: 1362 1390 busy = 0; 1363 1391 list_for_each_entry(net, net_exit_list, exit_list) { 1364 - nf_ct_iterate_cleanup(net, kill_all, NULL); 1392 + nf_ct_iterate_cleanup(net, kill_all, NULL, 0, 0); 1365 1393 nf_ct_release_dying_list(net); 1366 1394 if (atomic_read(&net->ct.count) != 0) 1367 1395 busy = 1;
+2 -2
net/netfilter/nf_conntrack_proto.c
··· 281 281 nf_ct_l3proto_unregister_sysctl(net, proto); 282 282 283 283 /* Remove all contrack entries for this protocol */ 284 - nf_ct_iterate_cleanup(net, kill_l3proto, proto); 284 + nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0); 285 285 } 286 286 EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_unregister); 287 287 ··· 476 476 nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); 477 477 478 478 /* Remove all contrack entries for this protocol */ 479 - nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); 479 + nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0); 480 480 } 481 481 EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister); 482 482
+3 -3
net/netfilter/nf_nat_core.c
··· 497 497 498 498 rtnl_lock(); 499 499 for_each_net(net) 500 - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean); 500 + nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0); 501 501 rtnl_unlock(); 502 502 } 503 503 ··· 511 511 rtnl_lock(); 512 512 513 513 for_each_net(net) 514 - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean); 514 + nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0); 515 515 rtnl_unlock(); 516 516 } 517 517 ··· 749 749 { 750 750 struct nf_nat_proto_clean clean = {}; 751 751 752 - nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean); 752 + nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean, 0, 0); 753 753 synchronize_rcu(); 754 754 nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size); 755 755 }