From: Pablo Neira Ayuso pablo@netfilter.org
[ Upstream commit 2cdaa3eefed83082923cf219c8b6a314e622da74 ]
e6d57e9ff0ae ("netfilter: conntrack: fix rmmod double-free race") consolidates IPS_CONFIRMED bit set in nf_conntrack_hash_check_insert(). However, this breaks ctnetlink:
# conntrack -I -p tcp --timeout 123 --src 1.2.3.4 --dst 5.6.7.8 --state ESTABLISHED --sport 1 --dport 4 -u SEEN_REPLY conntrack v1.4.6 (conntrack-tools): Operation failed: Device or resource busy
This is a partial revert of the aforementioned commit to restore IPS_CONFIRMED.
Fixes: e6d57e9ff0ae ("netfilter: conntrack: fix rmmod double-free race") Reported-by: Stéphane Graber stgraber@stgraber.org Tested-by: Stéphane Graber stgraber@stgraber.org Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nf_conntrack_bpf.c | 1 + net/netfilter/nf_conntrack_core.c | 1 - net/netfilter/nf_conntrack_netlink.c | 3 +++ 3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_conntrack_bpf.c b/net/netfilter/nf_conntrack_bpf.c index adae86e8e02e8..8639e7efd0e22 100644 --- a/net/netfilter/nf_conntrack_bpf.c +++ b/net/netfilter/nf_conntrack_bpf.c @@ -384,6 +384,7 @@ struct nf_conn *bpf_ct_insert_entry(struct nf_conn___init *nfct_i) struct nf_conn *nfct = (struct nf_conn *)nfct_i; int err;
+ nfct->status |= IPS_CONFIRMED; err = nf_conntrack_hash_check_insert(nfct); if (err < 0) { nf_conntrack_free(nfct); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 30ed45b1b57df..a0e9c7af08467 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -938,7 +938,6 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) goto out; }
- ct->status |= IPS_CONFIRMED; smp_wmb(); /* The caller holds a reference to this object */ refcount_set(&ct->ct_general.use, 2); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d095d3c1ceca6..a68391e228f0e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2316,6 +2316,9 @@ ctnetlink_create_conntrack(struct net *net, nfct_seqadj_ext_add(ct); nfct_synproxy_ext_add(ct);
+ /* we must add conntrack extensions before confirmation. */ + ct->status |= IPS_CONFIRMED; + if (cda[CTA_STATUS]) { err = ctnetlink_change_status(ct, cda); if (err < 0)