Skip to content

Commit f75b8da

Browse files
committed
netfilter: conntrack: add nf_ct_iter_data object for nf_ct_iterate_cleanup*()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2111270 Upstream Status: commit 8169ff5 commit 8169ff5 Author: Pablo Neira Ayuso <[email protected]> Date: Fri Apr 8 13:10:19 2022 +0200 netfilter: conntrack: add nf_ct_iter_data object for nf_ct_iterate_cleanup*() This patch adds a structure to collect all the context data that is passed to the cleanup iterator. struct nf_ct_iter_data { struct net *net; void *data; u32 portid; int report; }; There is a netns field that allows to clean up conntrack entries specifically owned by the specified netns. Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent dc33543 commit f75b8da

File tree

6 files changed

+56
-44
lines changed

6 files changed

+56
-44
lines changed

include/net/netfilter/nf_conntrack.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,16 @@ static inline bool nf_ct_kill(struct nf_conn *ct)
236236
return nf_ct_delete(ct, 0, 0);
237237
}
238238

239+
struct nf_ct_iter_data {
240+
struct net *net;
241+
void *data;
242+
u32 portid;
243+
int report;
244+
};
245+
239246
/* Iterate over all conntracks: if iter returns true, it's deleted. */
240-
void nf_ct_iterate_cleanup_net(struct net *net,
241-
int (*iter)(struct nf_conn *i, void *data),
242-
void *data, u32 portid, int report);
247+
void nf_ct_iterate_cleanup_net(int (*iter)(struct nf_conn *i, void *data),
248+
const struct nf_ct_iter_data *iter_data);
243249

244250
/* also set unconfirmed conntracks as dying. Only use in module exit path. */
245251
void nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data),

net/netfilter/nf_conntrack_core.c

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,7 +2356,7 @@ static bool nf_conntrack_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
23562356
/* Bring out ya dead! */
23572357
static struct nf_conn *
23582358
get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
2359-
void *data, unsigned int *bucket)
2359+
const struct nf_ct_iter_data *iter_data, unsigned int *bucket)
23602360
{
23612361
struct nf_conntrack_tuple_hash *h;
23622362
struct nf_conn *ct;
@@ -2387,7 +2387,12 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
23872387
* tuple while iterating.
23882388
*/
23892389
ct = nf_ct_tuplehash_to_ctrack(h);
2390-
if (iter(ct, data))
2390+
2391+
if (iter_data->net &&
2392+
!net_eq(iter_data->net, nf_ct_net(ct)))
2393+
continue;
2394+
2395+
if (iter(ct, iter_data->data))
23912396
goto found;
23922397
}
23932398
spin_unlock(lockp);
@@ -2404,57 +2409,36 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
24042409
}
24052410

24062411
static void nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data),
2407-
void *data, u32 portid, int report)
2412+
const struct nf_ct_iter_data *iter_data)
24082413
{
24092414
unsigned int bucket = 0;
24102415
struct nf_conn *ct;
24112416

24122417
might_sleep();
24132418

24142419
mutex_lock(&nf_conntrack_mutex);
2415-
while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
2420+
while ((ct = get_next_corpse(iter, iter_data, &bucket)) != NULL) {
24162421
/* Time to push up daises... */
24172422

2418-
nf_ct_delete(ct, portid, report);
2423+
nf_ct_delete(ct, iter_data->portid, iter_data->report);
24192424
nf_ct_put(ct);
24202425
cond_resched();
24212426
}
24222427
mutex_unlock(&nf_conntrack_mutex);
24232428
}
24242429

2425-
struct iter_data {
2426-
int (*iter)(struct nf_conn *i, void *data);
2427-
void *data;
2428-
struct net *net;
2429-
};
2430-
2431-
static int iter_net_only(struct nf_conn *i, void *data)
2432-
{
2433-
struct iter_data *d = data;
2434-
2435-
if (!net_eq(d->net, nf_ct_net(i)))
2436-
return 0;
2437-
2438-
return d->iter(i, d->data);
2439-
}
2440-
2441-
void nf_ct_iterate_cleanup_net(struct net *net,
2442-
int (*iter)(struct nf_conn *i, void *data),
2443-
void *data, u32 portid, int report)
2430+
void nf_ct_iterate_cleanup_net(int (*iter)(struct nf_conn *i, void *data),
2431+
const struct nf_ct_iter_data *iter_data)
24442432
{
2433+
struct net *net = iter_data->net;
24452434
struct nf_conntrack_net *cnet = nf_ct_pernet(net);
2446-
struct iter_data d;
24472435

24482436
might_sleep();
24492437

24502438
if (atomic_read(&cnet->count) == 0)
24512439
return;
24522440

2453-
d.iter = iter;
2454-
d.data = data;
2455-
d.net = net;
2456-
2457-
nf_ct_iterate_cleanup(iter_net_only, &d, portid, report);
2441+
nf_ct_iterate_cleanup(iter, iter_data);
24582442
}
24592443
EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup_net);
24602444

