Open and map the ClockBound shared memory segment. Make sure the file can be open, and that the raw pointers into memory are set. # Errors Returns `ShmError` if the path is not found, the file cannot be open or sanity checks fail.
(
path: &CStr,
)
| 237 | /// |
| 238 | /// Returns `ShmError` if the path is not found, the file cannot be open or sanity checks fail. |
| 239 | fn map_segment( |
| 240 | path: &CStr, |
| 241 | ) -> Result< |
| 242 | ( |
| 243 | MmapGuard, |
| 244 | *const AtomicU16, |
| 245 | *const AtomicU16, |
| 246 | *const ClockErrorBound, |
| 247 | ), |
| 248 | ShmError, |
| 249 | > { |
| 250 | let fdguard = FdGuard::new(path)?; |
| 251 | let mmap_guard = MmapGuard::new(&fdguard)?; |
| 252 | |
| 253 | // Create a cursor to pick the addresses of the various elements of interest in the shared |
| 254 | // memory segment. |
| 255 | let mut cursor: *const u8 = mmap_guard.segment.cast(); |
| 256 | |
| 257 | // Pick fields from the ShmHeader |
| 258 | // SAFETY: `cursor` is aligned to the start of the memory segment and the MmapGuard has |
| 259 | // validated the memory segment is large enough to contain the header. |
| 260 | let version = unsafe { ptr::addr_of!((*cursor.cast::<ShmHeader>()).version) }; |
| 261 | let generation = unsafe { ptr::addr_of!((*cursor.cast::<ShmHeader>()).generation) }; |
| 262 | |
| 263 | // Atomically read the current version in the shared memory segment |
| 264 | // SAFETY: `self.version` has been validated when creating the reader |
| 265 | let shm_version = unsafe { &*version }; |
| 266 | let shm_version = shm_version.load(atomic::Ordering::Acquire); |
| 267 | |
| 268 | // FIXME: temporary workaround waiting for https://github.com/aws/private-clock-bound-staging/pull/150 |
| 269 | // to be pulled in |
| 270 | let shm_version = ClockErrorBoundLayoutVersion::try_from(shm_version & 0x00ff)?; |
| 271 | |
| 272 | // Move to the end of the header and map the ClockErrorBound data, but only if the segment |
| 273 | // size allows it and matches our expectation. |
| 274 | let layout_size = match shm_version { |
| 275 | ClockErrorBoundLayoutVersion::V2 => size_of::<ClockErrorBoundV2>(), |
| 276 | ClockErrorBoundLayoutVersion::V3 => size_of::<ClockErrorBoundV3>(), |
| 277 | }; |
| 278 | |
| 279 | if mmap_guard.segsize < size_of::<ShmHeader>() + layout_size { |
| 280 | let msg = format!( |
| 281 | "Clockbound segment size is smaller than expected [{} < {}].", |
| 282 | mmap_guard.segsize, |
| 283 | size_of::<ShmHeader>() + layout_size |
| 284 | ); |
| 285 | return Err(ShmError::SegmentMalformed(msg)); |
| 286 | } |
| 287 | |
| 288 | // SAFETY: segment size has been checked to ensure `cursor` move leads to a valid cast |
| 289 | cursor = unsafe { cursor.add(size_of::<ShmHeader>()) }; |
| 290 | let ceb_shm = ptr::addr_of!(*cursor.cast::<ClockErrorBound>()); |
| 291 | |
| 292 | Ok((mmap_guard, version, generation, ceb_shm)) |
| 293 | } |
| 294 | |
| 295 | /// Return a consistent snapshot of the shared memory segment. |
| 296 | /// |