x86: crash_dump: Fix non-pae kdump kernel memory accesses
Non-PAE 32-bit dump kernels may wrap an address around 4G and poke unwanted space. ptes there are 32-bit long, and since pfn << PAGE_SIZE may exceed this limit, high pfn bits are cropped and wrong address mapped by kmap_atomic_pfn in copy_oldmem_page. Don't allow this behavior in non-PAE kdump kernels by checking pfns passed into copy_oldmem_page. In the case of failure, userspace process gets EFAULT. [v2] - fix comments - move ifdefs inside the function Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Simon Horman <horms@verge.net.au> Cc: Paul Mundt <lethal@linux-sh.org> LKML-Reference: <1256551903-30567-1-git-send-email-jirislaby@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>hifive-unleashed-5.1
parent
ae1b22f6e4
commit
72ed7de74e
|
@ -16,6 +16,22 @@ static void *kdump_buf_page;
|
||||||
/* Stores the physical address of elf header of crash image. */
|
/* Stores the physical address of elf header of crash image. */
|
||||||
unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
|
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"
|
* copy_oldmem_page - copy one page from "oldmem"
|
||||||
* @pfn: page frame number to be copied
|
* @pfn: page frame number to be copied
|
||||||
|
@ -41,6 +57,9 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
||||||
if (!csize)
|
if (!csize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!is_crashed_pfn_valid(pfn))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
|
vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
|
||||||
|
|
||||||
if (!userbuf) {
|
if (!userbuf) {
|
||||||
|
|
Loading…
Reference in New Issue