aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hackmann <ghackmann@google.com>2014-08-28 14:00:10 -0700
committerAmit Pundir <amit.pundir@linaro.org>2016-01-04 13:09:11 +0530
commitc1888542afafe0359b9bc86bb1cb2640e6b1fae6 (patch)
treee643989fd1964038056bca2521c2cde7f735db48
parented88b5e74eaea656cf1125399afe718fc8ddd82d (diff)
arm64: check for upper PAGE_SHIFT bits in pfn_valid()
pfn_valid() returns a false positive when the lower (64 - PAGE_SHIFT) bits match a valid pfn but some of the upper bits are set. This caused a kernel panic in kpageflags_read() when a userspace utility parsed /proc/*/pagemap, neglected to discard the upper flag bits, and tried to lseek()+read() from the corresponding offset in /proc/kpageflags. A valid pfn will never have the upper PAGE_SHIFT bits set, so simply check for this before passing the pfn to memblock_is_memory(). Change-Id: Ief5d8cd4dd93cbecd545a634a8d5885865cb5970 Signed-off-by: Greg Hackmann <ghackmann@google.com>
-rw-r--r--arch/arm64/mm/init.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 17bf39ac83ba..325f89ff897e 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -118,9 +118,11 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
}
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
+#define PFN_MASK ((1UL << (64 - PAGE_SHIFT)) - 1)
+
int pfn_valid(unsigned long pfn)
{
- return memblock_is_memory(pfn << PAGE_SHIFT);
+ return (pfn & PFN_MASK) == pfn && memblock_is_memory(pfn << PAGE_SHIFT);
}
EXPORT_SYMBOL(pfn_valid);
#endif