diff options
| -rw-r--r-- | arch/x86/kernel/crash_dump_32.c | 19 |
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 f7cdb3b457aa..cd97ce18c29d 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; | |||
| 16 | /* Stores the physical address of elf header of crash image. */ | 16 | /* Stores the physical address of elf header of crash image. */ |
| 17 | unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; | 17 | unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; |
| 18 | 18 | ||
| 19 | static inline bool is_crashed_pfn_valid(unsigned long pfn) | ||
| 20 | { | ||
| 21 | #ifndef CONFIG_X86_PAE | ||
| 22 | /* | ||
| 23 | * non-PAE kdump kernel executed from a PAE one will crop high pte | ||
| 24 | * bits and poke unwanted space counting again from address 0, we | ||
| 25 | * don't want that. pte must fit into unsigned long. In fact the | ||
| 26 | * test checks high 12 bits for being zero (pfn will be shifted left | ||
| 27 | * by PAGE_SHIFT). | ||
| 28 | */ | ||
| 29 | return pte_pfn(pfn_pte(pfn, __pgprot(0))) == pfn; | ||
| 30 | #else | ||
| 31 | return true; | ||
| 32 | #endif | ||
| 33 | } | ||
| 34 | |||
| 19 | /** | 35 | /** |
| 20 | * copy_oldmem_page - copy one page from "oldmem" | 36 | * copy_oldmem_page - copy one page from "oldmem" |
| 21 | * @pfn: page frame number to be copied | 37 | * @pfn: page frame number to be copied |
| @@ -41,6 +57,9 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
| 41 | if (!csize) | 57 | if (!csize) |
| 42 | return 0; | 58 | return 0; |
| 43 | 59 | ||
| 60 | if (!is_crashed_pfn_valid(pfn)) | ||
| 61 | return -EFAULT; | ||
| 62 | |||
| 44 | vaddr = kmap_atomic_pfn(pfn, KM_PTE0); | 63 | vaddr = kmap_atomic_pfn(pfn, KM_PTE0); |
| 45 | 64 | ||
| 46 | if (!userbuf) { | 65 | if (!userbuf) { |
