lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20240929052416.52-1-ebpqwerty472123@gmail.com>
Date: Sun, 29 Sep 2024 13:24:16 +0800
From: Shu Han <ebpqwerty472123@...il.com>
To: eadavis@...com
Cc: linux-kernel@...r.kernel.org,
	syzbot+1cd571a672400ef3a930@...kaller.appspotmail.com,
	syzkaller-bugs@...glegroups.com
Subject: Re: [integrity?] [lsm?] possible deadlock in process_measurement (4)

Hello,

I wanna put some comments for this patch:
1. Once mmap_lock is released, the vma should never be accessed again.
   Otherwise, it may lead to a use-after-free issue.
   So `vma->vm_file` should be replaced by `file` after the first unlock.
   The test is attached at the end of this email.
2. Once the second mmap_write_lock_killable(mm) failed, the ret
   should be set to -EINTR.
3. Unlocking the mm->mmap_lock destroy the atomicity of
   remap_file_pages(), all checks performed during the first lock period
   may not meet in the second period. If some userspace code rely on it,
   it may lead to a TOCTOU issue.

Best regards.

To show how the UAF is triggered, we enlarge the race window by inserting
a usleep_range() after the first mmap_write_unlock(mm)

At the begin of mm/mmap.c, add

#include <linux/delay.h>

and add the usleep_range() in the patch position

	mmap_write_unlock(mm);
+	usleep_range(1000000, 1200000);
 	ret = security_mmap_file(file, prot, flags);

Then, run the following userspace code:

#define _GNU_SOURCE
#include <linux/aio_abi.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <err.h>
#include <sys/personality.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <asm/prctl.h>
#include <sys/prctl.h>
#include <pthread.h>

size_t pagesz;
int mfd;

char *buf;

void *func(void*) {
	// ensure the order
	// call to remap_file_pages()
	// the first lock period in remap_file_pages()
	// ~500ms
	// this munmap
	// ~500ms
	// the second lock period in remap_file_pages()
	usleep(500000);
	munmap(buf, 4 * pagesz);
	return NULL;
}

int main(void) {
	pagesz = sysconf(_SC_PAGE_SIZE);
	mfd = syscall(SYS_memfd_create, "test", 0);
	buf = mmap(NULL, 4 * pagesz, PROT_READ | PROT_WRITE |
		   MAP_FIXED, MAP_SHARED, mfd, 0);
	pthread_t th;
	pthread_create(&th, NULL, func, NULL);
	pthread_detach(th);
	syscall(SYS_remap_file_pages, buf, pagesz, 0, 2, 0);
	return 0;
}

Will trigger the UAF as following KASAN report:

