| 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.0 |