Skip to content

Commit

Permalink
Extend wasi-emulated-mman with mprotect.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
whitequark committed May 21, 2024
1 parent 9e8c542 commit b55e3e8
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 0 deletions.
1 change: 1 addition & 0 deletions expected/wasm32-wasip1-threads/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,7 @@ mmap
modf
modff
modfl
mprotect
mrand48
munmap
nan
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasip1/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,7 @@ mmap
modf
modff
modfl
mprotect
mrand48
munmap
nan
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasip2/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,7 @@ monotonic_clock_now
monotonic_clock_resolution
monotonic_clock_subscribe_duration
monotonic_clock_subscribe_instant
mprotect
mrand48
munmap
nan
Expand Down
39 changes: 39 additions & 0 deletions libc-bottom-half/mman/mman.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/types.h>

Expand Down Expand Up @@ -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;
}

0 comments on commit b55e3e8

Please sign in to comment.