xref: /netbsd-src/lib/libc/sys/mremap.2 (revision 91811c4fb2110559685e3090399e1a1a23339712)
1.\"	$NetBSD: mremap.2,v 1.10 2023/10/25 18:23:10 riastradh Exp $
2.\"
3.\" Copyright (c) 2007 Thomas Klausner and Joerg Sonnenberger
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE
19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25.\" SUCH DAMAGE.
26.\"
27.\" ------------------------------------------------------------
28.Dd May 2, 2018
29.Dt MREMAP 2
30.Os
31.Sh NAME
32.Nm mremap
33.Nd re-map a virtual memory address
34.\" ------------------------------------------------------------
35.Sh LIBRARY
36.Lb libc
37.Sh SYNOPSIS
38.In sys/mman.h
39.Ft void *
40.Fn mremap "void *oldp" "size_t oldsize" "void *newp" "size_t newsize" \
41"int flags"
42.\" ------------------------------------------------------------
43.Sh DESCRIPTION
44The
45.Fn mremap
46function resizes the mapped range (see
47.Xr mmap 2 )
48starting at
49.Ar oldp
50and having size
51.Ar oldsize
52to
53.Ar newsize .
54The following arguments can be
55.Dv OR Ap ed
56together in the
57.Ar flags
58argument:
59.Bl -tag -width XXMAPXALIGNEDXnXX
60.It Dv MAP_ALIGNED Ns Pq Ar n
61The allocation should be aligned to the given boundary, i.e. ensure
62that the lowest
63.Ar n
64bits of the address are zero.
65The parameter
66.Ar n
67should be the base 2 logarithm of the desired alignment (e.g., to
68request alignment to 16K, use 14 as the value for n).
69The alignment must be equal to or greater than the platform's page
70size as returned by
71.Xr sysconf 3
72with the
73.Dv _SC_PAGESIZE
74request.
75.It Dv MAP_FIXED
76.Ar newp
77is tried and
78.Fn mremap
79fails if that address can't be used as new base address for the range.
80Otherwise,
81.Ar oldp
82and
83.Ar newp
84are used as hints for the position, factoring in the given alignment.
85.It Dv MAP_REMAPDUP
86Duplicate the mapping.
87Both address ranges reference the same pages, but can have different protection flags.
88.El
89.Sh RETURN VALUES
90.Fn mremap
91returns the new address or
92.Dv MAP_FAILED ,
93if the remap failed.
94.Sh EXAMPLES
95The following example program creates a two mappings for the same
96memory range, one RW- and one R-X.
97.Bd -literal
98#include <sys/types.h>
99#include <sys/mman.h>
100
101#include <stdio.h>
102#include <string.h>
103#include <unistd.h>
104#include <stdlib.h>
105#include <err.h>
106
107static int
108return_1(void)
109{
110	return 1;
111}
112
113static void
114return_1_end(void)
115{
116}
117
118static int
119return_2(void)
120{
121	return 2;
122}
123
124static void
125return_2_end(void)
126{
127}
128
129int
130main(int argc, char *argv[])
131{
132        void *maprw, *maprx;
133	int rv;
134	size_t page = (size_t)sysconf(_SC_PAGESIZE);
135
136	// Create the first mapping that has no protections, but intended
137	// protections only
138	maprw = mmap(NULL, page,
139	    PROT_MPROTECT(PROT_EXEC|PROT_WRITE|PROT_READ),
140            MAP_ANON|MAP_PRIVATE, -1, 0);
141	if (maprw == MAP_FAILED)
142		err(EXIT_FAILURE, "mmap failed");
143
144        // Create the second mapping for the same physical space, which
145	// again has no protections.
146	maprx = mremap(maprw, page, NULL, page, MAP_REMAPDUP);
147	if (maprx == MAP_FAILED)
148		err(EXIT_FAILURE, "mremap failed");
149
150	// Set the first mapping read/write
151        if (mprotect(maprw, page, PROT_READ|PROT_WRITE) == -1)
152		err(EXIT_FAILURE, "mprotect(rw) failed");
153
154	// Set the second mapping read/execute
155        if (mprotect(maprx, page, PROT_READ|PROT_EXEC) == -1)
156		err(EXIT_FAILURE, "mprotect(rx) failed");
157
158#define XS(a) (size_t)((uintptr_t)(a ## _end) - (uintptr_t)(a))
159
160	// Copy and run the first function
161	memcpy(maprw, return_1, XS(return_1));
162	__builtin___clear_cache(maprw, (void *)((uintptr_t)maprw + page));
163	rv = ((int (*)(void))maprx)();
164	printf("%d\en", rv);
165
166	// Copy and run the second function
167	memcpy(maprw, return_2, XS(return_2));
168	__builtin___clear_cache(maprw, (void *)((uintptr_t)maprw + page));
169	rv = ((int (*)(void))maprx)();
170	printf("%d\en", rv);
171
172	return EXIT_SUCCESS;
173}
174.Ed
175.Sh COMPATIBILITY
176The semantics of
177.Fn mremap
178differ from the one provided by glibc on Linux in that the
179.Ar newp
180argument was added and a different set of
181.Ar flags
182are implemented.
183.Sh ERRORS
184The
185.Fn mremap
186function fails if:
187.Bl -tag -width Er
188.It Bq Er E2BIG
189A request to extend
190.Fa oldp
191failed because of address overflow.
192.It Bq Er EINVAL
193If
194.Fa oldp
195or
196.Fa newp
197are not page aligned, or
198.Fa oldsize
199or
200.Fa newsize
201are not a multiple of the page size, or if
202.Fa oldp +
203.Fa oldsize
204or
205.Fa newp +
206.Fa newsize
207wrap around, or if an invalid alignment was requested in the
208.Fa flags
209argument, or if the request was to extend
210.Fa oldp
211and the extension address space either did not fit, was already occupied,
212or had set permissions.
213.It Bq Er ENOENT
214If the
215.Fa oldp
216segmented was not already mapped.
217.It Bq Er ENOMEM
218If there was either no space to allocate/move memory,
219or if a fixed allocation was requested in the
220.Fa flags
221that could not be accommodated.
222.El
223.Sh SEE ALSO
224.Xr mmap 2 ,
225.Xr munmap 2
226.Sh HISTORY
227The
228.Fn mremap
229system call appeared in
230.Nx 5.0 .
231It was based on the code that supports
232.Fn mremap
233compatibility for Linux binaries.
234.Sh BUGS
235If a mapping is created by
236.Xr mmap 2
237with
238.Dv MAP_PRIVATE
239and then duplicated by
240.Nm
241with
242.Dv MAP_REMAPDUP ,
243calling
244.Xr fork 2
245destroys the coupling between the original and duplicate mapping.
246Workarounds:
247.Bl -dash
248.It
249Create the original mapping with
250.Dv MAP_SHARED .
251.It
252Use
253.Xr minherit 2
254with
255.Dv MAP_INHERIT_NONE
256on the writable mapping.
257.It
258Don't use
259.Xr fork 2 ;
260use
261.Xr posix_spawn 2 .
262.El
263.Pp
264See
265.Lk https://gnats.NetBSD.org/55177 "PR lib/55177"
266for details.
267