x86/mm: Limit mmap() of /dev/mem to valid physical addresses
Currently, it is possible to mmap() any offset from /dev/mem. If a program mmaps() /dev/mem offsets outside of the addressable limits of a system, the page table can be corrupted by setting reserved bits. For example if you mmap() offset 0x0001000000000000 of /dev/mem on an x86_64 system with a 48-bit bus, the page fault handler will be called with error_code set to RSVD. The kernel then crashes with a page table corruption error. This change prevents this page table corruption on x86 by refusing to mmap offsets higher than the highest valid address in the system. Signed-off-by: Craig Bergstrom <craigb@google.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Luis R. Rodriguez <mcgrof@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Toshi Kani <toshi.kani@hp.com> Cc: dsafonov@virtuozzo.com Cc: kirill.shutemov@linux.intel.com Cc: mhocko@suse.com Cc: oleg@redhat.com Link: http://lkml.kernel.org/r/20171019192856.39672-1-craigb@google.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
7ac7f2c315
commit
ce56a86e2a
|
@ -110,6 +110,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", )
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||||
|
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
|
||||||
|
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virt_to_phys - map virtual addresses to physical
|
* virt_to_phys - map virtual addresses to physical
|
||||||
* @address: address to remap
|
* @address: address to remap
|
||||||
|
|
|
@ -174,3 +174,15 @@ const char *arch_vma_name(struct vm_area_struct *vma)
|
||||||
return "[mpx]";
|
return "[mpx]";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int valid_phys_addr_range(phys_addr_t addr, size_t count)
|
||||||
|
{
|
||||||
|
return addr + count <= __pa(high_memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
|
||||||
|
{
|
||||||
|
phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT;
|
||||||
|
|
||||||
|
return valid_phys_addr_range(addr, count);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue