skb->active_extensions = 0;
        }
 }
+
+static inline bool skb_has_extensions(struct sk_buff *skb)
+{
+       return unlikely(skb->active_extensions);
+}
 #else
 static inline void skb_ext_put(struct sk_buff *skb) {}
 static inline void skb_ext_reset(struct sk_buff *skb) {}
 static inline void skb_ext_del(struct sk_buff *skb, int unused) {}
 static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
 static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
+static inline bool skb_has_extensions(struct sk_buff *skb) { return false; }
 #endif /* CONFIG_SKB_EXTENSIONS */
 
 static inline void nf_reset_ct(struct sk_buff *skb)
 
 
 #define UDP_SKB_IS_STATELESS 0x80000000
 
+/* all head states (dst, sk, nf conntrack) except skb extensions are
+ * cleared by udp_rcv().
+ *
+ * We need to preserve secpath, if present, to eventually process
+ * IP_CMSG_PASSSEC at recvmsg() time.
+ *
+ * Other extensions can be cleared.
+ */
+static bool udp_try_make_stateless(struct sk_buff *skb)
+{
+       if (!skb_has_extensions(skb))
+               return true;
+
+       if (!secpath_exists(skb)) {
+               skb_ext_reset(skb);
+               return true;
+       }
+
+       return false;
+}
+
 static void udp_set_dev_scratch(struct sk_buff *skb)
 {
        struct udp_dev_scratch *scratch = udp_skb_scratch(skb);
        scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
        scratch->is_linear = !skb_is_nonlinear(skb);
 #endif
-       /* all head states execept sp (dst, sk, nf) are always cleared by
-        * udp_rcv() and we need to preserve secpath, if present, to eventually
-        * process IP_CMSG_PASSSEC at recvmsg() time
-        */
-       if (likely(!skb_sec_path(skb)))
+       if (udp_try_make_stateless(skb))
                scratch->_tsize_state |= UDP_SKB_IS_STATELESS;
 }