Multicast delivery clones packets for listeners after the first one. Commit 3cb8d4b9bfeb ("udp: fix encapsulation packet resubmit in multicast deliver") fixed encapsulation packet resubmission for the primary listener by propagating positive return values from udp_queue_rcv_skb() to the outer IP layer. However, it left the loop over secondary matching sockets unchanged. When an encapsulation receive handler requests protocol resubmission for a clone (ret > 0), the secondary delivery loop currently calls consume_skb(nskb), silently dropping the packet. Resubmit cloned IPv4 and IPv6 packets directly to the returned protocol via ip_protocol_deliver_rcu() and ip6_protocol_deliver_rcu(..., true), matching the ownership and resubmission conventions used in the segmented GSO paths. Fixes: 3cb8d4b9bfeb ("udp: fix encapsulation packet resubmit in multicast deliver") Signed-off-by: Mariano Baragiola --- net/ipv4/udp.c | 5 +++-- net/ipv6/udp.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index bb8cfc62cb00..d79be57854e3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2522,8 +2522,9 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, __UDP_INC_STATS(net, UDP_MIB_INERRORS); continue; } - if (udp_queue_rcv_skb(sk, nskb) > 0) - consume_skb(nskb); + ret = udp_queue_rcv_skb(sk, nskb); + if (ret > 0) + ip_protocol_deliver_rcu(net, nskb, ret); } /* Also lookup *:port if we are using hash2 and haven't done so yet. */ diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 93478d1ad576..ca8d0a1844d2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1001,8 +1001,9 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, continue; } - if (udpv6_queue_rcv_skb(sk, nskb) > 0) - consume_skb(nskb); + ret = udpv6_queue_rcv_skb(sk, nskb); + if (ret > 0) + ip6_protocol_deliver_rcu(net, nskb, ret, true); } /* Also lookup *:port if we are using hash2 and haven't done so yet. */ -- 2.55.0