From: Eric Dumazet edumazet@google.com
stable inclusion from stable-v5.10.129 commit 5f614f5f70bf401a75af60b0adf9e7d63b05ad8a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5YNDQ
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 6f0012e35160cd08a53e46e3b3bbf724b92dfe68 upstream.
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.
This means that if the data is left unread in the socket receive queue, conntrack module can not be unloaded.
As most applications usually reads the incoming data immediately after accept(), bug has been hiding for quite a long time.
Commit 68822bdf76f1 ("net: generalize skb freeing deferral to per-cpu lists") exposed this bug because even if the application reads this data, the skb with nfct state could stay in a per-cpu cache for an arbitrary time, if said cpu no longer process RX softirqs.
Many thanks to Ilya Maximets for reporting this issue, and for testing various patches: https://lore.kernel.org/netdev/20220619003919.394622-1-i.maximets@ovn.org/
Note that I also added a missing xfrm4_policy_check() call, although this is probably not a big issue, as the SYN packet should have been dropped earlier.
Fixes: b59c270104f0 ("[NETFILTER]: Keep conntrack reference until IPsec policy checks are done") Reported-by: Ilya Maximets i.maximets@ovn.org Signed-off-by: Eric Dumazet edumazet@google.com Cc: Florian Westphal fw@strlen.de Cc: Pablo Neira Ayuso pablo@netfilter.org Cc: Steffen Klassert steffen.klassert@secunet.com Tested-by: Ilya Maximets i.maximets@ovn.org Reviewed-by: Ilya Maximets i.maximets@ovn.org Link: https://lore.kernel.org/r/20220623050436.1290307-1-edumazet@google.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Wei Li liwei391@huawei.com --- net/ipv4/tcp_ipv4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 078f3a5d65b3..c854d17cf99a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1983,7 +1983,8 @@ int tcp_v4_rcv(struct sk_buff *skb) struct sock *nsk;
sk = req->rsk_listener; - if (unlikely(tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))) { + if (unlikely(!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb) || + tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))) { sk_drops_add(sk, skb); reqsk_put(req); goto discard_it; @@ -2022,6 +2023,7 @@ int tcp_v4_rcv(struct sk_buff *skb) } goto discard_and_relse; } + nf_reset_ct(skb); if (nsk == sk) { reqsk_put(req); tcp_v4_restore_cb(skb);