Re: Re: [PATCH] ipv6: udp: fix memory leak in udpv6_sendmsg error path

From: 王明煜

Date: Thu Apr 23 2026 - 03:37:34 EST


Hi Sabrina and Jakub,

Thank you for the detailed review and pointing out the crash risk in v1.

You are absolutely correct. My previous patch would lead to a Double Free/UAF because functions like ip6_setup_cork() and __ip6_flush_pending_frames() already handle the dst release in their error paths.

After a deeper investigation, I found the actual source of the memory leak reported by the fuzzer. It occurs inside `__ip6_make_skb()` in `net/ipv6/ip6_output.c`.

In specific cases (such as fault injection during packet construction), `__ip6_append_data()` can succeed while leaving the queue empty. When `__ip6_make_skb()` is then called, `__skb_dequeue(queue)` returns NULL.

Currently, the code handles a NULL skb with a `goto out;`, which completely bypasses the call to `ip6_cork_release(cork);`. Since the `cork` structure still holds the `dst_entry` reference at this point, skipping the release causes the memory leak.

I am abandoning the v1 approach and will submit a v2 patch that fixes the logic in `__ip6_make_skb()` to ensure `ip6_cork_release()` is always called.

Best regards,
Mingyu Wang


> -----原始邮件-----
> 发件人: "Sabrina Dubroca" <sd@xxxxxxxxxxxxxxx>
> 发送时间:2026-04-22 19:55:44 (星期三)
> 收件人: "Mingyu Wang" <25181214217@xxxxxxxxxxxxxxxxx>
> 抄送: willemdebruijn.kernel@xxxxxxxxx, davem@xxxxxxxxxxxxx, dsahern@xxxxxxxxxx, edumazet@xxxxxxxxxx, kuba@xxxxxxxxxx, pabeni@xxxxxxxxxx, horms@xxxxxxxxxx, netdev@xxxxxxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx
> 主题: Re: [PATCH] ipv6: udp: fix memory leak in udpv6_sendmsg error path
>
> 2026-04-22, 18:58:02 +0800, Mingyu Wang wrote:
> > During fuzzing with failslab enabled, a memory leak was observed in the
> > IPv6 UDP send path.
> >
> > When sending via the lockless fast path (!corkreq), udpv6_sendmsg()
> > calls ip6_make_skb() and assumes that the routing entry (dst_entry)
> > reference has been stolen by the callee. However, if ip6_make_skb()
> > fails early (e.g., due to an ENOMEM from memory allocation failure),
> > it returns an error pointer without consuming the dst reference.
>
> Not in all cases? If ip6_setup_cork() fails, we call
> ip6_cork_release() which will release the dst. The MSG_PROBE path also
> releases the dst. __ip6_flush_pending_frames() also looks like it does
> that.
>
> > Since udpv6_sendmsg() unconditionally jumps to the 'out_no_dst' label,
> > the unconsumed dst_entry is never released, resulting in a memory leak.
> >
> > Fix this by explicitly calling dst_release(dst) when ip6_make_skb()
> > returns an error.
> >
> > Signed-off-by: Mingyu Wang <25181214217@xxxxxxxxxxxxxxxxx>
>
> And this is missing a Fixes tag.
>
> > net/ipv6/udp.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> > index 15e032194ecc..b83ecfd729af 100644
> > --- a/net/ipv6/udp.c
> > +++ b/net/ipv6/udp.c
> > @@ -1706,8 +1706,11 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
> > dst_rt6_info(dst),
> > msg->msg_flags, &cork);
> > err = PTR_ERR(skb);
> > - if (!IS_ERR_OR_NULL(skb))
> > + if (!IS_ERR_OR_NULL(skb)) {
> > err = udp_v6_send_skb(skb, fl6, &cork.base);
> > + } else {
> > + dst_release(dst);
> > + }
> > /* ip6_make_skb steals dst reference */
>
> This comment becomes really confusing after your patch.
>
> > goto out_no_dst;
> > }
> > --
> > 2.34.1
> >
> >
>
> --
> Sabrina