@@ -2472,6 +2456,7 @@ EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup_net);
24722456
void
24732457
nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data)
24742458
{
2459+
struct nf_ct_iter_data iter_data = {};
24752460
struct net *net;
24762461

24772462
down_read(&net_rwsem);
@@ -2499,7 +2484,8 @@ nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data)
24992484
synchronize_net();
25002485

25012486
nf_ct_ext_bump_genid();
2502-
nf_ct_iterate_cleanup(iter, data, 0, 0);
2487+
iter_data.data = data;
2488+
nf_ct_iterate_cleanup(iter, &iter_data);
25032489

25042490
/* Another cpu might be in a rcu read section with
25052491
* rcu protected pointer cleared in iter callback
@@ -2513,7 +2499,7 @@ EXPORT_SYMBOL_GPL(nf_ct_iterate_destroy);
25132499

25142500
static int kill_all(struct nf_conn *i, void *data)
25152501
{
2516-
return net_eq(nf_ct_net(i), data);
2502+
return 1;
25172503
}
25182504

25192505
void nf_conntrack_cleanup_start(void)
@@ -2548,8 +2534,9 @@ void nf_conntrack_cleanup_net(struct net *net)
25482534

25492535
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
25502536
{
2551-
int busy;
2537+
struct nf_ct_iter_data iter_data = {};
25522538
struct net *net;
2539+
int busy;
25532540

25542541
/*
25552542
* This makes sure all current packets have passed through
@@ -2562,7 +2549,8 @@ void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
25622549
list_for_each_entry(net, net_exit_list, exit_list) {
25632550
struct nf_conntrack_net *cnet = nf_ct_pernet(net);
25642551

2565-
nf_ct_iterate_cleanup(kill_all, net, 0, 0);
2552+
iter_data.net = net;
2553+
nf_ct_iterate_cleanup_net(kill_all, &iter_data);
25662554
if (atomic_read(&cnet->count) != 0)
25672555
busy = 1;
25682556
}

net/netfilter/nf_conntrack_netlink.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,11 @@ static int ctnetlink_flush_conntrack(struct net *net,
15601560
u32 portid, int report, u8 family)
15611561
{
15621562
struct ctnetlink_filter *filter = NULL;
1563+
struct nf_ct_iter_data iter = {
1564+
.net = net,
1565+
.portid = portid,
1566+
.report = report,
1567+
};
15631568

15641569
if (ctnetlink_needs_filter(family, cda)) {
15651570
if (cda[CTA_FILTER])
@@ -1568,10 +1573,11 @@ static int ctnetlink_flush_conntrack(struct net *net,
15681573
filter = ctnetlink_alloc_filter(cda, family);
15691574
if (IS_ERR(filter))
15701575
return PTR_ERR(filter);
1576+
1577+
iter.data = filter;
15711578
}
15721579

1573-
nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter,
1574-
portid, report);
1580+
nf_ct_iterate_cleanup_net(ctnetlink_flush_iterate, &iter);
15751581
kfree(filter);
15761582

15771583
return 0;

net/netfilter/nf_conntrack_proto.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,9 +538,13 @@ static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
538538
out_unlock:
539539
mutex_unlock(&nf_ct_proto_mutex);
540540

541-
if (fixup_needed)
542-
nf_ct_iterate_cleanup_net(net, nf_ct_tcp_fixup,
543-
(void *)(unsigned long)nfproto, 0, 0);
541+
if (fixup_needed) {
542+
struct nf_ct_iter_data iter_data = {
543+
.net = net,
544+
.data = (void *)(unsigned long)nfproto,
545+
};
546+
nf_ct_iterate_cleanup_net(nf_ct_tcp_fixup, &iter_data);
547+
}
544548

545549
return err;
546550
}

net/netfilter/nf_conntrack_timeout.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ static int untimeout(struct nf_conn *ct, void *timeout)
3838

3939
void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout)
4040
{
41-
nf_ct_iterate_cleanup_net(net, untimeout, timeout, 0, 0);
41+
struct nf_ct_iter_data iter_data = {
42+
.net = net,
43+
.data = timeout,
44+
};
45+
46+
nf_ct_iterate_cleanup_net(untimeout, &iter_data);
4247
}
4348
EXPORT_SYMBOL_GPL(nf_ct_untimeout);
4449

net/netfilter/nf_nat_masquerade.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,14 @@ EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4);
7777

7878
static void iterate_cleanup_work(struct work_struct *work)
7979
{
80+
struct nf_ct_iter_data iter_data = {};
8081
struct masq_dev_work *w;
8182

8283
w = container_of(work, struct masq_dev_work, work);
8384

84-
nf_ct_iterate_cleanup_net(w->net, w->iter, (void *)w, 0, 0);
85+
iter_data.net = w->net;
86+
iter_data.data = (void *)w;
87+
nf_ct_iterate_cleanup_net(w->iter, &iter_data);
8588

8689
put_net_track(w->net, &w->ns_tracker);
8790
kfree(w);

0 commit comments

Comments
 (0)