From 7528b13170462c82e367d91ae0ecead84e470ceb Mon Sep 17 00:00:00 2001 From: Catherine Date: Wed, 22 May 2024 18:09:22 +0100 Subject: [PATCH] Extend wasi-emulated-mman with `mprotect`. (#500) This implementation never changes actual memory protection, but it does verify that the address range and flags are valid. The direct motivation is fixing a linker error where LLVM links to `mprotect` in dead code. --- .../wasm32-wasip1-threads/defined-symbols.txt | 1 + expected/wasm32-wasip1/defined-symbols.txt | 1 + expected/wasm32-wasip2/defined-symbols.txt | 1 + libc-bottom-half/mman/mman.c | 33 +++++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/expected/wasm32-wasip1-threads/defined-symbols.txt b/expected/wasm32-wasip1-threads/defined-symbols.txt index ea52ecc7a..730648fe3 100644 --- a/expected/wasm32-wasip1-threads/defined-symbols.txt +++ b/expected/wasm32-wasip1-threads/defined-symbols.txt @@ -928,6 +928,7 @@ mmap modf modff modfl +mprotect mrand48 munmap nan diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 61ee95bb7..694e58cc9 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -861,6 +861,7 @@ mmap modf modff modfl +mprotect mrand48 munmap nan diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 4501921a1..2c3ba4207 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -980,6 +980,7 @@ monotonic_clock_now monotonic_clock_resolution monotonic_clock_subscribe_duration monotonic_clock_subscribe_instant +mprotect mrand48 munmap nan diff --git a/libc-bottom-half/mman/mman.c b/libc-bottom-half/mman/mman.c index f02b136cd..6f672e289 100644 --- a/libc-bottom-half/mman/mman.c +++ b/libc-bottom-half/mman/mman.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -122,3 +123,35 @@ int munmap(void *addr, size_t length) { // Success! return 0; } + +int mprotect(void *addr, size_t length, int prot) { + // Address must be page-aligned. + size_t begin = (size_t)addr; + if ((begin & (PAGESIZE - 1)) != 0) { + errno = EINVAL; + return -1; + } + + // Length must not be big enough to wrap around. + size_t end; + if (__builtin_add_overflow(begin, length, &end)) { + errno = ENOMEM; + return -1; + } + + // Range must be in bounds of linear memory. + size_t memory_size = __builtin_wasm_memory_size(0) * PAGESIZE; + if (end > memory_size) { + errno = ENOMEM; + return -1; + } + + // Can only protect memory as read/write (which is a no-op). + if (prot != (PROT_READ | PROT_WRITE)) { + errno = ENOTSUP; + return -1; + } + + // Success! + return 0; +}