linux_api/
mman.rs

1use linux_syscall::{Result as _, Result64, syscall};
2
3use crate::errno::Errno;
4use crate::posix_types::{RawFd, kernel_size_t, kernel_ulong_t};
5use crate::{bindings, const_conversions};
6
7bitflags::bitflags! {
8    /// Prot flags, as used with `mmap`. These are u64 to match the x86-64 `mmap`
9    /// syscall parameter:
10    /// <https://github.com/torvalds/linux/tree/v6.3/arch/x86/kernel/sys_x86_64.c#L86>
11    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
12    pub struct ProtFlags: u64 {
13        const PROT_READ = const_conversions::u64_from_u32(bindings::LINUX_PROT_READ);
14        const PROT_WRITE = const_conversions::u64_from_u32(bindings::LINUX_PROT_WRITE);
15        const PROT_EXEC = const_conversions::u64_from_u32(bindings::LINUX_PROT_EXEC);
16        const PROT_SEM = const_conversions::u64_from_u32(bindings::LINUX_PROT_SEM);
17        const PROT_NONE = const_conversions::u64_from_u32(bindings::LINUX_PROT_NONE);
18        const PROT_GROWSDOWN = const_conversions::u64_from_u32(bindings::LINUX_PROT_GROWSDOWN);
19        const PROT_GROWSUP = const_conversions::u64_from_u32(bindings::LINUX_PROT_GROWSUP);
20    }
21}
22
23bitflags::bitflags! {
24    /// Map flags, as used with `mmap`. These are u64 to match the x86-64 `mmap`
25    /// syscall parameter:
26    /// <https://github.com/torvalds/linux/tree/v6.3/arch/x86/kernel/sys_x86_64.c#L86>
27    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
28    pub struct MapFlags: u64 {
29        const MAP_TYPE = const_conversions::u64_from_u32(bindings::LINUX_MAP_TYPE);
30        const MAP_FIXED = const_conversions::u64_from_u32(bindings::LINUX_MAP_FIXED);
31        const MAP_ANONYMOUS = const_conversions::u64_from_u32(bindings::LINUX_MAP_ANONYMOUS);
32        const MAP_POPULATE = const_conversions::u64_from_u32(bindings::LINUX_MAP_POPULATE);
33        const MAP_NONBLOCK = const_conversions::u64_from_u32(bindings::LINUX_MAP_NONBLOCK);
34        const MAP_STACK = const_conversions::u64_from_u32(bindings::LINUX_MAP_STACK);
35        const MAP_HUGETLB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGETLB);
36        const MAP_SYNC = const_conversions::u64_from_u32(bindings::LINUX_MAP_SYNC);
37        const MAP_FIXED_NOREPLACE = const_conversions::u64_from_u32(bindings::LINUX_MAP_FIXED_NOREPLACE);
38        const MAP_UNINITIALIZED = const_conversions::u64_from_u32(bindings::LINUX_MAP_UNINITIALIZED);
39        const MAP_SHARED = const_conversions::u64_from_u32(bindings::LINUX_MAP_SHARED);
40        const MAP_PRIVATE = const_conversions::u64_from_u32(bindings::LINUX_MAP_PRIVATE);
41        const MAP_SHARED_VALIDATE = const_conversions::u64_from_u32(bindings::LINUX_MAP_SHARED_VALIDATE);
42        const MAP_HUGE_SHIFT = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_SHIFT);
43        const MAP_HUGE_MASK = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_MASK);
44        const MAP_HUGE_16KB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_16KB);
45        const MAP_HUGE_64KB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_64KB);
46        const MAP_HUGE_512KB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_512KB);
47        const MAP_HUGE_1MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_1MB);
48        const MAP_HUGE_2MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_2MB);
49        const MAP_HUGE_8MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_8MB);
50        const MAP_HUGE_16MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_16MB);
51        const MAP_HUGE_32MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_32MB);
52        const MAP_HUGE_256MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_256MB);
53        const MAP_HUGE_512MB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_512MB);
54        const MAP_HUGE_1GB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_1GB);
55        const MAP_HUGE_2GB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_2GB);
56        const MAP_HUGE_16GB = const_conversions::u64_from_u32(bindings::LINUX_MAP_HUGE_16GB);
57        const MAP_GROWSDOWN = const_conversions::u64_from_u32(bindings::LINUX_MAP_GROWSDOWN);
58        const MAP_DENYWRITE = const_conversions::u64_from_u32(bindings::LINUX_MAP_DENYWRITE);
59        const MAP_EXECUTABLE = const_conversions::u64_from_u32(bindings::LINUX_MAP_EXECUTABLE);
60        const MAP_LOCKED = const_conversions::u64_from_u32(bindings::LINUX_MAP_LOCKED);
61        const MAP_NORESERVE = const_conversions::u64_from_u32(bindings::LINUX_MAP_NORESERVE);
62        const MAP_DROPPABLE = const_conversions::u64_from_u32(bindings::LINUX_MAP_DROPPABLE);
63    }
64}
65
66bitflags::bitflags! {
67    /// Flags used with `mremap`. u64 to match the x86-64 `mremap` syscall parameter:
68    /// <https://github.com/torvalds/linux/tree/v6.3/mm/mremap.c#L895>
69    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
70    pub struct MRemapFlags: u64 {
71        const MREMAP_MAYMOVE = const_conversions::u64_from_u32(bindings::LINUX_MREMAP_MAYMOVE);
72        const MREMAP_FIXED = const_conversions::u64_from_u32(bindings::LINUX_MREMAP_FIXED);
73        const MREMAP_DONTUNMAP = const_conversions::u64_from_u32(bindings::LINUX_MREMAP_DONTUNMAP);
74    }
75}
76
77/// Make the `mmap` syscall. See `mmap(2)`.
78///
79/// Signature from `SYSCALL_DEFINE6(mmap, ...`, in linux's arch/x86/kernel/sys_x86_64.c.
80///
81/// # Safety
82///
83/// Can clobber existing memory. See `mmap(2)`.
84pub unsafe fn mmap_raw(
85    addr: kernel_ulong_t,
86    length: kernel_ulong_t,
87    prot: kernel_ulong_t,
88    flags: kernel_ulong_t,
89    fd: kernel_ulong_t,
90    off: kernel_ulong_t,
91) -> Result<kernel_ulong_t, Errno> {
92    unsafe { syscall!(linux_syscall::SYS_mmap, addr, length, prot, flags, fd, off) }
93        .try_u64()
94        .map_err(Errno::from)
95}
96
97/// Make the `mmap` syscall, with a thin layer of type-safety over `mmap_raw`.
98/// See `mmap(2)`.
99///
100/// # Safety
101///
102/// Can clobber existing memory. See `mmap(2)`.
103pub unsafe fn mmap(
104    addr: *mut core::ffi::c_void,
105    length: usize,
106    prot: ProtFlags,
107    flags: MapFlags,
108    fd: RawFd,
109    offset: usize,
110) -> Result<*mut core::ffi::c_void, Errno> {
111    unsafe {
112        mmap_raw(
113            addr as kernel_ulong_t,
114            u64::try_from(length).unwrap(),
115            prot.bits(),
116            flags.bits(),
117            fd as kernel_ulong_t,
118            offset.try_into().unwrap(),
119        )
120        .map(|x| x as *mut core::ffi::c_void)
121    }
122}
123
124/// Make the `munmap` syscall. See `munmap(2)`.
125///
126/// Signature from `SYSCALL_DEFINE2(munmap, ...`, in linux's mm/mmap.c.
127///
128/// # Safety
129///
130/// Invalidates the referenced memory range. See `munmap(2)`.
131pub unsafe fn munmap_raw(addr: kernel_ulong_t, length: kernel_size_t) -> Result<(), Errno> {
132    unsafe { syscall!(linux_syscall::SYS_munmap, addr, length) }
133        .check()
134        .map_err(Errno::from)
135}
136
137/// Make the `munmap` syscall, with a thin layer of type-safety over `munmap_raw`. See `munmap(2)`.
138///
139/// # Safety
140///
141/// Invalidates the referenced memory range. See `munmap(2)`.
142pub unsafe fn munmap(addr: *mut core::ffi::c_void, length: usize) -> Result<(), Errno> {
143    unsafe { munmap_raw(addr as kernel_ulong_t, length.try_into().unwrap()) }
144}
145
146/// Make the `mprotect` syscall. See `mprotect(2)`.
147///
148/// Signature from `SYSCALL_DEFINE2(mprotect, ...`, in linux's mm/mprotect.c.
149///
150/// # Safety
151///
152/// See `mprotect(2)`.
153pub unsafe fn mprotect_raw(
154    addr: kernel_ulong_t,
155    length: kernel_size_t,
156    prot: kernel_ulong_t,
157) -> Result<(), Errno> {
158    unsafe { syscall!(linux_syscall::SYS_mprotect, addr, length, prot) }
159        .check()
160        .map_err(Errno::from)
161}
162
163/// Make the `mprotect` syscall, with a thin layer of type-safety over `mprotect_raw`. See `mprotect(2)`.
164///
165/// # Safety
166///
167/// See `mprotect(2)`.
168pub unsafe fn mprotect(
169    addr: *mut core::ffi::c_void,
170    length: usize,
171    prot: ProtFlags,
172) -> Result<(), Errno> {
173    unsafe {
174        mprotect_raw(
175            addr as kernel_ulong_t,
176            length.try_into().unwrap(),
177            prot.bits(),
178        )
179    }
180}