Hello,

While fuzzing the amdgpu driver on Linux 6.19.10 with a hardware-free
device-model approach on syzkaller, I found a slab-use-after-free (read) 
in the DRM buddy allocator. The faulting object is a drm_buddy_block from 
the drm_buddy_block slab cache (80-byte region).

The bug is reached through DRM_IOCTL_MODE_CREATE_DUMB on amdgpu, but the root
cause is in the generic DRM buddy allocator (drivers/gpu/drm/drm_buddy.c), not
in amdgpu itself.

Root cause analysis:

During a single drm_buddy_alloc_blocks() request, a block B is allocated and
then trimmed via drm_buddy_block_trim(), which marks B free, detaches its
parent, and calls __alloc_range() over B's subtree. __alloc_range() repeatedly
splits blocks (split_block) and pushes the left/right children onto its DFS
list. When a deeper split_block() fails, control reaches the err_undo path
(drm_buddy.c:885), which calls __drm_buddy_free() on a still-free block. The
merge loop in __drm_buddy_free() (drm_buddy.c:209-213) frees the current block
and its buddy via drm_block_free() and climbs upward, re-inserting the merged
block into the free tree.

The problem is that a stale reference to one of the just-freed child blocks
survives in the allocator's traversal/bookkeeping. When the outer allocation
loop then allocates again, it revisits that already-freed block and calls
mark_allocated() -> rbtree_remove() -> rb_erase(&block->rb, root)
(drm_buddy.c:112), reading from the freed rb-node. This is the reported UAF.

Relevant call stacks from the KASAN report:

Use (read), drm_buddy_alloc_blocks -> mark_allocated -> rbtree_remove
(drm_buddy.c:112) -> rb_erase.
Freed, drm_buddy_alloc_blocks -> drm_buddy_block_trim -> __alloc_range
(drm_buddy.c:885) -> __drm_buddy_free -> drm_block_free.
Allocated, drm_buddy_alloc_blocks -> split_block -> drm_block_alloc.
The free task and the use task are the same, so the entire free-then-use cycle
happens within one drm_buddy_alloc_blocks() invocation.

I also found a closely related slab-use-after-free (write) in __drm_buddy_free()
via the amdgpu_vram_mgr free path, which appears to share the same underlying
allocator rollback defect. I am reporting it separately.

The crash report attached below:

==================================================================
BUG: KASAN: slab-use-after-free in __rb_change_child 
include/linux/rbtree_augmented.h:199 [inline]
BUG: KASAN: slab-use-after-free in __rb_erase_augmented 
include/linux/rbtree_augmented.h:242 [inline]
BUG: KASAN: slab-use-after-free in rb_erase+0x135/0xe20 lib/rbtree.c:443
Read of size 8 at addr ffff888107266ea8 by task syz.0.131/1294

CPU: 0 UID: 0 PID: 1294 Comm: syz.0.131 Not tainted 6.19.10 #3 
PREEMPT(voluntary) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Arch Linux 1.17.0-2-2 
04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0xa2/0xd0 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0xbc/0x260 mm/kasan/report.c:482
 kasan_report+0x117/0x150 mm/kasan/report.c:595
 __rb_change_child include/linux/rbtree_augmented.h:199 [inline]
 __rb_erase_augmented include/linux/rbtree_augmented.h:242 [inline]
 rb_erase+0x135/0xe20 lib/rbtree.c:443
 rbtree_remove drivers/gpu/drm/drm_buddy.c:112 [inline]
 mark_allocated drivers/gpu/drm/drm_buddy.c:132 [inline]
 drm_buddy_alloc_blocks+0x642/0xce0 drivers/gpu/drm/drm_buddy.c:1210
 amdgpu_vram_mgr_new+0x72c/0x10e0 
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:539
 ttm_resource_alloc+0x13b/0x230 drivers/gpu/drm/ttm/ttm_resource.c:392
 ttm_bo_alloc_resource+0x2c7/0x8c0 drivers/gpu/drm/ttm/ttm_bo.c:742
 ttm_bo_validate+0x1e8/0x530 drivers/gpu/drm/ttm/ttm_bo.c:858
 ttm_bo_init_reserved+0x32e/0x480 drivers/gpu/drm/ttm/ttm_bo.c:972
 amdgpu_bo_create+0x6a2/0xe00 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:703
 amdgpu_bo_create_user+0x87/0x100 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:768
 amdgpu_gem_object_create drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:188 [inline]
 amdgpu_mode_dumb_create+0x250/0x400 
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:1259
 drm_mode_create_dumb drivers/gpu/drm/drm_dumb_buffers.c:227 [inline]
 drm_mode_create_dumb_ioctl+0x211/0x2a0 drivers/gpu/drm/drm_dumb_buffers.c:236
 drm_ioctl_kernel+0x23f/0x300 drivers/gpu/drm/drm_ioctl.c:804
 drm_ioctl+0x644/0xac0 drivers/gpu/drm/drm_ioctl.c:901
 amdgpu_drm_ioctl+0xb0/0x120 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c:2996
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd8/0x360 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f38d47a9c6d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 
89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 
c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f38d2ddeff8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f38d49d5fa0 RCX: 00007f38d47a9c6d
RDX: 0000200000000040 RSI: 00000000c02064b2 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f38d49d5fac
R13: 0000000000000000 R14: 00007f38d2ddfce4 R15: 00007ffd443c5027
 </TASK>

