From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752726AbdJST3N (ORCPT ); Thu, 19 Oct 2017 15:29:13 -0400 Received: from mail-io0-f202.google.com ([209.85.223.202]:43157 "EHLO mail-io0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751974AbdJST3L (ORCPT ); Thu, 19 Oct 2017 15:29:11 -0400 X-Google-Smtp-Source: ABhQp+SyoMn/Q18TYSpifEYRMLVvT/pPP+4DG26wMHycS36HLQhWlbeE58O+PZa+r4ghSnF+MAhfZuYgTLg= MIME-Version: 1.0 Date: Thu, 19 Oct 2017 13:28:56 -0600 Message-Id: <20171019192856.39672-1-craigb@google.com> X-Mailer: git-send-email 2.15.0.rc1.287.g2b38de12cc-goog Subject: [PATCH] X86/mm limit mmap of /dev/mem to valid addrs. From: Craig Bergstrom To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com, dsafonov@virtuozzo.com, oleg@redhat.com, kirill.shutemov@linux.intel.com, mhocko@suse.com, Craig Bergstrom Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 is corrupted by setting some reserved bits. If you mmap offset 0x0001000000000000 of /dev/mem on an x86_64 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 --- arch/x86/include/asm/io.h | 4 ++++ arch/x86/mm/mmap.c | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index c40a95c33bb8..322d25ae23ab 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -110,6 +110,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", ) #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 * @address: address to remap diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index a99679826846..320c6237e1d1 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -174,3 +174,15 @@ const char *arch_vma_name(struct vm_area_struct *vma) return "[mpx]"; 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); +} -- 2.15.0.rc1.287.g2b38de12cc-goog