Thread (5 messages) flat view 5 messages, 2 authors, 2021-04-14

Re: [PATCH] arch/arm64/kernel/traps: Use find_vma_intersection() in traps for setting si_code

From: Liam Howlett <hidden>
Date: 2021-04-13 16:54:27
Also in: bpf, linux-arm-kernel, lkml

* Catalin Marinas [off-list ref] [210412 13:44]:
On Wed, Apr 07, 2021 at 03:11:06PM +0000, Liam Howlett wrote:
quoted
find_vma() will continue to search upwards until the end of the virtual
memory space.  This means the si_code would almost never be set to
SEGV_MAPERR even when the address falls outside of any VMA.  The result
is that the si_code is not reliable as it may or may not be set to the
correct result, depending on where the address falls in the address
space.

Using find_vma_intersection() allows for what is intended by only
returning a VMA if it falls within the range provided, in this case a
window of 1.

Signed-off-by: Liam R. Howlett <redacted>
---
 arch/arm64/kernel/traps.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index a05d34f0e82a..a44007904a64 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -383,9 +383,10 @@ void force_signal_inject(int signal, int code, unsigned long address, unsigned i
 void arm64_notify_segfault(unsigned long addr)
 {
 	int code;
+	unsigned long ut_addr = untagged_addr(addr);
 
 	mmap_read_lock(current->mm);
-	if (find_vma(current->mm, untagged_addr(addr)) == NULL)
+	if (find_vma_intersection(current->mm, ut_addr, ut_addr + 1) == NULL)
 		code = SEGV_MAPERR;
 	else
 		code = SEGV_ACCERR;

Thank you for taking the time to thoroughly review this patch.
I don't think your change is entirely correct either. We can have a
fault below the vma of a stack (with VM_GROWSDOWN) and
find_vma_intersection() would return NULL but it should be a SEGV_ACCERR
instead.
I'm pretty sure I am missing something.  From what you said above, I
think this means that there can be a user cache fault below the stack
which should notify the user application that they are not allowed to
expand the stack by sending a SIGV_ACCERR in the si_code?  Is this
expected behaviour or am I missing a code path to this function?
Maybe this should employ similar checks as __do_page_fault() (with
expand_stack() and VM_GROWSDOWN).
You mean the code needs to detect endianness and to check if this is an
attempt to expand the stack for both cases?

Thanks,
Liam
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help