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

Configure Feed

Select the types of activity you want to include in your feed.

ipv6: tcp: add a missing nf_reset_ct() in 3WHS handling

Commit b0e214d21203 ("netfilter: keep conntrack reference until
IPsecv6 policy checks are done") is a direct copy of the old
commit b59c270104f0 ("[NETFILTER]: Keep conntrack reference until
IPsec policy checks are done") but for IPv6. However, it also
copies a bug that this old commit had. That is: when the third
packet of 3WHS connection establishment contains payload, it is
added into socket receive queue without the XFRM check and the
drop of connection tracking context.

That leads to nf_conntrack module being impossible to unload as
it waits for all the conntrack references to be dropped while
the packet release is deferred in per-cpu cache indefinitely, if
not consumed by the application.

The issue for IPv4 was fixed in commit 6f0012e35160 ("tcp: add a
missing nf_reset_ct() in 3WHS handling") by adding a missing XFRM
check and correctly dropping the conntrack context. However, the
issue was introduced to IPv6 code afterwards. Fixing it the
same way for IPv6 now.

Fixes: b0e214d21203 ("netfilter: keep conntrack reference until IPsecv6 policy checks are done")
Link: https://lore.kernel.org/netdev/d589a999-d4dd-2768-b2d5-89dec64a4a42@ovn.org/
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Acked-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20230922210530.2045146-1-i.maximets@ovn.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Ilya Maximets and committed by
Paolo Abeni
9593c7cb 4b2b6060

+7 -3
+7 -3
net/ipv6/tcp_ipv6.c
··· 1640 1640 struct sock *nsk; 1641 1641 1642 1642 sk = req->rsk_listener; 1643 - drop_reason = tcp_inbound_md5_hash(sk, skb, 1644 - &hdr->saddr, &hdr->daddr, 1645 - AF_INET6, dif, sdif); 1643 + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1644 + drop_reason = SKB_DROP_REASON_XFRM_POLICY; 1645 + else 1646 + drop_reason = tcp_inbound_md5_hash(sk, skb, 1647 + &hdr->saddr, &hdr->daddr, 1648 + AF_INET6, dif, sdif); 1646 1649 if (drop_reason) { 1647 1650 sk_drops_add(sk, skb); 1648 1651 reqsk_put(req); ··· 1692 1689 } 1693 1690 goto discard_and_relse; 1694 1691 } 1692 + nf_reset_ct(skb); 1695 1693 if (nsk == sk) { 1696 1694 reqsk_put(req); 1697 1695 tcp_v6_restore_cb(skb);