| 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_FIXEDmremap()
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_REMAPDUPmremap() 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 |