From aab38443b7e5a84e26fe417a55047e02a0f66a29 Mon Sep 17 00:00:00 2001 From: Catherine Date: Tue, 21 May 2024 01:31:05 +0000 Subject: [PATCH] Extend wasi-emulated-mman with `mprotect`. 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 | 39 +++++++++++++++++++ 4 files changed, 42 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..289a05686 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,41 @@ 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 0. + if (length == 0) { + errno = ENOMEM; + return -1; + } + + // Length must not be big enough to wrap around. + size_t end; + if (__builtin_add_overflow(begin, length - 1, &end)) { + errno = ENOMEM; + return -1; + } + + // Range must be in bounds of linear memory. + size_t memory_size = __builtin_wasm_memory_size(0) * PAGESIZE; + if ((begin >= memory_size) || (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 = EINVAL; + return -1; + } + + // Success! + return 0; +}