[    4.594781] ==================================================================
[    4.594794] BUG: KASAN: slab-use-after-free in __do_sys_remap_file_pages+0x8fc/0x950
[    4.594838] Read of size 8 at addr ffff888002035240 by task rwx_test/67
[    4.594847] 
[    4.594868] CPU: 1 UID: 0 PID: 67 Comm: rwx_test Not tainted 6.11.0-rc1-00041-g66661576d6d7-dirty #56
[    4.594880] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[    4.594892] Call Trace:
[    4.594899]  <TASK>
[    4.594910]  dump_stack_lvl+0x55/0x70
[    4.594931]  print_report+0xcb/0x5d0
[    4.594944]  ? mtree_load+0x411/0x500
[    4.594953]  ? __do_sys_remap_file_pages+0x8fc/0x950
[    4.594965]  kasan_report+0xaf/0xe0
[    4.594975]  ? __do_sys_remap_file_pages+0x8fc/0x950
[    4.594988]  __do_sys_remap_file_pages+0x8fc/0x950
[    4.595001]  ? __pfx___do_sys_remap_file_pages+0x10/0x10
[    4.595013]  ? __x64_sys_rt_sigprocmask+0x164/0x230
[    4.595024]  ? __pfx___x64_sys_rt_sigprocmask+0x10/0x10
[    4.595034]  ? do_user_addr_fault+0x478/0x930
[    4.595047]  do_syscall_64+0xa6/0x1a0
[    4.595057]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.595072] RIP: 0033:0x44b8ad
[    4.595086] Code: c3 e8 d7 1e 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 8
[    4.595096] RSP: 002b:00007ffc1117b2a8 EFLAGS: 00000246 ORIG_RAX: 00000000000000d8
[    4.595108] RAX: ffffffffffffffda RBX: 00007ffc1117b4b8 RCX: 000000000044b8ad
[    4.595116] RDX: 0000000000000000 RSI: 0000000000001000 RDI: 00007f9149ea7000
[    4.595123] RBP: 00007ffc1117b2c0 R08: 0000000000000000 R09: 00007f9149ea6640
[    4.595130] R10: 0000000000000002 R11: 0000000000000246 R12: 0000000000000001
[    4.595136] R13: 00007ffc1117b4a8 R14: 00000000004dc790 R15: 0000000000000001
[    4.595145]  </TASK>
[    4.595150] 
[    4.595154] Allocated by task 67 on cpu 1 at 3.394365s:
[    4.595163]  kasan_save_stack+0x24/0x50
[    4.595173]  kasan_save_track+0x17/0x60
[    4.595181]  __kasan_slab_alloc+0x59/0x70
[    4.595190]  kmem_cache_alloc_noprof+0xbf/0x240
[    4.595199]  vm_area_alloc+0x1b/0x1c0
[    4.595211]  mmap_region+0x290/0x1fe0
[    4.595221]  do_mmap+0x88a/0xd70
[    4.595231]  vm_mmap_pgoff+0x16c/0x2c0
[    4.595242]  ksys_mmap_pgoff+0x2e7/0x450
[    4.595252]  do_syscall_64+0xa6/0x1a0
[    4.595259]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.595270] 
[    4.595274] Freed by task 0 on cpu 2 at 3.904339s:
[    4.595281]  kasan_save_stack+0x24/0x50
[    4.595289]  kasan_save_track+0x17/0x60
[    4.595301]  kasan_save_free_info+0x3b/0x60
[    4.595313]  __kasan_slab_free+0x10d/0x190
[    4.595321]  kmem_cache_free+0xa1/0x230
[    4.595330]  rcu_core+0x60f/0x1ab0
[    4.595342]  handle_softirqs+0x188/0x570
[    4.595353]  irq_exit_rcu+0x7f/0xb0
[    4.595362]  sysvec_apic_timer_interrupt+0x70/0x80
[    4.595374]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
[    4.595383] 
[    4.595386] Last potentially related work creation:
[    4.595391]  kasan_save_stack+0x24/0x50
[    4.595399]  __kasan_record_aux_stack+0x8e/0xa0
[    4.595410]  __call_rcu_common.constprop.0+0x6a/0xaa0
[    4.595421]  do_vmi_align_munmap.constprop.0+0x8a0/0xe30
[    4.595431]  __vm_munmap+0x11e/0x270
[    4.595441]  __x64_sys_munmap+0x54/0x80
[    4.595450]  do_syscall_64+0xa6/0x1a0
[    4.595458]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.595469] 
[    4.595472] The buggy address belongs to the object at ffff8880020351c0
[    4.595472]  which belongs to the cache vm_area_struct of size 160
[    4.595481] The buggy address is located 128 bytes inside of
[    4.595481]  freed 160-byte region [ffff8880020351c0, ffff888002035260)
[    4.595490] 
[    4.595494] The buggy address belongs to the physical page:
[    4.595500] page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x2035
[    4.595514] flags: 0x100000000000000(node=0|zone=1)
[    4.595527] page_type: 0xfdffffff(slab)
[    4.595538] raw: 0100000000000000 ffff888001196780 dead000000000122 0000000000000000
[    4.595546] raw: 0000000000000000 0000000080120012 00000001fdffffff 0000000000000000
[    4.595551] page dumped because: kasan: bad access detected
[    4.595557] 
[    4.595560] Memory state around the buggy address:
[    4.595566]  ffff888002035100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    4.595573]  ffff888002035180: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb
[    4.595579] >ffff888002035200: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
[    4.595584]                                            ^
[    4.595590]  ffff888002035280: fc fc fc fc 00 00 00 00 00 00 00 00 00 00 00 00
[    4.595596]  ffff888002035300: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
[    4.595601] ==================================================================


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