public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: tip-bot for Craig Bergstrom <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: peterz@infradead.org, hpa@zytor.com,
	torvalds@linux-foundation.org, mchehab@s-opensource.com,
	hans.verkuil@cisco.com, boris.ostrovsky@oracle.com,
	sean@mess.org, fengguang.wu@intel.com, craigb@google.com,
	tglx@linutronix.de, linux-kernel@vger.kernel.org,
	gregkh@linuxfoundation.org, mingo@kernel.org,
	linux@eikelenboom.it
Subject: [tip:x86/urgent] x86/mm: Limit mmap() of /dev/mem to valid physical addresses
Date: Thu, 16 Nov 2017 07:49:08 -0800	[thread overview]
Message-ID: <tip-be62a32044061cb4a3b70a10598e093f1319102e@git.kernel.org> (raw)
In-Reply-To: <CA+55aFyEcOMb657vWSmrM13OxmHxC-XxeBmNis=DwVvpJUOogQ@mail.gmail.com>

Commit-ID:  be62a32044061cb4a3b70a10598e093f1319102e
Gitweb:     https://git.kernel.org/tip/be62a32044061cb4a3b70a10598e093f1319102e
Author:     Craig Bergstrom <craigb@google.com>
AuthorDate: Wed, 15 Nov 2017 15:29:51 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 16 Nov 2017 12:49:48 +0100

x86/mm: Limit mmap() of /dev/mem to valid physical addresses

One thing /dev/mem access APIs should verify is that there's no way
that excessively large pfn's can leak into the high bits of the
page table entry.

In particular, if people can use "very large physical page addresses"
through /dev/mem to set the bits past bit 58 - SOFTW4 and permission
key bits and NX bit, that could *really* confuse the kernel.

We had an earlier attempt:

  ce56a86e2ade ("x86/mm: Limit mmap() of /dev/mem to valid physical addresses")

... which turned out to be too restrictive (breaking mem=... bootups for example) and
had to be reverted in:

  90edaac62729 ("Revert "x86/mm: Limit mmap() of /dev/mem to valid physical addresses"")

This v2 attempt modifies the original patch and makes sure that mmap(/dev/mem)
limits the pfns so that it at least fits in the actual pteval_t architecturally:

 - Make sure mmap_mem() actually validates that the offset fits in phys_addr_t

    ( This may be indirectly true due to some other check, but it's not
      entirely obvious. )

 - Change valid_mmap_phys_addr_range() to just use phys_addr_valid()
   on the top byte

    ( Top byte is sufficient, because mmap_mem() has already checked that
      it cannot wrap. )

 - Add a few comments about what the valid_phys_addr_range() vs.
   valid_mmap_phys_addr_range() difference is.

Signed-off-by: Craig Bergstrom <craigb@google.com>
[ Fixed the checks and added comments. ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ Collected the discussion and patches into a commit. ]
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sander Eikelenboom <linux@eikelenboom.it>
Cc: Sean Young <sean@mess.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/CA+55aFyEcOMb657vWSmrM13OxmHxC-XxeBmNis=DwVvpJUOogQ@mail.gmail.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/io.h |  4 ++++
 arch/x86/mm/mmap.c        | 16 ++++++++++++++++
 drivers/char/mem.c        |  4 ++++
 3 files changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 93ae8ae..95e9486 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -111,6 +111,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 62285fe..155ecba 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -33,6 +33,8 @@
 #include <linux/compat.h>
 #include <asm/elf.h>
 
+#include "physaddr.h"
+
 struct va_alignment __read_mostly va_align = {
 	.flags = -1,
 };
@@ -220,3 +222,17 @@ bool mmap_address_hint_valid(unsigned long addr, unsigned long len)
 
 	return (addr > DEFAULT_MAP_WINDOW) == (addr + len > DEFAULT_MAP_WINDOW);
 }
+
+/* Can we access it for direct reading/writing? Must be RAM: */
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+	return addr + count <= __pa(high_memory);
+}
+
+/* Can we access it through mmap? Must be a valid physical address: */
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+	phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT;
+
+	return phys_addr_valid(addr + count - 1);
+}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 970e124..6aefe53 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -343,6 +343,10 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 	size_t size = vma->vm_end - vma->vm_start;
 	phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
 
+	/* Does it even fit in phys_addr_t? */
+	if (offset >> PAGE_SHIFT != vma->vm_pgoff)
+		return -EINVAL;
+
 	/* It's illegal to wrap around the end of the physical address space. */
 	if (offset + (phys_addr_t)size - 1 < offset)
 		return -EINVAL;

  reply	other threads:[~2017-11-16 15:58 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-24  2:44 ce56a86e2a ("x86/mm: Limit mmap() of /dev/mem to valid physical addresses"): kernel BUG at arch/x86/mm/physaddr.c:79! Fengguang Wu
2017-10-25 20:50 ` Boris Ostrovsky
     [not found]   ` <CAOJUGyfTM2J-P29yPhUx2A2SDjA0rv972SE0hmbMHonthMd_bQ@mail.gmail.com>
2017-10-26  8:05     ` Sander Eikelenboom
2017-10-26  8:12       ` Sander Eikelenboom
2017-10-26  8:58         ` Sander Eikelenboom
2017-10-26 16:35           ` Craig Bergstrom
2017-10-26 16:39             ` Ingo Molnar
2017-10-26 17:49               ` Craig Bergstrom
2017-10-26 19:02                 ` Ingo Molnar
2017-10-26 19:29                   ` Linus Torvalds
2017-10-26 19:50                     ` Craig Bergstrom
2017-10-26 21:12                       ` Linus Torvalds
2017-11-16 15:49                         ` tip-bot for Craig Bergstrom [this message]
2017-10-27 19:24                       ` Ingo Molnar
2017-10-27 19:28                         ` Craig Bergstrom
2017-11-03 19:54                           ` Craig Bergstrom
2017-10-27  8:25                     ` Ingo Molnar
2017-10-26 19:29                 ` Sander Eikelenboom
2017-10-26 20:01                   ` [Xen-devel] " Andrew Cooper
2017-10-27  7:07                   ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=tip-be62a32044061cb4a3b70a10598e093f1319102e@git.kernel.org \
    --to=tipbot@zytor.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=craigb@google.com \
    --cc=fengguang.wu@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hans.verkuil@cisco.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=linux@eikelenboom.it \
    --cc=mchehab@s-opensource.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=sean@mess.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox