提交 01eb873b 编写于 作者: E Eugeniy Paltsev 提交者: Xie XiuQi

ARC: mm: SIGSEGV userspace trying to access kernel virtual memory

[ Upstream commit a8c715b4dd73c26a81a9cc8dc792aa715d8b4bb2 ]

As of today if userspace process tries to access a kernel virtual addres
(0x7000_0000 to 0x7ffff_ffff) such that a legit kernel mapping already
exists, that process hangs instead of being killed with SIGSEGV

Fix that by ensuring that do_page_fault() handles kenrel vaddr only if
in kernel mode.

And given this, we can also simplify the code a bit. Now a vmalloc fault
implies kernel mode so its failure (for some reason) can reuse the
@no_context label and we can remove @bad_area_nosemaphore.

Reproduce user test for original problem:

------------------------>8-----------------
 #include <stdlib.h>
 #include <stdint.h>

 int main(int argc, char *argv[])
 {
 	volatile uint32_t temp;

 	temp = *(uint32_t *)(0x70000000);
 }
------------------------>8-----------------

Cc: <stable@vger.kernel.org>
Signed-off-by: NEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: NVineet Gupta <vgupta@synopsys.com>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 d82a674e
...@@ -66,7 +66,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) ...@@ -66,7 +66,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
struct vm_area_struct *vma = NULL; struct vm_area_struct *vma = NULL;
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
int si_code = 0; int si_code = SEGV_MAPERR;
int ret; int ret;
vm_fault_t fault; vm_fault_t fault;
int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */
...@@ -81,16 +81,14 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) ...@@ -81,16 +81,14 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
* only copy the information from the master page table, * only copy the information from the master page table,
* nothing more. * nothing more.
*/ */
if (address >= VMALLOC_START) { if (address >= VMALLOC_START && !user_mode(regs)) {
ret = handle_kernel_vaddr_fault(address); ret = handle_kernel_vaddr_fault(address);
if (unlikely(ret)) if (unlikely(ret))
goto bad_area_nosemaphore; goto no_context;
else else
return; return;
} }
si_code = SEGV_MAPERR;
/* /*
* If we're in an interrupt or have no user * If we're in an interrupt or have no user
* context, we must not take the fault.. * context, we must not take the fault..
...@@ -198,7 +196,6 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) ...@@ -198,7 +196,6 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
bad_area: bad_area:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */ /* User mode accesses just cause a SIGSEGV */
if (user_mode(regs)) { if (user_mode(regs)) {
tsk->thread.fault_address = address; tsk->thread.fault_address = address;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册