Skip to content

Commit 7492a15

Browse files
jiangliuandreeaflorescu
authored andcommitted
memory-model: do not assume memory address is continuous
GuestMemory::address_in_range() and GuestMemory::checked_offset() assumes memory address is continuous. It's a dangerous assumption because there is a black hole just below 4G when guest memory is about 4G or more. Then it may cause invalid memory access in VirtIO subsystem. Signed-off-by: Liu Jiang <[email protected]>
1 parent d9d2ec1 commit 7492a15

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

memory_model/src/guest_memory.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,24 @@ impl GuestMemory {
113113

114114
/// Returns true if the given address is within the memory range available to the guest.
115115
pub fn address_in_range(&self, addr: GuestAddress) -> bool {
116-
addr < self.end_addr()
116+
for region in self.regions.iter() {
117+
if addr >= region.guest_base && addr < region_end(region) {
118+
return true;
119+
}
120+
}
121+
false
117122
}
118123

119124
/// Returns the address plus the offset if it is in range.
120-
pub fn checked_offset(&self, addr: GuestAddress, offset: usize) -> Option<GuestAddress> {
121-
addr.checked_add(offset)
122-
.and_then(|a| if a < self.end_addr() { Some(a) } else { None })
125+
pub fn checked_offset(&self, base: GuestAddress, offset: usize) -> Option<GuestAddress> {
126+
if let Some(addr) = base.checked_add(offset) {
127+
for region in self.regions.iter() {
128+
if addr >= region.guest_base && addr < region_end(region) {
129+
return Some(addr);
130+
}
131+
}
132+
}
133+
None
123134
}
124135

125136
/// Returns the size of the memory region in bytes.
@@ -469,17 +480,19 @@ mod tests {
469480
);
470481

471482
let start_addr1 = GuestAddress(0x0);
472-
let start_addr2 = GuestAddress(0x400);
483+
let start_addr2 = GuestAddress(0x800);
473484
let guest_mem =
474485
GuestMemory::new(&vec![(start_addr1, 0x400), (start_addr2, 0x400)]).unwrap();
475486
assert_eq!(guest_mem.num_regions(), 2);
476487
assert!(guest_mem.address_in_range(GuestAddress(0x200)));
477-
assert!(guest_mem.address_in_range(GuestAddress(0x600)));
478-
let end_addr = GuestAddress(0x800);
488+
assert!(!guest_mem.address_in_range(GuestAddress(0x600)));
489+
assert!(guest_mem.address_in_range(GuestAddress(0xa00)));
490+
let end_addr = GuestAddress(0xc00);
479491
assert!(!guest_mem.address_in_range(end_addr));
480492
assert_eq!(guest_mem.end_addr(), end_addr);
481-
assert!(guest_mem.checked_offset(start_addr1, 0x700).is_some());
482-
assert!(guest_mem.checked_offset(start_addr2, 0x800).is_none());
493+
assert!(guest_mem.checked_offset(start_addr1, 0x900).is_some());
494+
assert!(guest_mem.checked_offset(start_addr1, 0x700).is_none());
495+
assert!(guest_mem.checked_offset(start_addr2, 0xc00).is_none());
483496
}
484497

485498
#[test]

0 commit comments

Comments
 (0)