@@ -9,6 +9,7 @@ use std::fs::File;
9
9
use std:: io:: { Read , Seek , SeekFrom , Write } ;
10
10
use std:: mem:: ManuallyDrop ;
11
11
use std:: os:: fd:: { AsFd , AsRawFd } ;
12
+ use std:: ptr:: null_mut;
12
13
use std:: sync:: Arc ;
13
14
14
15
use kvm_bindings:: { KVM_MEM_LOG_DIRTY_PAGES , kvm_userspace_memory_region2} ;
@@ -55,6 +56,8 @@ pub enum MemoryError {
55
56
MemfdSetLen ( std:: io:: Error ) ,
56
57
/// Total sum of memory regions exceeds largest possible file offset
57
58
OffsetTooLarge ,
59
+ /// Error calling mmap: {0}
60
+ Mmap ( std:: io:: Error ) ,
58
61
}
59
62
60
63
/// Newtype that implements [`ReadVolatile`] and [`WriteVolatile`] if `T` implements `Read` or
@@ -254,16 +257,40 @@ pub fn create(
254
257
let mut builder = MmapRegionBuilder :: new_with_bitmap (
255
258
size,
256
259
track_dirty_pages. then ( || AtomicBitmap :: with_len ( size) ) ,
257
- )
258
- . with_mmap_prot ( libc:: PROT_READ | libc:: PROT_WRITE )
259
- . with_mmap_flags ( libc:: MAP_NORESERVE | mmap_flags) ;
260
+ ) ;
260
261
261
- if let Some ( ref file) = file {
262
+ // when computing offset below we ensure it fits into i64
263
+ #[ allow( clippy:: cast_possible_wrap) ]
264
+ let ( fd, fd_off) = if let Some ( ref file) = file {
262
265
let file_offset = FileOffset :: from_arc ( Arc :: clone ( file) , offset) ;
263
266
264
267
builder = builder. with_file_offset ( file_offset) ;
268
+
269
+ ( file. as_raw_fd ( ) , offset as libc:: off_t )
270
+ } else {
271
+ ( -1 , 0 )
272
+ } ;
273
+
274
+ // SAFETY: the arguments to mmap cannot cause any memory unsafety in the rust sense
275
+ let ptr = unsafe {
276
+ libc:: mmap (
277
+ null_mut ( ) ,
278
+ size,
279
+ libc:: PROT_READ | libc:: PROT_WRITE ,
280
+ libc:: MAP_NORESERVE | mmap_flags,
281
+ fd,
282
+ fd_off,
283
+ )
284
+ } ;
285
+
286
+ if ptr == libc:: MAP_FAILED {
287
+ return Err ( MemoryError :: Mmap ( std:: io:: Error :: last_os_error ( ) ) ) ;
265
288
}
266
289
290
+ // SAFETY: we check above that mmap succeeded, and the size we passed to builder is the
291
+ // same as the size of the mmap area.
292
+ let builder = unsafe { builder. with_raw_mmap_pointer ( ptr. cast ( ) ) } ;
293
+
267
294
offset = match offset. checked_add ( size as u64 ) {
268
295
None => return Err ( MemoryError :: OffsetTooLarge ) ,
269
296
Some ( new_off) if new_off >= i64:: MAX as u64 => {
0 commit comments