]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: preserve MSG_ZEROCOPY with forwarding
authorWillem de Bruijn <willemb@google.com>
Mon, 30 Jun 2025 19:42:11 +0000 (15:42 -0400)
committerJakub Kicinski <kuba@kernel.org>
Wed, 2 Jul 2025 22:07:16 +0000 (15:07 -0700)
MSG_ZEROCOPY data must be copied before data is queued to local
sockets, to avoid indefinite timeout until memory release.

This test is performed by skb_orphan_frags_rx, which is called when
looping an egress skb to packet sockets, error queue or ingress path.

To preserve zerocopy for skbs that are looped to ingress but are then
forwarded to an egress device rather than delivered locally, defer
this last check until an skb enters the local IP receive path.

This is analogous to existing behavior of skb_clear_delivery_time.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20250630194312.1571410-2-willemdebruijn.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/dev.c
net/ipv4/ip_input.c
net/ipv6/ip6_input.c

index 7ee808eb068e4c52baa199b491ca51394d3c8757..96d33dead604f4e4bbbfb27096c94a641c81f604 100644 (file)
@@ -5937,8 +5937,6 @@ check_vlan_id:
        }
 
        if (pt_prev) {
-               if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC)))
-                       goto drop;
                *ppt_prev = pt_prev;
        } else {
 drop:
index 30a5e9460d006de306b5bac49c92f9b9bf21f2f5..f8696e67def4d1c83efc19234f4d5d048cdac6fb 100644 (file)
@@ -226,6 +226,12 @@ resubmit:
 
 static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) {
+               __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
+               kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
+               return 0;
+       }
+
        skb_clear_delivery_time(skb);
        __skb_pull(skb, skb_network_header_len(skb));
 
index 0b3b81fd4a58ad62a83b807f38fd51ff24d47117..168ec07e31cc378843703483ae43bf30260f027b 100644 (file)
@@ -478,6 +478,13 @@ discard:
 
 static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) {
+               __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
+                               IPSTATS_MIB_INDISCARDS);
+               kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
+               return 0;
+       }
+
        skb_clear_delivery_time(skb);
        ip6_protocol_deliver_rcu(net, skb, 0, false);