Skip to content
cvekernelf2fsout-of-bounds

Linux kernel ttm slab out-of-bounds read

7 min read

Overview

Some operation(with crafted f2fs filesystem image) can cause out of bounds read in ttm_put_pages

It may needs reboot(after run poc binary, not umount), or more tries to reproduce this vulnerability.

Same image and binary in CVE-2018-14616, but that was Null-Deref vulnerability and patched. This is Revoked vulnerability or other related slab-out-of-bounds read vulnerability in linux kernel vmwgfx or ttm module.

Target

Linux kernel f2fs FileSystem (Tested on 11/13/2019, used source with git clone git://kernel.ubuntu.com/ubuntu/linux.git, emulated on VMWare 15 WorkStation with VMWare tools)

Linux Version Availablity
5.0.0-rc7 True

Reproduce

gcc -o poc poc_2019_19927.c
mkdir mnt
mount poc_2019_19927.img ./mnt
cp poc ./mnt
cd mnt
./poc
cd ..
sync
umount mnt

Root cause

/* Put all pages in pages list to correct pool to wait for reuse */
static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
			  enum ttm_caching_state cstate)
{
	struct ttm_page_pool *pool = ttm_get_pool(flags, false, cstate);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
	struct ttm_page_pool *huge = ttm_get_pool(flags, true, cstate);
#endif
	unsigned long irq_flags;
	unsigned i;
 
