MREMAP(2) | System Calls Manual | MREMAP(2) |
mremap
—
#include <sys/mman.h>
void *
mremap
(void
*oldp, size_t
oldsize, void
*newp, size_t
newsize, int
flags);
mremap
() function resizes the mapped range (see
mmap(2)) starting at
oldp and having size oldsize to
newsize. The following arguments can be
OR
'ed together in the flags
argument:
MAP_ALIGNED
(n)_SC_PAGESIZE
request.MAP_FIXED
mremap
()
fails if that address can't be used as new base address for the range.
Otherwise, oldp and newp are
used as hints for the position, factoring in the given alignment.MAP_REMAPDUP
mremap
() returns the new address or
MAP_FAILED
, if the remap failed.
#include <sys/types.h> #include <sys/mman.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <err.h> static int return_1(void) { return 1; } static void return_1_end(void) { } static int return_2(void) { return 2; } static void return_2_end(void) { } int main(int argc, char *argv[]) { void *maprw, *maprx; int rv; size_t page = (size_t)sysconf(_SC_PAGESIZE); // Create the first mapping that has no protections, but intended // protections only maprw = mmap(NULL, page, PROT_MPROTECT(PROT_EXEC|PROT_WRITE|PROT_READ), MAP_ANON|MAP_PRIVATE, -1, 0); if (maprw == MAP_FAILED) err(EXIT_FAILURE, "mmap failed"); // Create the second mapping for the same physical space, which // again has no protections. maprx = mremap(maprw, page, NULL, page, MAP_REMAPDUP); if (maprx == MAP_FAILED) err(EXIT_FAILURE, "mremap failed"); // Set the first mapping read/write if (mprotect(maprw, page, PROT_READ|PROT_WRITE) == -1) err(EXIT_FAILURE, "mprotect(rw) failed"); // Set the second mapping read/execute if (mprotect(maprx, page, PROT_READ|PROT_EXEC) == -1) err(EXIT_FAILURE, "mprotect(rx) failed"); #define XS(a) (size_t)((uintptr_t)(a ## _end) - (uintptr_t)(a)) // Copy and run the first function memcpy(maprw, return_1, XS(return_1)); __builtin___clear_cache(maprw, (void *)((uintptr_t)maprw + page)); rv = ((int (*)(void))maprx)(); printf("%d\n", rv); // Copy and run the second function memcpy(maprw, return_2, XS(return_2)); __builtin___clear_cache(maprw, (void *)((uintptr_t)maprw + page)); rv = ((int (*)(void))maprx)(); printf("%d\n", rv); return EXIT_SUCCESS; }
mremap
() differ from the one provided
by glibc on Linux in that the newp argument was added
and a different set of flags are implemented.
mremap
() function fails if:
E2BIG
]EINVAL
]ENOENT
]ENOMEM
]mremap
() system call appeared in
NetBSD 5.0. It was based on the code that supports
mremap
() compatibility for Linux binaries.
MAP_PRIVATE
and then duplicated by
mremap
with MAP_REMAPDUP
,
calling fork(2) destroys the
coupling between the original and duplicate mapping. Workarounds:
MAP_SHARED
.MAP_INHERIT_NONE
on the writable mapping.See https://gnats.NetBSD.org/55177 for details.
May 2, 2018 | NetBSD 10.1 |