mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
misc: Mark memory region APIs as unsafe
To ensure that struct sizes are the same on 32-bit and 64-bit, various kernel APIs use __u64 (Rust u64) to represent userspace pointers. Userspace is expected to cast pointers to __u64 before passing them to the kernel, and cast kernel-provided __u64 to a pointer before using them. However, various safe APIs in Cloud Hypervisor took caller-provided u64 values and passed them to syscalls that treat them as userspace addresses. Therefore, passing bad u64 values would cause memory disclosure or corruption. The memory region APIs are one example of this, so mark them as unsafe. Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This commit is contained in:
committed by
Rob Bradford
parent
00f0b9e42c
commit
fdc19ad85e
@@ -3464,17 +3464,18 @@ mod unit_tests {
|
||||
.expect("new VM creation failed");
|
||||
|
||||
for (index, region) in mem.iter().enumerate() {
|
||||
let mem_region = vm.make_user_memory_region(
|
||||
index as u32,
|
||||
region.start_addr().raw_value(),
|
||||
region.len(),
|
||||
region.as_ptr() as u64,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
|
||||
vm.create_user_memory_region(mem_region)
|
||||
// SAFETY: inputs are valid
|
||||
unsafe {
|
||||
vm.create_user_memory_region(
|
||||
index as u32,
|
||||
region.start_addr().raw_value(),
|
||||
region.len(),
|
||||
region.as_ptr() as u64,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.expect("Cannot configure guest memory");
|
||||
}
|
||||
}
|
||||
mem.write_slice(&code, load_addr)
|
||||
.expect("Writing code to memory failed");
|
||||
@@ -3574,3 +3575,71 @@ mod unit_tests {
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[test]
|
||||
pub fn test_vm() {
|
||||
use hypervisor::VmExit;
|
||||
use vm_memory::{Address, GuestMemory, GuestMemoryRegion};
|
||||
// This example based on https://lwn.net/Articles/658511/
|
||||
let code = [
|
||||
0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */
|
||||
0x00, 0xd8, /* add %bl, %al */
|
||||
0x04, b'0', /* add $'0', %al */
|
||||
0xee, /* out %al, (%dx) */
|
||||
0xb0, b'\n', /* mov $'\n', %al */
|
||||
0xee, /* out %al, (%dx) */
|
||||
0xf4, /* hlt */
|
||||
];
|
||||
|
||||
let mem_size = 0x1000;
|
||||
let load_addr = GuestAddress(0x1000);
|
||||
let mem = GuestMemoryMmap::from_ranges(&[(load_addr, mem_size)]).unwrap();
|
||||
|
||||
let hv = hypervisor::new().unwrap();
|
||||
let vm = hv
|
||||
.create_vm(HypervisorVmConfig::default())
|
||||
.expect("new VM creation failed");
|
||||
|
||||
for (index, region) in mem.iter().enumerate() {
|
||||
// SAFETY: parameters are correct
|
||||
unsafe {
|
||||
vm.create_user_memory_region(
|
||||
index as u32,
|
||||
region.start_addr().raw_value(),
|
||||
region.len(),
|
||||
region.as_ptr() as u64,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.expect("Cannot configure guest memory");
|
||||
}
|
||||
}
|
||||
mem.write_slice(&code, load_addr)
|
||||
.expect("Writing code to memory failed");
|
||||
|
||||
let mut vcpu = vm.create_vcpu(0, None).expect("new Vcpu failed");
|
||||
|
||||
let mut vcpu_sregs = vcpu.get_sregs().expect("get sregs failed");
|
||||
vcpu_sregs.cs.base = 0;
|
||||
vcpu_sregs.cs.selector = 0;
|
||||
vcpu.set_sregs(&vcpu_sregs).expect("set sregs failed");
|
||||
|
||||
let mut vcpu_regs = vcpu.get_regs().expect("get regs failed");
|
||||
vcpu_regs.set_rip(0x1000);
|
||||
vcpu_regs.set_rax(2);
|
||||
vcpu_regs.set_rbx(3);
|
||||
vcpu_regs.set_rflags(2);
|
||||
vcpu.set_regs(&vcpu_regs).expect("set regs failed");
|
||||
|
||||
loop {
|
||||
match vcpu.run().expect("run failed") {
|
||||
VmExit::Reset => {
|
||||
println!("HLT");
|
||||
break;
|
||||
}
|
||||
VmExit::Ignore => {}
|
||||
r => panic!("unexpected exit reason: {r:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user