	if (pool == NULL) {
		/* No pool for this memory type so free the pages */
		i = 0;
		while (i < npages) {
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
			struct page *p = pages[i];
#endif
			unsigned order = 0, j;
 
			if (!pages[i]) {
				++i;
				continue;
			}
 
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
			if (!(flags & TTM_PAGE_FLAG_DMA32)) {
				for (j = 0; j < HPAGE_PMD_NR; ++j)
[1]					if (p++ != pages[i + j]) // CRASH HERE
					    break;
 
				if (j == HPAGE_PMD_NR)
					order = HPAGE_PMD_ORDER;
			}
#endif

In line [1], pages[i+j] occurs out-of-bounds read.

Debugger / KASAN

KASAN log (the trailing repeated f2fs warning traces are truncated):

[   12.920937] ==================================================================
[   12.920954] BUG: KASAN: slab-out-of-bounds in ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.920958] Read of size 8 at addr ffff888032301fa8 by task Xorg/891

[   12.920964] CPU: 2 PID: 891 Comm: Xorg Not tainted 5.0.0-rc7-custom #1
[   12.920966] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   12.920968] Call Trace:
[   12.920974]  dump_stack+0xd6/0x165
[   12.920977]  ? show_regs_print_info+0xb/0xb
[   12.920981]  ? printk+0x9c/0xc3
[   12.920984]  ? kmsg_dump_rewind_nolock+0x64/0x64
[   12.920994]  ? ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.920998]  print_address_description+0x78/0x290
[   12.921007]  ? ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.921016]  ? ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.921019]  kasan_report+0x149/0x18c
[   12.921028]  ? ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.921032]  __asan_load8+0x54/0x90
[   12.921041]  ttm_put_pages+0x8bf/0x9c0 [ttm]
[   12.921051]  ? ttm_pool_shrink_scan+0x170/0x170 [ttm]
[   12.921055]  ? kasan_check_write+0x14/0x20
[   12.921059]  ? iomem_map_sanity_check+0xd0/0x120
[   12.921062]  ? kasan_check_read+0x11/0x20
[   12.921064]  ? _raw_spin_lock+0x90/0xe0
[   12.921067]  ? _raw_write_lock_irq+0xf0/0xf0
[   12.921076]  ? ttm_mem_reg_ioremap+0x147/0x1c0 [ttm]
[   12.921085]  ? ttm_mem_global_free_zone+0x77/0xb0 [ttm]
[   12.921096]  ttm_pool_unpopulate_helper+0xd9/0x100 [ttm]
[   12.921105]  ttm_pool_unpopulate+0x21/0x30 [ttm]
[   12.921123]  vmw_ttm_unpopulate+0x70/0xe0 [vmwgfx]
[   12.921132]  ttm_tt_unpopulate.part.10+0xbc/0xd0 [ttm]
[   12.921142]  ttm_tt_destroy.part.11+0x8d/0x90 [ttm]
[   12.921151]  ttm_tt_destroy+0x13/0x20 [ttm]
[   12.921160]  ttm_bo_move_memcpy+0x90e/0x960 [ttm]
[   12.921170]  ? ttm_bo_kunmap+0x150/0x150 [ttm]
[   12.921174]  ? __mutex_lock_slowpath+0x20/0x20
[   12.921184]  ? ttm_mem_io_free_vm+0x196/0x1e0 [ttm]
[   12.921187]  ? kasan_check_write+0x14/0x20
[   12.921190]  ? mutex_unlock+0x22/0x40
[   12.921202]  ttm_bo_handle_move_mem+0xc90/0xcb0 [ttm]
[   12.921204]  ? _raw_write_lock_irq+0xf0/0xf0
[   12.921214]  ? ttm_bo_man_get_node+0xef/0x160 [ttm]
[   12.921224]  ? ttm_bo_add_move_fence.isra.18+0x31/0xc0 [ttm]
[   12.921254]  ? ttm_bo_mem_space+0x2a7/0x670 [ttm]
[   12.921273]  ttm_bo_validate+0x2a7/0x2e0 [ttm]
[   12.921285]  ? ttm_bo_evict_mm+0x70/0x70 [ttm]
[   12.921288]  ? _raw_write_lock_irq+0xf0/0xf0
[   12.921299]  ? ttm_eu_fence_buffer_objects+0x1c0/0x1c0 [ttm]
[   12.921318]  vmw_validation_bo_validate_single+0x116/0x160 [vmwgfx]
[   12.921335]  ? vmw_validation_res_reserve+0x2c0/0x2c0 [vmwgfx]
[   12.921353]  ? vmw_validation_res_reserve+0x210/0x2c0 [vmwgfx]
[   12.921370]  vmw_validation_bo_validate+0x178/0x1d0 [vmwgfx]
[   12.921387]  ? vmw_validation_bo_validate_single+0x160/0x160 [vmwgfx]
[   12.921402]  ? vmw_cmd_wait_query+0x220/0x220 [vmwgfx]
[   12.921406]  ? vzalloc+0x75/0x80
[   12.921439]  ? drm_ht_create+0x76/0xa0 [drm]
[   12.921455]  vmw_execbuf_process+0xf8a/0x1ec0 [vmwgfx]
[   12.921490]  ? vmw_cmd_wait_query+0x220/0x220 [vmwgfx]
[   12.921511]  ? __vmw_execbuf_release_pinned_bo+0x560/0x560 [vmwgfx]
[   12.921516]  ? unlock_page+0x86/0xf0
[   12.921518]  ? wake_up_page_bit+0x330/0x330
[   12.921522]  ? kasan_check_write+0x14/0x20
[   12.921525]  ? do_wp_page+0x51e/0x10a0
[   12.921529]  ? finish_mkwrite_fault+0x280/0x280
[   12.921532]  ? switch_mm_irqs_off+0x494/0xa80
[   12.921538]  ? __switch_to_asm+0x34/0x70
[   12.921540]  ? __switch_to_asm+0x34/0x70
[   12.921543]  ? __switch_to_asm+0x34/0x70
[   12.921545]  ? __switch_to_asm+0x34/0x70
[   12.921548]  ? __switch_to_asm+0x40/0x70
[   12.921550]  ? __switch_to_asm+0x34/0x70
[   12.921552]  ? __switch_to_asm+0x40/0x70
[   12.921554]  ? __switch_to_asm+0x34/0x70
[   12.921556]  ? __switch_to_asm+0x34/0x70
[   12.921558]  ? __switch_to_asm+0x40/0x70
[   12.921561]  ? __switch_to_asm+0x34/0x70
[   12.921563]  ? __switch_to_asm+0x40/0x70
[   12.921566]  ? _raw_spin_lock+0x90/0xe0
[   12.921584]  ? _raw_write_lock_irq+0xf0/0xf0
[   12.921587]  ? __schedule+0x529/0xe90
[   12.921589]  ? __account_cfs_rq_runtime+0x2f0/0x2f0
[   12.921604]  ? __ttm_read_lock+0x47/0x90 [vmwgfx]
[   12.921651]  ? ttm_read_lock+0x91/0x1a0 [vmwgfx]
[   12.921668]  ? ttm_read_unlock+0x50/0x50 [vmwgfx]
[   12.921672]  ? avc_has_extended_perms+0x4b6/0xa40
[   12.921676]  ? trace_event_raw_event_sched_process_exec+0x270/0x270
[   12.921693]  vmw_execbuf_ioctl+0x241/0x350 [vmwgfx]
[   12.921710]  ? vmw_execbuf_release_pinned_bo+0x50/0x50 [vmwgfx]
[   12.921713]  ? __rwsem_mark_wake+0x50c/0x5e0
[   12.921717]  ? kasan_check_read+0x11/0x20
[   12.921720]  ? __fget+0x2b1/0x350
[   12.921737]  vmw_generic_ioctl+0x3c2/0x440 [vmwgfx]
[   12.921781]  ? drm_ioctl_kernel+0x1d0/0x1d0 [drm]
[   12.921795]  ? vmw_probe+0x20/0x20 [vmwgfx]
[   12.921798]  ? rcu_cleanup_dead_rnp+0xa0/0xa0
[   12.921801]  ? kasan_check_read+0x11/0x20
[   12.921815]  vmw_unlocked_ioctl+0x15/0x20 [vmwgfx]
[   12.921818]  do_vfs_ioctl+0x150/0xad0
[   12.921821]  ? ioctl_preallocate+0x1b0/0x1b0
[   12.921824]  ? selinux_capable+0x30/0x30
[   12.921827]  ? handle_mm_fault+0x29b/0x4a0
[   12.921831]  ksys_ioctl+0x75/0x80
[   12.921833]  __x64_sys_ioctl+0x43/0x50
[   12.921837]  do_syscall_64+0x133/0x300
[   12.921839]  ? syscall_return_slowpath+0x200/0x200
[   12.921842]  ? do_page_fault+0x9a/0x270
[   12.921844]  ? __do_page_fault+0x600/0x600
[   12.921847]  ? prepare_exit_to_usermode+0xf8/0x170
[   12.921849]  ? perf_trace_sys_enter+0x500/0x500
[   12.921852]  ? calculate_sigpending+0x48/0x70
[   12.921856]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   12.921858] RIP: 0033:0x7fe155b495d7
[   12.921861] Code: b3 66 90 48 8b 05 b1 48 2d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 81 48 2d 00 f7 d8 64 89 01 48
[   12.921863] RSP: 002b:00007ffd864c2a28 EFLAGS: 00003246 ORIG_RAX: 0000000000000010
[   12.921865] RAX: ffffffffffffffda RBX: 00007ffd864c2bb8 RCX: 00007fe155b495d7
[   12.921867] RDX: 00007ffd864c2aa0 RSI: 000000004020644c RDI: 000000000000000f
[   12.921868] RBP: 00007ffd864c2aa0 R08: 0000000000000c80 R09: 0000000000000005
[   12.921870] R10: 0000000000000039 R11: 0000000000003246 R12: 000000004020644c
[   12.921871] R13: 000000000000000f R14: 000000000000004c R15: 0000000000000001

