| 1 | //! linux_raw syscalls supporting `rustix::io`. |
| 2 | //! |
| 3 | //! # Safety |
| 4 | //! |
| 5 | //! See the `rustix::backend` module documentation for details. |
| 6 | #![allow (unsafe_code)] |
| 7 | #![allow (clippy::undocumented_unsafe_blocks)] |
| 8 | |
| 9 | use super::types::{ |
| 10 | Advice, MapFlags, MlockAllFlags, MlockFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags, |
| 11 | UserfaultfdFlags, |
| 12 | }; |
| 13 | use crate::backend::c; |
| 14 | #[cfg (target_pointer_width = "64" )] |
| 15 | use crate::backend::conv::loff_t_from_u64; |
| 16 | use crate::backend::conv::{c_uint, no_fd, pass_usize, ret, ret_owned_fd, ret_void_star}; |
| 17 | use crate::fd::{BorrowedFd, OwnedFd}; |
| 18 | use crate::io; |
| 19 | use linux_raw_sys::general::{MAP_ANONYMOUS, MREMAP_FIXED}; |
| 20 | |
| 21 | #[inline ] |
| 22 | pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> { |
| 23 | unsafe { |
| 24 | ret(raw:syscall!( |
| 25 | __NR_madvise, |
| 26 | addr, |
| 27 | pass_usize(len), |
| 28 | c_uint(advice as c::c_uint) |
| 29 | )) |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | #[inline ] |
| 34 | pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> { |
| 35 | ret(raw:syscall!(__NR_msync, addr, pass_usize(len), flags)) |
| 36 | } |
| 37 | |
| 38 | /// # Safety |
| 39 | /// |
| 40 | /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working |
| 41 | /// with memory pointed to by raw pointers is unsafe. |
| 42 | #[inline ] |
| 43 | pub(crate) unsafe fn mmap( |
| 44 | addr: *mut c::c_void, |
| 45 | length: usize, |
| 46 | prot: ProtFlags, |
| 47 | flags: MapFlags, |
| 48 | fd: BorrowedFd<'_>, |
| 49 | offset: u64, |
| 50 | ) -> io::Result<*mut c::c_void> { |
| 51 | #[cfg (target_pointer_width = "32" )] |
| 52 | { |
| 53 | ret_void_star(syscall!( |
| 54 | __NR_mmap2, |
| 55 | addr, |
| 56 | pass_usize(length), |
| 57 | prot, |
| 58 | flags, |
| 59 | fd, |
| 60 | (offset / 4096) |
| 61 | .try_into() |
| 62 | .map(pass_usize) |
| 63 | .map_err(|_| io::Errno::INVAL)? |
| 64 | )) |
| 65 | } |
| 66 | #[cfg (target_pointer_width = "64" )] |
| 67 | { |
| 68 | ret_void_star(syscall!( |
| 69 | __NR_mmap, |
| 70 | addr, |
| 71 | pass_usize(length), |
| 72 | prot, |
| 73 | flags, |
| 74 | fd, |
| 75 | loff_t_from_u64(offset) |
| 76 | )) |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | /// # Safety |
| 81 | /// |
| 82 | /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working |
| 83 | /// with memory pointed to by raw pointers is unsafe. |
| 84 | #[inline ] |
| 85 | pub(crate) unsafe fn mmap_anonymous( |
| 86 | addr: *mut c::c_void, |
| 87 | length: usize, |
| 88 | prot: ProtFlags, |
| 89 | flags: MapFlags, |
| 90 | ) -> io::Result<*mut c::c_void> { |
| 91 | #[cfg (target_pointer_width = "32" )] |
| 92 | { |
| 93 | ret_void_star(syscall!( |
| 94 | __NR_mmap2, |
| 95 | addr, |
| 96 | pass_usize(length), |
| 97 | prot, |
| 98 | c_uint(flags.bits() | MAP_ANONYMOUS), |
| 99 | no_fd(), |
| 100 | pass_usize(0) |
| 101 | )) |
| 102 | } |
| 103 | #[cfg (target_pointer_width = "64" )] |
| 104 | { |
| 105 | ret_void_star(syscall!( |
| 106 | __NR_mmap, |
| 107 | addr, |
| 108 | pass_usize(length), |
| 109 | prot, |
| 110 | c_uint(flags.bits() | MAP_ANONYMOUS), |
| 111 | no_fd(), |
| 112 | loff_t_from_u64(0) |
| 113 | )) |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | #[inline ] |
| 118 | pub(crate) unsafe fn mprotect( |
| 119 | ptr: *mut c::c_void, |
| 120 | len: usize, |
| 121 | flags: MprotectFlags, |
| 122 | ) -> io::Result<()> { |
| 123 | ret(raw:syscall!(__NR_mprotect, ptr, pass_usize(len), flags)) |
| 124 | } |
| 125 | |
| 126 | /// # Safety |
| 127 | /// |
| 128 | /// `munmap` is primarily unsafe due to the `addr` parameter, as anything |
| 129 | /// working with memory pointed to by raw pointers is unsafe. |
| 130 | #[inline ] |
| 131 | pub(crate) unsafe fn munmap(addr: *mut c::c_void, length: usize) -> io::Result<()> { |
| 132 | ret(raw:syscall!(__NR_munmap, addr, pass_usize(length))) |
| 133 | } |
| 134 | |
| 135 | /// # Safety |
| 136 | /// |
| 137 | /// `mremap` is primarily unsafe due to the `old_address` parameter, as |
| 138 | /// anything working with memory pointed to by raw pointers is unsafe. |
| 139 | #[inline ] |
| 140 | pub(crate) unsafe fn mremap( |
| 141 | old_address: *mut c::c_void, |
| 142 | old_size: usize, |
| 143 | new_size: usize, |
| 144 | flags: MremapFlags, |
| 145 | ) -> io::Result<*mut c::c_void> { |
| 146 | ret_void_star(raw:syscall!( |
| 147 | __NR_mremap, |
| 148 | old_address, |
| 149 | pass_usize(old_size), |
| 150 | pass_usize(new_size), |
| 151 | flags |
| 152 | )) |
| 153 | } |
| 154 | |
| 155 | /// # Safety |
| 156 | /// |
| 157 | /// `mremap_fixed` is primarily unsafe due to the `old_address` and |
| 158 | /// `new_address` parameters, as anything working with memory pointed to by raw |
| 159 | /// pointers is unsafe. |
| 160 | #[inline ] |
| 161 | pub(crate) unsafe fn mremap_fixed( |
| 162 | old_address: *mut c::c_void, |
| 163 | old_size: usize, |
| 164 | new_size: usize, |
| 165 | flags: MremapFlags, |
| 166 | new_address: *mut c::c_void, |
| 167 | ) -> io::Result<*mut c::c_void> { |
| 168 | ret_void_star(raw:syscall!( |
| 169 | __NR_mremap, |
| 170 | old_address, |
| 171 | pass_usize(old_size), |
| 172 | pass_usize(new_size), |
| 173 | c_uint(flags.bits() | MREMAP_FIXED), |
| 174 | new_address |
| 175 | )) |
| 176 | } |
| 177 | |
| 178 | /// # Safety |
| 179 | /// |
| 180 | /// `mlock` operates on raw pointers and may round out to the nearest page |
| 181 | /// boundaries. |
| 182 | #[inline ] |
| 183 | pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { |
| 184 | ret(raw:syscall!(__NR_mlock, addr, pass_usize(length))) |
| 185 | } |
| 186 | |
| 187 | /// # Safety |
| 188 | /// |
| 189 | /// `mlock_with` operates on raw pointers and may round out to the nearest page |
| 190 | /// boundaries. |
| 191 | #[inline ] |
| 192 | pub(crate) unsafe fn mlock_with( |
| 193 | addr: *mut c::c_void, |
| 194 | length: usize, |
| 195 | flags: MlockFlags, |
| 196 | ) -> io::Result<()> { |
| 197 | ret(raw:syscall!(__NR_mlock2, addr, pass_usize(length), flags)) |
| 198 | } |
| 199 | |
| 200 | /// # Safety |
| 201 | /// |
| 202 | /// `munlock` operates on raw pointers and may round out to the nearest page |
| 203 | /// boundaries. |
| 204 | #[inline ] |
| 205 | pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { |
| 206 | ret(raw:syscall!(__NR_munlock, addr, pass_usize(length))) |
| 207 | } |
| 208 | |
| 209 | #[inline ] |
| 210 | pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> { |
| 211 | ret_owned_fd(raw:syscall_readonly!(__NR_userfaultfd, flags)) |
| 212 | } |
| 213 | |
| 214 | /// Locks all pages mapped into the address space of the calling process. |
| 215 | /// |
| 216 | /// This includes the pages of the code, data, and stack segment, as well as |
| 217 | /// shared libraries, user space kernel data, shared memory, and memory-mapped |
| 218 | /// files. All mapped pages are guaranteed to be resident in RAM when the call |
| 219 | /// returns successfully; the pages are guaranteed to stay in RAM until later |
| 220 | /// unlocked. |
| 221 | #[inline ] |
| 222 | pub(crate) fn mlockall(flags: MlockAllFlags) -> io::Result<()> { |
| 223 | // When `mlockall` is used with `MCL_ONFAULT | MCL_FUTURE`, the ordering |
| 224 | // of `mlockall` with respect to arbitrary loads may be significant, |
| 225 | // because if a load happens and evokes a fault before the `mlockall`, |
| 226 | // the memory doesn't get locked, but if the load and therefore |
| 227 | // the fault happens after, then the memory does get locked. |
| 228 | // So to be conservative in this regard, we use `syscall` instead |
| 229 | // of `syscall_readonly` |
| 230 | unsafe { ret(raw:syscall!(__NR_mlockall, flags)) } |
| 231 | } |
| 232 | |
| 233 | /// Unlocks all pages mapped into the address space of the calling process. |
| 234 | #[inline ] |
| 235 | pub(crate) fn munlockall() -> io::Result<()> { |
| 236 | unsafe { ret(raw:syscall_readonly!(__NR_munlockall)) } |
| 237 | } |
| 238 | |