]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.1.9/mips-bounds-check-virt_addr_valid.patch
Linux 5.1.9
[thirdparty/kernel/stable-queue.git] / releases / 5.1.9 / mips-bounds-check-virt_addr_valid.patch
CommitLineData
7a7567a2
GKH
1From 074a1e1167afd82c26f6d03a9a8b997d564bb241 Mon Sep 17 00:00:00 2001
2From: Paul Burton <paul.burton@mips.com>
3Date: Tue, 28 May 2019 17:05:03 +0000
4Subject: MIPS: Bounds check virt_addr_valid
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Paul Burton <paul.burton@mips.com>
10
11commit 074a1e1167afd82c26f6d03a9a8b997d564bb241 upstream.
12
13The virt_addr_valid() function is meant to return true iff
14virt_to_page() will return a valid struct page reference. This is true
15iff the address provided is found within the unmapped address range
16between PAGE_OFFSET & MAP_BASE, but we don't currently check for that
17condition. Instead we simply mask the address to obtain what will be a
18physical address if the virtual address is indeed in the desired range,
19shift it to form a PFN & then call pfn_valid(). This can incorrectly
20return true if called with a virtual address which, after masking,
21happens to form a physical address corresponding to a valid PFN.
22
23For example we may vmalloc an address in the kernel mapped region
24starting a MAP_BASE & obtain the virtual address:
25
26 addr = 0xc000000000002000
27
28When masked by virt_to_phys(), which uses __pa() & in turn CPHYSADDR(),
29we obtain the following (bogus) physical address:
30
31 addr = 0x2000
32
33In a common system with PHYS_OFFSET=0 this will correspond to a valid
34struct page which should really be accessed by virtual address
35PAGE_OFFSET+0x2000, causing virt_addr_valid() to incorrectly return 1
36indicating that the original address corresponds to a struct page.
37
38This is equivalent to the ARM64 change made in commit ca219452c6b8
39("arm64: Correctly bounds check virt_addr_valid").
40
41This fixes fallout when hardened usercopy is enabled caused by the
42related commit 517e1fbeb65f ("mm/usercopy: Drop extra
43is_vmalloc_or_module() check") which removed a check for the vmalloc
44range that was present from the introduction of the hardened usercopy
45feature.
46
47Signed-off-by: Paul Burton <paul.burton@mips.com>
48References: ca219452c6b8 ("arm64: Correctly bounds check virt_addr_valid")
49References: 517e1fbeb65f ("mm/usercopy: Drop extra is_vmalloc_or_module() check")
50Reported-by: Julien Cristau <jcristau@debian.org>
51Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
52Tested-by: YunQiang Su <ysu@wavecomp.com>
53URL: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=929366
54Cc: stable@vger.kernel.org # v4.12+
55Cc: linux-mips@vger.kernel.org
56Cc: Yunqiang Su <ysu@wavecomp.com>
57Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
58
59---
60 arch/mips/mm/mmap.c | 5 +++++
61 1 file changed, 5 insertions(+)
62
63--- a/arch/mips/mm/mmap.c
64+++ b/arch/mips/mm/mmap.c
65@@ -203,6 +203,11 @@ unsigned long arch_randomize_brk(struct
66
67 int __virt_addr_valid(const volatile void *kaddr)
68 {
69+ unsigned long vaddr = (unsigned long)vaddr;
70+
71+ if ((vaddr < PAGE_OFFSET) || (vaddr >= MAP_BASE))
72+ return 0;
73+
74 return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
75 }
76 EXPORT_SYMBOL_GPL(__virt_addr_valid);