[   12.921877] Allocated by task 891:
[   12.921881]  save_stack+0x43/0xd0
[   12.921883]  __kasan_kmalloc.constprop.8+0xa7/0xd0
[   12.921885]  kasan_kmalloc+0x9/0x10
[   12.921887]  __kmalloc_node+0x121/0x2f0
[   12.921890]  kvmalloc_node+0x31/0x80
[   12.921897]  ttm_tt_init+0xcb/0x130 [ttm]
[   12.921910]  vmw_ttm_tt_create+0xa8/0xe0 [vmwgfx]
[   12.921917]  ttm_tt_create+0xa3/0x110 [ttm]
[   12.921925]  ttm_bo_validate+0x28e/0x2e0 [ttm]
[   12.921932]  ttm_bo_init_reserved+0x8e5/0xa30 [ttm]
[   12.921961]  ttm_bo_init+0x138/0x210 [ttm]
[   12.921978]  vmw_bo_init+0x1b2/0x260 [vmwgfx]
[   12.921995]  vmw_user_bo_alloc+0x112/0x220 [vmwgfx]
[   12.922012]  vmw_bo_alloc_ioctl+0x117/0x280 [vmwgfx]
[   12.922069]  drm_ioctl_kernel+0x176/0x1d0 [drm]
[   12.922119]  drm_ioctl+0x58d/0x680 [drm]
[   12.922135]  vmw_generic_ioctl+0x2ed/0x440 [vmwgfx]
[   12.922150]  vmw_unlocked_ioctl+0x15/0x20 [vmwgfx]
[   12.922153]  do_vfs_ioctl+0x150/0xad0
[   12.922155]  ksys_ioctl+0x75/0x80
[   12.922158]  __x64_sys_ioctl+0x43/0x50
[   12.922160]  do_syscall_64+0x133/0x300
[   12.922163]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

