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