Thread (4 messages) 4 messages, 3 authors, 2d ago

Re: 答复: [外部邮件] Re: [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err

From: Ido Schimmel <idosch@nvidia.com>
Date: 2026-07-19 06:37:28
Also in: lkml

On Sat, Jul 18, 2026 at 12:43:48AM +0000, Li,Rongqing wrote:
quoted
-----邮件原件-----
发件人: Xin Long [off-list ref]
发送时间: 2026年7月17日 23:53
收件人: Li,Rongqing [off-list ref]
抄送: David Ahern [off-list ref]; Ido Schimmel
[off-list ref]; David S . Miller [off-list ref]; Eric
Dumazet [off-list ref]; Jakub Kicinski [off-list ref]; Paolo
Abeni [off-list ref]; Simon Horman [off-list ref];
netdev@vger.kernel.org; linux-kernel@vger.kernel.org
主题: [外部邮件] Re: [PATCH] net: ipv6: fix a potential use-after-free in
ip4ip6_err

On Fri, Jul 17, 2026 at 10:33 AM lirongqing [off-list ref] wrote:
quoted
From: Li RongQing <redacted>

Fix a use-after-free bug in ip4ip6_err() where rt->rt_flags is
accessed after the route entry object has been released via ip_rt_put(rt).

If ip_rt_put() decrements the reference count to zero and frees the
rtable structure, reading rt->rt_flags immediately afterward results
in a use-after-free pointer dereference.

Fix this by caching rt->rt_flags into a local variable before calling
ip_rt_put().

Fixes: 77552cfa39c4 ("ip6_tunnel: clean up ip4ip6 and ip6ip6's
err_handlers")
Signed-off-by: Li RongQing <redacted>
---
 net/ipv6/ip6_tunnel.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index
bf8e40a..984cb0c 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -569,6 +569,7 @@ ip4ip6_err(struct sk_buff *skb, struct
inet6_skb_parm *opt,  {
        __u32 rel_info = ntohl(info);
        const struct iphdr *eiph;
+       unsigned int rt_flags;
        struct sk_buff *skb2;
        int err, rel_msg = 0;
        u8 rel_type = type;
@@ -627,10 +628,11 @@ ip4ip6_err(struct sk_buff *skb, struct
inet6_skb_parm *opt,
quoted
                goto out;

        skb2->dev = rt->dst.dev;
+       rt_flags = rt->rt_flags;
        ip_rt_put(rt);

        /* route "incoming" packet */
-       if (rt->rt_flags & RTCF_LOCAL) {
+       if (rt_flags & RTCF_LOCAL) {
                rt = ip_route_output_ports(dev_net(skb->dev), &fl4,
NULL,
quoted
                                           eiph->daddr, eiph->saddr,
0, 0,
quoted
                                           IPPROTO_IPIP,
--
2.9.4
Have you already seen any problem triggered by this?

I don't really think there's a use-after-free issue here.

The entire IPv6 input path, including ICMPv6 error handling, runs under
rcu_read_lock(). Since dst_release() uses call_rcu_hurry() to defer the actual
freeing until after the RCU grace period, accessing rt->rt_flags after
ip_rt_put(rt) is completely safe in this context.
Thanks for the review. However, The issue is that after ip_rt_put(rt), the rt pointer may be logically freed if refcnt drops to zero, and dereferencing it afterwards is illegal even if memory isn't recycled immediately. The patch avoids this by caching rt->rt_flags before the put operation. This is a defensive fix against potential UAF reported by static analyzers. 
I agree with Xin. I don't see how a UAF can happen here. If you are
claiming to fix a use-after-free, then reproduce it and put a relevant
trace in the commit message.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help