[   12.922166] Freed by task 442:
[   12.922170]  save_stack+0x43/0xd0
[   12.922173]  __kasan_slab_free+0x135/0x190
[   12.922175]  kasan_slab_free+0xe/0x10
[   12.922178]  kfree+0x98/0x1d0
[   12.922180]  kvfree+0x2a/0x40
[   12.922183]  single_release+0x3f/0x60
[   12.922185]  __fput+0x21a/0x510
[   12.922187]  ____fput+0xe/0x10
[   12.922206]  task_work_run+0x14a/0x1a0
[   12.922208]  exit_to_usermode_loop+0x227/0x240
[   12.922210]  do_syscall_64+0x2d8/0x300
[   12.922212]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

[   12.922215] The buggy address belongs to the object at ffff888032301100
                which belongs to the cache kmalloc-4k of size 4096
[   12.922219] The buggy address is located 3752 bytes inside of
                4096-byte region [ffff888032301100, ffff888032302100)
[   12.922220] The buggy address belongs to the page:
[   12.922244] page:ffffea0000c8c000 count:1 mapcount:0 mapping:ffff88805a80e840 index:0x0 compound_mapcount: 0
[   12.922248] flags: 0xfffffc0010200(slab|head)
[   12.922252] raw: 000fffffc0010200 0000000000000000 0000000100000001 ffff88805a80e840
[   12.922255] raw: 0000000000000000 0000000000070007 00000001ffffffff 0000000000000000
[   12.922256] page dumped because: kasan: bad access detected

[   12.922258] Memory state around the buggy address:
[   12.922262]  ffff888032301e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[   12.922265]  ffff888032301f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[   12.922268] >ffff888032301f80: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
[   12.922270]                                   ^
[   12.922273]  ffff888032302000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   12.922276]  ffff888032302080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   12.922277] ==================================================================
[   12.922279] Disabling lock debugging due to kernel taint
...

Details

CVSS 6.0 (CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:H), CWE-125, published 2019-12-31, last modified 2024-11-21.

Attribution

Found as part of the Best of the Best (BoB) 8th bobfuzzer team project — a five-person team that ported the JANUS file-system fuzzer. This is team work, not sole authorship.

References