Skip to content

Commit c9f2c1a

Browse files
Paolo Abenidavem330
authored andcommitted
udp6: fix socket leak on early demux
When an early demuxed packet reaches __udp6_lib_lookup_skb(), the sk reference is retrieved and used, but the relevant reference count is leaked and the socket destructor is never called. Beyond leaking the sk memory, if there are pending UDP packets in the receive queue, even the related accounted memory is leaked. In the long run, this will cause persistent forward allocation errors and no UDP skbs (both ipv4 and ipv6) will be able to reach the user-space. Fix this by explicitly accessing the early demux reference before the lookup, and properly decreasing the socket reference count after usage. Also drop the skb_steal_sock() in __udp6_lib_lookup_skb(), and the now obsoleted comment about "socket cache". The newly added code is derived from the current ipv4 code for the similar path. v1 -> v2: fixed the __udp6_lib_rcv() return code for resubmission, as suggested by Eric Reported-by: Sam Edwards <CFSworks@gmail.com> Reported-by: Marc Haber <mh+netdev@zugschlus.de> Fixes: 5425077 ("net: ipv6: Add early demux handler for UDP unicast") Signed-off-by: Paolo Abeni <pabeni@redhat.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 500268e commit c9f2c1a

File tree

3 files changed

+21
-10
lines changed

3 files changed

+21
-10
lines changed

include/net/udp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ static inline struct sk_buff *skb_recv_udp(struct sock *sk, unsigned int flags,
260260
}
261261

262262
void udp_v4_early_demux(struct sk_buff *skb);
263+
void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
263264
int udp_get_port(struct sock *sk, unsigned short snum,
264265
int (*saddr_cmp)(const struct sock *,
265266
const struct sock *));

net/ipv4/udp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1928,7 +1928,7 @@ static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
19281928
/* For TCP sockets, sk_rx_dst is protected by socket lock
19291929
* For UDP, we use xchg() to guard against concurrent changes.
19301930
*/
1931-
static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
1931+
void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
19321932
{
19331933
struct dst_entry *old;
19341934

@@ -1937,6 +1937,7 @@ static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
19371937
dst_release(old);
19381938
}
19391939
}
1940+
EXPORT_SYMBOL(udp_sk_rx_dst_set);
19401941

19411942
/*
19421943
* Multicasts and broadcasts go to each listener.

net/ipv6/udp.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
291291
struct udp_table *udptable)
292292
{
293293
const struct ipv6hdr *iph = ipv6_hdr(skb);
294-
struct sock *sk;
295294

296-
sk = skb_steal_sock(skb);
297-
if (unlikely(sk))
298-
return sk;
299295
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
300296
&iph->daddr, dport, inet6_iif(skb),
301297
udptable, skb);
@@ -804,6 +800,24 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
804800
if (udp6_csum_init(skb, uh, proto))
805801
goto csum_error;
806802

803+
/* Check if the socket is already available, e.g. due to early demux */
804+
sk = skb_steal_sock(skb);
805+
if (sk) {
806+
struct dst_entry *dst = skb_dst(skb);
807+
int ret;
808+
809+
if (unlikely(sk->sk_rx_dst != dst))
810+
udp_sk_rx_dst_set(sk, dst);
811+
812+
ret = udpv6_queue_rcv_skb(sk, skb);
813+
sock_put(sk);
814+
815+
/* a return value > 0 means to resubmit the input */
816+
if (ret > 0)
817+
return ret;
818+
return 0;
819+
}
820+
807821
/*
808822
* Multicast receive code
809823
*/
@@ -812,11 +826,6 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
812826
saddr, daddr, udptable, proto);
813827

814828
/* Unicast */
815-
816-
/*
817-
* check socket cache ... must talk to Alan about his plans
818-
* for sock caches... i'll skip this for now.
819-
*/
820829
sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
821830
if (sk) {
822831
int ret;

0 commit comments

Comments
 (0)