Subject: Re: [PATCH v1 net] ipv6: Fix use-after-free in inet6_addr_del().

From: Hangbin Liu <[email-masked]>
Date: Tue, 13 Jan 2026 04:35:19 +0000

On Tue, Jan 13, 2026 at 01:05:08AM +0000, Kuniyuki Iwashima wrote:
> syzbot reported use-after-free of inet6_ifaddr in
> inet6_addr_del(). [0]
> 
> The cited commit accidentally moved ipv6_del_addr() for
> mngtmpaddr before reading its ifp->flags for temporary
> addresses in inet6_addr_del().
> 
> Let's move ipv6_del_addr() down to fix the UAF.
> 
> [0]:
> BUG: KASAN: slab-use-after-free in inet6_addr_del.constprop.0+0x67a/0x6b0 net/ipv6/addrconf.c:3117
> Read of size 4 at addr ffff88807b89c86c by task syz.3.1618/9593
> 
> CPU: 0 UID: 0 PID: 9593 Comm: syz.3.1618 Not tainted syzkaller #0 PREEMPT(full)
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
> Call Trace:
>  <TASK>
>  __dump_stack lib/dump_stack.c:94 [inline]
>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>  print_address_description mm/kasan/report.c:378 [inline]
>  print_report+0xcd/0x630 mm/kasan/report.c:482
>  kasan_report+0xe0/0x110 mm/kasan/report.c:595
>  inet6_addr_del.constprop.0+0x67a/0x6b0 net/ipv6/addrconf.c:3117
>  addrconf_del_ifaddr+0x11e/0x190 net/ipv6/addrconf.c:3181
>  inet6_ioctl+0x1e5/0x2b0 net/ipv6/af_inet6.c:582
>  sock_do_ioctl+0x118/0x280 net/socket.c:1254
>  sock_ioctl+0x227/0x6b0 net/socket.c:1375
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:597 [inline]
>  __se_sys_ioctl fs/ioctl.c:583 [inline]
>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:583
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0xcd/0xf80 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> RIP: 0033:0x7f164cf8f749
> Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
> RSP: 002b:00007f164de64038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
> RAX: ffffffffffffffda RBX: 00007f164d1e5fa0 RCX: 00007f164cf8f749
> RDX: 0000200000000000 RSI: 0000000000008936 RDI: 0000000000000003
> RBP: 00007f164d013f91 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
> R13: 00007f164d1e6038 R14: 00007f164d1e5fa0 R15: 00007ffde15c8288
>  </TASK>
> 
> Allocated by task 9593:
>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:56
>  kasan_save_track+0x14/0x30 mm/kasan/common.c:77
>  poison_kmalloc_redzone mm/kasan/common.c:397 [inline]
>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:414
>  kmalloc_noprof include/linux/slab.h:957 [inline]
>  kzalloc_noprof include/linux/slab.h:1094 [inline]
>  ipv6_add_addr+0x4e3/0x2010 net/ipv6/addrconf.c:1120
>  inet6_addr_add+0x256/0x9b0 net/ipv6/addrconf.c:3050
>  addrconf_add_ifaddr+0x1fc/0x450 net/ipv6/addrconf.c:3160
>  inet6_ioctl+0x103/0x2b0 net/ipv6/af_inet6.c:580
>  sock_do_ioctl+0x118/0x280 net/socket.c:1254
>  sock_ioctl+0x227/0x6b0 net/socket.c:1375
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:597 [inline]
>  __se_sys_ioctl fs/ioctl.c:583 [inline]
>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:583
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0xcd/0xf80 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
> Freed by task 6099:
>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:56
>  kasan_save_track+0x14/0x30 mm/kasan/common.c:77
>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:584
>  poison_slab_object mm/kasan/common.c:252 [inline]
>  __kasan_slab_free+0x5f/0x80 mm/kasan/common.c:284
>  kasan_slab_free include/linux/kasan.h:234 [inline]
>  slab_free_hook mm/slub.c:2540 [inline]
>  slab_free_freelist_hook mm/slub.c:2569 [inline]
>  slab_free_bulk mm/slub.c:6696 [inline]
>  kmem_cache_free_bulk mm/slub.c:7383 [inline]
>  kmem_cache_free_bulk+0x2bf/0x680 mm/slub.c:7362
>  kfree_bulk include/linux/slab.h:830 [inline]
>  kvfree_rcu_bulk+0x1b7/0x1e0 mm/slab_common.c:1523
>  kvfree_rcu_drain_ready mm/slab_common.c:1728 [inline]
>  kfree_rcu_monitor+0x1d0/0x2f0 mm/slab_common.c:1801
>  process_one_work+0x9ba/0x1b20 kernel/workqueue.c:3257
>  process_scheduled_works kernel/workqueue.c:3340 [inline]
>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3421
>  kthread+0x3c5/0x780 kernel/kthread.c:463
>  ret_from_fork+0x983/0xb10 arch/x86/kernel/process.c:158
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:246
> 
> Fixes: 00b5b7aab9e42 ("net/ipv6: delete temporary address if mngtmpaddr is removed or unmanaged")
> Reported-by: [email-masked]
> Closes: https://lore.kernel.org/netdev/[email-masked]/
> Signed-off-by: Kuniyuki Iwashima <[email-masked]>
> ---
>  net/ipv6/addrconf.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index b66217d1b2f82..27ab9d7adc649 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -3112,12 +3112,12 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
>  			in6_ifa_hold(ifp);
>  			read_unlock_bh(&idev->lock);
>  
> -			ipv6_del_addr(ifp);
> -
>  			if (!(ifp->flags & IFA_F_TEMPORARY) &&
>  			    (ifp->flags & IFA_F_MANAGETEMPADDR))
>  				delete_tempaddrs(idev, ifp);
>  
> +			ipv6_del_addr(ifp);
> +
>  			addrconf_verify_rtnl(net);
>  			if (ipv6_addr_is_multicast(pfx)) {
>  				ipv6_mc_config(net->ipv6.mc_autojoin_sk,
> -- 
> 2.52.0.457.g6b5491de43-goog
> 

Hmm, I'm unable to recall why I moved delete_tempaddrs() after
ipv6_del_addr(). But your patch make sense to me. Checking the ifp flags
before ipv6_del_addr(ifp) is safer.

Reviewed-by: Hangbin Liu <[email-masked]>