}
 }
 
+DECLARE_STATIC_KEY_FALSE(udp_encap_needed_key);
+#if IS_ENABLED(CONFIG_IPV6)
+DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
+#endif
+
+static inline bool udp_encap_needed(void)
+{
+       if (static_branch_unlikely(&udp_encap_needed_key))
+               return true;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (static_branch_unlikely(&udpv6_encap_needed_key))
+               return true;
+#endif
+
+       return false;
+}
+
 static inline bool udp_unexpected_gso(struct sock *sk, struct sk_buff *skb)
 {
        if (!skb_is_gso(skb))
            !udp_test_bit(ACCEPT_FRAGLIST, sk))
                return true;
 
+       /* GSO packets lacking the SKB_GSO_UDP_TUNNEL/_CSUM bits might still
+        * land in a tunnel as the socket check in udp_gro_receive cannot be
+        * foolproof.
+        */
+       if (udp_encap_needed() &&
+           READ_ONCE(udp_sk(sk)->encap_rcv) &&
+           !(skb_shinfo(skb)->gso_type &
+             (SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM)))
+               return true;
+
        return false;
 }
 
 
 }
 
 DEFINE_STATIC_KEY_FALSE(udp_encap_needed_key);
+EXPORT_SYMBOL(udp_encap_needed_key);
+
+#if IS_ENABLED(CONFIG_IPV6)
+DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
+EXPORT_SYMBOL(udpv6_encap_needed_key);
+#endif
+
 void udp_encap_enable(void)
 {
        static_branch_inc(&udp_encap_needed_key);
 
        unsigned int off = skb_gro_offset(skb);
        int flush = 1;
 
-       /* we can do L4 aggregation only if the packet can't land in a tunnel
-        * otherwise we could corrupt the inner stream
+       /* We can do L4 aggregation only if the packet can't land in a tunnel
+        * otherwise we could corrupt the inner stream. Detecting such packets
+        * cannot be foolproof and the aggregation might still happen in some
+        * cases. Such packets should be caught in udp_unexpected_gso later.
         */
        NAPI_GRO_CB(skb)->is_flist = 0;
        if (!sk || !udp_sk(sk)->gro_receive) {
 
        goto try_again;
 }
 
-DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
+DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
 void udpv6_encap_enable(void)
 {
        static_branch_inc(&udpv6_encap_needed_key);