Implement Windows boundary check with hardware trap (#623)

This commit is contained in:
Wenyong Huang
2021-04-27 17:18:27 +08:00
committed by GitHub
parent eb29385963
commit fa5f4fe940
13 changed files with 400 additions and 63 deletions

View File

@ -43,3 +43,16 @@ os_vprintf(const char *format, va_list ap)
#endif
}
unsigned
os_getpagesize()
{
SYSTEM_INFO sys_info;
GetNativeSystemInfo(&sys_info);
return (unsigned)sys_info.dwPageSize;
}
void
os_dcache_flush(void)
{
}

View File

@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <malloc.h>
#include <Windows.h>
#ifdef __cplusplus
@ -49,13 +50,34 @@ typedef struct {
unsigned int waiting_count;
} korp_cond;
static inline size_t
getpagesize()
{
SYSTEM_INFO S;
GetNativeSystemInfo(&S);
return S.dwPageSize;
}
unsigned os_getpagesize();
void *os_mem_commit(void *ptr, size_t size, int flags);
void os_mem_decommit(void *ptr, size_t size);
#define os_thread_local_attribute __declspec(thread)
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64)
#include <setjmp.h>
#define OS_ENABLE_HW_BOUND_CHECK
typedef jmp_buf korp_jmpbuf;
#define os_setjmp setjmp
#define os_longjmp longjmp
bool os_thread_init_stack_guard_pages();
void os_thread_destroy_stack_guard_pages();
#define os_signal_unmask() (void)0
#define os_sigreturn() (void)0
#endif /* end of BUILD_TARGET_X86_64/AMD_64 */
#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
#ifdef __cplusplus
}

View File

