Re: general protection fault in __fib6_drop_pcpu_from [CVE-2024-40905 Incomplete fix]

From: Eric Dumazet
Date: Tue Feb 04 2025 - 00:19:31 EST


On Tue, Feb 4, 2025 at 5:27 AM YAN KANG <kangyan91@xxxxxxxxxxx> wrote:
>
> Dear developers and maintainers,
>
> I found a new kernel UAF bug titiled "general protection fault in __fib6_drop_pcpu_from" while using modified syzkaller fuzzing tool. I Itested it on the latest Linux upstream version (6.13.0-rc1), and it was able to be triggered many times .
>
>
> After preliminary analysis, I found CVE-2024-40905 vlunerability maybe fixed incomplete.
> https://lore.kernel.org/linux-cve-announce/2024071208-CVE-2024-40905-44f9@gregkh/T/
> I am sure that this security patch is apply to linux 6.13.
>
>

Yes, I have syzbot reports pointing to the issue.

Do you have a fix already ?

I have been waiting, because I think the bug is caused by a per-cpu
data mangling,
not necessarily in network layers.

Unfortunately, KASAN does not have per-cpu data support I think.

> In function __fib6_drop_pcpu_from (/net/ipv6/ip6_fib.c)
> crashing code:
> ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu); //fib6_nh->rt6i_pcpu is dangling
> pcpu_rt = READ_ONCE(*ppcpu_rt); // Crash here
>
> rootcause of concurrent-UAF:
> The crash occurs because fib6_nh->rt6i_pcpu is accessed after being freed.
> The problematic code path appears to be:
> void fib6_nh_release(struct fib6_nh *fib6_nh) (/net/ipv6/route.c)
> {
> ……
> fib6_nh_release_dsts(fib6_nh); //pcpu_rt = xchg(ppcpu_rt, NULL);
> free_percpu(fib6_nh->rt6i_pcpu);
> // MISSING: fib6_nh->rt6i_pcpu = NULL;
>
> After free_percpu() is called, rt6i_pcpu becomes a dangling pointer. Subsequent accesses to it in __fib6_drop_pcpu_from() via per_cpu_ptr() will trigger use-after-free.
>
> If you fix this issue, please add the following tag to the commit:
> Reported-by: yan kang <kangyan91@xxxxxxxxxxx>
> Reported-by: yue sun <samsun1006219@xxxxxxxxx
>
>
> I hope it helps.
> Best regards
> yan kang
>
> Kernel crash log is listed below.
>
> ==================================================================
> crash log
> ==================================================================
> batman_adv: batadv0: Removing interface: batadv_slave_1
> veth1_macvtap: left promiscuous mode
> veth0_macvtap: left promiscuous mode
> veth1_vlan: left promiscuous mode
> veth0_vlan: left promiscuous mode
> Oops: general protection fault, probably for non-canonical address 0xdffffc0000000012: 0000 [#1] PREEMPT SMP KASAN NOPTI
> KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097]
> CPU: 0 UID: 0 PID: 11 Comm: kworker/u8:0 Not tainted 6.13.0-rc1-00003-gd4774759e15b-dirty #87
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
> Workqueue: netns cleanup_net
> RIP: 0010:__fib6_drop_pcpu_from.part.0+0x18e/0x570 net/ipv6/ip6_fib.c:980
> Code: c2 48 c1 ea 03 80 3c 2a 00 0f 85 8a 03 00 00 4c 8b 38 4d 85 ff 74 2e e8 80 0c ca f7 49 8d bf 90 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 7c 03 00 00 49 8b 87 90 00 00 00 48 3b 04 24 0f
> RSP: 0018:ffffc900000defb8 EFLAGS: 00010207
> RAX: 0000000000000012 RBX: 0000000000000000 RCX: 1ffffffff1b0cb7c
> RDX: ffff88801cee2500 RSI: ffffffff89ceb460 RDI: 0000000000000096
> RBP: dffffc0000000000 R08: 0000000000000000 R09: fffffbfff2d8a198
> R10: 0000000000000000 R11: 0000000000000000 R12: fffffbfff1b0cc71
> R13: ffff88810669a8c8 R14: ffffed1020cd3524 R15: 0000000000000006
> FS: 0000000000000000(0000) GS:ffff888062800000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f6eecc57000 CR3: 0000000024d02000 CR4: 0000000000752ef0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
> PKRU: 55555554
> Call Trace:
> <TASK>
> __fib6_drop_pcpu_from net/ipv6/ip6_fib.c:1023 [inline]
> fib6_drop_pcpu_from net/ipv6/ip6_fib.c:1024 [inline]
> fib6_purge_rt+0x888/0xa80 net/ipv6/ip6_fib.c:1035
> fib6_del_route net/ipv6/ip6_fib.c:1995 [inline]
> fib6_del+0xa63/0x17f0 net/ipv6/ip6_fib.c:2040
> fib6_clean_node+0x3a1/0x5d0 net/ipv6/ip6_fib.c:2202
> fib6_walk_continue+0x450/0x860 net/ipv6/ip6_fib.c:2124
> fib6_walk+0x182/0x370 net/ipv6/ip6_fib.c:2172
> fib6_clean_tree+0xdb/0x120 net/ipv6/ip6_fib.c:2252
> __fib6_clean_all+0x105/0x2d0 net/ipv6/ip6_fib.c:2268
> rt6_sync_down_dev net/ipv6/route.c:4908 [inline]
> rt6_disable_ip+0x80a/0xa10 net/ipv6/route.c:4913
> addrconf_ifdown.isra.0+0x12e/0x1ba0 net/ipv6/addrconf.c:3877
> addrconf_notify+0x109/0x1a60 net/ipv6/addrconf.c:3800
> notifier_call_chain+0xba/0x450 kernel/notifier.c:85
> call_netdevice_notifiers_info+0xbe/0x140 net/core/dev.c:1996
> call_netdevice_notifiers_extack net/core/dev.c:2034 [inline]
> call_netdevice_notifiers net/core/dev.c:2048 [inline]
> dev_close_many+0x33d/0x690 net/core/dev.c:1589
> unregister_netdevice_many_notify+0x47a/0x1d30 net/core/dev.c:11494
> unregister_netdevice_many net/core/dev.c:11584 [inline]
> default_device_exit_batch+0x740/0x980 net/core/dev.c:12067
> ops_exit_list+0x128/0x180 net/core/net_namespace.c:177
> cleanup_net+0x5b3/0xb60 net/core/net_namespace.c:632
> process_one_work+0x99f/0x1bb0 kernel/workqueue.c:3229
> process_scheduled_works kernel/workqueue.c:3310 [inline]
> worker_thread+0x66e/0xe80 kernel/workqueue.c:3391
> kthread+0x2c7/0x3b0 kernel/kthread.c:389
> ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
> ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> </TASK>
> Modules linked in:
> ---[ end trace 0000000000000000 ]---
> RIP: 0010:__fib6_drop_pcpu_from.part.0+0x18e/0x570 net/ipv6/ip6_fib.c:980
> Code: c2 48 c1 ea 03 80 3c 2a 00 0f 85 8a 03 00 00 4c 8b 38 4d 85 ff 74 2e e8 80 0c ca f7 49 8d bf 90 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 7c 03 00 00 49 8b 87 90 00 00 00 48 3b 04 24 0f
> RSP: 0018:ffffc900000defb8 EFLAGS: 00010207
> RAX: 0000000000000012 RBX: 0000000000000000 RCX: 1ffffffff1b0cb7c
> RDX: ffff88801cee2500 RSI: ffffffff89ceb460 RDI: 0000000000000096
> RBP: dffffc0000000000 R08: 0000000000000000 R09: fffffbfff2d8a198
> R10: 0000000000000000 R11: 0000000000000000 R12: fffffbfff1b0cc71
> R13: ffff88810669a8c8 R14: ffffed1020cd3524 R15: 0000000000000006
> FS: 0000000000000000(0000) GS:ffff888062800000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f6eecc57000 CR3: 0000000024d02000 CR4: 0000000000752ef0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
> PKRU: 55555554
> ----------------
> Code disassembly (best guess), 1 bytes skipped:
> 0: 48 c1 ea 03 shr $0x3,%rdx
> 4: 80 3c 2a 00 cmpb $0x0,(%rdx,%rbp,1)
> 8: 0f 85 8a 03 00 00 jne 0x398
> e: 4c 8b 38 mov (%rax),%r15
> 11: 4d 85 ff test %r15,%r15
> 14: 74 2e je 0x44
> 16: e8 80 0c ca f7 call 0xf7ca0c9b
> 1b: 49 8d bf 90 00 00 00 lea 0x90(%r15),%rdi
> 22: 48 89 f8 mov %rdi,%rax
> 25: 48 c1 e8 03 shr $0x3,%rax
> * 29: 80 3c 28 00 cmpb $0x0,(%rax,%rbp,1) <-- trapping instruction
> 2d: 0f 85 7c 03 00 00 jne 0x3af
> 33: 49 8b 87 90 00 00 00 mov 0x90(%r15),%rax
> 3a: 48 3b 04 24 cmp (%rsp),%rax
> 3e: 0f .byte 0xf