From: Pavel Begunkov <[email protected]>
To: yangerkun <[email protected]>, [email protected]
Cc: [email protected], [email protected],
Matthew Wilcox <[email protected]>
Subject: Re: [PATCH 1/2] io_uring: fix UAF for personality_idr
Date: Mon, 8 Mar 2021 10:46:37 +0000 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
On 08/03/2021 06:59, yangerkun wrote:
> Loop with follow can trigger a UAF:
>
> void main()
> {
> int ret;
> struct io_uring ring;
> struct io_uring_params p;
> int i;
>
> ret = io_uring_queue_init(1, &ring, 0);
> assert(ret == 0);
>
> for (i = 0; i < 10000; i++) {
> ret = io_uring_register_personality(&ring);
> if (ret < 0)
> break;
> }
>
> ret = io_uring_unregister_personality(&ring, 1024);
> assert(ret == 0);
> }
Matthew, any chance you remember whether idr_for_each tolerates
idr_remove() from within the callback? Nothing else is happening in
parallel.
> ==================================================================
> BUG: KASAN: use-after-free in radix_tree_next_slot
> include/linux/radix-tree.h:422 [inline]
> BUG: KASAN: use-after-free in idr_for_each+0x88/0x18c lib/idr.c:202
> Read of size 8 at addr ffff0001096539f8 by task syz-executor.2/3166
>
> CPU: 0 PID: 3166 Comm: syz-executor.2 Not tainted
> 5.10.0-00843-g352c8610ccd2 #2
> Hardware name: linux,dummy-virt (DT)
> Call trace:
> dump_backtrace+0x0/0x1d8 arch/arm64/kernel/stacktrace.c:132
> show_stack+0x28/0x34 arch/arm64/kernel/stacktrace.c:196
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0x110/0x164 lib/dump_stack.c:118
> print_address_description+0x78/0x5c8 mm/kasan/report.c:385
> __kasan_report mm/kasan/report.c:545 [inline]
> kasan_report+0x148/0x1e4 mm/kasan/report.c:562
> check_memory_region_inline mm/kasan/generic.c:183 [inline]
> __asan_load8+0xb4/0xbc mm/kasan/generic.c:252
> radix_tree_next_slot include/linux/radix-tree.h:422 [inline]
> idr_for_each+0x88/0x18c lib/idr.c:202
> io_ring_ctx_wait_and_kill+0xf0/0x210 fs/io_uring.c:8429
> io_uring_release+0x3c/0x50 fs/io_uring.c:8454
> __fput+0x1b8/0x3a8 fs/file_table.c:281
> ____fput+0x1c/0x28 fs/file_table.c:314
> task_work_run+0xec/0x13c kernel/task_work.c:151
> exit_task_work include/linux/task_work.h:30 [inline]
> do_exit+0x384/0xd68 kernel/exit.c:809
> do_group_exit+0xb8/0x13c kernel/exit.c:906
> get_signal+0x794/0xb04 kernel/signal.c:2758
> do_signal arch/arm64/kernel/signal.c:658 [inline]
> do_notify_resume+0x1dc/0x8a8 arch/arm64/kernel/signal.c:722
> work_pending+0xc/0x180
>
> Allocated by task 3149:
> stack_trace_save+0x80/0xb8 kernel/stacktrace.c:121
> kasan_save_stack mm/kasan/common.c:48 [inline]
> kasan_set_track mm/kasan/common.c:56 [inline]
> __kasan_kmalloc+0xdc/0x120 mm/kasan/common.c:461
> kasan_slab_alloc+0x14/0x1c mm/kasan/common.c:469
> slab_post_alloc_hook+0x50/0x8c mm/slab.h:535
> slab_alloc_node mm/slub.c:2891 [inline]
> slab_alloc mm/slub.c:2899 [inline]
> kmem_cache_alloc+0x1f4/0x2fc mm/slub.c:2904
> radix_tree_node_alloc+0x70/0x19c lib/radix-tree.c:274
> idr_get_free+0x180/0x528 lib/radix-tree.c:1504
> idr_alloc_u32+0xa8/0x164 lib/idr.c:46
> idr_alloc_cyclic+0x8c/0x150 lib/idr.c:125
> io_register_personality fs/io_uring.c:9512 [inline]
> __io_uring_register+0xed8/0x1d9c fs/io_uring.c:9741
> __do_sys_io_uring_register fs/io_uring.c:9791 [inline]
> __se_sys_io_uring_register fs/io_uring.c:9773 [inline]
> __arm64_sys_io_uring_register+0xd0/0x108 fs/io_uring.c:9773
> __invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
> invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
> el0_svc_common arch/arm64/kernel/syscall.c:158 [inline]
> do_el0_svc+0x120/0x260 arch/arm64/kernel/syscall.c:227
> el0_svc+0x20/0x2c arch/arm64/kernel/entry-common.c:367
> el0_sync_handler+0x98/0x170 arch/arm64/kernel/entry-common.c:383
> el0_sync+0x140/0x180 arch/arm64/kernel/entry.S:670
>
> Freed by task 4399:
> stack_trace_save+0x80/0xb8 kernel/stacktrace.c:121
> kasan_save_stack mm/kasan/common.c:48 [inline]
> kasan_set_track+0x38/0x6c mm/kasan/common.c:56
> kasan_set_free_info+0x20/0x40 mm/kasan/generic.c:355
> __kasan_slab_free+0x124/0x150 mm/kasan/common.c:422
> kasan_slab_free+0x10/0x1c mm/kasan/common.c:431
> slab_free_hook mm/slub.c:1544 [inline]
> slab_free_freelist_hook+0xb0/0x1ac mm/slub.c:1577
> slab_free mm/slub.c:3142 [inline]
> kmem_cache_free+0xc4/0x268 mm/slub.c:3158
> radix_tree_node_rcu_free+0x60/0x6c lib/radix-tree.c:302
> rcu_do_batch+0x180/0x404 kernel/rcu/tree.c:2479
> rcu_core+0x3e0/0x410 kernel/rcu/tree.c:2714
> rcu_core_si+0xc/0x14 kernel/rcu/tree.c:2727
> __do_softirq+0x180/0x3e0 kernel/softirq.c:298
>
> radix_tree_next_slot called by idr_for_each will traverse all slot
> regardless of whether the slot is valid. And once the last valid slot
> has been remove, we will try to free the node, and lead to a UAF.
>
> idr_destroy will do what we want. So, just stop call idr_remove in
> io_unregister_personality to fix the problem.
>
> Reported-by: Hulk Robot <[email protected]>
> Signed-off-by: yangerkun <[email protected]>
> ---
> fs/io_uring.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/io_uring.c b/fs/io_uring.c
> index 92c25b5f1349..b462c2bf0f2c 100644
> --- a/fs/io_uring.c
> +++ b/fs/io_uring.c
> @@ -8494,9 +8494,9 @@ static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id)
>
> static int io_remove_personalities(int id, void *p, void *data)
> {
> - struct io_ring_ctx *ctx = data;
> + const struct cred *creds = p;
>
> - io_unregister_personality(ctx, id);
> + put_cred(creds);
> return 0;
> }
>
>
--
Pavel Begunkov
next prev parent reply other threads:[~2021-03-08 10:51 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-08 6:59 [PATCH 1/2] io_uring: fix UAF for personality_idr yangerkun
2021-03-08 6:59 ` [PATCH 2/2] io_uring: fix UAF for io_buffer_idr yangerkun
2021-03-08 7:04 ` [PATCH 1/2] io_uring: fix UAF for personality_idr yangerkun
2021-03-08 10:46 ` Pavel Begunkov [this message]
2021-03-08 13:20 ` Matthew Wilcox
2021-03-08 13:54 ` Pavel Begunkov
2021-03-08 14:12 ` Matthew Wilcox
2021-03-08 13:57 ` Stefan Metzmacher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox