Skip to content

Commit dc33543

Browse files
committed
netfilter: nfnetlink: allow to detect if ctnetlink listeners exist
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2111270 Upstream Status: commit 2794cdb commit 2794cdb Author: Florian Westphal <[email protected]> Date: Mon Apr 25 15:15:41 2022 +0200 netfilter: nfnetlink: allow to detect if ctnetlink listeners exist At this time, every new conntrack gets the 'event cache extension' enabled for it. This is because the 'net.netfilter.nf_conntrack_events' sysctl defaults to 1. Changing the default to 0 means that commands that rely on the event notification extension, e.g. 'conntrack -E' or conntrackd, stop working. We COULD detect if there is a listener by means of 'nfnetlink_has_listeners()' and only add the extension if this is true. The downside is a dependency from conntrack module to nfnetlink module. This adds a different way: inc/dec a counter whenever a ctnetlink group is being (un)subscribed and toggle a flag in struct net. Next patches will take advantage of this and will only add the event extension if the flag is set. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent 709573a commit dc33543

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

include/net/netns/conntrack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct nf_ip_net {
9595

9696
struct netns_ct {
9797
#ifdef CONFIG_NF_CONNTRACK_EVENTS
98+
bool ctnetlink_has_listener;
9899
bool ecache_dwork_pending;
99100
#endif
100101
u8 sysctl_log_invalid; /* Log invalid packets */

net/netfilter/nfnetlink.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ MODULE_DESCRIPTION("Netfilter messages via netlink socket");
4545
static unsigned int nfnetlink_pernet_id __read_mostly;
4646

4747
struct nfnl_net {
48+
unsigned int ctnetlink_listeners;
4849
struct sock *nfnl;
4950
};
5051

@@ -654,7 +655,6 @@ static void nfnetlink_rcv(struct sk_buff *skb)
654655
netlink_rcv_skb(skb, nfnetlink_rcv_msg);
655656
}
656657

657-
#ifdef CONFIG_MODULES
658658
static int nfnetlink_bind(struct net *net, int group)
659659
{
660660
const struct nfnetlink_subsystem *ss;
@@ -670,19 +670,53 @@ static int nfnetlink_bind(struct net *net, int group)
670670
rcu_read_unlock();
671671
if (!ss)
672672
request_module_nowait("nfnetlink-subsys-%d", type);
673+
674+
#ifdef CONFIG_NF_CONNTRACK_EVENTS
675+
if (type == NFNL_SUBSYS_CTNETLINK) {
676+
struct nfnl_net *nfnlnet = nfnl_pernet(net);
677+
678+
nfnl_lock(NFNL_SUBSYS_CTNETLINK);
679+
680+
if (WARN_ON_ONCE(nfnlnet->ctnetlink_listeners == UINT_MAX)) {
681+
nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
682+
return -EOVERFLOW;
683+
}
684+
685+
nfnlnet->ctnetlink_listeners++;
686+
if (nfnlnet->ctnetlink_listeners == 1)
687+
WRITE_ONCE(net->ct.ctnetlink_has_listener, true);
688+
nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
689+
}
690+
#endif
673691
return 0;
674692
}
693+
694+
static void nfnetlink_unbind(struct net *net, int group)
695+
{
696+
#ifdef CONFIG_NF_CONNTRACK_EVENTS
697+
int type = nfnl_group2type[group];
698+
699+
if (type == NFNL_SUBSYS_CTNETLINK) {
700+
struct nfnl_net *nfnlnet = nfnl_pernet(net);
701+
702+
nfnl_lock(NFNL_SUBSYS_CTNETLINK);
703+
WARN_ON_ONCE(nfnlnet->ctnetlink_listeners == 0);
704+
nfnlnet->ctnetlink_listeners--;
705+
if (nfnlnet->ctnetlink_listeners == 0)
706+
WRITE_ONCE(net->ct.ctnetlink_has_listener, false);
707+
nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
708+
}
675709
#endif
710+
}
676711

677712
static int __net_init nfnetlink_net_init(struct net *net)
678713
{
679714
struct nfnl_net *nfnlnet = nfnl_pernet(net);
680715
struct netlink_kernel_cfg cfg = {
681716
.groups = NFNLGRP_MAX,
682717
.input = nfnetlink_rcv,
683-
#ifdef CONFIG_MODULES
684718
.bind = nfnetlink_bind,
685-
#endif
719+
.unbind = nfnetlink_unbind,
686720
};
687721

688722
nfnlnet->nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);

0 commit comments

Comments
 (0)