Implement Windows boundary check with hardware trap (#623)
This commit is contained in:
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user