Re: KASAN: use-after-free Read in fib6_table_lookup
From: Eric Dumazet
Date: Mon Jun 18 2018 - 08:15:00 EST
On 06/17/2018 11:06 PM, syzbot wrote:
> Hello,
>
> syzbot found the following crash on:
>
> HEAD commit:ÂÂÂ f0dc7f9c6dd9 Merge git://git.kernel.org/pub/scm/linux/kern..
> git tree:ÂÂÂÂÂÂ bpf-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=16725130400000
> kernel config:Â https://syzkaller.appspot.com/x/.config?x=fa9c20c48788d1c1
> dashboard link: https://syzkaller.appspot.com/bug?extid=9e6d75e3edef427ee888
> compiler:ÂÂÂÂÂÂ gcc (GCC) 8.0.1 20180413 (experimental)
>
> Unfortunately, I don't have any reproducer for this crash yet.
>
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+9e6d75e3edef427ee888@xxxxxxxxxxxxxxxxxxxxxxxxx
>
> ==================================================================
> BUG: KASAN: use-after-free in __read_once_size include/linux/compiler.h:188 [inline]
> BUG: KASAN: use-after-free in find_rr_leaf net/ipv6/route.c:705 [inline]
> BUG: KASAN: use-after-free in rt6_select net/ipv6/route.c:761 [inline]
> BUG: KASAN: use-after-free in fib6_table_lookup+0x12b7/0x14d0 net/ipv6/route.c:1823
> Read of size 8 at addr ffff8801b5df2588 by task udevd/1407
>
> overlayfs: unrecognized mount option "SlïtIïïpï5ïWÓïïïcïï&ïe"ïMïïqïWïïïïuïr'ïvï-brE1nïïU(ïïKïgï==;GZïï ïïï<ïï2ÂÂÂ Nïïðïïïïïïïïlï8_ïï'ï%]ï]Xï7ïïïaNvDïcAïï_ï(ï"ïïwïïQïï++Q%5ïïïïï/ïï>*4Ïïïkï{ï)<ïï^rÎïBïïbÌïï(ïÓïÓïïïlÃï
> ïbïïïïïïïïbï@iOïAïsïïNï ï ï91ïÂïïmïGcïïïïjïï\ï2G-kïï'ïïUIï\8ïï}0ïï.ïGhïPïwïïïïïUï^9ï\ïïïSÝïÊïïnïïa]ïïTïEïïïïïgaj=ZÚï_kPïïl!ïÃïïïrïïsïï.ï9ïï\ïD]ïïbïy$ïïïmQïïïïïÚÒMïqïï~vX'ïï6ïÅ$5ïïa+ï.}ïUuc9Ýo.×ï.SÜIïï7ï5ïeïD8ïïkïïEïM#ïïïïïïmïïïïïVyïïïï7=jVïïïï:ïk[(>M
> #ïbïïïZç]k/^ïïïïïàïï;ïvïïïï`G6ïm>ïïï'e0ïïq
> ïs|ïwJï'rAïïïïMï$ïïïr0ï uïUU~|ïï}>P{1fltïïiï1+Aï ï%Û(7ËÈï?Üïïïïï)_ïïïïï[ïwïïïïïï9Wï
> ïØïïï&BïMïmï2ïbÖÉïS@ïqï
> ïï4jïhï%ïïTï'$'ï!ïÙtï4C3ïgïnypBÅïïïoïBïqïoï'ôï}ïï!ïTp9dËïïïcïïU`}_EÒïï\ïIïXïÂïq^ï7-[ïïv[ï-ï_Gïg)ï?#~ïïh
> CPU: 0 PID: 1407 Comm: udevd Not tainted 4.17.0+ #39
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> Call Trace:
> Â<IRQ>
> Â__dump_stack lib/dump_stack.c:77 [inline]
> Âdump_stack+0x1b9/0x294 lib/dump_stack.c:113
> Âprint_address_description+0x6c/0x20b mm/kasan/report.c:256
> Âkasan_report_error mm/kasan/report.c:354 [inline]
> Âkasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412
> Â__asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433
> Â__read_once_size include/linux/compiler.h:188 [inline]
> Âfind_rr_leaf net/ipv6/route.c:705 [inline]
> Ârt6_select net/ipv6/route.c:761 [inline]
> Âfib6_table_lookup+0x12b7/0x14d0 net/ipv6/route.c:1823
> Âip6_pol_route+0x1c2/0x1020 net/ipv6/route.c:1856
> Âip6_pol_route_output+0x54/0x70 net/ipv6/route.c:2082
> Âfib6_rule_lookup+0x211/0x6d0 net/ipv6/fib6_rules.c:122
> Âip6_route_output_flags+0x2c5/0x350 net/ipv6/route.c:2110
> Âip6_route_output include/net/ip6_route.h:82 [inline]
> Âicmpv6_xrlim_allow net/ipv6/icmp.c:211 [inline]
> Âicmp6_send+0x147c/0x2da0 net/ipv6/icmp.c:535
> Âicmpv6_send+0x17a/0x300 net/ipv6/ip6_icmp.c:43
> Âip6_link_failure+0xa5/0x790 net/ipv6/route.c:2244
> Âdst_link_failure include/net/dst.h:427 [inline]
> Ândisc_error_report+0xd1/0x1c0 net/ipv6/ndisc.c:695
> Âneigh_invalidate+0x246/0x550 net/core/neighbour.c:892
> Âneigh_timer_handler+0xaf9/0xde0 net/core/neighbour.c:978
> Âcall_timer_fn+0x230/0x940 kernel/time/timer.c:1326
> Âexpire_timers kernel/time/timer.c:1363 [inline]
> Â__run_timers+0x79e/0xc50 kernel/time/timer.c:1666
> Ârun_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692
> Â__do_softirq+0x2e0/0xaf5 kernel/softirq.c:284
> Âinvoke_softirq kernel/softirq.c:364 [inline]
> Âirq_exit+0x1d1/0x200 kernel/softirq.c:404
> Âexiting_irq arch/x86/include/asm/apic.h:527 [inline]
> Âsmp_apic_timer_interrupt+0x17e/0x710 arch/x86/kernel/apic/apic.c:1052
> Âapic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:863
> Â</IRQ>
> RIP: 0010:strlen+0x5e/0xa0 lib/string.c:482
> Code: 24 00 74 3b 48 bb 00 00 00 00 00 fc ff df 4c 89 e0 48 83 c0 01 48 89 c2 48 89 c1 48 c1 ea 03 83 e1 07 0f b6 14 1a 38 ca 7f 04 <84> d2 75 23 80 38 00 75 de 48 83 c4 08 4c 29 e0 5b 41 5c 5d c3 48
> RSP: 0018:ffff8801af117850 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13
> RAX: ffff880197f53bd0 RBX: dffffc0000000000 RCX: 0000000000000000
> RDX: 0000000000000000 RSI: ffffffff81c5b06c RDI: ffff880197f53bc0
> RBP: ffff8801af117868 R08: ffff88019a976540 R09: 0000000000000000
> R10: ffff88019a976540 R11: 0000000000000000 R12: ffff880197f53bc0
> R13: ffff880197f53bc0 R14: ffffffff899e4e90 R15: ffff8801d91c6a00
> Âstrlen include/linux/string.h:267 [inline]
> Âgetname_kernel+0x24/0x370 fs/namei.c:218
> Âopen_exec+0x17/0x70 fs/exec.c:882
> Âload_elf_binary+0x968/0x5610 fs/binfmt_elf.c:780
> Âsearch_binary_handler+0x17d/0x570 fs/exec.c:1653
> Âexec_binprm fs/exec.c:1695 [inline]
> Â__do_execve_file.isra.35+0x16fe/0x2710 fs/exec.c:1819
> Âdo_execveat_common fs/exec.c:1866 [inline]
> Âdo_execve fs/exec.c:1883 [inline]
> Â__do_sys_execve fs/exec.c:1964 [inline]
> Â__se_sys_execve fs/exec.c:1959 [inline]
> Â__x64_sys_execve+0x8f/0xc0 fs/exec.c:1959
> Âdo_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:290
> Âentry_SYSCALL_64_after_hwframe+0x49/0xbe
> RIP: 0033:0x7f1576a46207
> Code: 77 19 f4 48 89 d7 44 89 c0 0f 05 48 3d 00 f0 ff ff 76 e0 f7 d8 64 41 89 01 eb d8 f7 d8 64 41 89 01 eb df b8 3b 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 02 f3 c3 48 8b 15 00 8c 2d 00 f7 d8 64 89 02
> RSP: 002b:00007ffff2784568 EFLAGS: 00000202 ORIG_RAX: 000000000000003b
> RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 00007f1576a46207
> RDX: 0000000001215b10 RSI: 00007ffff2784660 RDI: 00007ffff2785670
> RBP: 0000000000625500 R08: 000000000000589c R09: 000000000000589c
> R10: 0000000000000000 R11: 0000000000000202 R12: 0000000001215b10
> R13: 0000000000000007 R14: 0000000001204250 R15: 0000000000000005
>
> Allocated by task 12188:
> Âsave_stack+0x43/0xd0 mm/kasan/kasan.c:448
> Âset_track mm/kasan/kasan.c:460 [inline]
> Âkasan_kmalloc+0xc4/0xe0 mm/kasan/kasan.c:553
> Âkmem_cache_alloc_trace+0x152/0x780 mm/slab.c:3620
> Âkmalloc include/linux/slab.h:513 [inline]
> Âkzalloc include/linux/slab.h:706 [inline]
> Âfib6_info_alloc+0xbb/0x280 net/ipv6/ip6_fib.c:152
> Âip6_route_info_create+0x782/0x2b50 net/ipv6/route.c:3013
> Âip6_route_add+0x23/0xb0 net/ipv6/route.c:3154
> Âipv6_route_ioctl+0x5a5/0x760 net/ipv6/route.c:3660
> Âinet6_ioctl+0x100/0x1f0 net/ipv6/af_inet6.c:546
> Âsock_do_ioctl+0xe4/0x3e0 net/socket.c:973
> Âsock_ioctl+0x30d/0x680 net/socket.c:1097
> Âvfs_ioctl fs/ioctl.c:46 [inline]
> Âfile_ioctl fs/ioctl.c:500 [inline]
> Âdo_vfs_ioctl+0x1cf/0x16f0 fs/ioctl.c:684
> Âksys_ioctl+0xa9/0xd0 fs/ioctl.c:701
> Â__do_sys_ioctl fs/ioctl.c:708 [inline]
> Â__se_sys_ioctl fs/ioctl.c:706 [inline]
> Â__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:706
> Âdo_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:290
> Âentry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> Freed by task 1402:
> Âsave_stack+0x43/0xd0 mm/kasan/kasan.c:448
> Âset_track mm/kasan/kasan.c:460 [inline]
> Â__kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
> Âkasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
> Â__cache_free mm/slab.c:3498 [inline]
> Âkfree+0xd9/0x260 mm/slab.c:3813
> Âfib6_info_destroy+0x29b/0x350 net/ipv6/ip6_fib.c:207
> Âfib6_info_release include/net/ip6_fib.h:286 [inline]
> Â__ip6_del_rt_siblings net/ipv6/route.c:3235 [inline]
> Âip6_route_del+0x11c4/0x13b0 net/ipv6/route.c:3316
> Âipv6_route_ioctl+0x616/0x760 net/ipv6/route.c:3663
> Âinet6_ioctl+0x100/0x1f0 net/ipv6/af_inet6.c:546
> Âsock_do_ioctl+0xe4/0x3e0 net/socket.c:973
> Âsock_ioctl+0x30d/0x680 net/socket.c:1097
> Âvfs_ioctl fs/ioctl.c:46 [inline]
> Âfile_ioctl fs/ioctl.c:500 [inline]
> Âdo_vfs_ioctl+0x1cf/0x16f0 fs/ioctl.c:684
> Âksys_ioctl+0xa9/0xd0 fs/ioctl.c:701
> Â__do_sys_ioctl fs/ioctl.c:708 [inline]
> Â__se_sys_ioctl fs/ioctl.c:706 [inline]
> Â__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:706
> Âdo_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:290
> Âentry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> The buggy address belongs to the object at ffff8801b5df2580
> Âwhich belongs to the cache kmalloc-256 of size 256
> The buggy address is located 8 bytes inside of
> Â256-byte region [ffff8801b5df2580, ffff8801b5df2680)
> The buggy address belongs to the page:
> page:ffffea0006d77c80 count:1 mapcount:0 mapping:ffff8801da8007c0 index:0xffff8801b5df2e40
> flags: 0x2fffc0000000100(slab)
> raw: 02fffc0000000100 ffffea0006c5cc48 ffffea0007363308 ffff8801da8007c0
> raw: ffff8801b5df2e40 ffff8801b5df2080 0000000100000006 0000000000000000
> page dumped because: kasan: bad access detected
>
> Memory state around the buggy address:
> Âffff8801b5df2480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> Âffff8801b5df2500: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>> ffff8801b5df2580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ^
> Âffff8801b5df2600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> Âffff8801b5df2680: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
> ==================================================================
>
>
> ---
> This bug is generated by a bot. It may contain errors.
> See https://goo.gl/tpsmEJ for more information about syzbot.
> syzbot engineers can be reached at syzkaller@xxxxxxxxxxxxxxxxx
>
> syzbot will keep track of this bug report. See:
> https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot.
I will test the following fix, and sent it formally.
Fixes: a64efe142f5e ("net/ipv6: introduce fib6_info struct and helpers")
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 5cba71d2dc44b9ea2366725ff68c9f668f639345..71b9043aa0e7995c7e61f17b4493acd99410d1bc 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -170,6 +170,7 @@ struct fib6_info {
unused:3;
struct fib6_nh fib6_nh;
+ struct rcu_head rcu;
};
struct rt6_info {
@@ -273,7 +274,7 @@ static inline void ip6_rt_put(struct rt6_info *rt)
}
struct fib6_info *fib6_info_alloc(gfp_t gfp_flags);
-void fib6_info_destroy(struct fib6_info *f6i);
+void fib6_info_destroy_rcu(struct rcu_head *head);
static inline void fib6_info_hold(struct fib6_info *f6i)
{
@@ -283,7 +284,7 @@ static inline void fib6_info_hold(struct fib6_info *f6i)
static inline void fib6_info_release(struct fib6_info *f6i)
{
if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
- fib6_info_destroy(f6i);
+ call_rcu(&f6i->rcu, fib6_info_destroy_rcu);
}
enum fib6_walk_state {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 39d1d487eca25faceacbc3619fc6c4c38088d62a..1fb2f3118d60c73433e09f3a71abdbf9a8d92227 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -167,8 +167,9 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
return f6i;
}
-void fib6_info_destroy(struct fib6_info *f6i)
+void fib6_info_destroy_rcu(struct rcu_head *head)
{
+ struct fib6_info *f6i = container_of(head, struct fib6_info, rcu);
struct rt6_exception_bucket *bucket;
struct dst_metrics *m;
@@ -206,7 +207,7 @@ void fib6_info_destroy(struct fib6_info *f6i)
kfree(f6i);
}
-EXPORT_SYMBOL_GPL(fib6_info_destroy);
+EXPORT_SYMBOL_GPL(fib6_info_destroy_rcu);
static struct fib6_node *node_alloc(struct net *net)
{