diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/cacheflush.c | 71 | ||||
-rw-r--r-- | util/main-loop.c | 11 | ||||
-rw-r--r-- | util/meson.build | 2 | ||||
-rw-r--r-- | util/oslib-posix.c | 11 | ||||
-rw-r--r-- | util/oslib-win32.c | 1 |
5 files changed, 94 insertions, 2 deletions
diff --git a/util/cacheflush.c b/util/cacheflush.c new file mode 100644 index 0000000000..2881832a38 --- /dev/null +++ b/util/cacheflush.c @@ -0,0 +1,71 @@ +/* + * Flush the host cpu caches. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/cacheflush.h" + + +#if defined(__i386__) || defined(__x86_64__) || defined(__s390__) + +/* Caches are coherent and do not require flushing; symbol inline. */ + +#elif defined(__mips__) + +#ifdef __OpenBSD__ +#include <machine/sysarch.h> +#else +#include <sys/cachectl.h> +#endif + +void flush_icache_range(uintptr_t start, uintptr_t stop) +{ + cacheflush((void *)start, stop - start, ICACHE); +} + +#elif defined(__powerpc__) + +void flush_icache_range(uintptr_t start, uintptr_t stop) +{ + uintptr_t p, start1, stop1; + size_t dsize = qemu_dcache_linesize; + size_t isize = qemu_icache_linesize; + + start1 = start & ~(dsize - 1); + stop1 = (stop + dsize - 1) & ~(dsize - 1); + for (p = start1; p < stop1; p += dsize) { + asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); + } + asm volatile ("sync" : : : "memory"); + + start &= start & ~(isize - 1); + stop1 = (stop + isize - 1) & ~(isize - 1); + for (p = start1; p < stop1; p += isize) { + asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); + } + asm volatile ("sync" : : : "memory"); + asm volatile ("isync" : : : "memory"); +} + +#elif defined(__sparc__) + +void flush_icache_range(uintptr_t start, uintptr_t stop) +{ + uintptr_t p; + + for (p = start & -8; p < ((stop + 7) & -8); p += 8) { + __asm__ __volatile__("flush\t%0" : : "r" (p)); + } +} + +#else + +void flush_icache_range(uintptr_t start, uintptr_t stop) +{ + __builtin___clear_cache((char *)start, (char *)stop); +} + +#endif diff --git a/util/main-loop.c b/util/main-loop.c index 6470f8eae3..6bfc7c46f5 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -33,6 +33,7 @@ #include "block/aio.h" #include "qemu/error-report.h" #include "qemu/queue.h" +#include "qemu/compiler.h" #ifndef _WIN32 #include <sys/wait.h> @@ -44,6 +45,16 @@ * use signalfd to listen for them. We rely on whatever the current signal * handler is to dispatch the signals when we receive them. */ +/* + * Disable CFI checks. + * We are going to call a signal hander directly. Such handler may or may not + * have been defined in our binary, so there's no guarantee that the pointer + * used to set the handler is a cfi-valid pointer. Since the handlers are + * stored in kernel memory, changing the handler to an attacker-defined + * function requires being able to call a sigaction() syscall, + * which is not as easy as overwriting a pointer in memory. + */ +QEMU_DISABLE_CFI static void sigfd_handler(void *opaque) { int fd = (intptr_t)opaque; diff --git a/util/meson.build b/util/meson.build index f359af0d46..a3dfc0f966 100644 --- a/util/meson.build +++ b/util/meson.build @@ -21,7 +21,7 @@ util_ss.add(files('envlist.c', 'path.c', 'module.c')) util_ss.add(files('host-utils.c')) util_ss.add(files('bitmap.c', 'bitops.c')) util_ss.add(files('fifo8.c')) -util_ss.add(files('cacheinfo.c')) +util_ss.add(files('cacheinfo.c', 'cacheflush.c')) util_ss.add(files('error.c', 'qemu-error.c')) util_ss.add(files('qemu-print.c')) util_ss.add(files('id.c')) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index f15234b5c0..f1e2801b11 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -39,6 +39,7 @@ #include "qemu/thread.h" #include <libgen.h> #include "qemu/cutils.h" +#include "qemu/compiler.h" #ifdef CONFIG_LINUX #include <sys/syscall.h> @@ -773,6 +774,16 @@ void qemu_free_stack(void *stack, size_t sz) munmap(stack, sz); } +/* + * Disable CFI checks. + * We are going to call a signal hander directly. Such handler may or may not + * have been defined in our binary, so there's no guarantee that the pointer + * used to set the handler is a cfi-valid pointer. Since the handlers are + * stored in kernel memory, changing the handler to an attacker-defined + * function requires being able to call a sigaction() syscall, + * which is not as easy as overwriting a pointer in memory. + */ +QEMU_DISABLE_CFI void sigaction_invoke(struct sigaction *action, struct qemu_signalfd_siginfo *info) { diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 23a7c7320b..01787df74c 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -221,7 +221,6 @@ int qemu_try_set_nonblock(int fd) if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) { return -socket_error(); } - qemu_fd_register(fd); return 0; } |