Allocated by task 1292:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 unpoison_slab_object mm/kasan/common.c:340 [inline]
 __kasan_slab_alloc+0x4b/0x60 mm/kasan/common.c:366
 kasan_slab_alloc include/linux/kasan.h:253 [inline]
 slab_post_alloc_hook mm/slub.c:5045 [inline]
 slab_alloc_node mm/slub.c:5355 [inline]
 kmem_cache_alloc_noprof+0x1f3/0x670 mm/slub.c:5362
 drm_block_alloc drivers/gpu/drm/drm_buddy.c:36 [inline]
 split_block+0xa6/0x7f0 drivers/gpu/drm/drm_buddy.c:437
 __alloc_range+0x4c8/0xa30 drivers/gpu/drm/drm_buddy.c:857
 drm_buddy_block_trim+0x721/0x8e0 drivers/gpu/drm/drm_buddy.c:1055
 drm_buddy_alloc_blocks+0xadb/0xce0 drivers/gpu/drm/drm_buddy.c:1241
 amdgpu_vram_mgr_new+0x72c/0x10e0 
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:539
 ttm_resource_alloc+0x13b/0x230 drivers/gpu/drm/ttm/ttm_resource.c:392
 ttm_bo_alloc_resource+0x2c7/0x8c0 drivers/gpu/drm/ttm/ttm_bo.c:742
 ttm_bo_validate+0x1e8/0x530 drivers/gpu/drm/ttm/ttm_bo.c:858
 ttm_bo_init_reserved+0x32e/0x480 drivers/gpu/drm/ttm/ttm_bo.c:972
 amdgpu_bo_create+0x6a2/0xe00 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:703
 amdgpu_bo_create_user+0x87/0x100 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:768
 amdgpu_gem_object_create drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:188 [inline]
 amdgpu_mode_dumb_create+0x250/0x400 
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:1259
 drm_mode_create_dumb drivers/gpu/drm/drm_dumb_buffers.c:227 [inline]
 drm_mode_create_dumb_ioctl+0x211/0x2a0 drivers/gpu/drm/drm_dumb_buffers.c:236
 drm_ioctl_kernel+0x23f/0x300 drivers/gpu/drm/drm_ioctl.c:804
 drm_ioctl+0x644/0xac0 drivers/gpu/drm/drm_ioctl.c:901
 amdgpu_drm_ioctl+0xb0/0x120 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c:2996
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd8/0x360 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Freed by task 1292:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x3a/0x60 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2580 [inline]
 slab_free mm/slub.c:6791 [inline]
 kmem_cache_free+0x180/0x560 mm/slub.c:6906
 drm_block_free drivers/gpu/drm/drm_buddy.c:53 [inline]
 __drm_buddy_free+0x357/0x5a0 drivers/gpu/drm/drm_buddy.c:213
 __alloc_range+0x9ff/0xa30 drivers/gpu/drm/drm_buddy.c:885
 drm_buddy_block_trim+0x721/0x8e0 drivers/gpu/drm/drm_buddy.c:1055
 drm_buddy_alloc_blocks+0xadb/0xce0 drivers/gpu/drm/drm_buddy.c:1241
 amdgpu_vram_mgr_new+0x72c/0x10e0 
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:539
 ttm_resource_alloc+0x13b/0x230 drivers/gpu/drm/ttm/ttm_resource.c:392
 ttm_bo_alloc_resource+0x2c7/0x8c0 drivers/gpu/drm/ttm/ttm_bo.c:742
 ttm_bo_validate+0x1e8/0x530 drivers/gpu/drm/ttm/ttm_bo.c:858
 ttm_bo_init_reserved+0x32e/0x480 drivers/gpu/drm/ttm/ttm_bo.c:972
 amdgpu_bo_create+0x6a2/0xe00 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:703
 amdgpu_bo_create_user+0x87/0x100 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c:768
 amdgpu_gem_object_create drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:188 [inline]
 amdgpu_mode_dumb_create+0x250/0x400 
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:1259
 drm_mode_create_dumb drivers/gpu/drm/drm_dumb_buffers.c:227 [inline]
 drm_mode_create_dumb_ioctl+0x211/0x2a0 drivers/gpu/drm/drm_dumb_buffers.c:236
 drm_ioctl_kernel+0x23f/0x300 drivers/gpu/drm/drm_ioctl.c:804
 drm_ioctl+0x644/0xac0 drivers/gpu/drm/drm_ioctl.c:901
 amdgpu_drm_ioctl+0xb0/0x120 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c:2996
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd8/0x360 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff888107266e70
 which belongs to the cache drm_buddy_block of size 80
The buggy address is located 56 bytes inside of
 freed 80-byte region [ffff888107266e70, ffff888107266ec0)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x107266
anon flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff88810497a780 ffffea0004257d00 dead000000000003
raw: 0000000000000000 0000000000240024 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888107266d80: fc fc fa fb fb fb fb fb fb fb fb fb fc fc fc fc
 ffff888107266e00: fa fb fb fb fb fb fb fb fb fb fc fc fc fc fa fb
>ffff888107266e80: fb fb fb fb fb fb fb fb fc fc fc fc fa fb fb fb
                                  ^
 ffff888107266f00: fb fb fb fb fb fb fc fc fc fc 00 00 00 00 00 00
 ffff888107266f80: 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================

Regards,
Yang Zi

Reply via email to