Re: [PATCH net v2] ipv6: raw: fix use-after-free in rawv6_send_hdrinc()
From: David Laight
Date: Fri Oct 30 2026 - 15:52:55 EST
On Sat, 31 Oct 2026 01:38:22 +0800
Zhou Qiuyue <n0ps1edzz@xxxxxxxxx> wrote:
> Thanks, David.
>
> Yes, in the redirect case it passes the old rt->dst.dev, while skb->dst
> has already been replaced. That changes the NF_HOOK outdev, so it
> probably belongs in a separate fix.
Does that actually mean that it doesn't matter?
Or has no one every actually used that path.
What holds the reference on rt->dst.dev?
Something needs to stop the interface (I think that is what it is)
being deleted mid request.
> A bare rt6i_idev or dst.dev pointer looks unsafe, since dropping the old
> route drops the refs they rely on. An explicit hold/put could replace the
> RCU lock, but adds per-packet refs, and doesn't avoid the deferred route
> free. As far as I can tell, that uses the embedded dst rcu_head; the
> temporary rt6 in this path comes from the existing HDRINCL lookup, and v2
> doesn't add a new alloc/free there.
>
> I'll test moving the RCU read lock before l3mdev_ip6_out().
IIRC the rcu free happens for every packet and uses kmalloc() to add
the item to the list of things to be freed. So an extra reference count
may be better - especially since it should let you do a not-rcu free
of the temporary rt.
In the non-redirect case the temporary rt_info would have a reference
count of 2, one owned by the skb, the other be the sending function.
That would mean it could safely be freed at the end of transmit.
I've not looked today, but I remember this code always allocating
an rt_info for our application that was sending udp using raw sockets.
The app uses a different raw socket for each thread that sends udp
in order to guarantee the sendmsg() doesn't block anywhere.
(There are associated udp sockets, they have to be unconnected and are
only used for receive - monitoring 10k of those is 'interesting'.)
David