20
20
//! - [GuestMemoryMmap](struct.GuestMemoryMmap.html): provides methods to access a collection of
21
21
//! GuestRegionMmap objects.
22
22
23
- use libc;
24
23
use std:: io:: { self , Read , Write } ;
25
24
use std:: ops:: Deref ;
26
- use std:: os:: unix:: io:: AsRawFd ;
27
- use std:: ptr:: null_mut;
28
25
use std:: sync:: Arc ;
29
26
30
27
use address:: Address ;
31
28
use guest_memory:: * ;
32
- use volatile_memory:: { self , compute_offset , VolatileMemory , VolatileSlice } ;
29
+ use volatile_memory:: VolatileMemory ;
33
30
use Bytes ;
34
31
35
- /// A backend driver to access guest's physical memory by mmapping guest's memory into the current
36
- /// process.
37
- /// For a combination of 32-bit hypervisor and 64-bit virtual machine, only partial of guest's
38
- /// physical memory may be mapped into current process due to limited process virtual address
39
- /// space size.
40
- #[ derive( Debug ) ]
41
- pub struct MmapRegion {
42
- addr : * mut u8 ,
43
- size : usize ,
32
+ #[ cfg( unix) ]
33
+ pub use mmap_unix:: MmapRegion ;
34
+
35
+ #[ cfg( windows) ]
36
+ pub use mmap_windows:: MmapRegion ;
37
+
38
+ // For MmapRegion
39
+ pub ( crate ) trait AsSlice {
40
+ unsafe fn as_slice ( & self ) -> & [ u8 ] ;
41
+
42
+ #[ allow( clippy:: mut_from_ref) ]
43
+ unsafe fn as_mut_slice ( & self ) -> & mut [ u8 ] ;
44
44
}
45
45
46
46
/// Errors that can happen when creating a memory map
@@ -54,116 +54,6 @@ pub enum MmapError {
54
54
MemoryRegionOverlap ,
55
55
}
56
56
57
- // Send and Sync aren't automatically inherited for the raw address pointer.
58
- // Accessing that pointer is only done through the stateless interface which
59
- // allows the object to be shared by multiple threads without a decrease in
60
- // safety.
61
- unsafe impl Send for MmapRegion { }
62
- unsafe impl Sync for MmapRegion { }
63
-
64
- impl MmapRegion {
65
- /// Creates an anonymous shared mapping of `size` bytes.
66
- ///
67
- /// # Arguments
68
- /// * `size` - Size of memory region in bytes.
69
- pub fn new ( size : usize ) -> io:: Result < Self > {
70
- // This is safe because we are creating an anonymous mapping in a place not already used by
71
- // any other area in this process.
72
- let addr = unsafe {
73
- libc:: mmap (
74
- null_mut ( ) ,
75
- size,
76
- libc:: PROT_READ | libc:: PROT_WRITE ,
77
- libc:: MAP_ANONYMOUS | libc:: MAP_SHARED | libc:: MAP_NORESERVE ,
78
- -1 ,
79
- 0 ,
80
- )
81
- } ;
82
- if addr == libc:: MAP_FAILED {
83
- return Err ( io:: Error :: last_os_error ( ) ) ;
84
- }
85
- Ok ( Self {
86
- addr : addr as * mut u8 ,
87
- size,
88
- } )
89
- }
90
-
91
- /// Maps the `size` bytes starting at `offset` bytes of the given `fd`.
92
- ///
93
- /// # Arguments
94
- /// * `fd` - File descriptor to mmap from.
95
- /// * `size` - Size of memory region in bytes.
96
- /// * `offset` - Offset in bytes from the beginning of `fd` to start the mmap.
97
- pub fn from_fd ( fd : & AsRawFd , size : usize , offset : libc:: off_t ) -> io:: Result < Self > {
98
- // This is safe because we are creating a mapping in a place not already used by any other
99
- // area in this process.
100
- let addr = unsafe {
101
- libc:: mmap (
102
- null_mut ( ) ,
103
- size,
104
- libc:: PROT_READ | libc:: PROT_WRITE ,
105
- libc:: MAP_SHARED ,
106
- fd. as_raw_fd ( ) ,
107
- offset,
108
- )
109
- } ;
110
- if addr == libc:: MAP_FAILED {
111
- return Err ( io:: Error :: last_os_error ( ) ) ;
112
- }
113
- Ok ( Self {
114
- addr : addr as * mut u8 ,
115
- size,
116
- } )
117
- }
118
-
119
- /// Returns a pointer to the beginning of the memory region. Should only be
120
- /// used for passing this region to ioctls for setting guest memory.
121
- pub fn as_ptr ( & self ) -> * mut u8 {
122
- self . addr
123
- }
124
-
125
- unsafe fn as_slice ( & self ) -> & [ u8 ] {
126
- // This is safe because we mapped the area at addr ourselves, so this slice will not
127
- // overflow. However, it is possible to alias.
128
- std:: slice:: from_raw_parts ( self . addr , self . size )
129
- }
130
-
131
- // safe because it's expected interior mutability
132
- #[ allow( clippy:: mut_from_ref) ]
133
- unsafe fn as_mut_slice ( & self ) -> & mut [ u8 ] {
134
- // This is safe because we mapped the area at addr ourselves, so this slice will not
135
- // overflow. However, it is possible to alias.
136
- std:: slice:: from_raw_parts_mut ( self . addr , self . size )
137
- }
138
- }
139
-
140
- impl VolatileMemory for MmapRegion {
141
- fn len ( & self ) -> usize {
142
- self . size
143
- }
144
-
145
- fn get_slice ( & self , offset : usize , count : usize ) -> volatile_memory:: Result < VolatileSlice > {
146
- let end = compute_offset ( offset, count) ?;
147
- if end > self . size {
148
- return Err ( volatile_memory:: Error :: OutOfBounds { addr : end } ) ;
149
- }
150
-
151
- // Safe because we checked that offset + count was within our range and we only ever hand
152
- // out volatile accessors.
153
- Ok ( unsafe { VolatileSlice :: new ( ( self . addr as usize + offset) as * mut _ , count) } )
154
- }
155
- }
156
-
157
- impl Drop for MmapRegion {
158
- fn drop ( & mut self ) {
159
- // This is safe because we mmap the area at addr ourselves, and nobody
160
- // else is holding a reference to it.
161
- unsafe {
162
- libc:: munmap ( self . addr as * mut libc:: c_void , self . size ) ;
163
- }
164
- }
165
- }
166
-
167
57
/// Tracks a mapping of memory in the current process and the corresponding base address
168
58
/// in the guest's memory space.
169
59
#[ derive( Debug ) ]
@@ -262,7 +152,11 @@ impl Bytes<MemoryRegionAddress> for GuestRegionMmap {
262
152
/// # use std::path::Path;
263
153
/// # let start_addr = GuestAddress(0x1000);
264
154
/// # let gm = GuestMemoryMmap::new(&vec![(start_addr, 0x400)]).unwrap();
265
- /// let mut file = File::open(Path::new("/dev/urandom")).unwrap();
155
+ /// let mut file = if cfg!(unix) {
156
+ /// File::open(Path::new("/dev/urandom")).unwrap()
157
+ /// } else {
158
+ /// File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe")).unwrap()
159
+ /// };
266
160
/// let addr = GuestAddress(0x1010);
267
161
/// gm.read_from(addr, &mut file, 128).unwrap();
268
162
/// let read_addr = addr.checked_add(8).unwrap();
@@ -283,12 +177,18 @@ impl Bytes<MemoryRegionAddress> for GuestRegionMmap {
283
177
/// * Read bytes from /dev/urandom
284
178
///
285
179
/// ```
180
+ /// # extern crate tempfile;
181
+ /// # use self::tempfile::tempfile;
286
182
/// # use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
287
183
/// # use std::fs::File;
288
184
/// # use std::path::Path;
289
185
/// # let start_addr = GuestAddress(0x1000);
290
186
/// # let gm = GuestMemoryMmap::new(&vec![(start_addr, 0x400)]).unwrap();
291
- /// let mut file = File::open(Path::new("/dev/urandom")).unwrap();
187
+ /// let mut file = if cfg!(unix) {
188
+ /// File::open(Path::new("/dev/urandom")).unwrap()
189
+ /// } else {
190
+ /// File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe")).unwrap()
191
+ /// };
292
192
/// let addr = GuestAddress(0x1010);
293
193
/// gm.read_exact_from(addr, &mut file, 128).unwrap();
294
194
/// let read_addr = addr.checked_add(8).unwrap();
@@ -304,18 +204,20 @@ impl Bytes<MemoryRegionAddress> for GuestRegionMmap {
304
204
. map_err ( Into :: into)
305
205
}
306
206
307
- /// Reads data from the region to a writable object.
207
+ /// Writes data from the region to a writable object.
308
208
///
309
209
/// # Examples
310
210
///
311
- /// * Write 128 bytes to /dev/null
211
+ /// * Write 128 bytes to a temp file
312
212
///
313
213
/// ```
214
+ /// # extern crate tempfile;
215
+ /// # use self::tempfile::tempfile;
314
216
/// # use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
315
217
/// # use std::fs::OpenOptions;
316
218
/// # let start_addr = GuestAddress(0x1000);
317
219
/// # let gm = GuestMemoryMmap::new(&vec![(start_addr, 0x400)]).unwrap();
318
- /// let mut file = OpenOptions::new().write(true).open("/dev/null" ).unwrap();
220
+ /// let mut file = tempfile( ).unwrap();
319
221
/// let mut mem = [0u8; 1024];
320
222
/// gm.write_to(start_addr, &mut file, 128).unwrap();
321
223
/// ```
@@ -329,18 +231,20 @@ impl Bytes<MemoryRegionAddress> for GuestRegionMmap {
329
231
. map_err ( Into :: into)
330
232
}
331
233
332
- /// Reads data from the region to a writable object.
234
+ /// Writes data from the region to a writable object.
333
235
///
334
236
/// # Examples
335
237
///
336
- /// * Write 128 bytes to /dev/null
238
+ /// * Write 128 bytes to a temp file
337
239
///
338
240
/// ```
241
+ /// # extern crate tempfile;
242
+ /// # use self::tempfile::tempfile;
339
243
/// # use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
340
244
/// # use std::fs::OpenOptions;
341
245
/// # let start_addr = GuestAddress(0x1000);
342
246
/// # let gm = GuestMemoryMmap::new(&vec![(start_addr, 0x400)]).unwrap();
343
- /// let mut file = OpenOptions::new().write(true).open("/dev/null" ).unwrap();
247
+ /// let mut file = tempfile( ).unwrap();
344
248
/// let mut mem = [0u8; 1024];
345
249
/// gm.write_all_to(start_addr, &mut file, 128).unwrap();
346
250
/// ```
@@ -495,7 +399,6 @@ mod tests {
495
399
use super :: * ;
496
400
use std:: fs:: File ;
497
401
use std:: mem;
498
- use std:: os:: unix:: io:: FromRawFd ;
499
402
use std:: path:: Path ;
500
403
501
404
use Bytes ;
@@ -512,13 +415,6 @@ mod tests {
512
415
assert_eq ! ( e. raw_os_error( ) , Some ( libc:: EINVAL ) ) ;
513
416
}
514
417
515
- #[ test]
516
- fn map_invalid_fd ( ) {
517
- let fd = unsafe { std:: fs:: File :: from_raw_fd ( -1 ) } ;
518
- let e = MmapRegion :: from_fd ( & fd, 1024 , 0 ) . unwrap_err ( ) ;
519
- assert_eq ! ( e. raw_os_error( ) , Some ( libc:: EBADF ) ) ;
520
- }
521
-
522
418
#[ test]
523
419
fn slice_addr ( ) {
524
420
let m = MmapRegion :: new ( 5 ) . unwrap ( ) ;
@@ -720,20 +616,29 @@ mod tests {
720
616
fn read_to_and_write_from_mem ( ) {
721
617
let gm = GuestMemoryMmap :: new ( & [ ( GuestAddress ( 0x1000 ) , 0x400 ) ] ) . unwrap ( ) ;
722
618
let addr = GuestAddress ( 0x1010 ) ;
619
+ let mut file = if cfg ! ( unix) {
620
+ File :: open ( Path :: new ( "/dev/zero" ) ) . unwrap ( )
621
+ } else {
622
+ File :: open ( Path :: new ( "c:\\ Windows\\ system32\\ ntoskrnl.exe" ) ) . unwrap ( )
623
+ } ;
723
624
gm. write_obj ( !0u32 , addr) . unwrap ( ) ;
724
- gm. read_exact_from (
725
- addr,
726
- & mut File :: open ( Path :: new ( "/dev/zero" ) ) . unwrap ( ) ,
727
- mem:: size_of :: < u32 > ( ) ,
728
- )
729
- . unwrap ( ) ;
625
+ gm. read_exact_from ( addr, & mut file, mem:: size_of :: < u32 > ( ) )
626
+ . unwrap ( ) ;
730
627
let value: u32 = gm. read_obj ( addr) . unwrap ( ) ;
731
- assert_eq ! ( value, 0 ) ;
628
+ if cfg ! ( unix) {
629
+ assert_eq ! ( value, 0 ) ;
630
+ } else {
631
+ assert_eq ! ( value, 0x0090_5a4d ) ;
632
+ }
732
633
733
634
let mut sink = Vec :: new ( ) ;
734
635
gm. write_all_to ( addr, & mut sink, mem:: size_of :: < u32 > ( ) )
735
636
. unwrap ( ) ;
736
- assert_eq ! ( sink, vec![ 0 ; mem:: size_of:: <u32 >( ) ] ) ;
637
+ if cfg ! ( unix) {
638
+ assert_eq ! ( sink, vec![ 0 ; mem:: size_of:: <u32 >( ) ] ) ;
639
+ } else {
640
+ assert_eq ! ( sink, vec![ 0x4d , 0x5a , 0x90 , 0x00 ] ) ;
641
+ } ;
737
642
}
738
643
739
644
#[ test]
0 commit comments