| MREMAP(2) | System Calls Manual | MREMAP(2) |
mremap — re-map a
virtual memory address
Standard C Library (libc, -lc)
#include
<sys/mman.h>
void *
mremap(void
*oldp, size_t
oldsize, void
*newp, size_t
newsize, int
flags);
The
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.
The following example program creates a two mappings for the same memory range, one RW- and one R-X.
#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;
}
The semantics of 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.
The mremap() function fails if:
E2BIG]EINVAL]ENOENT]ENOMEM]The mremap() system call appeared in
NetBSD 5.0. It was based on the code that supports
mremap() compatibility for Linux binaries.
If a mapping is created by
mmap(2) with
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 PR lib/55177 for details.
| May 2, 2018 | NetBSD 11.0 |