xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/shm.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CStr;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_char;
11*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int;
12*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_long;
13*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_uint;
14*bb4ee6a4SAndroid Build Coastguard Worker use libc::close;
15*bb4ee6a4SAndroid Build Coastguard Worker use libc::fcntl;
16*bb4ee6a4SAndroid Build Coastguard Worker use libc::ftruncate64;
17*bb4ee6a4SAndroid Build Coastguard Worker use libc::off64_t;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::syscall;
19*bb4ee6a4SAndroid Build Coastguard Worker use libc::SYS_memfd_create;
20*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_ADD_SEALS;
21*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_GET_SEALS;
22*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SEAL_FUTURE_WRITE;
23*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SEAL_GROW;
24*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SEAL_SEAL;
25*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SEAL_SHRINK;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SEAL_WRITE;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::MFD_ALLOW_SEALING;
28*bb4ee6a4SAndroid Build Coastguard Worker use once_cell::sync::Lazy;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno_result;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::shm::PlatformSharedMemory;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::trace;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::FromRawDescriptor;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::SharedMemory;
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker // from <sys/memfd.h>
40*bb4ee6a4SAndroid Build Coastguard Worker const MFD_CLOEXEC: c_uint = 0x0001;
41*bb4ee6a4SAndroid Build Coastguard Worker const MFD_NOEXEC_SEAL: c_uint = 0x0008;
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: It is caller's responsibility to ensure the args are valid and check the
44*bb4ee6a4SAndroid Build Coastguard Worker // return value of the function.
memfd_create(name: *const c_char, flags: c_uint) -> c_int45*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn memfd_create(name: *const c_char, flags: c_uint) -> c_int {
46*bb4ee6a4SAndroid Build Coastguard Worker     syscall(SYS_memfd_create as c_long, name, flags) as c_int
47*bb4ee6a4SAndroid Build Coastguard Worker }
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker /// A set of memfd seals.
50*bb4ee6a4SAndroid Build Coastguard Worker ///
51*bb4ee6a4SAndroid Build Coastguard Worker /// An enumeration of each bit can be found at `fcntl(2)`.
52*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default)]
53*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemfdSeals(i32);
54*bb4ee6a4SAndroid Build Coastguard Worker 
55*bb4ee6a4SAndroid Build Coastguard Worker impl MemfdSeals {
56*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns an empty set of memfd seals.
57*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
new() -> MemfdSeals58*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> MemfdSeals {
59*bb4ee6a4SAndroid Build Coastguard Worker         MemfdSeals(0)
60*bb4ee6a4SAndroid Build Coastguard Worker     }
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the raw bitmask of seals enumerated in `fcntl(2)`.
63*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
bitmask(self) -> i3264*bb4ee6a4SAndroid Build Coastguard Worker     pub fn bitmask(self) -> i32 {
65*bb4ee6a4SAndroid Build Coastguard Worker         self.0
66*bb4ee6a4SAndroid Build Coastguard Worker     }
67*bb4ee6a4SAndroid Build Coastguard Worker 
68*bb4ee6a4SAndroid Build Coastguard Worker     /// True if the grow seal bit is present.
69*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
grow_seal(self) -> bool70*bb4ee6a4SAndroid Build Coastguard Worker     pub fn grow_seal(self) -> bool {
71*bb4ee6a4SAndroid Build Coastguard Worker         self.0 & F_SEAL_GROW != 0
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the grow seal bit.
75*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
set_grow_seal(&mut self)76*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_grow_seal(&mut self) {
77*bb4ee6a4SAndroid Build Coastguard Worker         self.0 |= F_SEAL_GROW;
78*bb4ee6a4SAndroid Build Coastguard Worker     }
79*bb4ee6a4SAndroid Build Coastguard Worker 
80*bb4ee6a4SAndroid Build Coastguard Worker     /// True if the shrink seal bit is present.
81*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
shrink_seal(self) -> bool82*bb4ee6a4SAndroid Build Coastguard Worker     pub fn shrink_seal(self) -> bool {
83*bb4ee6a4SAndroid Build Coastguard Worker         self.0 & F_SEAL_SHRINK != 0
84*bb4ee6a4SAndroid Build Coastguard Worker     }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the shrink seal bit.
87*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
set_shrink_seal(&mut self)88*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_shrink_seal(&mut self) {
89*bb4ee6a4SAndroid Build Coastguard Worker         self.0 |= F_SEAL_SHRINK;
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker     /// True if the write seal bit is present.
93*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
write_seal(self) -> bool94*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_seal(self) -> bool {
95*bb4ee6a4SAndroid Build Coastguard Worker         self.0 & F_SEAL_WRITE != 0
96*bb4ee6a4SAndroid Build Coastguard Worker     }
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the write seal bit.
99*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
set_write_seal(&mut self)100*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_write_seal(&mut self) {
101*bb4ee6a4SAndroid Build Coastguard Worker         self.0 |= F_SEAL_WRITE;
102*bb4ee6a4SAndroid Build Coastguard Worker     }
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker     /// True if the future write seal bit is present.
105*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
future_write_seal(self) -> bool106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn future_write_seal(self) -> bool {
107*bb4ee6a4SAndroid Build Coastguard Worker         self.0 & F_SEAL_FUTURE_WRITE != 0
108*bb4ee6a4SAndroid Build Coastguard Worker     }
109*bb4ee6a4SAndroid Build Coastguard Worker 
110*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the future write seal bit.
111*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
set_future_write_seal(&mut self)112*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_future_write_seal(&mut self) {
113*bb4ee6a4SAndroid Build Coastguard Worker         self.0 |= F_SEAL_FUTURE_WRITE;
114*bb4ee6a4SAndroid Build Coastguard Worker     }
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker     /// True of the seal seal bit is present.
117*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
seal_seal(self) -> bool118*bb4ee6a4SAndroid Build Coastguard Worker     pub fn seal_seal(self) -> bool {
119*bb4ee6a4SAndroid Build Coastguard Worker         self.0 & F_SEAL_SEAL != 0
120*bb4ee6a4SAndroid Build Coastguard Worker     }
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the seal seal bit.
123*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
set_seal_seal(&mut self)124*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_seal_seal(&mut self) {
125*bb4ee6a4SAndroid Build Coastguard Worker         self.0 |= F_SEAL_SEAL;
126*bb4ee6a4SAndroid Build Coastguard Worker     }
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker 
129*bb4ee6a4SAndroid Build Coastguard Worker static MFD_NOEXEC_SEAL_SUPPORTED: Lazy<bool> = Lazy::new(|| {
130*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: We pass a valid zero-terminated C string and check the result.
131*bb4ee6a4SAndroid Build Coastguard Worker     let fd = unsafe {
132*bb4ee6a4SAndroid Build Coastguard Worker         // The memfd name used here does not need to be unique, since duplicates are allowed and
133*bb4ee6a4SAndroid Build Coastguard Worker         // will not cause failures.
134*bb4ee6a4SAndroid Build Coastguard Worker         memfd_create(
135*bb4ee6a4SAndroid Build Coastguard Worker             b"MFD_NOEXEC_SEAL_test\0".as_ptr() as *const c_char,
136*bb4ee6a4SAndroid Build Coastguard Worker             MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL,
137*bb4ee6a4SAndroid Build Coastguard Worker         )
138*bb4ee6a4SAndroid Build Coastguard Worker     };
139*bb4ee6a4SAndroid Build Coastguard Worker     if fd < 0 {
140*bb4ee6a4SAndroid Build Coastguard Worker         trace!("MFD_NOEXEC_SEAL is not supported");
141*bb4ee6a4SAndroid Build Coastguard Worker         false
142*bb4ee6a4SAndroid Build Coastguard Worker     } else {
143*bb4ee6a4SAndroid Build Coastguard Worker         trace!("MFD_NOEXEC_SEAL is supported");
144*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: We know `fd` is a valid file descriptor owned by us.
145*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
146*bb4ee6a4SAndroid Build Coastguard Worker             close(fd);
147*bb4ee6a4SAndroid Build Coastguard Worker         }
148*bb4ee6a4SAndroid Build Coastguard Worker         true
149*bb4ee6a4SAndroid Build Coastguard Worker     }
150*bb4ee6a4SAndroid Build Coastguard Worker });
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker impl PlatformSharedMemory for SharedMemory {
153*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a new shared memory file descriptor with the specified `size` in bytes.
154*bb4ee6a4SAndroid Build Coastguard Worker     ///
155*bb4ee6a4SAndroid Build Coastguard Worker     /// `name` will appear in `/proc/self/fd/<shm fd>` for the purposes of debugging. The name does
156*bb4ee6a4SAndroid Build Coastguard Worker     /// not need to be unique.
157*bb4ee6a4SAndroid Build Coastguard Worker     ///
158*bb4ee6a4SAndroid Build Coastguard Worker     /// The file descriptor is opened with the close on exec flag and allows memfd sealing.
159*bb4ee6a4SAndroid Build Coastguard Worker     ///
160*bb4ee6a4SAndroid Build Coastguard Worker     /// If the `MFD_NOEXEC_SEAL` flag is supported, the resulting file will also be created with a
161*bb4ee6a4SAndroid Build Coastguard Worker     /// non-executable file mode (in other words, it cannot be passed to the `exec` family of system
162*bb4ee6a4SAndroid Build Coastguard Worker     /// calls).
new(debug_name: &CStr, size: u64) -> Result<SharedMemory>163*bb4ee6a4SAndroid Build Coastguard Worker     fn new(debug_name: &CStr, size: u64) -> Result<SharedMemory> {
164*bb4ee6a4SAndroid Build Coastguard Worker         let mut flags = MFD_CLOEXEC | MFD_ALLOW_SEALING;
165*bb4ee6a4SAndroid Build Coastguard Worker         if *MFD_NOEXEC_SEAL_SUPPORTED {
166*bb4ee6a4SAndroid Build Coastguard Worker             flags |= MFD_NOEXEC_SEAL;
167*bb4ee6a4SAndroid Build Coastguard Worker         }
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker         let shm_name = debug_name.as_ptr() as *const c_char;
170*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
171*bb4ee6a4SAndroid Build Coastguard Worker         // The following are safe because we give a valid C string and check the
172*bb4ee6a4SAndroid Build Coastguard Worker         // results of the memfd_create call.
173*bb4ee6a4SAndroid Build Coastguard Worker         let fd = unsafe { memfd_create(shm_name, flags) };
174*bb4ee6a4SAndroid Build Coastguard Worker         if fd < 0 {
175*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
176*bb4ee6a4SAndroid Build Coastguard Worker         }
177*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because fd is valid.
178*bb4ee6a4SAndroid Build Coastguard Worker         let descriptor = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
179*bb4ee6a4SAndroid Build Coastguard Worker 
180*bb4ee6a4SAndroid Build Coastguard Worker         // Set the size of the memfd.
181*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because we check the return value to ftruncate64 and all the args to the
182*bb4ee6a4SAndroid Build Coastguard Worker         // function are valid.
183*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ftruncate64(descriptor.as_raw_descriptor(), size as off64_t) };
184*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
185*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
186*bb4ee6a4SAndroid Build Coastguard Worker         }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SharedMemory { descriptor, size })
189*bb4ee6a4SAndroid Build Coastguard Worker     }
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a SharedMemory instance from a SafeDescriptor owning a reference to a
192*bb4ee6a4SAndroid Build Coastguard Worker     /// shared memory descriptor. Ownership of the underlying descriptor is transferred to the
193*bb4ee6a4SAndroid Build Coastguard Worker     /// new SharedMemory object.
from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>194*bb4ee6a4SAndroid Build Coastguard Worker     fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory> {
195*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SharedMemory { descriptor, size })
196*bb4ee6a4SAndroid Build Coastguard Worker     }
197*bb4ee6a4SAndroid Build Coastguard Worker }
198*bb4ee6a4SAndroid Build Coastguard Worker 
199*bb4ee6a4SAndroid Build Coastguard Worker pub trait SharedMemoryLinux {
200*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a `SharedMemory` instance from a `File` that represents shared memory.
201*bb4ee6a4SAndroid Build Coastguard Worker     ///
202*bb4ee6a4SAndroid Build Coastguard Worker     /// The size of the resulting shared memory will be determined using `File::seek`. If the given
203*bb4ee6a4SAndroid Build Coastguard Worker     /// file's size can not be determined this way, this will return an error.
from_file(file: File) -> Result<SharedMemory>204*bb4ee6a4SAndroid Build Coastguard Worker     fn from_file(file: File) -> Result<SharedMemory>;
205*bb4ee6a4SAndroid Build Coastguard Worker 
206*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the memfd seals that have already been added to this.
207*bb4ee6a4SAndroid Build Coastguard Worker     ///
208*bb4ee6a4SAndroid Build Coastguard Worker     /// This may fail if this instance was not constructed from a memfd.
get_seals(&self) -> Result<MemfdSeals>209*bb4ee6a4SAndroid Build Coastguard Worker     fn get_seals(&self) -> Result<MemfdSeals>;
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker     /// Adds the given set of memfd seals.
212*bb4ee6a4SAndroid Build Coastguard Worker     ///
213*bb4ee6a4SAndroid Build Coastguard Worker     /// This may fail if this instance was not constructed from a memfd with sealing allowed or if
214*bb4ee6a4SAndroid Build Coastguard Worker     /// the seal seal (`F_SEAL_SEAL`) bit was already added.
add_seals(&mut self, seals: MemfdSeals) -> Result<()>215*bb4ee6a4SAndroid Build Coastguard Worker     fn add_seals(&mut self, seals: MemfdSeals) -> Result<()>;
216*bb4ee6a4SAndroid Build Coastguard Worker }
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker impl SharedMemoryLinux for SharedMemory {
from_file(mut file: File) -> Result<SharedMemory>219*bb4ee6a4SAndroid Build Coastguard Worker     fn from_file(mut file: File) -> Result<SharedMemory> {
220*bb4ee6a4SAndroid Build Coastguard Worker         let file_size = file.seek(SeekFrom::End(0))?;
221*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SharedMemory {
222*bb4ee6a4SAndroid Build Coastguard Worker             descriptor: file.into(),
223*bb4ee6a4SAndroid Build Coastguard Worker             size: file_size,
224*bb4ee6a4SAndroid Build Coastguard Worker         })
225*bb4ee6a4SAndroid Build Coastguard Worker     }
226*bb4ee6a4SAndroid Build Coastguard Worker 
get_seals(&self) -> Result<MemfdSeals>227*bb4ee6a4SAndroid Build Coastguard Worker     fn get_seals(&self) -> Result<MemfdSeals> {
228*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because we check the return value to fcntl and all the args to the
229*bb4ee6a4SAndroid Build Coastguard Worker         // function are valid.
230*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { fcntl(self.descriptor.as_raw_descriptor(), F_GET_SEALS) };
231*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
232*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
233*bb4ee6a4SAndroid Build Coastguard Worker         }
234*bb4ee6a4SAndroid Build Coastguard Worker         Ok(MemfdSeals(ret))
235*bb4ee6a4SAndroid Build Coastguard Worker     }
236*bb4ee6a4SAndroid Build Coastguard Worker 
add_seals(&mut self, seals: MemfdSeals) -> Result<()>237*bb4ee6a4SAndroid Build Coastguard Worker     fn add_seals(&mut self, seals: MemfdSeals) -> Result<()> {
238*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because we check the return value to fcntl and all the args to the
239*bb4ee6a4SAndroid Build Coastguard Worker         // function are valid.
240*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { fcntl(self.descriptor.as_raw_descriptor(), F_ADD_SEALS, seals) };
241*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
242*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
243*bb4ee6a4SAndroid Build Coastguard Worker         }
244*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker 
248*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
249*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
250*bb4ee6a4SAndroid Build Coastguard Worker     use std::fs::read_link;
251*bb4ee6a4SAndroid Build Coastguard Worker 
252*bb4ee6a4SAndroid Build Coastguard Worker     use libc::EINVAL;
253*bb4ee6a4SAndroid Build Coastguard Worker 
254*bb4ee6a4SAndroid Build Coastguard Worker     use crate::linux::SharedMemoryLinux;
255*bb4ee6a4SAndroid Build Coastguard Worker     use crate::pagesize;
256*bb4ee6a4SAndroid Build Coastguard Worker     use crate::AsRawDescriptor;
257*bb4ee6a4SAndroid Build Coastguard Worker     use crate::Error;
258*bb4ee6a4SAndroid Build Coastguard Worker     use crate::MemoryMappingBuilder;
259*bb4ee6a4SAndroid Build Coastguard Worker     use crate::Result;
260*bb4ee6a4SAndroid Build Coastguard Worker     use crate::SharedMemory;
261*bb4ee6a4SAndroid Build Coastguard Worker     use crate::VolatileMemory;
262*bb4ee6a4SAndroid Build Coastguard Worker 
263*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads the name from the underlying file as a `String`.
264*bb4ee6a4SAndroid Build Coastguard Worker     ///
265*bb4ee6a4SAndroid Build Coastguard Worker     /// If the underlying file was not created with `SharedMemory::new` or with `memfd_create`, the
266*bb4ee6a4SAndroid Build Coastguard Worker     /// results are undefined. Because this returns a `String`, the name's bytes are interpreted as
267*bb4ee6a4SAndroid Build Coastguard Worker     /// utf-8.
read_name(shm: &SharedMemory) -> Result<String>268*bb4ee6a4SAndroid Build Coastguard Worker     fn read_name(shm: &SharedMemory) -> Result<String> {
269*bb4ee6a4SAndroid Build Coastguard Worker         let fd_path = format!("/proc/self/fd/{}", shm.as_raw_descriptor());
270*bb4ee6a4SAndroid Build Coastguard Worker         let link_name = read_link(fd_path)?;
271*bb4ee6a4SAndroid Build Coastguard Worker         link_name
272*bb4ee6a4SAndroid Build Coastguard Worker             .to_str()
273*bb4ee6a4SAndroid Build Coastguard Worker             .map(|s| {
274*bb4ee6a4SAndroid Build Coastguard Worker                 s.trim_start_matches("/memfd:")
275*bb4ee6a4SAndroid Build Coastguard Worker                     .trim_end_matches(" (deleted)")
276*bb4ee6a4SAndroid Build Coastguard Worker                     .to_owned()
277*bb4ee6a4SAndroid Build Coastguard Worker             })
278*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or_else(|| Error::new(EINVAL))
279*bb4ee6a4SAndroid Build Coastguard Worker     }
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new()282*bb4ee6a4SAndroid Build Coastguard Worker     fn new() {
283*bb4ee6a4SAndroid Build Coastguard Worker         const TEST_NAME: &str = "Name McCool Person";
284*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new(TEST_NAME, 0).expect("failed to create shared memory");
285*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(read_name(&shm), Ok(TEST_NAME.to_owned()));
286*bb4ee6a4SAndroid Build Coastguard Worker     }
287*bb4ee6a4SAndroid Build Coastguard Worker 
288*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new_huge()289*bb4ee6a4SAndroid Build Coastguard Worker     fn new_huge() {
290*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 0x7fff_ffff_ffff_ffff)
291*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to create shared memory");
292*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(shm.size(), 0x7fff_ffff_ffff_ffff);
293*bb4ee6a4SAndroid Build Coastguard Worker     }
294*bb4ee6a4SAndroid Build Coastguard Worker 
295*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new_sealed()296*bb4ee6a4SAndroid Build Coastguard Worker     fn new_sealed() {
297*bb4ee6a4SAndroid Build Coastguard Worker         let mut shm = SharedMemory::new("test", 0).expect("failed to create shared memory");
298*bb4ee6a4SAndroid Build Coastguard Worker         let mut seals = shm.get_seals().expect("failed to get seals");
299*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!seals.seal_seal());
300*bb4ee6a4SAndroid Build Coastguard Worker         seals.set_seal_seal();
301*bb4ee6a4SAndroid Build Coastguard Worker         shm.add_seals(seals).expect("failed to add seals");
302*bb4ee6a4SAndroid Build Coastguard Worker         seals = shm.get_seals().expect("failed to get seals");
303*bb4ee6a4SAndroid Build Coastguard Worker         assert!(seals.seal_seal());
304*bb4ee6a4SAndroid Build Coastguard Worker         // Adding more seals should be rejected by the kernel.
305*bb4ee6a4SAndroid Build Coastguard Worker         shm.add_seals(seals).unwrap_err();
306*bb4ee6a4SAndroid Build Coastguard Worker     }
307*bb4ee6a4SAndroid Build Coastguard Worker 
308*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mmap_page()309*bb4ee6a4SAndroid Build Coastguard Worker     fn mmap_page() {
310*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 4096).expect("failed to create shared memory");
311*bb4ee6a4SAndroid Build Coastguard Worker 
312*bb4ee6a4SAndroid Build Coastguard Worker         let mmap1 = MemoryMappingBuilder::new(shm.size() as usize)
313*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(&shm)
314*bb4ee6a4SAndroid Build Coastguard Worker             .build()
315*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to map shared memory");
316*bb4ee6a4SAndroid Build Coastguard Worker         let mmap2 = MemoryMappingBuilder::new(shm.size() as usize)
317*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(&shm)
318*bb4ee6a4SAndroid Build Coastguard Worker             .build()
319*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to map shared memory");
320*bb4ee6a4SAndroid Build Coastguard Worker 
321*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(
322*bb4ee6a4SAndroid Build Coastguard Worker             mmap1.get_slice(0, 1).unwrap().as_ptr(),
323*bb4ee6a4SAndroid Build Coastguard Worker             mmap2.get_slice(0, 1).unwrap().as_ptr()
324*bb4ee6a4SAndroid Build Coastguard Worker         );
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker         mmap1
327*bb4ee6a4SAndroid Build Coastguard Worker             .get_slice(0, 4096)
328*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to get mmap slice")
329*bb4ee6a4SAndroid Build Coastguard Worker             .write_bytes(0x45);
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..4096 {
332*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(mmap2.read_obj::<u8>(i).unwrap(), 0x45u8);
333*bb4ee6a4SAndroid Build Coastguard Worker         }
334*bb4ee6a4SAndroid Build Coastguard Worker     }
335*bb4ee6a4SAndroid Build Coastguard Worker 
336*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mmap_page_offset()337*bb4ee6a4SAndroid Build Coastguard Worker     fn mmap_page_offset() {
338*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 2 * pagesize() as u64)
339*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to create shared memory");
340*bb4ee6a4SAndroid Build Coastguard Worker 
341*bb4ee6a4SAndroid Build Coastguard Worker         let mmap1 = MemoryMappingBuilder::new(shm.size() as usize)
342*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(&shm)
343*bb4ee6a4SAndroid Build Coastguard Worker             .offset(pagesize() as u64)
344*bb4ee6a4SAndroid Build Coastguard Worker             .build()
345*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to map shared memory");
346*bb4ee6a4SAndroid Build Coastguard Worker         let mmap2 = MemoryMappingBuilder::new(shm.size() as usize)
347*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(&shm)
348*bb4ee6a4SAndroid Build Coastguard Worker             .build()
349*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to map shared memory");
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker         mmap1
352*bb4ee6a4SAndroid Build Coastguard Worker             .get_slice(0, pagesize())
353*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to get mmap slice")
354*bb4ee6a4SAndroid Build Coastguard Worker             .write_bytes(0x45);
355*bb4ee6a4SAndroid Build Coastguard Worker 
356*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..pagesize() {
357*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(mmap2.read_obj::<u8>(i).unwrap(), 0);
358*bb4ee6a4SAndroid Build Coastguard Worker         }
359*bb4ee6a4SAndroid Build Coastguard Worker         for i in pagesize()..(2 * pagesize()) {
360*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(mmap2.read_obj::<u8>(i).unwrap(), 0x45u8);
361*bb4ee6a4SAndroid Build Coastguard Worker         }
362*bb4ee6a4SAndroid Build Coastguard Worker     }
363*bb4ee6a4SAndroid Build Coastguard Worker }
364