Skip to content

Commit c929e9b

Browse files
heicarstbwhacks
authored andcommitted
s390/mm: fix fault handling for page table walk case
commit 008c2e8 upstream. Make sure the kernel does not incorrectly create a SIGBUS signal during user space accesses: For user space accesses in the switched addressing mode case the kernel may walk page tables and access user address space via the kernel mapping. If a page table entry is invalid the function __handle_fault() gets called in order to emulate a page fault and trigger all the usual actions like paging in a missing page etc. by calling handle_mm_fault(). If handle_mm_fault() returns with an error fixup handling is necessary. For the switched addressing mode case all errors need to be mapped to -EFAULT, so that the calling uaccess function can return -EFAULT to user space. Unfortunately the __handle_fault() incorrectly calls do_sigbus() if VM_FAULT_SIGBUS is set. This however should only happen if a page fault was triggered by a user space instruction. For kernel mode uaccesses the correct action is to only return -EFAULT. So user space may incorrectly see SIGBUS signals because of this bug. For current machines this would only be possible for the switched addressing mode case in conjunction with futex operations. Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]> [bwh: Backported to 3.2: do_exception() and do_sigbus() parameters differ] Signed-off-by: Ben Hutchings <[email protected]>
1 parent e551857 commit c929e9b

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

arch/s390/mm/fault.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
453453
struct pt_regs regs;
454454
int access, fault;
455455

456+
/* Emulate a uaccess fault from kernel mode. */
456457
regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
457458
if (!irqs_disabled())
458459
regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
@@ -461,12 +462,12 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
461462
uaddr &= PAGE_MASK;
462463
access = write ? VM_WRITE : VM_READ;
463464
fault = do_exception(&regs, access, uaddr | 2);
464-
if (unlikely(fault)) {
465-
if (fault & VM_FAULT_OOM)
466-
return -EFAULT;
467-
else if (fault & VM_FAULT_SIGBUS)
468-
do_sigbus(&regs, pgm_int_code, uaddr);
469-
}
465+
/*
466+
* Since the fault happened in kernel mode while performing a uaccess
467+
* all we need to do now is emulating a fixup in case "fault" is not
468+
* zero.
469+
* For the calling uaccess functions this results always in -EFAULT.
470+
*/
470471
return fault ? -EFAULT : 0;
471472
}
472473

0 commit comments

Comments
 (0)