Skip to content

Commit 4922107

Browse files
committed
Add check_range() to validate guest address range
Current implementation of GuestMemory::checked_offset() validates the GuestAddress(base + offset) is valid. By auditting invocations of GuestMemory::checked_offset(), most callers expect that the whole range [base, base + offset) is valid. So add a new interface check_range() to validate the address range. Signed-off-by: Liu Jiang <[email protected]>
1 parent 68e1cc6 commit 4922107

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
### Added
99
- [[#109]](https://github.com/rust-vmm/vm-memory/pull/109): Added `build_raw` to
1010
`MmapRegion` which can be used to operate on externally created mappings.
11+
- [[#101]](https://github.com/rust-vmm/vm-memory/pull/101): Added `check_range` for
12+
GuestMemory which could be used to validate a range of guest memory.
1113

1214
## [v0.2.0]
1315

src/guest_memory.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,14 @@ pub trait GuestMemory {
515515
self.find_region(addr).map(|_| addr)
516516
}
517517

518+
/// Check whether the range [base, base + len) is valid.
519+
fn check_range(&self, base: GuestAddress, len: usize) -> bool {
520+
match self.try_access(len, base, |_, count, _, _| -> Result<usize> { Ok(count) }) {
521+
Ok(count) if count == len => true,
522+
_ => false,
523+
}
524+
}
525+
518526
/// Returns the address plus the offset if it is present within the memory of the guest.
519527
fn checked_offset(&self, base: GuestAddress, offset: usize) -> Option<GuestAddress> {
520528
base.checked_add(offset as u64)

src/mmap.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,4 +1394,54 @@ mod tests {
13941394
assert!(guest_mem.get_slice(GuestAddress(0x600), 0x100).is_err());
13951395
assert!(guest_mem.get_slice(GuestAddress(0xc00), 0x100).is_err());
13961396
}
1397+
1398+
#[test]
1399+
fn test_checked_offset() {
1400+
let start_addr1 = GuestAddress(0);
1401+
let start_addr2 = GuestAddress(0x800);
1402+
let start_addr3 = GuestAddress(0xc00);
1403+
let guest_mem = GuestMemoryMmap::from_ranges(&[
1404+
(start_addr1, 0x400),
1405+
(start_addr2, 0x400),
1406+
(start_addr3, 0x400),
1407+
])
1408+
.unwrap();
1409+
1410+
assert_eq!(
1411+
guest_mem.checked_offset(start_addr1, 0x200),
1412+
Some(GuestAddress(0x200))
1413+
);
1414+
assert_eq!(
1415+
guest_mem.checked_offset(start_addr1, 0xa00),
1416+
Some(GuestAddress(0xa00))
1417+
);
1418+
assert_eq!(
1419+
guest_mem.checked_offset(start_addr2, 0x7ff),
1420+
Some(GuestAddress(0xfff))
1421+
);
1422+
assert_eq!(guest_mem.checked_offset(start_addr2, 0xc00), None);
1423+
assert_eq!(guest_mem.checked_offset(start_addr1, std::usize::MAX), None);
1424+
}
1425+
1426+
#[test]
1427+
fn test_check_range() {
1428+
let start_addr1 = GuestAddress(0);
1429+
let start_addr2 = GuestAddress(0x800);
1430+
let start_addr3 = GuestAddress(0xc00);
1431+
let guest_mem = GuestMemoryMmap::from_ranges(&[
1432+
(start_addr1, 0x400),
1433+
(start_addr2, 0x400),
1434+
(start_addr3, 0x400),
1435+
])
1436+
.unwrap();
1437+
1438+
assert_eq!(guest_mem.check_range(start_addr1, 0x0), true);
1439+
assert_eq!(guest_mem.check_range(start_addr1, 0x200), true);
1440+
assert_eq!(guest_mem.check_range(start_addr1, 0xa00), false);
1441+
assert_eq!(guest_mem.check_range(start_addr2, 0x7ff), true);
1442+
assert_eq!(guest_mem.check_range(start_addr2, 0x800), true);
1443+
assert_eq!(guest_mem.check_range(start_addr2, 0x801), false);
1444+
assert_eq!(guest_mem.check_range(start_addr2, 0xc00), false);
1445+
assert_eq!(guest_mem.check_range(start_addr1, std::usize::MAX), false);
1446+
}
13971447
}

0 commit comments

Comments
 (0)