From e843e42a5792b7007ea7ee37b14da4bfb4155b3d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 31 Aug 2018 13:14:08 -0700 Subject: [PATCH] 4.4-stable patches added patches: arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch --- ...r-upper-page_shift-bits-in-pfn_valid.patch | 59 +++++++++++++++++++ queue-4.4/series | 1 + 2 files changed, 60 insertions(+) create mode 100644 queue-4.4/arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch diff --git a/queue-4.4/arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch b/queue-4.4/arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch new file mode 100644 index 00000000000..97b1fe195e9 --- /dev/null +++ b/queue-4.4/arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch @@ -0,0 +1,59 @@ +From 5ad356eabc47d26a92140a0c4b20eba471c10de3 Mon Sep 17 00:00:00 2001 +From: Greg Hackmann +Date: Wed, 15 Aug 2018 12:51:21 -0700 +Subject: arm64: mm: check for upper PAGE_SHIFT bits in pfn_valid() + +From: Greg Hackmann + +commit 5ad356eabc47d26a92140a0c4b20eba471c10de3 upstream. + +ARM64's pfn_valid() shifts away the upper PAGE_SHIFT bits of the input +before seeing if the PFN is valid. This leads to false positives when +some of the upper bits are set, but the lower bits match a valid PFN. + +For example, the following userspace code looks up a bogus entry in +/proc/kpageflags: + + int pagemap = open("/proc/self/pagemap", O_RDONLY); + int pageflags = open("/proc/kpageflags", O_RDONLY); + uint64_t pfn, val; + + lseek64(pagemap, [...], SEEK_SET); + read(pagemap, &pfn, sizeof(pfn)); + if (pfn & (1UL << 63)) { /* valid PFN */ + pfn &= ((1UL << 55) - 1); /* clear flag bits */ + pfn |= (1UL << 55); + lseek64(pageflags, pfn * sizeof(uint64_t), SEEK_SET); + read(pageflags, &val, sizeof(val)); + } + +On ARM64 this causes the userspace process to crash with SIGSEGV rather +than reading (1 << KPF_NOPAGE). kpageflags_read() treats the offset as +valid, and stable_page_flags() will try to access an address between the +user and kernel address ranges. + +Fixes: c1cc1552616d ("arm64: MMU initialisation") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Hackmann +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm64/mm/init.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/arm64/mm/init.c ++++ b/arch/arm64/mm/init.c +@@ -120,7 +120,11 @@ static void __init zone_sizes_init(unsig + #ifdef CONFIG_HAVE_ARCH_PFN_VALID + int pfn_valid(unsigned long pfn) + { +- return memblock_is_memory(pfn << PAGE_SHIFT); ++ phys_addr_t addr = pfn << PAGE_SHIFT; ++ ++ if ((addr >> PAGE_SHIFT) != pfn) ++ return 0; ++ return memblock_is_memory(addr); + } + EXPORT_SYMBOL(pfn_valid); + #endif diff --git a/queue-4.4/series b/queue-4.4/series index 292dc501107..d77acb44be6 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -47,3 +47,4 @@ s390-kvm-fix-deadlock-when-killed-by-oom.patch ext4-check-for-nul-characters-in-extended-attribute-s-name.patch ext4-sysfs-print-ext4_super_block-fields-as-little-endian.patch ext4-reset-error-code-in-ext4_find_entry-in-fallback.patch +arm64-mm-check-for-upper-page_shift-bits-in-pfn_valid.patch -- 2.47.3