diff mbox series

arm64: fault: Route pte translation faults via do_translation_fault

Message ID 1506684461-24162-1-git-send-email-will.deacon@arm.com
State Accepted
Commit 760bfb47c36a07741a089bf6a28e854ffbee7dc9
Headers show
Series arm64: fault: Route pte translation faults via do_translation_fault | expand

Commit Message

Will Deacon Sept. 29, 2017, 11:27 a.m. UTC
We currently route pte translation faults via do_page_fault, which elides
the address check against TASK_SIZE before invoking the mm fault handling
code. However, this can cause issues with the path walking code in
conjunction with our word-at-a-time implementation because
load_unaligned_zeropad can end up faulting in kernel space if it reads
across a page boundary and runs into a page fault (e.g. by attempting to
read from a guard region).

In the case of such a fault, load_unaligned_zeropad has registered a
fixup to shift the valid data and pad with zeroes, however the abort is
reported as a level 3 translation fault and we dispatch it straight to
do_page_fault, despite it being a kernel address. This results in calling
a sleeping function from atomic context:

  BUG: sleeping function called from invalid context at arch/arm64/mm/fault.c:313
  in_atomic(): 0, irqs_disabled(): 0, pid: 10290
  Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
  [...]
  [<ffffff8e016cd0cc>] ___might_sleep+0x134/0x144
  [<ffffff8e016cd158>] __might_sleep+0x7c/0x8c
  [<ffffff8e016977f0>] do_page_fault+0x140/0x330
  [<ffffff8e01681328>] do_mem_abort+0x54/0xb0
  Exception stack(0xfffffffb20247a70 to 0xfffffffb20247ba0)
  [...]
  [<ffffff8e016844fc>] el1_da+0x18/0x78
  [<ffffff8e017f399c>] path_parentat+0x44/0x88
  [<ffffff8e017f4c9c>] filename_parentat+0x5c/0xd8
  [<ffffff8e017f5044>] filename_create+0x4c/0x128
  [<ffffff8e017f59e4>] SyS_mkdirat+0x50/0xc8
  [<ffffff8e01684e30>] el0_svc_naked+0x24/0x28
  Code: 36380080 d5384100 f9400800 9402566d (d4210000)
  ---[ end trace 2d01889f2bca9b9f ]---

Fix this by dispatching all translation faults to do_translation_faults,
which avoids invoking the page fault logic for faults on kernel addresses.

Cc: <stable@vger.kernel.org>
Reported-by: Ankit Jain <ankijain@codeaurora.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>

---
 arch/arm64/mm/fault.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.1.4

Comments

Catalin Marinas Sept. 29, 2017, 3:47 p.m. UTC | #1
On Fri, Sep 29, 2017 at 12:27:41PM +0100, Will Deacon wrote:
> We currently route pte translation faults via do_page_fault, which elides

> the address check against TASK_SIZE before invoking the mm fault handling

> code. However, this can cause issues with the path walking code in

> conjunction with our word-at-a-time implementation because

> load_unaligned_zeropad can end up faulting in kernel space if it reads

> across a page boundary and runs into a page fault (e.g. by attempting to

> read from a guard region).

> 

> In the case of such a fault, load_unaligned_zeropad has registered a

> fixup to shift the valid data and pad with zeroes, however the abort is

> reported as a level 3 translation fault and we dispatch it straight to

> do_page_fault, despite it being a kernel address. This results in calling

> a sleeping function from atomic context:

> 

>   BUG: sleeping function called from invalid context at arch/arm64/mm/fault.c:313

>   in_atomic(): 0, irqs_disabled(): 0, pid: 10290

>   Internal error: Oops - BUG: 0 [#1] PREEMPT SMP

>   [...]

>   [<ffffff8e016cd0cc>] ___might_sleep+0x134/0x144

>   [<ffffff8e016cd158>] __might_sleep+0x7c/0x8c

>   [<ffffff8e016977f0>] do_page_fault+0x140/0x330

>   [<ffffff8e01681328>] do_mem_abort+0x54/0xb0

>   Exception stack(0xfffffffb20247a70 to 0xfffffffb20247ba0)

>   [...]

>   [<ffffff8e016844fc>] el1_da+0x18/0x78

>   [<ffffff8e017f399c>] path_parentat+0x44/0x88

>   [<ffffff8e017f4c9c>] filename_parentat+0x5c/0xd8

>   [<ffffff8e017f5044>] filename_create+0x4c/0x128

>   [<ffffff8e017f59e4>] SyS_mkdirat+0x50/0xc8

>   [<ffffff8e01684e30>] el0_svc_naked+0x24/0x28

>   Code: 36380080 d5384100 f9400800 9402566d (d4210000)

>   ---[ end trace 2d01889f2bca9b9f ]---

> 

> Fix this by dispatching all translation faults to do_translation_faults,

> which avoids invoking the page fault logic for faults on kernel addresses.

> 

> Cc: <stable@vger.kernel.org>

> Reported-by: Ankit Jain <ankijain@codeaurora.org>

> Signed-off-by: Will Deacon <will.deacon@arm.com>


Applied. Thanks.

-- 
Catalin
diff mbox series

Patch

diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 89993c4be1be..2069e9bc0fca 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -651,7 +651,7 @@  static const struct fault_info fault_info[] = {
 	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 0 translation fault"	},
 	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 1 translation fault"	},
 	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 2 translation fault"	},
-	{ do_page_fault,	SIGSEGV, SEGV_MAPERR,	"level 3 translation fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 3 translation fault"	},
 	{ do_bad,		SIGBUS,  0,		"unknown 8"			},
 	{ do_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 1 access flag fault"	},
 	{ do_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 2 access flag fault"	},