All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC 0/3] add mitigation against buffer overflows
@ 2015-09-10 14:20 Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 1/3] oslib: rework anonimous RAM allocation Michael S. Tsirkin
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2015-09-10 14:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, Peter Maydell

Multiple places in QEMU map guest memory, then access it
directly. Unfortunately since we are using C, there's always
a chance that we'll miss a bounds check when we do this.
This has a potential to corrupt QEMU memory.

As a mitigation strategy against such exploits,
allocate a page in HVA space on top of each RAM chunk
with PROT_NONE protection.

Buffer overflows will now cause QEMU to crash.

Lightly tested.

Michael S. Tsirkin (3):
  oslib: rework anonimous RAM allocation
  oslib: allocate PROT_NONE pages on top of RAM
  exec: allocate PROT_NONE pages on top of RAM

 exec.c             | 42 +++++++++++++++++++++++++++++++++++++++---
 util/oslib-posix.c | 20 ++++++++++++++------
 2 files changed, 53 insertions(+), 9 deletions(-)

-- 
MST

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH RFC 1/3] oslib: rework anonimous RAM allocation
  2015-09-10 14:20 [Qemu-devel] [PATCH RFC 0/3] add mitigation against buffer overflows Michael S. Tsirkin
@ 2015-09-10 14:20 ` Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 2/3] oslib: allocate PROT_NONE pages on top of RAM Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 3/3] exec: " Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2015-09-10 14:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Peter Maydell, Michael Tokarev, pbonzini

At the moment we first allocate RAM, sometimes more than necessary for
alignment reasons.  We then free the extra RAM.

Rework this to avoid the temporary allocation: reserve the
range by mapping it with PROT_NONE, then use just the
necessary range with MAP_FIXED.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 util/oslib-posix.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 3ae4987..27972d4 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -129,9 +129,9 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
 {
     size_t align = QEMU_VMALLOC_ALIGN;
     size_t total = size + align - getpagesize();
-    void *ptr = mmap(0, total, PROT_READ | PROT_WRITE,
-                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+    void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
+    void *ptr1;
 
     if (ptr == MAP_FAILED) {
         return NULL;
@@ -140,6 +140,14 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
     if (alignment) {
         *alignment = align;
     }
+
+    ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE,
+                MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+    if (ptr1 == MAP_FAILED) {
+        munmap(ptr, total);
+        return NULL;
+    }
+
     ptr += offset;
     total -= offset;
 
-- 
MST

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH RFC 2/3] oslib: allocate PROT_NONE pages on top of RAM
  2015-09-10 14:20 [Qemu-devel] [PATCH RFC 0/3] add mitigation against buffer overflows Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 1/3] oslib: rework anonimous RAM allocation Michael S. Tsirkin
@ 2015-09-10 14:20 ` Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 3/3] exec: " Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2015-09-10 14:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Peter Maydell, Michael Tokarev, pbonzini

This inserts a read and write protected page between RAM and QEMU
memory. This makes it harder to exploit QEMU bugs resulting from buffer
overflows in devices using variants of cpu_physical_memory_map,
dma_memory_map etc.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 util/oslib-posix.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 27972d4..a0fcdc2 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -128,7 +128,7 @@ void *qemu_memalign(size_t alignment, size_t size)
 void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
 {
     size_t align = QEMU_VMALLOC_ALIGN;
-    size_t total = size + align - getpagesize();
+    size_t total = size + align;
     void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
     void *ptr1;
@@ -154,8 +154,8 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
     if (offset > 0) {
         munmap(ptr - offset, offset);
     }
-    if (total > size) {
-        munmap(ptr + size, total - size);
+    if (total > size + getpagesize()) {
+        munmap(ptr + size + getpagesize(), total - size - getpagesize());
     }
 
     trace_qemu_anon_ram_alloc(size, ptr);
@@ -172,7 +172,7 @@ void qemu_anon_ram_free(void *ptr, size_t size)
 {
     trace_qemu_anon_ram_free(ptr, size);
     if (ptr) {
-        munmap(ptr, size);
+        munmap(ptr, size + getpagesize());
     }
 }
 
-- 
MST

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH RFC 3/3] exec: allocate PROT_NONE pages on top of RAM
  2015-09-10 14:20 [Qemu-devel] [PATCH RFC 0/3] add mitigation against buffer overflows Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 1/3] oslib: rework anonimous RAM allocation Michael S. Tsirkin
  2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 2/3] oslib: allocate PROT_NONE pages on top of RAM Michael S. Tsirkin
