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::super::c; 10 #[cfg(target_pointer_width = "64")] 11 use super::super::conv::loff_t_from_u64; 12 use super::super::conv::{c_uint, no_fd, pass_usize, ret, ret_owned_fd, ret_void_star}; 13 use super::types::{ 14 Advice, MapFlags, MlockFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags, 15 UserfaultfdFlags, 16 }; 17 use crate::fd::{BorrowedFd, OwnedFd}; 18 use crate::io; 19 #[cfg(target_pointer_width = "32")] 20 use core::convert::TryInto; 21 use linux_raw_sys::general::MAP_ANONYMOUS; 22 23 #[inline] 24 pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> { 25 unsafe { 26 ret(syscall!( 27 __NR_madvise, 28 addr, 29 pass_usize(len), 30 c_uint(advice as c::c_uint) 31 )) 32 } 33 } 34 35 #[inline] 36 pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> { 37 ret(syscall!(__NR_msync, addr, pass_usize(len), flags)) 38 } 39 40 /// # Safety 41 /// 42 /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working 43 /// with memory pointed to by raw pointers is unsafe. 44 #[inline] 45 pub(crate) unsafe fn mmap( 46 addr: *mut c::c_void, 47 length: usize, 48 prot: ProtFlags, 49 flags: MapFlags, 50 fd: BorrowedFd<'_>, 51 offset: u64, 52 ) -> io::Result<*mut c::c_void> { 53 #[cfg(target_pointer_width = "32")] 54 { 55 ret_void_star(syscall!( 56 __NR_mmap2, 57 addr, 58 pass_usize(length), 59 prot, 60 flags, 61 fd, 62 (offset / 4096) 63 .try_into() 64 .map(pass_usize) 65 .map_err(|_| io::Errno::INVAL)? 66 )) 67 } 68 #[cfg(target_pointer_width = "64")] 69 { 70 ret_void_star(syscall!( 71 __NR_mmap, 72 addr, 73 pass_usize(length), 74 prot, 75 flags, 76 fd, 77 loff_t_from_u64(offset) 78 )) 79 } 80 } 81 82 /// # Safety 83 /// 84 /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working 85 /// with memory pointed to by raw pointers is unsafe. 86 #[inline] 87 pub(crate) unsafe fn mmap_anonymous( 88 addr: *mut c::c_void, 89 length: usize, 90 prot: ProtFlags, 91 flags: MapFlags, 92 ) -> io::Result<*mut c::c_void> { 93 #[cfg(target_pointer_width = "32")] 94 { 95 ret_void_star(syscall!( 96 __NR_mmap2, 97 addr, 98 pass_usize(length), 99 prot, 100 c_uint(flags.bits() | MAP_ANONYMOUS), 101 no_fd(), 102 pass_usize(0) 103 )) 104 } 105 #[cfg(target_pointer_width = "64")] 106 { 107 ret_void_star(syscall!( 108 __NR_mmap, 109 addr, 110 pass_usize(length), 111 prot, 112 c_uint(flags.bits() | MAP_ANONYMOUS), 113 no_fd(), 114 loff_t_from_u64(0) 115 )) 116 } 117 } 118 119 #[inline] 120 pub(crate) unsafe fn mprotect( 121 ptr: *mut c::c_void, 122 len: usize, 123 flags: MprotectFlags, 124 ) -> io::Result<()> { 125 ret(syscall!(__NR_mprotect, ptr, pass_usize(len), flags)) 126 } 127 128 /// # Safety 129 /// 130 /// `munmap` is primarily unsafe due to the `addr` parameter, as anything 131 /// working with memory pointed to by raw pointers is unsafe. 132 #[inline] 133 pub(crate) unsafe fn munmap(addr: *mut c::c_void, length: usize) -> io::Result<()> { 134 ret(syscall!(__NR_munmap, addr, pass_usize(length))) 135 } 136 137 /// # Safety 138 /// 139 /// `mremap` is primarily unsafe due to the `old_address` parameter, as 140 /// anything working with memory pointed to by raw pointers is unsafe. 141 #[inline] 142 pub(crate) unsafe fn mremap( 143 old_address: *mut c::c_void, 144 old_size: usize, 145 new_size: usize, 146 flags: MremapFlags, 147 ) -> io::Result<*mut c::c_void> { 148 ret_void_star(syscall!( 149 __NR_mremap, 150 old_address, 151 pass_usize(old_size), 152 pass_usize(new_size), 153 flags 154 )) 155 } 156 157 /// # Safety 158 /// 159 /// `mremap_fixed` is primarily unsafe due to the `old_address` and 160 /// `new_address` parameters, as anything working with memory pointed to by raw 161 /// pointers is unsafe. 162 #[inline] 163 pub(crate) unsafe fn mremap_fixed( 164 old_address: *mut c::c_void, 165 old_size: usize, 166 new_size: usize, 167 flags: MremapFlags, 168 new_address: *mut c::c_void, 169 ) -> io::Result<*mut c::c_void> { 170 ret_void_star(syscall!( 171 __NR_mremap, 172 old_address, 173 pass_usize(old_size), 174 pass_usize(new_size), 175 flags, 176 new_address 177 )) 178 } 179 180 /// # Safety 181 /// 182 /// `mlock` operates on raw pointers and may round out to the nearest page 183 /// boundaries. 184 #[inline] 185 pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { 186 ret(syscall!(__NR_mlock, addr, pass_usize(length))) 187 } 188 189 /// # Safety 190 /// 191 /// `mlock_with` operates on raw pointers and may round out to the nearest page 192 /// boundaries. 193 #[inline] 194 pub(crate) unsafe fn mlock_with( 195 addr: *mut c::c_void, 196 length: usize, 197 flags: MlockFlags, 198 ) -> io::Result<()> { 199 ret(syscall!(__NR_mlock2, addr, pass_usize(length), flags)) 200 } 201 202 /// # Safety 203 /// 204 /// `munlock` operates on raw pointers and may round out to the nearest page 205 /// boundaries. 206 #[inline] 207 pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { 208 ret(syscall!(__NR_munlock, addr, pass_usize(length))) 209 } 210 211 #[inline] 212 pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> { 213 ret_owned_fd(syscall_readonly!(__NR_userfaultfd, flags)) 214 } 215