diff options
| author | Zhou Qiuyue <n0ps1edzz@gmail.com> | 2026-10-26 12:48:08 +0800 |
|---|---|---|
| committer | Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb> | 2026-10-30 09:32:15 +0000 |
| commit | 66dfb2cacda7faae614d688943d85e75abf7f586 (patch) | |
| tree | cc3e124ee9b7befc90b54fdfc2b33281cff4efdb | |
| parent | ed9179fc7228315fb745dc3b111bae446e6894d2 (diff) | |
| download | linux-next-66dfb2cacda7faae614d688943d85e75abf7f586.tar.gz linux-next-66dfb2cacda7faae614d688943d85e75abf7f586.zip | |
ipv6: raw: fix use-after-free in rawv6_send_hdrinc()
rawv6_send_hdrinc() caches the route before handing the skb to
l3mdev_ip6_out(). The VRF output path may replace skb->dst and release
the original route, leaving the cached pointer stale.
The function later dereferences that pointer for statistics accounting
and as the output device passed to NF_HOOK(). Its RCU read-side critical
section starts after l3mdev_ip6_out(), so it cannot prevent the old route
from being reclaimed in between.
Reload the route from the current skb destination after
l3mdev_ip6_out() returns.
KASAN reports a slab-use-after-free in rawv6_sendmsg(), with the route
allocated by ip6_dst_alloc(), freed by dst_destroy() from rcu_core(), and
the related RCU callback queued from vrf_l3_out().
Fixes: 4c1feac58e06 ("net: vrf: Flip IPv6 output path from FIB lookup hook to out hook")
Cc: stable@vger.kernel.org
Signed-off-by: Zhou Qiuyue <n0ps1edzz@gmail.com>
Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
| -rw-r--r-- | net/ipv6/raw.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index b965258cf9e5..bdea825434ea 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -654,6 +654,9 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, if (unlikely(!skb)) return 0; + /* l3mdev_ip6_out() may have replaced the skb dst. */ + rt = dst_rt6_info(skb_dst(skb)); + /* Acquire rcu_read_lock() in case we need to use rt->rt6i_idev * in the error path. Since skb has been freed, the dst could * have been queued for deletion. |
