@@ -9,6 +9,7 @@ use std::fs::File;
99use std:: io:: { Read , Seek , SeekFrom } ;
1010use std:: mem:: ManuallyDrop ;
1111use std:: os:: fd:: { AsFd , AsRawFd } ;
12+ use std:: ptr:: null_mut;
1213use std:: sync:: Arc ;
1314
1415use kvm_bindings:: { KVM_MEM_LOG_DIRTY_PAGES , kvm_userspace_memory_region2} ;
@@ -55,6 +56,8 @@ pub enum MemoryError {
5556 MemfdSetLen ( std:: io:: Error ) ,
5657 /// Total sum of memory regions exceeds largest possible file offset
5758 OffsetTooLarge ,
59+ /// Error calling mmap: {0}
60+ Mmap ( std:: io:: Error ) ,
5861}
5962
6063/// Newtype that implements [`ReadVolatile`] and [`WriteVolatile`] if `T` implements `Read` or
@@ -237,16 +240,40 @@ pub fn create(
237240 let mut builder = MmapRegionBuilder :: new_with_bitmap (
238241 size,
239242 track_dirty_pages. then ( || AtomicBitmap :: with_len ( size) ) ,
240- )
241- . with_mmap_prot ( libc:: PROT_READ | libc:: PROT_WRITE )
242- . with_mmap_flags ( libc:: MAP_NORESERVE | mmap_flags) ;
243+ ) ;
243244
244- if let Some ( ref file) = file {
245+ // when computing offset below we ensure it fits into i64
246+ #[ allow( clippy:: cast_possible_wrap) ]
247+ let ( fd, fd_off) = if let Some ( ref file) = file {
245248 let file_offset = FileOffset :: from_arc ( Arc :: clone ( file) , offset) ;
246249
247250 builder = builder. with_file_offset ( file_offset) ;
251+
252+ ( file. as_raw_fd ( ) , offset as libc:: off_t )
253+ } else {
254+ ( -1 , 0 )
255+ } ;
256+
257+ // SAFETY: the arguments to mmap cannot cause any memory unsafety in the rust sense
258+ let ptr = unsafe {
259+ libc:: mmap (
260+ null_mut ( ) ,
261+ size,
262+ libc:: PROT_READ | libc:: PROT_WRITE ,
263+ libc:: MAP_NORESERVE | mmap_flags,
264+ fd,
265+ fd_off,
266+ )
267+ } ;
268+
269+ if ptr == libc:: MAP_FAILED {
270+ return Err ( MemoryError :: Mmap ( std:: io:: Error :: last_os_error ( ) ) ) ;
248271 }
249272
273+ // SAFETY: we check above that mmap succeeded, and the size we passed to builder is the
274+ // same as the size of the mmap area.
275+ let builder = unsafe { builder. with_raw_mmap_pointer ( ptr. cast ( ) ) } ;
276+
250277 offset = match offset. checked_add ( size as u64 ) {
251278 None => return Err ( MemoryError :: OffsetTooLarge ) ,
252279 Some ( new_off) if new_off >= i64:: MAX as u64 => {
0 commit comments