• Joerg Roedel's avatar
    x86/mm/32: Bring back vmalloc faulting on x86_32 · 4819e15f
    Joerg Roedel authored
    One can not simply remove vmalloc faulting on x86-32. Upstream
    
    	commit: 7f0a002b ("x86/mm: remove vmalloc faulting")
    
    removed it on x86 alltogether because previously the
    arch_sync_kernel_mappings() interface was introduced. This interface
    added synchronization of vmalloc/ioremap page-table updates to all
    page-tables in the system at creation time and was thought to make
    vmalloc faulting obsolete.
    
    But that assumption was incredibly naive.
    
    It turned out that there is a race window between the time the vmalloc
    or ioremap code establishes a mapping and the time it synchronizes
    this change to other page-tables in the system.
    
    During this race window another CPU or thread can establish a vmalloc
    mapping which uses the same intermediate page-table entries (e.g. PMD
    or PUD) and does no synchronization in the end, because it found all
    necessary mappings already present in the kernel reference page-table.
    
    But when these intermediate page-table entries are not yet
    synchronized, the other CPU or thread will continue with a vmalloc
    address that is not yet mapped in the page-table it currently uses,
    causing an unhandled page fault and oops like below:
    
    	BUG: unable to handle page fault for address: fe80c000
    	#PF: supervisor write access in kernel mode
    	#PF: error_code(0x0002) - not-present page
    	*pde = 33183067 *pte = a8648163
    	Oops: 0002 [#1] SMP
    	CPU: 1 PID: 13514 Comm: cve-2017-17053 Tainted: G
    	...
    	Call Trace:
    	 ldt_dup_context+0x66/0x80
    	 dup_mm+0x2b3/0x480
    	 copy_process+0x133b/0x15c0
    	 _do_fork+0x94/0x3e0
    	 __ia32_sys_clone+0x67/0x80
    	 __do_fast_syscall_32+0x3f/0x70
    	 do_fast_syscall_32+0x29/0x60
    	 do_SYSENTER_32+0x15/0x20
    	 entry_SYSENTER_32+0x9f/0xf2
    	EIP: 0xb7eef549
    
    So the arch_sync_kernel_mappings() interface is racy, but removing it
    would mean to re-introduce the vmalloc_sync_all() interface, which is
    even more awful. Keep arch_sync_kernel_mappings() in place and catch
    the race condition in the page-fault handler instead.
    
    Do a partial revert of above commit to get vmalloc faulting on x86-32
    back in place.
    
    Fixes: 7f0a002b ("x86/mm: remove vmalloc faulting")
    Reported-by: default avatarNaresh Kamboju <naresh.kamboju@linaro.org>
    Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    Link: https://lore.kernel.org/r/20200902155904.17544-1-joro@8bytes.org
    4819e15f
fault.c 39.7 KB