diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index dfc81ee969ae..fa1710e27e50 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -104,6 +104,13 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, struct aead_request *req; struct scatterlist *sg; + /* Managed frags are owned by the zerocopy ubuf; the skb holds no + * per-frag page reference, so we must not drop one here. Mirrors + * the SKBFL_MANAGED_FRAG_REFS handling in skb_release_data(). + */ + if (skb_zcopy_managed(skb)) + return; + if (x->props.flags & XFRM_STATE_ESN) extralen += sizeof(struct esp_output_extra); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 296b57926abb..7d216b9c59f0 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -121,6 +121,13 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, struct aead_request *req; struct scatterlist *sg; + /* Managed frags are owned by the zerocopy ubuf; the skb holds no + * per-frag page reference, so we must not drop one here. Mirrors + * the SKBFL_MANAGED_FRAG_REFS handling in skb_release_data(). + */ + if (skb_zcopy_managed(skb)) + return; + if (x->props.flags & XFRM_STATE_ESN) extralen += sizeof(struct esp_output_extra);