* [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err
@ 2026-07-17 14:33 lirongqing
2026-07-17 15:53 ` Xin Long
0 siblings, 1 reply; 3+ messages in thread
From: lirongqing @ 2026-07-17 14:33 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Xin Long, netdev,
linux-kernel
Cc: Li RongQing
From: Li RongQing <lirongqing@baidu.com>
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@baidu.com>
---
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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err
2026-07-17 14:33 [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err lirongqing
@ 2026-07-17 15:53 ` Xin Long
2026-07-18 0:43 ` 答复: [外部邮件] " Li,Rongqing
0 siblings, 1 reply; 3+ messages in thread
From: Xin Long @ 2026-07-17 15:53 UTC (permalink / raw)
To: lirongqing
Cc: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-kernel
On Fri, Jul 17, 2026 at 10:33 AM lirongqing <lirongqing@baidu.com> wrote:
>
> From: Li RongQing <lirongqing@baidu.com>
>
> 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@baidu.com>
> ---
> 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.
^ permalink raw reply [flat|nested] 3+ messages in thread
* 答复: [外部邮件] Re: [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err
2026-07-17 15:53 ` Xin Long
@ 2026-07-18 0:43 ` Li,Rongqing
0 siblings, 0 replies; 3+ messages in thread
From: Li,Rongqing @ 2026-07-18 0:43 UTC (permalink / raw)
To: Xin Long
Cc: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
> -----邮件原件-----
> 发件人: Xin Long <lucien.xin@gmail.com>
> 发送时间: 2026年7月17日 23:53
> 收件人: Li,Rongqing <lirongqing@baidu.com>
> 抄送: David Ahern <dsahern@kernel.org>; Ido Schimmel
> <idosch@nvidia.com>; David S . Miller <davem@davemloft.net>; Eric
> Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo
> Abeni <pabeni@redhat.com>; Simon Horman <horms@kernel.org>;
> 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 <lirongqing@baidu.com> wrote:
> >
> > From: Li RongQing <lirongqing@baidu.com>
> >
> > 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@baidu.com>
> > ---
> > 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.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-18 0:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17 14:33 [PATCH] net: ipv6: fix a potential use-after-free in ip4ip6_err lirongqing
2026-07-17 15:53 ` Xin Long
2026-07-18 0:43 ` 答复: [外部邮件] " Li,Rongqing
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox