Commit 17e2377abf16c3951d7d34521ceade4d7dc31d01

Authored by pbrook
1 parent 82e671d9

Prevent guest reusing host memory allocations.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4710 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -39,7 +39,7 @@ recurse-all: $(SUBDIR_RULES)
39 39 #######################################################################
40 40 # BLOCK_OBJS is code used by both qemu system emulation and qemu-img
41 41  
42   -BLOCK_OBJS=cutils.o
  42 +BLOCK_OBJS=cutils.o qemu-malloc.o
43 43 BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
44 44 BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
45 45 BLOCK_OBJS+=block-qcow2.o block-parallels.o
... ...
Makefile.target
... ... @@ -387,7 +387,7 @@ LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
387 387 endif
388 388 endif
389 389  
390   -OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \
  390 +OBJS= main.o syscall.o strace.o mmap.o signal.o path.o thunk.o \
391 391 elfload.o linuxload.o uaccess.o
392 392 LIBS+= $(AIOLIBS)
393 393 ifdef TARGET_HAS_BFLT
... ... @@ -444,7 +444,7 @@ LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
444 444  
445 445 LIBS+=-lmx
446 446  
447   -OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
  447 +OBJS= main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o
448 448  
449 449 OBJS+= libqemu.a
450 450  
... ...
cutils.c
... ... @@ -95,38 +95,3 @@ time_t mktimegm(struct tm *tm)
95 95 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
96 96 return t;
97 97 }
98   -
99   -void *get_mmap_addr(unsigned long size)
100   -{
101   - return NULL;
102   -}
103   -
104   -void qemu_free(void *ptr)
105   -{
106   - free(ptr);
107   -}
108   -
109   -void *qemu_malloc(size_t size)
110   -{
111   - return malloc(size);
112   -}
113   -
114   -void *qemu_mallocz(size_t size)
115   -{
116   - void *ptr;
117   - ptr = qemu_malloc(size);
118   - if (!ptr)
119   - return NULL;
120   - memset(ptr, 0, size);
121   - return ptr;
122   -}
123   -
124   -char *qemu_strdup(const char *str)
125   -{
126   - char *ptr;
127   - ptr = qemu_malloc(strlen(str) + 1);
128   - if (!ptr)
129   - return NULL;
130   - strcpy(ptr, str);
131   - return ptr;
132   -}
... ...
... ... @@ -263,13 +263,33 @@ static inline PageDesc *page_find_alloc(target_ulong index)
263 263 {
264 264 PageDesc **lp, *p;
265 265  
  266 +#if TARGET_LONG_BITS > 32
  267 + /* Host memory outside guest VM. For 32-bit targets we have already
  268 + excluded high addresses. */
  269 + if (index > ((target_ulong)L2_SIZE * L1_SIZE * TARGET_PAGE_SIZE))
  270 + return NULL;
  271 +#endif
266 272 lp = &l1_map[index >> L2_BITS];
267 273 p = *lp;
268 274 if (!p) {
269 275 /* allocate if not found */
270   - p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
271   - memset(p, 0, sizeof(PageDesc) * L2_SIZE);
  276 +#if defined(CONFIG_USER_ONLY)
  277 + unsigned long addr;
  278 + size_t len = sizeof(PageDesc) * L2_SIZE;
  279 + /* Don't use qemu_malloc because it may recurse. */
  280 + p = mmap(0, len, PROT_READ | PROT_WRITE,
  281 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  282 + *lp = p;
  283 + addr = h2g(p);
  284 + if (addr == (target_ulong)addr) {
  285 + page_set_flags(addr & TARGET_PAGE_MASK,
  286 + TARGET_PAGE_ALIGN(addr + len),
  287 + PAGE_RESERVED);
  288 + }
  289 +#else
  290 + p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
272 291 *lp = p;
  292 +#endif
273 293 }
274 294 return p + (index & (L2_SIZE - 1));
275 295 }
... ... @@ -1912,6 +1932,10 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
1912 1932 flags |= PAGE_WRITE_ORG;
1913 1933 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1914 1934 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
  1935 + /* We may be called for host regions that are outside guest
  1936 + address space. */
  1937 + if (!p)
  1938 + return;
1915 1939 /* if the write protection is set, then we invalidate the code
1916 1940 inside */
1917 1941 if (!(p->flags & PAGE_WRITE) &&
... ...
linux-user/mmap.c
... ... @@ -73,6 +73,52 @@ void mmap_unlock(void)
73 73 }
74 74 #endif
75 75  
  76 +void *qemu_vmalloc(size_t size)
  77 +{
  78 + void *p;
  79 + unsigned long addr;
  80 + mmap_lock();
  81 + /* Use map and mark the pages as used. */
  82 + p = mmap(NULL, size, PROT_READ | PROT_WRITE,
  83 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  84 +
  85 + addr = (unsigned long)p;
  86 + if (addr == (target_ulong) addr) {
  87 + /* Allocated region overlaps guest address space.
  88 + This may recurse. */
  89 + page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size),
  90 + PAGE_RESERVED);
  91 + }
  92 +
  93 + mmap_unlock();
  94 + return p;
  95 +}
  96 +
  97 +void *qemu_malloc(size_t size)
  98 +{
  99 + char * p;
  100 + size += 16;
  101 + p = qemu_vmalloc(size);
  102 + *(size_t *)p = size;
  103 + return p + 16;
  104 +}
  105 +
  106 +/* We use map, which is always zero initialized. */
  107 +void * qemu_mallocz(size_t size)
  108 +{
  109 + return qemu_malloc(size);
  110 +}
  111 +
  112 +void qemu_free(void *ptr)
  113 +{
  114 + /* FIXME: We should unmark the reserved pages here. However this gets
  115 + complicated when one target page spans multiple host pages, so we
  116 + don't bother. */
  117 + size_t *p;
  118 + p = (size_t *)((char *)ptr - 16);
  119 + munmap(p, *p);
  120 +}
  121 +
76 122 /* NOTE: all the constants are the HOST ones, but addresses are target. */
77 123 int target_mprotect(abi_ulong start, abi_ulong len, int prot)
78 124 {
... ...
qemu-malloc.c 0 → 100644
  1 +/*
  2 + * malloc-like functions for system emulation.
  3 + *
  4 + * Copyright (c) 2006 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "qemu-common.h"
  25 +
  26 +void *get_mmap_addr(unsigned long size)
  27 +{
  28 + return NULL;
  29 +}
  30 +
  31 +void qemu_free(void *ptr)
  32 +{
  33 + free(ptr);
  34 +}
  35 +
  36 +void *qemu_malloc(size_t size)
  37 +{
  38 + return malloc(size);
  39 +}
  40 +
  41 +void *qemu_mallocz(size_t size)
  42 +{
  43 + void *ptr;
  44 + ptr = qemu_malloc(size);
  45 + if (!ptr)
  46 + return NULL;
  47 + memset(ptr, 0, size);
  48 + return ptr;
  49 +}
  50 +
  51 +char *qemu_strdup(const char *str)
  52 +{
  53 + char *ptr;
  54 + ptr = qemu_malloc(strlen(str) + 1);
  55 + if (!ptr)
  56 + return NULL;
  57 + strcpy(ptr, str);
  58 + return ptr;
  59 +}
... ...