aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kernel/crash_dump_32.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-11-02 09:45:17 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-02 09:45:17 -0800
commitefcd9e0b91bcb92a1dd530d1a1f26eb83a5d21e2 (patch)
tree167fb89a3e0ae3b83a89207e0c42a35dcf2a8ad4 /arch/x86/kernel/crash_dump_32.c
parent32c5fc10e79a7053ac5728b01a0bff55cbcb9d49 (diff)
parent772be899bc022ef2b911c3611b487d417e3269c3 (diff)
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86: Make EFI RTC function depend on 32bit again x86-64: Fix register leak in 32-bit syscall audting x86: crash_dump: Fix non-pae kdump kernel memory accesses x86: Side-step lguest problem by only building cmpxchg8b_emu for pre-Pentium x86: Remove STACKPROTECTOR_ALL
Diffstat (limited to 'arch/x86/kernel/crash_dump_32.c')
-rw-r--r--arch/x86/kernel/crash_dump_32.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c
index f7cdb3b457a..cd97ce18c29 100644
--- a/arch/x86/kernel/crash_dump_32.c
+++ b/arch/x86/kernel/crash_dump_32.c
@@ -16,6 +16,22 @@ static void *kdump_buf_page;
/* Stores the physical address of elf header of crash image. */
unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+static inline bool is_crashed_pfn_valid(unsigned long pfn)
+{
+#ifndef CONFIG_X86_PAE
+ /*
+ * non-PAE kdump kernel executed from a PAE one will crop high pte
+ * bits and poke unwanted space counting again from address 0, we
+ * don't want that. pte must fit into unsigned long. In fact the
+ * test checks high 12 bits for being zero (pfn will be shifted left
+ * by PAGE_SHIFT).
+ */
+ return pte_pfn(pfn_pte(pfn, __pgprot(0))) == pfn;
+#else
+ return true;
+#endif
+}
+
/**
* copy_oldmem_page - copy one page from "oldmem"
* @pfn: page frame number to be copied
@@ -41,6 +57,9 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
if (!csize)
return 0;
+ if (!is_crashed_pfn_valid(pfn))
+ return -EFAULT;
+
vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
if (!userbuf) {