Issue 2373: Arm Mali CSF: kbase_kcpu_command_queue UAF in kbase_csf_kcpu_queue_enqueue()

浏览器安全 1年前 (2023) admin
304 0 0

Tested version VX504X08X-SW-99002-r40p0-01eac0.
Tested using CONFIG_MALI_NO_MALI on X86-64.

kbase_csf_kcpu_queue_enqueue() locks the kctx->csf.kcpu_queues, looks up a pointer from inside that structure, then drops the lock before continuing to use the kbase_kcpu_command_queue that was looked up.
This is a classic use-after-free pattern, where the lookup of a pointer is protected but the protective lock is then released without first acquiring any other lock or reference to keep the referenced object alive.

When kbase_csf_kcpu_queue_enqueue() races with kbase_csf_kcpu_queue_delete(), this can lead to use-after-free of the queue object:

A: kbase_csf_kcpu_queue_enqueue() begins
A: takes kctx->csf.kcpu_queues.lock
A: looks up queue from kctx->csf.kcpu_queues.array[enq->id]
A: drops kctx->csf.kcpu_queues.lock
B: kbase_csf_kcpu_queue_delete() runs (looks up queue, unlinks it from the array, frees it)
A: calls mutex_lock(&queue->lock), triggering UAF

To be able to reproduce this reliably without having to hit the race window, I patched Mali like this:

diff -r -U5 software/arm/VX504X08X-SW-99002-r40p0-01eac0/driver/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c ./drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c
— software/arm/VX504X08X-SW-99002-r40p0-01eac0/driver/product/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c 2022-10-06 13:51:16.000000000 +0200
+++ ./drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c 2022-10-19 20:22:01.103762465 +0200
@@ -23,10 +23,11 @@
#include <tl/mali_kbase_tracepoints.h>
#include <mali_kbase_ctx_sched.h>
#include “device/mali_kbase_device.h”
#include “mali_kbase_csf.h”
#include <linux/export.h>
+#include <linux/delay.h>

#if IS_ENABLED(CONFIG_SYNC_FILE)
#include “mali_kbase_fence.h”
#include “mali_kbase_sync.h”

@@ -2108,10 +2109,14 @@
mutex_unlock(&kctx->csf.kcpu_queues.lock);

if (queue == NULL)
return -EINVAL;

+ pr_warn(“%s: BEGIN mdelay\n”, __func__);
+ mdelay(5000);
+ pr_warn(“%s: END mdelay\n”, __func__);
+
mutex_lock(&queue->lock);

if (kcpu_queue_get_space(queue) < enq->nr_commands) {
ret = -EBUSY;
queue->enqueue_failed = true;

With that kernel patch applied, the attached reproducer will cause a KASAN splat.

This bug is subject to a 90-day disclosure deadline. If a fix for this
issue is made available to users before the end of the 90-day deadline,
this bug report will become public 30 days after the fix was made
available. Otherwise, this bug report will become public at the deadline.
The scheduled deadline is 2023-01-17.

ASAN splat:

mali mali.0: created base context
mali mali.0: Return 0 from ioctl kbase_api_set_flags
mali mali.0: kbase_mmap
mali mali.0: Enter ioctl kbasep_kcpu_queue_new
mali mali.0: Return 0 from ioctl kbasep_kcpu_queue_new
mali mali.0: Enter ioctl kbasep_kcpu_queue_enqueue
kbase_csf_kcpu_queue_enqueue: BEGIN mdelay
mali mali.0: Enter ioctl kbasep_kcpu_queue_delete
mali mali.0: Return 0 from ioctl kbasep_kcpu_queue_delete
kbase_csf_kcpu_queue_enqueue: END mdelay
==================================================================
BUG: KASAN: use-after-free in mutex_lock (./include/linux/instrumented.h:101 ./include/linux/atomic/atomic-instrumented.h:1668 kernel/locking/mutex.c:165 kernel/locking/mutex.c:279)
Write of size 8 at addr ffff888027a4c000 by task mali_csf_kcpu_e/825

CPU: 13 PID: 825 Comm: mali_csf_kcpu_e Not tainted 5.15.74-dirty #200
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1))
print_address_description.constprop.0 (mm/kasan/report.c:257)
[…]
kasan_report.cold (mm/kasan/report.c:443 mm/kasan/report.c:459)
[…]
kasan_check_range (mm/kasan/generic.c:190)
mutex_lock (./include/linux/instrumented.h:101 ./include/linux/atomic/atomic-instrumented.h:1668 kernel/locking/mutex.c:165 kernel/locking/mutex.c:279)
[…]
kbase_csf_kcpu_queue_enqueue.cold (drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c:1970 drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c:2120)
[…]
kbase_ioctl (drivers/gpu/arm/midgard/mali_kbase_core_linux.c:1456 drivers/gpu/arm/midgard/mali_kbase_core_linux.c:2014)
[…]
__x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:874 fs/ioctl.c:860 fs/ioctl.c:860)
do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:118)
[…]
</TASK>

The buggy address belongs to the page:
page:00000000fc3d7380 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x27a4c
flags: 0x100000000000000(node=0|zone=1)
raw: 0100000000000000 ffffea000040f408 ffff88806ccb9b70 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as freed
page last allocated via order 2, migratetype Unmovable, gfp_mask 0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), pid 825, ts 2443497615569, free_ts 2444503328638
get_page_from_freelist (mm/page_alloc.c:4130)
__alloc_pages (mm/page_alloc.c:5421)
kmalloc_order (mm/slab_common.c:966)
kmalloc_order_trace (mm/slab_common.c:983)
kbase_csf_kcpu_queue_new (./include/linux/slab.h:520 ./include/linux/slab.h:584 ./include/linux/slab.h:721 drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c:2317)
kbase_ioctl (./include/linux/uaccess.h:200 (discriminator 10) drivers/gpu/arm/midgard/mali_kbase_core_linux.c:2002 (discriminator 10))
__x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:874 fs/ioctl.c:860 fs/ioctl.c:860)
do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:118)
page last free stack trace:
free_pcp_prepare (./include/linux/page_owner.h:24 mm/page_alloc.c:1340 mm/page_alloc.c:1391)
free_unref_page (mm/page_alloc.c:3317 mm/page_alloc.c:3396)
delete_queue (drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c:1577 (discriminator 3))
kbase_ioctl (drivers/gpu/arm/midgard/mali_kbase_core_linux.c:1450 drivers/gpu/arm/midgard/mali_kbase_core_linux.c:2008)
__x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:874 fs/ioctl.c:860 fs/ioctl.c:860)
do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:118)

 

版权声明:admin 发表于 2023年3月1日 上午10:40。
转载请注明:Issue 2373: Arm Mali CSF: kbase_kcpu_command_queue UAF in kbase_csf_kcpu_queue_enqueue() | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...