xfrm: Provide private skb extensions for segmented and hw offloaded ESP packets
authorSteffen Klassert <steffen.klassert@secunet.com>
Fri, 26 Mar 2021 08:44:48 +0000 (09:44 +0100)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 29 Mar 2021 07:14:12 +0000 (09:14 +0200)
Commit 94579ac3f6d0 ("xfrm: Fix double ESP trailer insertion in IPsec
crypto offload.") added a XFRM_XMIT flag to avoid duplicate ESP trailer
insertion on HW offload. This flag is set on the secpath that is shared
amongst segments. This lead to a situation where some segments are
not transformed correctly when segmentation happens at layer 3.

Fix this by using private skb extensions for segmented and hw offloaded
ESP packets.

Fixes: 94579ac3f6d0 ("xfrm: Fix double ESP trailer insertion in IPsec crypto offload.")
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/ipv4/esp4_offload.c
net/ipv6/esp6_offload.c
net/xfrm/xfrm_device.c

index ed3de486ea3482a86ffe793fceafb56fc34967ef..33687cf58286b7cf63958b6e0eb004524084e0f2 100644 (file)
@@ -314,8 +314,17 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features_
        ip_hdr(skb)->tot_len = htons(skb->len);
        ip_send_check(ip_hdr(skb));
 
-       if (hw_offload)
+       if (hw_offload) {
+               if (!skb_ext_add(skb, SKB_EXT_SEC_PATH))
+                       return -ENOMEM;
+
+               xo = xfrm_offload(skb);
+               if (!xo)
+                       return -EINVAL;
+
+               xo->flags |= XFRM_XMIT;
                return 0;
+       }
 
        err = esp_output_tail(x, skb, &esp);
        if (err)
index f35203ab39f5bac87c1a01780564d4bc7a610a2f..4af56affaafd436fbd35ade87ffd2b7c8e6d4d91 100644 (file)
@@ -348,8 +348,17 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features
 
        ipv6_hdr(skb)->payload_len = htons(len);
 
-       if (hw_offload)
+       if (hw_offload) {
+               if (!skb_ext_add(skb, SKB_EXT_SEC_PATH))
+                       return -ENOMEM;
+
+               xo = xfrm_offload(skb);
+               if (!xo)
+                       return -EINVAL;
+
+               xo->flags |= XFRM_XMIT;
                return 0;
+       }
 
        err = esp6_output_tail(x, skb, &esp);
        if (err)
index edf11893dbe81ffcc026a18b8b66f19355c6ff39..6d6917b68856fc7f544961d018a23a2c13bc63d9 100644 (file)
@@ -134,8 +134,6 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
                return skb;
        }
 
-       xo->flags |= XFRM_XMIT;
-
        if (skb_is_gso(skb) && unlikely(x->xso.dev != dev)) {
                struct sk_buff *segs;