1 //! The `mmap` API.
2 //!
3 //! # Safety
4 //!
5 //! `mmap` and related functions manipulate raw pointers and have special
6 //! semantics and are wildly unsafe.
7 #![allow(unsafe_code)]
8
9 use crate::{backend, io};
10 use backend::fd::AsFd;
11 use core::ffi::c_void;
12
13 #[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
14 pub use backend::mm::types::MlockAllFlags;
15 #[cfg(linux_kernel)]
16 pub use backend::mm::types::MlockFlags;
17 #[cfg(any(target_os = "emscripten", target_os = "linux"))]
18 pub use backend::mm::types::MremapFlags;
19 pub use backend::mm::types::{MapFlags, MprotectFlags, ProtFlags};
20
21 impl MapFlags {
22 /// Create `MAP_HUGETLB` with provided size of huge page.
23 ///
24 /// Under the hood it computes
25 /// `MAP_HUGETLB | (huge_page_size_log2 << MAP_HUGE_SHIFT)`.
26 /// `huge_page_size_log2` denotes logarithm of huge page size to use and
27 /// should be between 16 and 63 (inclusive).
28 ///
29 /// ```
30 /// use rustix::mm::MapFlags;
31 ///
32 /// let f = MapFlags::hugetlb_with_size_log2(30).unwrap();
33 /// assert_eq!(f, MapFlags::HUGETLB | MapFlags::HUGE_1GB);
34 /// ```
35 #[cfg(feature = "linux-raw-sys")]
hugetlb_with_size_log2(huge_page_size_log2: u32) -> Option<Self>36 pub const fn hugetlb_with_size_log2(huge_page_size_log2: u32) -> Option<Self> {
37 use linux_raw_sys::general::{MAP_HUGETLB, MAP_HUGE_SHIFT};
38 if 16 <= huge_page_size_log2 && huge_page_size_log2 <= 63 {
39 let bits = MAP_HUGETLB | (huge_page_size_log2 << MAP_HUGE_SHIFT);
40 Self::from_bits(bits)
41 } else {
42 None
43 }
44 }
45 }
46
47 /// `mmap(ptr, len, prot, flags, fd, offset)`—Create a file-backed memory
48 /// mapping.
49 ///
50 /// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see
51 /// [`mmap_anonymous`].
52 ///
53 /// # Safety
54 ///
55 /// Raw pointers and lots of special semantics.
56 ///
57 /// # References
58 /// - [POSIX]
59 /// - [Linux]
60 /// - [Apple]
61 /// - [FreeBSD]
62 /// - [NetBSD]
63 /// - [OpenBSD]
64 /// - [DragonFly BSD]
65 /// - [illumos]
66 /// - [glibc]
67 ///
68 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
69 /// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
70 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mmap.2.html
71 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mmap&sektion=2
72 /// [NetBSD]: https://man.netbsd.org/mmap.2
73 /// [OpenBSD]: https://man.openbsd.org/mmap.2
74 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mmap§ion=2
75 /// [illumos]: https://illumos.org/man/2/mmap
76 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-mmap
77 #[inline]
mmap<Fd: AsFd>( ptr: *mut c_void, len: usize, prot: ProtFlags, flags: MapFlags, fd: Fd, offset: u64, ) -> io::Result<*mut c_void>78 pub unsafe fn mmap<Fd: AsFd>(
79 ptr: *mut c_void,
80 len: usize,
81 prot: ProtFlags,
82 flags: MapFlags,
83 fd: Fd,
84 offset: u64,
85 ) -> io::Result<*mut c_void> {
86 backend::mm::syscalls::mmap(ptr, len, prot, flags, fd.as_fd(), offset)
87 }
88
89 /// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`—Create an anonymous
90 /// memory mapping.
91 ///
92 /// For file-backed mappings, see [`mmap`].
93 ///
94 /// # Safety
95 ///
96 /// Raw pointers and lots of special semantics.
97 ///
98 /// # References
99 /// - [POSIX]
100 /// - [Linux]
101 /// - [Apple]
102 /// - [FreeBSD]
103 /// - [NetBSD]
104 /// - [OpenBSD]
105 /// - [DragonFly BSD]
106 /// - [illumos]
107 /// - [glibc]
108 ///
109 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
110 /// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
111 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mmap.2.html
112 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mmap&sektion=2
113 /// [NetBSD]: https://man.netbsd.org/mmap.2
114 /// [OpenBSD]: https://man.openbsd.org/mmap.2
115 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mmap§ion=2
116 /// [illumos]: https://illumos.org/man/2/mmap
117 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-mmap
118 #[inline]
119 #[doc(alias = "mmap")]
mmap_anonymous( ptr: *mut c_void, len: usize, prot: ProtFlags, flags: MapFlags, ) -> io::Result<*mut c_void>120 pub unsafe fn mmap_anonymous(
121 ptr: *mut c_void,
122 len: usize,
123 prot: ProtFlags,
124 flags: MapFlags,
125 ) -> io::Result<*mut c_void> {
126 backend::mm::syscalls::mmap_anonymous(ptr, len, prot, flags)
127 }
128
129 /// `munmap(ptr, len)`—Remove a memory mapping.
130 ///
131 /// # Safety
132 ///
133 /// Raw pointers and lots of special semantics.
134 ///
135 /// # References
136 /// - [POSIX]
137 /// - [Linux]
138 /// - [Apple]
139 /// - [FreeBSD]
140 /// - [NetBSD]
141 /// - [OpenBSD]
142 /// - [DragonFly BSD]
143 /// - [illumos]
144 /// - [glibc]
145 ///
146 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html
147 /// [Linux]: https://man7.org/linux/man-pages/man2/munmap.2.html
148 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/munmap.2.html
149 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munmap&sektion=2
150 /// [NetBSD]: https://man.netbsd.org/munmap.2
151 /// [OpenBSD]: https://man.openbsd.org/munmap.2
152 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munmap§ion=2
153 /// [illumos]: https://illumos.org/man/2/munmap
154 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-munmap
155 #[inline]
munmap(ptr: *mut c_void, len: usize) -> io::Result<()>156 pub unsafe fn munmap(ptr: *mut c_void, len: usize) -> io::Result<()> {
157 backend::mm::syscalls::munmap(ptr, len)
158 }
159
160 /// `mremap(old_address, old_size, new_size, flags)`—Resize, modify, and/or
161 /// move a memory mapping.
162 ///
163 /// For moving a mapping to a fixed address (`MREMAP_FIXED`), see
164 /// [`mremap_fixed`].
165 ///
166 /// # Safety
167 ///
168 /// Raw pointers and lots of special semantics.
169 ///
170 /// # References
171 /// - [Linux]
172 ///
173 /// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
174 #[cfg(any(target_os = "emscripten", target_os = "linux"))]
175 #[inline]
mremap( old_address: *mut c_void, old_size: usize, new_size: usize, flags: MremapFlags, ) -> io::Result<*mut c_void>176 pub unsafe fn mremap(
177 old_address: *mut c_void,
178 old_size: usize,
179 new_size: usize,
180 flags: MremapFlags,
181 ) -> io::Result<*mut c_void> {
182 backend::mm::syscalls::mremap(old_address, old_size, new_size, flags)
183 }
184
185 /// `mremap(old_address, old_size, new_size, MREMAP_FIXED | flags)`—Resize,
186 /// modify, and/or move a memory mapping to a specific address.
187 ///
188 /// For `mremap` without moving to a specific address, see [`mremap`].
189 /// [`mremap_fixed`].
190 ///
191 /// # Safety
192 ///
193 /// Raw pointers and lots of special semantics.
194 ///
195 /// # References
196 /// - [Linux]
197 ///
198 /// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
199 #[cfg(any(target_os = "emscripten", target_os = "linux"))]
200 #[inline]
201 #[doc(alias = "mremap")]
mremap_fixed( old_address: *mut c_void, old_size: usize, new_size: usize, flags: MremapFlags, new_address: *mut c_void, ) -> io::Result<*mut c_void>202 pub unsafe fn mremap_fixed(
203 old_address: *mut c_void,
204 old_size: usize,
205 new_size: usize,
206 flags: MremapFlags,
207 new_address: *mut c_void,
208 ) -> io::Result<*mut c_void> {
209 backend::mm::syscalls::mremap_fixed(old_address, old_size, new_size, flags, new_address)
210 }
211
212 /// `mprotect(ptr, len, flags)`—Change the protection flags of a region of
213 /// memory.
214 ///
215 /// # Safety
216 ///
217 /// Raw pointers and lots of special semantics.
218 ///
219 /// # References
220 /// - [POSIX]
221 /// - [Linux]
222 /// - [Apple]
223 /// - [FreeBSD]
224 /// - [NetBSD]
225 /// - [OpenBSD]
226 /// - [DragonFly BSD]
227 /// - [illumos]
228 ///
229 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html
230 /// [Linux]: https://man7.org/linux/man-pages/man2/mprotect.2.html
231 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mprotect.2.html
232 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mprotect&sektion=2
233 /// [NetBSD]: https://man.netbsd.org/mprotect.2
234 /// [OpenBSD]: https://man.openbsd.org/mprotect.2
235 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mprotect§ion=2
236 /// [illumos]: https://illumos.org/man/2/mprotect
237 #[inline]
mprotect(ptr: *mut c_void, len: usize, flags: MprotectFlags) -> io::Result<()>238 pub unsafe fn mprotect(ptr: *mut c_void, len: usize, flags: MprotectFlags) -> io::Result<()> {
239 backend::mm::syscalls::mprotect(ptr, len, flags)
240 }
241
242 /// `mlock(ptr, len)`—Lock memory into RAM.
243 ///
244 /// # Safety
245 ///
246 /// This function operates on raw pointers, but it should only be used on
247 /// memory which the caller owns. Technically, locking memory shouldn't violate
248 /// any invariants, but since unlocking it can violate invariants, this
249 /// function is also unsafe for symmetry.
250 ///
251 /// Some implementations implicitly round the memory region out to the nearest
252 /// page boundaries, so this function may lock more memory than explicitly
253 /// requested if the memory isn't page-aligned. Other implementations fail if
254 /// the memory isn't page-aligned.
255 ///
256 /// # References
257 /// - [POSIX]
258 /// - [Linux]
259 /// - [Apple]
260 /// - [FreeBSD]
261 /// - [NetBSD]
262 /// - [OpenBSD]
263 /// - [DragonFly BSD]
264 /// - [illumos]
265 /// - [glibc]
266 ///
267 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlock.html
268 /// [Linux]: https://man7.org/linux/man-pages/man2/mlock.2.html
269 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mlock.2.html
270 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mlock&sektion=2
271 /// [NetBSD]: https://man.netbsd.org/mlock.2
272 /// [OpenBSD]: https://man.openbsd.org/mlock.2
273 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mlock§ion=2
274 /// [illumos]: https://illumos.org/man/3C/mlock
275 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlock
276 #[inline]
mlock(ptr: *mut c_void, len: usize) -> io::Result<()>277 pub unsafe fn mlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
278 backend::mm::syscalls::mlock(ptr, len)
279 }
280
281 /// `mlock2(ptr, len, flags)`—Lock memory into RAM, with flags.
282 ///
283 /// `mlock_with` is the same as [`mlock`] but adds an additional flags operand.
284 ///
285 /// # Safety
286 ///
287 /// This function operates on raw pointers, but it should only be used on
288 /// memory which the caller owns. Technically, locking memory shouldn't violate
289 /// any invariants, but since unlocking it can violate invariants, this
290 /// function is also unsafe for symmetry.
291 ///
292 /// Some implementations implicitly round the memory region out to the nearest
293 /// page boundaries, so this function may lock more memory than explicitly
294 /// requested if the memory isn't page-aligned.
295 ///
296 /// # References
297 /// - [Linux]
298 /// - [glibc]
299 ///
300 /// [Linux]: https://man7.org/linux/man-pages/man2/mlock2.2.html
301 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlock2
302 #[cfg(linux_kernel)]
303 #[inline]
304 #[doc(alias = "mlock2")]
mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io::Result<()>305 pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io::Result<()> {
306 backend::mm::syscalls::mlock_with(ptr, len, flags)
307 }
308
309 /// `munlock(ptr, len)`—Unlock memory.
310 ///
311 /// # Safety
312 ///
313 /// This function operates on raw pointers, but it should only be used on
314 /// memory which the caller owns, to avoid compromising the `mlock` invariants
315 /// of other unrelated code in the process.
316 ///
317 /// Some implementations implicitly round the memory region out to the nearest
318 /// page boundaries, so this function may unlock more memory than explicitly
319 /// requested if the memory isn't page-aligned.
320 ///
321 /// # References
322 /// - [POSIX]
323 /// - [Linux]
324 /// - [Apple]
325 /// - [FreeBSD]
326 /// - [NetBSD]
327 /// - [OpenBSD]
328 /// - [DragonFly BSD]
329 /// - [illumos]
330 /// - [glibc]
331 ///
332 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlock.html
333 /// [Linux]: https://man7.org/linux/man-pages/man2/munlock.2.html
334 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/munlock.2.html
335 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munlock&sektion=2
336 /// [NetBSD]: https://man.netbsd.org/munlock.2
337 /// [OpenBSD]: https://man.openbsd.org/munlock.2
338 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munlock§ion=2
339 /// [illumos]: https://illumos.org/man/3C/munlock
340 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-munlock
341 #[inline]
munlock(ptr: *mut c_void, len: usize) -> io::Result<()>342 pub unsafe fn munlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
343 backend::mm::syscalls::munlock(ptr, len)
344 }
345
346 /// Locks all pages mapped into the address space of the calling process.
347 ///
348 /// This includes the pages of the code, data, and stack segment, as well as
349 /// shared libraries, user space kernel data, shared memory, and memory-mapped
350 /// files. All mapped pages are guaranteed to be resident in RAM when the call
351 /// returns successfully; the pages are guaranteed to stay in RAM until later
352 /// unlocked.
353 ///
354 /// # References
355 /// - [POSIX]
356 /// - [Linux]
357 /// - [FreeBSD]
358 /// - [NetBSD]
359 /// - [OpenBSD]
360 /// - [DragonFly BSD]
361 /// - [illumos]
362 /// - [glibc]
363 ///
364 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlockall.html
365 /// [Linux]: https://man7.org/linux/man-pages/man2/mlockall.2.html
366 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mlockall&sektion=2
367 /// [NetBSD]: https://man.netbsd.org/mlockall.2
368 /// [OpenBSD]: https://man.openbsd.org/mlockall.2
369 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mlockall§ion=2
370 /// [illumos]: https://illumos.org/man/3C/mlockall
371 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlockall
372 #[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
373 #[inline]
mlockall(flags: MlockAllFlags) -> io::Result<()>374 pub fn mlockall(flags: MlockAllFlags) -> io::Result<()> {
375 backend::mm::syscalls::mlockall(flags)
376 }
377
378 /// Unlocks all pages mapped into the address space of the calling process.
379 ///
380 /// # Warnings
381 ///
382 /// This function is aware of all the memory pages in the process, as if it
383 /// were a debugger. It unlocks all the pages, which could potentially
384 /// compromise security assumptions made by code about memory it has
385 /// encapsulated.
386 ///
387 /// # References
388 /// - [POSIX]
389 /// - [Linux]
390 /// - [FreeBSD]
391 /// - [NetBSD]
392 /// - [OpenBSD]
393 /// - [DragonFly BSD]
394 /// - [illumos]
395 /// - [glibc]
396 ///
397 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlockall.html
398 /// [Linux]: https://man7.org/linux/man-pages/man2/munlockall.2.html
399 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munlockall&sektion=2
400 /// [NetBSD]: https://man.netbsd.org/munlockall.2
401 /// [OpenBSD]: https://man.openbsd.org/munlockall.2
402 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munlockall§ion=2
403 /// [illumos]: https://illumos.org/man/3C/munlockall
404 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-munlockall
405 #[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
406 #[inline]
munlockall() -> io::Result<()>407 pub fn munlockall() -> io::Result<()> {
408 backend::mm::syscalls::munlockall()
409 }
410