Module Name: src Committed By: christos Date: Wed May 2 15:25:13 UTC 2018
Modified Files: src/lib/libc/sys: mremap.2 Log Message: Add EXAMPLE and ERRORS section. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/lib/libc/sys/mremap.2 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/sys/mremap.2 diff -u src/lib/libc/sys/mremap.2:1.5 src/lib/libc/sys/mremap.2:1.6 --- src/lib/libc/sys/mremap.2:1.5 Sat May 6 17:34:51 2017 +++ src/lib/libc/sys/mremap.2 Wed May 2 11:25:13 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: mremap.2,v 1.5 2017/05/06 21:34:51 joerg Exp $ +.\" $NetBSD: mremap.2,v 1.6 2018/05/02 15:25:13 christos Exp $ .\" .\" Copyright (c) 2007 Thomas Klausner and Joerg Sonnenberger .\" All rights reserved. @@ -25,7 +25,7 @@ .\" SUCH DAMAGE. .\" .\" ------------------------------------------------------------ -.Dd April 28, 2017 +.Dd May 2, 2018 .Dt MREMAP 2 .Os .Sh NAME @@ -91,6 +91,127 @@ Both address ranges reference the same p returns the new address or .Dv MAP_FAILED , if the remap failed. +.Sh EXAMPLES +The following example program creates a two mappings for the same +memory range, one RW- and one R-X. +.Bd -literal +#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, -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\en", 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\en", rv); + + return EXIT_SUCCESS; +} +.Ed +.Sh ERRORS +The +.Fn mremap +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +If +.Fa oldp +or +.Fa newp +are not page aligned, or +.Fa oldsize +or +.Fa newsize +are not a multiple of the page size, or if +.Fa oldp + +.Fa oldsize +or +.Fa newp + +.Fa newsize +wrap around, or if an invalid alignment was requested in the +.Fa flags +argument, or if the request was to extend +.Fa oldp +and the extension address space either did not fit, was already occupied, +or had set permissions. +.It Bq Er ENOMEM +If there was either no space to allocate/move memory, +or if a fixed allocation was requested in the +.Fa flags +that could not be accommodated. +.It Bq Er ENOENT +If the +.Fa oldp +segmented was not already mapped. +.It Bq Er E2BIG +A request to extend +.Fa oldp +failed because of address overflow. +.El .Sh COMPATIBILITY The semantics of .Fn mremap