@ -5,81 +5,133 @@
#include "platform_api_vmcore.h"
void * os_mmap(void *hint, size_t size, int prot, int flags)
#define TRACE_MEMMAP 0
static DWORD
access_to_win32_flags(int prot)
{
DWORD AllocType = MEM_RESERVE | MEM_COMMIT;
DWORD flProtect = PAGE_NOACCESS;
DWORD protect = PAGE_NOACCESS;
if (prot & MMAP_PROT_EXEC) {
if (prot & MMAP_PROT_WRITE)
protect = PAGE_EXECUTE_READWRITE;
else
protect = PAGE_EXECUTE_READ;
}
else if (prot & MMAP_PROT_WRITE) {
protect = PAGE_READWRITE;
}
else if (prot & MMAP_PROT_READ) {
protect = PAGE_READONLY;
}
return protect;
}
void *
os_mmap(void *hint, size_t size, int prot, int flags)
{
DWORD alloc_type = MEM_RESERVE;
DWORD protect;
size_t request_size, page_size;
void *addr;
page_size = getpagesize();
page_size = os_getpagesize();
request_size = (size + page_size - 1) & ~(page_size - 1);
if (request_size < size)
/* integer overflow */
return NULL;
if (request_size == 0)
request_size = page_size;
if (prot & MMAP_PROT_EXEC) {
if (prot & MMAP_PROT_WRITE)
flProtect = PAGE_EXECUTE_READWRITE;
else
flProtect = PAGE_EXECUTE_READ;
protect = access_to_win32_flags(prot);
if (protect != PAGE_NOACCESS) {
alloc_type |= MEM_COMMIT;
}
else if (prot & MMAP_PROT_WRITE)
flProtect = PAGE_READWRITE;
else if (prot & MMAP_PROT_READ)
flProtect = PAGE_READONLY;
addr = VirtualAlloc((LPVOID)hint, request_size, alloc_type, protect);
addr = VirtualAlloc((LPVOID)hint, request_size, AllocType,
flProtect);
#if TRACE_MEMMAP != 0
printf("Map memory, request_size: %zu, alloc_type: 0x%x, "
"protect: 0x%x, ret: %p\n",
request_size, alloc_type, protect, addr);
#endif
return addr;
}
void
os_munmap(void *addr, size_t size)
{
size_t page_size = getpagesize();
size_t page_size = os_getpagesize();
size_t request_size = (size + page_size - 1) & ~(page_size - 1);
if (addr) {
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
os_printf("os_munmap error addr:%p, size:0x%lx, errno:%d\n",
addr, request_size, errno);
}
if (!VirtualFree(addr, request_size, MEM_DECOMMIT)) {
printf("warning: os_munmap decommit pages failed, "
"addr: %p, request_size: %zu, errno: %d\n",
addr, request_size, errno);
return;
}
if (!VirtualFree(addr, 0, MEM_RELEASE)) {
printf("warning: os_munmap release pages failed, "
"addr: %p, size: %zu, errno:%d\n",
addr, request_size, errno);
}
}
#if TRACE_MEMMAP != 0
printf("Unmap memory, addr: %p, request_size: %zu\n",
addr, request_size);
#endif
}
void *
os_mem_commit(void *addr, size_t size, int flags)
{
DWORD protect = access_to_win32_flags(flags);
size_t page_size = os_getpagesize();
size_t request_size = (size + page_size - 1) & ~(page_size - 1);
if (!addr)
return NULL;
#if TRACE_MEMMAP != 0
printf("Commit memory, addr: %p, request_size: %zu, protect: 0x%x\n",
addr, request_size, protect);
#endif
return VirtualAlloc((LPVOID)addr, request_size, MEM_COMMIT, protect);
}
void
os_mem_decommit(void *addr, size_t size)
{
size_t page_size = os_getpagesize();
size_t request_size = (size + page_size - 1) & ~(page_size - 1);
if (!addr)
return;
#if TRACE_MEMMAP != 0
printf("Decommit memory, addr: %p, request_size: %zu\n",
addr, request_size);
#endif
VirtualFree((LPVOID)addr, request_size, MEM_DECOMMIT);
}
int
os_mprotect(void *addr, size_t size, int prot)
{
DWORD AllocType = MEM_RESERVE | MEM_COMMIT;
DWORD flProtect = PAGE_NOACCESS;
DWORD protect;
size_t page_size = os_getpagesize();
size_t request_size = (size + page_size - 1) & ~(page_size - 1);
if (!addr)
return 0;
if (prot & MMAP_PROT_EXEC) {
if (prot & MMAP_PROT_WRITE)
flProtect = PAGE_EXECUTE_READWRITE;
else
flProtect = PAGE_EXECUTE_READ;
}
else if (prot & MMAP_PROT_WRITE)
flProtect = PAGE_READWRITE;
else if (prot & MMAP_PROT_READ)
flProtect = PAGE_READONLY;
return VirtualProtect((LPVOID)addr, size, flProtect, NULL);
protect = access_to_win32_flags(prot);
#if TRACE_MEMMAP != 0
printf("Mprotect memory, addr: %p, request_size: %zu, protect: 0x%x\n",
addr, request_size, protect);
#endif
return VirtualProtect((LPVOID)addr, request_size, protect, NULL);
}
void
os_dcache_flush(void)
{
}

View File

@ -149,7 +149,32 @@ void os_thread_exit(void *retval)
{
}
static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
uint8 *os_thread_get_stack_boundary()
{
return NULL;
ULONG_PTR low_limit = 0, high_limit = 0;
uint32 page_size;
if (thread_stack_boundary)
return thread_stack_boundary;
page_size = os_getpagesize();
GetCurrentThreadStackLimits(&low_limit, &high_limit);
/* 4 pages are set unaccessible by system, we reserved
one more page at least for safety */
thread_stack_boundary = (uint8*)(uintptr_t)low_limit + page_size * 5;
return thread_stack_boundary;
}
bool
os_thread_init_stack_guard_pages()
{
return true;
}
void
os_thread_destroy_stack_guard_pages()
{
}