[prev in list] [next in list] [prev in thread] [next in thread]
List: oss-security
Subject: [oss-security] CVE-2022-1976: Linux Kernel: A use-after-free in __lock_acquire
From: Gerald Lee <sundaywind2004 () gmail ! com>
Date: 2022-06-14 1:07:55
Message-ID: CAO3qeMXKb7vad9opV7B1oSsHbJ8D4jTpQaF2CwF=J1vVdcSe8g () mail ! gmail ! com
[Download RAW message or body]
[Attachment #2 (multipart/alternative)]
Hi all,
=*=*=*=*=*=*=*=*= BUG DETAILS =*=*=*=*=*=*=*=*=
The old inflight tracking for any file type that has io_uring_fops needs to
be assigned, otherwise
trivial circular references never get the ctx cleaned up and hence it'll
leak.
This issue was reported on May 31 and assigned CVE-2022-1976.
C repro is attached.
=*=*=*=*=*=*=*=*= BACKTRACE =*=*=*=*=*=*=*=*=
BUG: KASAN: use-after-free in __lock_acquire+0x385f/0x5840
root/opt/kernel/kernel/locking/lockdep.c:4899
Read of size 8 at addr ffff8880682db3b8 by task kworker/1:9/9642
CPU: 1 PID: 9642 Comm: kworker/1:9 Not tainted 5.18.0 #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
1.13.0-1ubuntu1.1 04/01/2014
Workqueue: events io_fallback_req_func
Call Trace:
<TASK>
__dump_stack root/opt/kernel/lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xcd/0x134 root/opt/kernel/lib/dump_stack.c:106
print_address_description root/opt/kernel/mm/kasan/report.c:313 [inline]
print_report.cold+0xe5/0x659 root/opt/kernel/mm/kasan/report.c:429
kasan_report+0x8a/0x1b0 root/opt/kernel/mm/kasan/report.c:491
__lock_acquire+0x385f/0x5840 root/opt/kernel/kernel/locking/lockdep.c:4899
lock_acquire root/opt/kernel/kernel/locking/lockdep.c:5641 [inline]
lock_acquire+0x1ab/0x520 root/opt/kernel/kernel/locking/lockdep.c:5606
__raw_spin_lock_irq root/opt/kernel/./include/linux/spinlock_api_smp.h:119
[inline]
_raw_spin_lock_irq+0x32/0x50 root/opt/kernel/kernel/locking/spinlock.c:170
spin_lock_irq root/opt/kernel/./include/linux/spinlock.h:374 [inline]
io_poll_remove_entry root/opt/kernel/fs/io_uring.c:6840 [inline]
io_poll_remove_entries.part.0+0x15f/0x7d0
root/opt/kernel/fs/io_uring.c:6873
io_poll_remove_entries root/opt/kernel/fs/io_uring.c:6853 [inline]
io_poll_task_func+0x187/0x500 root/opt/kernel/fs/io_uring.c:6971
io_fallback_req_func+0xfa/0x1b0 root/opt/kernel/fs/io_uring.c:1824
process_one_work+0x9cc/0x1650 root/opt/kernel/kernel/workqueue.c:2289
worker_thread+0x623/0x1070 root/opt/kernel/kernel/workqueue.c:2436
kthread+0x2e9/0x3a0 root/opt/kernel/kernel/kthread.c:376
ret_from_fork+0x1f/0x30 root/opt/kernel/arch/x86/entry/entry_64.S:302
</TASK>
Allocated by task 11840:
kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38
kasan_set_track root/opt/kernel/mm/kasan/common.c:45 [inline]
set_alloc_info root/opt/kernel/mm/kasan/common.c:436 [inline]
____kasan_kmalloc root/opt/kernel/mm/kasan/common.c:515 [inline]
____kasan_kmalloc root/opt/kernel/mm/kasan/common.c:474 [inline]
__kasan_kmalloc+0xa9/0xd0 root/opt/kernel/mm/kasan/common.c:524
kasan_kmalloc root/opt/kernel/./include/linux/kasan.h:234 [inline]
__kmalloc+0x1c9/0x4c0 root/opt/kernel/mm/slub.c:4414
io_ring_ctx_alloc root/opt/kernel/fs/io_uring.c:1838 [inline]
io_uring_create root/opt/kernel/fs/io_uring.c:12396 [inline]
io_uring_setup.cold+0x176/0x2a59 root/opt/kernel/fs/io_uring.c:12535
do_syscall_x64 root/opt/kernel/arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x35/0xb0 root/opt/kernel/arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x46/0xb0
Freed by task 787:
kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38
kasan_set_track+0x21/0x30 root/opt/kernel/mm/kasan/common.c:45
kasan_set_free_info+0x20/0x30 root/opt/kernel/mm/kasan/generic.c:370
____kasan_slab_free root/opt/kernel/mm/kasan/common.c:366 [inline]
____kasan_slab_free root/opt/kernel/mm/kasan/common.c:328 [inline]
__kasan_slab_free+0x11d/0x190 root/opt/kernel/mm/kasan/common.c:374
kasan_slab_free root/opt/kernel/./include/linux/kasan.h:200 [inline]
slab_free_hook root/opt/kernel/mm/slub.c:1728 [inline]
slab_free_freelist_hook root/opt/kernel/mm/slub.c:1754 [inline]
slab_free root/opt/kernel/mm/slub.c:3510 [inline]
kfree+0xec/0x4b0 root/opt/kernel/mm/slub.c:4552
io_ring_ctx_free root/opt/kernel/fs/io_uring.c:11159 [inline]
io_ring_exit_work+0xefb/0xf43 root/opt/kernel/fs/io_uring.c:11303
process_one_work+0x9cc/0x1650 root/opt/kernel/kernel/workqueue.c:2289
worker_thread+0x623/0x1070 root/opt/kernel/kernel/workqueue.c:2436
kthread+0x2e9/0x3a0 root/opt/kernel/kernel/kthread.c:376
ret_from_fork+0x1f/0x30 root/opt/kernel/arch/x86/entry/entry_64.S:302
Last potentially related work creation:
kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38
__kasan_record_aux_stack+0xbe/0xd0 root/opt/kernel/mm/kasan/generic.c:348
insert_work+0x4a/0x390 root/opt/kernel/kernel/workqueue.c:1358
__queue_work+0x4dd/0x1140 root/opt/kernel/kernel/workqueue.c:1517
queue_work_on+0xee/0x110 root/opt/kernel/kernel/workqueue.c:1545
queue_work root/opt/kernel/./include/linux/workqueue.h:502 [inline]
io_ring_ctx_wait_and_kill+0x2b6/0x2ec root/opt/kernel/fs/io_uring.c:11357
io_uring_release+0x42/0x46 root/opt/kernel/fs/io_uring.c:11365
__fput+0x277/0x9d0 root/opt/kernel/fs/file_table.c:317
task_work_run+0xe0/0x1a0 root/opt/kernel/kernel/task_work.c:177
exit_task_work root/opt/kernel/./include/linux/task_work.h:38 [inline]
do_exit+0xb16/0x2dc0 root/opt/kernel/kernel/exit.c:795
do_group_exit+0xd2/0x2f0 root/opt/kernel/kernel/exit.c:925
get_signal+0x2847/0x2880 root/opt/kernel/kernel/signal.c:2864
arch_do_signal_or_restart+0x81/0x1e30
root/opt/kernel/arch/x86/kernel/signal.c:869
exit_to_user_mode_loop root/opt/kernel/kernel/entry/common.c:166 [inline]
exit_to_user_mode_prepare+0x174/0x260
root/opt/kernel/kernel/entry/common.c:201
__syscall_exit_to_user_mode_work root/opt/kernel/kernel/entry/common.c:283
[inline]
syscall_exit_to_user_mode+0x19/0x60
root/opt/kernel/kernel/entry/common.c:294
do_syscall_64+0x42/0xb0 root/opt/kernel/arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x46/0xb0
The buggy address belongs to the object at ffff8880682db000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 952 bytes inside of
2048-byte region [ffff8880682db000, ffff8880682db800)
The buggy address belongs to the physical page:
page:ffffea0001a0b600 refcount:1 mapcount:0 mapping:0000000000000000
index:0x0 pfn:0x682d8
head:ffffea0001a0b600 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x4fff00000010200(slab|head|node=1|zone=1|lastcpupid=0x7ff)
raw: 04fff00000010200 ffffea00019e8e00 dead000000000002 ffff888010c42000
raw: 0000000000000000 0000000000080008 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask
0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC),
pid 6529, tgid 6529 (syz-executor.2), ts 33495069085, free_ts 0
set_page_owner root/opt/kernel/./include/linux/page_owner.h:31 [inline]
post_alloc_hook root/opt/kernel/mm/page_alloc.c:2434 [inline]
prep_new_page+0x297/0x330 root/opt/kernel/mm/page_alloc.c:2441
get_page_from_freelist+0x210e/0x3ab0 root/opt/kernel/mm/page_alloc.c:4182
__alloc_pages+0x30c/0x6e0 root/opt/kernel/mm/page_alloc.c:5408
alloc_pages+0x119/0x250 root/opt/kernel/mm/mempolicy.c:2272
alloc_slab_page root/opt/kernel/mm/slub.c:1799 [inline]
allocate_slab root/opt/kernel/mm/slub.c:1944 [inline]
new_slab+0x2a9/0x3f0 root/opt/kernel/mm/slub.c:2004
___slab_alloc+0xc62/0x1080 root/opt/kernel/mm/slub.c:3005
__slab_alloc.isra.0+0x4d/0xa0 root/opt/kernel/mm/slub.c:3092
slab_alloc_node root/opt/kernel/mm/slub.c:3183 [inline]
slab_alloc root/opt/kernel/mm/slub.c:3225 [inline]
kmem_cache_alloc_trace+0x383/0x460 root/opt/kernel/mm/slub.c:3256
kmalloc root/opt/kernel/./include/linux/slab.h:581 [inline]
kzalloc root/opt/kernel/./include/linux/slab.h:714 [inline]
ipv6_add_dev root/opt/kernel/net/ipv6/addrconf.c:378 [inline]
ipv6_add_dev+0xfe/0x12d0 root/opt/kernel/net/ipv6/addrconf.c:368
addrconf_notify+0x614/0x1bb0 root/opt/kernel/net/ipv6/addrconf.c:3521
notifier_call_chain+0xb5/0x200 root/opt/kernel/kernel/notifier.c:84
call_netdevice_notifiers_info root/opt/kernel/net/core/dev.c:1938 [inline]
call_netdevice_notifiers_info+0xb5/0x130
root/opt/kernel/net/core/dev.c:1923
call_netdevice_notifiers_extack root/opt/kernel/net/core/dev.c:1976
[inline]
call_netdevice_notifiers root/opt/kernel/net/core/dev.c:1990 [inline]
register_netdevice+0xeb5/0x12b0 root/opt/kernel/net/core/dev.c:9994
veth_newlink+0x405/0xa90 root/opt/kernel/drivers/net/veth.c:1764
__rtnl_newlink+0xf52/0x1600 root/opt/kernel/net/core/rtnetlink.c:3483
rtnl_newlink+0x64/0xa0 root/opt/kernel/net/core/rtnetlink.c:3531
page_owner free stack trace missing
Memory state around the buggy address:
ffff8880682db280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8880682db300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8880682db380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff8880682db400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8880682db480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
=*=*=*=*=*=*=*=*= PATCH =*=*=*=*=*=*=*=*=
The patch has been merged into the Linux kernel mainline and stable-master
tree.
It can be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9cae36a094e7e9d6e5fe8b6dcd4642138b3eb0c7
=*=*=*=*=*=*=*=*= CREDIT =*=*=*=*=*=*=*=*=
Zhixin Li from Zero-one Security <sundaywind2004@gmail.com>
Thanks.
[Attachment #5 (text/html)]
<div dir="ltr"><div class="gmail_default" style="font-size:small">Hi \
all,<br><br>=*=*=*=*=*=*=*=*= BUG DETAILS =*=*=*=*=*=*=*=*=<br><br>The old inflight \
tracking for any file type that has io_uring_fops needs to be assigned, otherwise<br>trivial \
circular references never get the ctx cleaned up and hence it'll leak.<br><br>This issue \
was reported on May 31 and assigned CVE-2022-1976.<br><br>C repro is \
attached.<br><br><br>=*=*=*=*=*=*=*=*= BACKTRACE =*=*=*=*=*=*=*=*=<br><br>BUG: \
KASAN: use-after-free in __lock_acquire+0x385f/0x5840 \
root/opt/kernel/kernel/locking/lockdep.c:4899<br>Read of size 8 at addr ffff8880682db3b8 by \
task kworker/1:9/9642<br><br>CPU: 1 PID: 9642 Comm: kworker/1:9 Not tainted 5.18.0 \
#7<br>Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 \
04/01/2014<br>Workqueue: events io_fallback_req_func<br>Call Trace:<br> <TASK><br> \
__dump_stack root/opt/kernel/lib/dump_stack.c:88 [inline]<br> dump_stack_lvl+0xcd/0x134 \
root/opt/kernel/lib/dump_stack.c:106<br> print_address_description \
root/opt/kernel/mm/kasan/report.c:313 [inline]<br> print_report.cold+0xe5/0x659 \
root/opt/kernel/mm/kasan/report.c:429<br> kasan_report+0x8a/0x1b0 \
root/opt/kernel/mm/kasan/report.c:491<br> __lock_acquire+0x385f/0x5840 \
root/opt/kernel/kernel/locking/lockdep.c:4899<br> lock_acquire \
root/opt/kernel/kernel/locking/lockdep.c:5641 [inline]<br> lock_acquire+0x1ab/0x520 \
root/opt/kernel/kernel/locking/lockdep.c:5606<br> __raw_spin_lock_irq \
root/opt/kernel/./include/linux/spinlock_api_smp.h:119 [inline]<br> \
_raw_spin_lock_irq+0x32/0x50 root/opt/kernel/kernel/locking/spinlock.c:170<br> spin_lock_irq \
root/opt/kernel/./include/linux/spinlock.h:374 [inline]<br> io_poll_remove_entry \
root/opt/kernel/fs/io_uring.c:6840 [inline]<br> io_poll_remove_entries.part.0+0x15f/0x7d0 \
root/opt/kernel/fs/io_uring.c:6873<br> io_poll_remove_entries \
root/opt/kernel/fs/io_uring.c:6853 [inline]<br> io_poll_task_func+0x187/0x500 \
root/opt/kernel/fs/io_uring.c:6971<br> io_fallback_req_func+0xfa/0x1b0 \
root/opt/kernel/fs/io_uring.c:1824<br> process_one_work+0x9cc/0x1650 \
root/opt/kernel/kernel/workqueue.c:2289<br> worker_thread+0x623/0x1070 \
root/opt/kernel/kernel/workqueue.c:2436<br> kthread+0x2e9/0x3a0 \
root/opt/kernel/kernel/kthread.c:376<br> ret_from_fork+0x1f/0x30 \
root/opt/kernel/arch/x86/entry/entry_64.S:302<br> </TASK><br><br>Allocated by task \
11840:<br> kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38<br> \
kasan_set_track root/opt/kernel/mm/kasan/common.c:45 [inline]<br> set_alloc_info \
root/opt/kernel/mm/kasan/common.c:436 [inline]<br> ____kasan_kmalloc \
root/opt/kernel/mm/kasan/common.c:515 [inline]<br> ____kasan_kmalloc \
root/opt/kernel/mm/kasan/common.c:474 [inline]<br> __kasan_kmalloc+0xa9/0xd0 \
root/opt/kernel/mm/kasan/common.c:524<br> kasan_kmalloc \
root/opt/kernel/./include/linux/kasan.h:234 [inline]<br> __kmalloc+0x1c9/0x4c0 \
root/opt/kernel/mm/slub.c:4414<br> io_ring_ctx_alloc root/opt/kernel/fs/io_uring.c:1838 \
[inline]<br> io_uring_create root/opt/kernel/fs/io_uring.c:12396 [inline]<br> \
io_uring_setup.cold+0x176/0x2a59 root/opt/kernel/fs/io_uring.c:12535<br> do_syscall_x64 \
root/opt/kernel/arch/x86/entry/common.c:50 [inline]<br> do_syscall_64+0x35/0xb0 \
root/opt/kernel/arch/x86/entry/common.c:80<br> \
entry_SYSCALL_64_after_hwframe+0x46/0xb0<br><br>Freed by task 787:<br> \
kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38<br> kasan_set_track+0x21/0x30 \
root/opt/kernel/mm/kasan/common.c:45<br> kasan_set_free_info+0x20/0x30 \
root/opt/kernel/mm/kasan/generic.c:370<br> ____kasan_slab_free \
root/opt/kernel/mm/kasan/common.c:366 [inline]<br> ____kasan_slab_free \
root/opt/kernel/mm/kasan/common.c:328 [inline]<br> __kasan_slab_free+0x11d/0x190 \
root/opt/kernel/mm/kasan/common.c:374<br> kasan_slab_free \
root/opt/kernel/./include/linux/kasan.h:200 [inline]<br> slab_free_hook \
root/opt/kernel/mm/slub.c:1728 [inline]<br> slab_free_freelist_hook \
root/opt/kernel/mm/slub.c:1754 [inline]<br> slab_free root/opt/kernel/mm/slub.c:3510 \
[inline]<br> kfree+0xec/0x4b0 root/opt/kernel/mm/slub.c:4552<br> io_ring_ctx_free \
root/opt/kernel/fs/io_uring.c:11159 [inline]<br> io_ring_exit_work+0xefb/0xf43 \
root/opt/kernel/fs/io_uring.c:11303<br> process_one_work+0x9cc/0x1650 \
root/opt/kernel/kernel/workqueue.c:2289<br> worker_thread+0x623/0x1070 \
root/opt/kernel/kernel/workqueue.c:2436<br> kthread+0x2e9/0x3a0 \
root/opt/kernel/kernel/kthread.c:376<br> ret_from_fork+0x1f/0x30 \
root/opt/kernel/arch/x86/entry/entry_64.S:302<br><br>Last potentially related work \
creation:<br> kasan_save_stack+0x1e/0x40 root/opt/kernel/mm/kasan/common.c:38<br> \
__kasan_record_aux_stack+0xbe/0xd0 root/opt/kernel/mm/kasan/generic.c:348<br> \
insert_work+0x4a/0x390 root/opt/kernel/kernel/workqueue.c:1358<br> __queue_work+0x4dd/0x1140 \
root/opt/kernel/kernel/workqueue.c:1517<br> queue_work_on+0xee/0x110 \
root/opt/kernel/kernel/workqueue.c:1545<br> queue_work \
root/opt/kernel/./include/linux/workqueue.h:502 [inline]<br> \
io_ring_ctx_wait_and_kill+0x2b6/0x2ec root/opt/kernel/fs/io_uring.c:11357<br> \
io_uring_release+0x42/0x46 root/opt/kernel/fs/io_uring.c:11365<br> __fput+0x277/0x9d0 \
root/opt/kernel/fs/file_table.c:317<br> task_work_run+0xe0/0x1a0 \
root/opt/kernel/kernel/task_work.c:177<br> exit_task_work \
root/opt/kernel/./include/linux/task_work.h:38 [inline]<br> do_exit+0xb16/0x2dc0 \
root/opt/kernel/kernel/exit.c:795<br> do_group_exit+0xd2/0x2f0 \
root/opt/kernel/kernel/exit.c:925<br> get_signal+0x2847/0x2880 \
root/opt/kernel/kernel/signal.c:2864<br> arch_do_signal_or_restart+0x81/0x1e30 \
root/opt/kernel/arch/x86/kernel/signal.c:869<br> exit_to_user_mode_loop \
root/opt/kernel/kernel/entry/common.c:166 [inline]<br> exit_to_user_mode_prepare+0x174/0x260 \
root/opt/kernel/kernel/entry/common.c:201<br> __syscall_exit_to_user_mode_work \
root/opt/kernel/kernel/entry/common.c:283 [inline]<br> syscall_exit_to_user_mode+0x19/0x60 \
root/opt/kernel/kernel/entry/common.c:294<br> do_syscall_64+0x42/0xb0 \
root/opt/kernel/arch/x86/entry/common.c:86<br> \
entry_SYSCALL_64_after_hwframe+0x46/0xb0<br><br>The buggy address belongs to the object at \
ffff8880682db000<br> which belongs to the cache kmalloc-2k of size 2048<br>The buggy address \
is located 952 bytes inside of<br> 2048-byte region [ffff8880682db000, \
ffff8880682db800)<br><br>The buggy address belongs to the physical \
page:<br>page:ffffea0001a0b600 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 \
pfn:0x682d8<br>head:ffffea0001a0b600 order:3 compound_mapcount:0 compound_pincount:0<br>flags: \
0x4fff00000010200(slab|head|node=1|zone=1|lastcpupid=0x7ff)<br>raw: 04fff00000010200 \
ffffea00019e8e00 dead000000000002 ffff888010c42000<br>raw: 0000000000000000 0000000000080008 \
00000001ffffffff 0000000000000000<br>page dumped because: kasan: bad access \
detected<br>page_owner tracks the page as allocated<br>page last allocated via order 3, \
migratetype Unmovable, gfp_mask \
0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 6529, \
tgid 6529 (syz-executor.2), ts 33495069085, free_ts 0<br> set_page_owner \
root/opt/kernel/./include/linux/page_owner.h:31 [inline]<br> post_alloc_hook \
root/opt/kernel/mm/page_alloc.c:2434 [inline]<br> prep_new_page+0x297/0x330 \
root/opt/kernel/mm/page_alloc.c:2441<br> get_page_from_freelist+0x210e/0x3ab0 \
root/opt/kernel/mm/page_alloc.c:4182<br> __alloc_pages+0x30c/0x6e0 \
root/opt/kernel/mm/page_alloc.c:5408<br> alloc_pages+0x119/0x250 \
root/opt/kernel/mm/mempolicy.c:2272<br> alloc_slab_page root/opt/kernel/mm/slub.c:1799 \
[inline]<br> allocate_slab root/opt/kernel/mm/slub.c:1944 [inline]<br> new_slab+0x2a9/0x3f0 \
root/opt/kernel/mm/slub.c:2004<br> ___slab_alloc+0xc62/0x1080 \
root/opt/kernel/mm/slub.c:3005<br> __slab_alloc.isra.0+0x4d/0xa0 \
root/opt/kernel/mm/slub.c:3092<br> slab_alloc_node root/opt/kernel/mm/slub.c:3183 [inline]<br> \
slab_alloc root/opt/kernel/mm/slub.c:3225 [inline]<br> kmem_cache_alloc_trace+0x383/0x460 \
root/opt/kernel/mm/slub.c:3256<br> kmalloc root/opt/kernel/./include/linux/slab.h:581 \
[inline]<br> kzalloc root/opt/kernel/./include/linux/slab.h:714 [inline]<br> ipv6_add_dev \
root/opt/kernel/net/ipv6/addrconf.c:378 [inline]<br> ipv6_add_dev+0xfe/0x12d0 \
root/opt/kernel/net/ipv6/addrconf.c:368<br> addrconf_notify+0x614/0x1bb0 \
root/opt/kernel/net/ipv6/addrconf.c:3521<br> notifier_call_chain+0xb5/0x200 \
root/opt/kernel/kernel/notifier.c:84<br> call_netdevice_notifiers_info \
root/opt/kernel/net/core/dev.c:1938 [inline]<br> call_netdevice_notifiers_info+0xb5/0x130 \
root/opt/kernel/net/core/dev.c:1923<br> call_netdevice_notifiers_extack \
root/opt/kernel/net/core/dev.c:1976 [inline]<br> call_netdevice_notifiers \
root/opt/kernel/net/core/dev.c:1990 [inline]<br> register_netdevice+0xeb5/0x12b0 \
root/opt/kernel/net/core/dev.c:9994<br> veth_newlink+0x405/0xa90 \
root/opt/kernel/drivers/net/veth.c:1764<br> __rtnl_newlink+0xf52/0x1600 \
root/opt/kernel/net/core/rtnetlink.c:3483<br> rtnl_newlink+0x64/0xa0 \
root/opt/kernel/net/core/rtnetlink.c:3531<br>page_owner free stack trace missing<br><br>Memory \
state around the buggy address:<br> ffff8880682db280: fb fb fb fb fb fb fb fb fb fb fb fb fb \
fb fb fb<br> ffff8880682db300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb \
fb<br>>ffff8880682db380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb<br> \
^<br> ffff8880682db400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb<br> ffff8880682db480: \
fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb<br><br><br>=*=*=*=*=*=*=*=*= PATCH \
=*=*=*=*=*=*=*=*=<br><br>The patch has been merged into the Linux kernel mainline and \
stable-master tree. <br></div><div class="gmail_default" style="font-size:small">It can be \
found here:<br><a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9cae36a094e7e9d6e5fe8b6dcd4642138b3eb0c7" \
target="_blank">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9cae36a094e7e9d6e5fe8b6dcd4642138b3eb0c7</a><br><br><br>=*=*=*=*=*=*=*=*= \
CREDIT =*=*=*=*=*=*=*=*=<br><br>Zhixin Li from Zero-one Security <<a \
href="mailto:sundaywind2004@gmail.com" \
target="_blank">sundaywind2004@gmail.com</a>><br><br><br>Thanks.<br></div></div>
--00000000000092088e05e15e0955--
["repro.c" (text/x-c-code)]
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>
#ifndef __NR_io_uring_enter
#define __NR_io_uring_enter 426
#endif
#ifndef __NR_io_uring_setup
#define __NR_io_uring_setup 425
#endif
static __thread int clone_ongoing;
static __thread int skip_segv;
static __thread jmp_buf segv_env;
static void segv_handler(int sig, siginfo_t* info, void* ctx)
{
if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
exit(sig);
}
uintptr_t addr = (uintptr_t)info->si_addr;
const uintptr_t prog_start = 1 << 20;
const uintptr_t prog_end = 100 << 20;
int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
int valid = addr < prog_start || addr > prog_end;
if (skip && valid) {
_longjmp(segv_env, 1);
}
exit(sig);
}
static void install_segv_handler(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = segv_handler;
sa.sa_flags = SA_NODEFER | SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
}
#define NONFAILING(...) ({ int ok = 1; __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); if \
(_setjmp(segv_env) == 0) { __VA_ARGS__; } else ok = 0; __atomic_fetch_sub(&skip_segv, 1, \
__ATOMIC_SEQ_CST); ok; })
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}
#define SIZEOF_IO_URING_SQE 64
#define SIZEOF_IO_URING_CQE 16
#define SQ_HEAD_OFFSET 0
#define SQ_TAIL_OFFSET 64
#define SQ_RING_MASK_OFFSET 256
#define SQ_RING_ENTRIES_OFFSET 264
#define SQ_FLAGS_OFFSET 276
#define SQ_DROPPED_OFFSET 272
#define CQ_HEAD_OFFSET 128
#define CQ_TAIL_OFFSET 192
#define CQ_RING_MASK_OFFSET 260
#define CQ_RING_ENTRIES_OFFSET 268
#define CQ_RING_OVERFLOW_OFFSET 284
#define CQ_FLAGS_OFFSET 280
#define CQ_CQES_OFFSET 320
struct io_sqring_offsets {
uint32_t head;
uint32_t tail;
uint32_t ring_mask;
uint32_t ring_entries;
uint32_t flags;
uint32_t dropped;
uint32_t array;
uint32_t resv1;
uint64_t resv2;
};
struct io_cqring_offsets {
uint32_t head;
uint32_t tail;
uint32_t ring_mask;
uint32_t ring_entries;
uint32_t overflow;
uint32_t cqes;
uint64_t resv[2];
};
struct io_uring_params {
uint32_t sq_entries;
uint32_t cq_entries;
uint32_t flags;
uint32_t sq_thread_cpu;
uint32_t sq_thread_idle;
uint32_t features;
uint32_t resv[4];
struct io_sqring_offsets sq_off;
struct io_cqring_offsets cq_off;
};
#define IORING_OFF_SQ_RING 0
#define IORING_OFF_SQES 0x10000000ULL
static long syz_io_uring_setup(volatile long a0, volatile long a1, volatile long a2, volatile \
long a3, volatile long a4, volatile long a5) {
uint32_t entries = (uint32_t)a0;
struct io_uring_params* setup_params = (struct io_uring_params*)a1;
void* vma1 = (void*)a2;
void* vma2 = (void*)a3;
void** ring_ptr_out = (void**)a4;
void** sqes_ptr_out = (void**)a5;
uint32_t fd_io_uring = syscall(__NR_io_uring_setup, entries, setup_params);
uint32_t sq_ring_sz = setup_params->sq_off.array + setup_params->sq_entries * \
sizeof(uint32_t); uint32_t cq_ring_sz = setup_params->cq_off.cqes + setup_params->cq_entries * \
SIZEOF_IO_URING_CQE; uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz;
*ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | \
MAP_FIXED, fd_io_uring, IORING_OFF_SQ_RING); uint32_t sqes_sz = setup_params->sq_entries * \
SIZEOF_IO_URING_SQE;
*sqes_ptr_out = mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | \
MAP_FIXED, fd_io_uring, IORING_OFF_SQES); return fd_io_uring;
}
static long syz_io_uring_submit(volatile long a0, volatile long a1, volatile long a2, volatile \
long a3) {
char* ring_ptr = (char*)a0;
char* sqes_ptr = (char*)a1;
char* sqe = (char*)a2;
uint32_t sqes_index = (uint32_t)a3;
uint32_t sq_ring_entries = *(uint32_t*)(ring_ptr + SQ_RING_ENTRIES_OFFSET);
uint32_t cq_ring_entries = *(uint32_t*)(ring_ptr + CQ_RING_ENTRIES_OFFSET);
uint32_t sq_array_off = (CQ_CQES_OFFSET + cq_ring_entries * SIZEOF_IO_URING_CQE + 63) & ~63;
if (sq_ring_entries)
sqes_index %= sq_ring_entries;
char* sqe_dest = sqes_ptr + sqes_index * SIZEOF_IO_URING_SQE;
memcpy(sqe_dest, sqe, SIZEOF_IO_URING_SQE);
uint32_t sq_ring_mask = *(uint32_t*)(ring_ptr + SQ_RING_MASK_OFFSET);
uint32_t* sq_tail_ptr = (uint32_t*)(ring_ptr + SQ_TAIL_OFFSET);
uint32_t sq_tail = *sq_tail_ptr & sq_ring_mask;
uint32_t sq_tail_next = *sq_tail_ptr + 1;
uint32_t* sq_array = (uint32_t*)(ring_ptr + sq_array_off);
*(sq_array + sq_tail) = sqes_index;
__atomic_store_n(sq_tail_ptr, sq_tail_next, __ATOMIC_RELEASE);
return 0;
}
static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void execute_one(void)
{
int i, call, thread;
for (call = 0; call < 7; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}
static void execute_one(void);
#define WAIT_FLAGS __WALL
static void loop(void)
{
int iter = 0;
for (;; iter++) {
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
}
}
uint64_t r[5] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
NONFAILING(*(uint32_t*)0x200001c4 = 0);
NONFAILING(*(uint32_t*)0x200001c8 = 0);
NONFAILING(*(uint32_t*)0x200001cc = 0);
NONFAILING(*(uint32_t*)0x200001d0 = 0);
NONFAILING(*(uint32_t*)0x200001d8 = -1);
NONFAILING(memset((void*)0x200001dc, 0, 12));
res = -1;
NONFAILING(res = syz_io_uring_setup(0x1b30, 0x200001c0, 0x20ffa000, 0x20ffb000, 0x200002c0, \
0x20000140)); if (res != -1) {
r[0] = res;
NONFAILING(r[1] = *(uint64_t*)0x200002c0);
NONFAILING(r[2] = *(uint64_t*)0x20000140);
}
break;
case 1:
NONFAILING(*(uint32_t*)0x20000084 = 0);
NONFAILING(*(uint32_t*)0x20000088 = 0);
NONFAILING(*(uint32_t*)0x2000008c = 0);
NONFAILING(*(uint32_t*)0x20000090 = 0);
NONFAILING(*(uint32_t*)0x20000098 = 0);
NONFAILING(memset((void*)0x2000009c, 0, 12));
res = -1;
NONFAILING(res = syz_io_uring_setup(1, 0x20000080, 0x200a0000, 0x200b0000, 0x20000100, \
0x20000140)); if (res != -1) {
r[3] = res;
NONFAILING(r[4] = *(uint64_t*)0x20000100);
}
break;
case 2:
NONFAILING(*(uint8_t*)0x20000000 = 6);
NONFAILING(*(uint8_t*)0x20000001 = 0);
NONFAILING(*(uint16_t*)0x20000002 = 0);
NONFAILING(*(uint32_t*)0x20000004 = r[3]);
NONFAILING(*(uint64_t*)0x20000008 = 0);
NONFAILING(*(uint64_t*)0x20000010 = 0);
NONFAILING(*(uint32_t*)0x20000018 = 0);
NONFAILING(*(uint16_t*)0x2000001c = 0);
NONFAILING(*(uint16_t*)0x2000001e = 0);
NONFAILING(*(uint64_t*)0x20000020 = 0);
NONFAILING(*(uint16_t*)0x20000028 = 0);
NONFAILING(*(uint16_t*)0x2000002a = 0);
NONFAILING(memset((void*)0x2000002c, 0, 20));
NONFAILING(syz_io_uring_submit(r[4], r[2], 0x20000000, 0));
break;
case 3:
syscall(__NR_mremap, 0x20ffc000ul, 0x4000ul, 0x1000ul, 3ul, 0x20ffb000ul);
break;
case 4:
NONFAILING(*(uint8_t*)0x20000180 = 0xb);
NONFAILING(*(uint8_t*)0x20000181 = 0);
NONFAILING(*(uint16_t*)0x20000182 = 0);
NONFAILING(*(uint32_t*)0x20000184 = 0);
NONFAILING(*(uint64_t*)0x20000188 = 0);
NONFAILING(*(uint64_t*)0x20000190 = 0);
NONFAILING(*(uint32_t*)0x20000198 = 1);
NONFAILING(*(uint32_t*)0x2000019c = 0);
NONFAILING(*(uint64_t*)0x200001a0 = 0);
NONFAILING(*(uint16_t*)0x200001a8 = 0);
NONFAILING(*(uint16_t*)0x200001aa = 0);
NONFAILING(memset((void*)0x200001ac, 0, 20));
NONFAILING(syz_io_uring_submit(r[1], r[2], 0x20000180, 0));
break;
case 5:
syscall(__NR_io_uring_enter, r[0], 0x2dfa, 0, 0ul, 0ul, 0ul);
break;
case 6:
syscall(__NR_io_uring_enter, r[3], 0x7fe7, 0, 0ul, 0ul, 0ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
install_segv_handler();
loop();
return 0;
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic