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

From: Li,Rongqing

Date: Fri Jul 17 2026 - 20:46:20 EST




> -----邮件原件-----
> 发件人: Xin Long <lucien.xin@xxxxxxxxx>
> 发送时间: 2026年7月17日 23:53
> 收件人: Li,Rongqing <lirongqing@xxxxxxxxx>
> 抄送: David Ahern <dsahern@xxxxxxxxxx>; Ido Schimmel
> <idosch@xxxxxxxxxx>; David S . Miller <davem@xxxxxxxxxxxxx>; Eric
> Dumazet <edumazet@xxxxxxxxxx>; Jakub Kicinski <kuba@xxxxxxxxxx>; Paolo
> Abeni <pabeni@xxxxxxxxxx>; Simon Horman <horms@xxxxxxxxxx>;
> netdev@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> 主题: [外部邮件] Re: [PATCH] net: ipv6: fix a potential use-after-free in
> ip4ip6_err
>
> On Fri, Jul 17, 2026 at 10:33 AM lirongqing <lirongqing@xxxxxxxxx> wrote:
> >
> > From: Li RongQing <lirongqing@xxxxxxxxx>
> >
> > 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 <lirongqing@xxxxxxxxx>
> > ---
> > 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,
> > 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,
> > eiph->daddr, eiph->saddr,
> 0, 0,
> > 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.

Thanks

[Li,Rongqing]


> Thanks.