@ 2015-09-10 14:20 ` Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2015-09-10 14:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, Peter Maydell

This inserts a read and write protected page between RAM and QEMU
memory, for file-backend RAM.
This makes it harder to exploit QEMU bugs resulting from buffer
overflows in devices using variants of cpu_physical_memory_map,
dma_memory_map etc.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---

This patch is untested yet - it also creates some code duplication
with qemu_anon_ram_alloc, which needs to be cleaned up.

 exec.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/exec.c b/exec.c
index 31d2dc7..ae31296 100644
--- a/exec.c
+++ b/exec.c
@@ -85,6 +85,9 @@ static MemoryRegion io_mem_unassigned;
  */
 #define RAM_RESIZEABLE (1 << 2)
 
+/* An extra page is mapped on top of this RAM.
+ */
+#define RAM_EXTRA (1 << 3)
 #endif
 
 struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
@@ -1164,10 +1167,13 @@ static void *file_ram_alloc(RAMBlock *block,
     char *filename;
     char *sanitized_name;
     char *c;
+    void *ptr;
     void *area = NULL;
     int fd;
     uint64_t hpagesize;
+    uint64_t total;
     Error *local_err = NULL;
+    size_t offset;
 
     hpagesize = gethugepagesize(path, &local_err);
     if (local_err) {
@@ -1211,6 +1217,7 @@ static void *file_ram_alloc(RAMBlock *block,
     g_free(filename);
 
     memory = ROUND_UP(memory, hpagesize);
+    total = memory + hpagesize;
 
     /*
      * ftruncate is not supported by hugetlbfs in older
@@ -1222,16 +1229,40 @@ static void *file_ram_alloc(RAMBlock *block,
         perror("ftruncate");
     }
 
-    area = mmap(0, memory, PROT_READ | PROT_WRITE,
-                (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE),
+    ptr = mmap(0, total, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+                -1, 0);
+    if (ptr == MAP_FAILED) {
+        error_setg_errno(errp, errno,
+                         "unable to allocate memory range for hugepages");
+        close(fd);
+        goto error;
+    }
+
+    offset = QEMU_ALIGN_UP((uintptr_t)ptr, hpagesize) - (uintptr_t)ptr;
+
+    area = mmap(ptr + offset, memory, PROT_READ | PROT_WRITE,
+                (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE) |
+                MAP_FIXED,
                 fd, 0);
     if (area == MAP_FAILED) {
         error_setg_errno(errp, errno,
                          "unable to map backing store for hugepages");
+        munmap(ptr, total);
         close(fd);
         goto error;
     }
 
+    if (offset > 0) {
+        munmap(ptr, offset);
+    }
+    ptr += offset;
+    total -= offset;
+
+    if (total > memory + getpagesize()) {
+        munmap(ptr + memory + getpagesize(),
+               total - memory - getpagesize());
+    }
+
     if (mem_prealloc) {
         os_mem_prealloc(fd, area, memory);
     }
@@ -1549,6 +1580,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
     new_block->used_length = size;
     new_block->max_length = size;
     new_block->flags = share ? RAM_SHARED : 0;
+    new_block->flags |= RAM_EXTRA;
     new_block->host = file_ram_alloc(new_block, size,
                                      mem_path, errp);
     if (!new_block->host) {
@@ -1650,7 +1682,11 @@ static void reclaim_ramblock(RAMBlock *block)
         xen_invalidate_map_cache_entry(block->host);
 #ifndef _WIN32
     } else if (block->fd >= 0) {
-        munmap(block->host, block->max_length);
+        if (block->flags & RAM_EXTRA) {
+            munmap(block->host, block->max_length + getpagesize());
+        } else {
+            munmap(block->host, block->max_length);
+        }
         close(block->fd);
 #endif
     } else {
-- 
MST

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-09-10 14:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-10 14:20 [Qemu-devel] [PATCH RFC 0/3] add mitigation against buffer overflows Michael S. Tsirkin
2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 1/3] oslib: rework anonimous RAM allocation Michael S. Tsirkin
2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 2/3] oslib: allocate PROT_NONE pages on top of RAM Michael S. Tsirkin
2015-09-10 14:20 ` [Qemu-devel] [PATCH RFC 3/3] exec: " Michael S. Tsirkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.