[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&#39;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>  &lt;TASK&gt;<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>  &lt;/TASK&gt;<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>&gt;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 &lt;<a \
href="mailto:sundaywind2004@gmail.com" \
target="_blank">sundaywind2004@gmail.com</a>&gt;<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