Skip to content

Commit 87b9c43

Browse files
gabhijitandreeaflorescu
authored andcommitted
Fix Check For num_entries for CpuId #119
Added a check to verify that the number of entires passed is less than or equal to `KVM_MAX_CPUID_ENTRIES` (`Kvm.get_cpuid`, `VcpuFd.get_cpuid2`). Added test cases for failure scenarios for `get_emulated_cpuid` and `get_supported_cpuid`. Renamed param `max_entries_count` to `num_entries` consistent with `VcpuFd.get_cpuid2` Signed-off-by: Abhijit Gadgil <[email protected]>
1 parent 366d4f9 commit 87b9c43

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

src/ioctls/system.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use ioctls::Result;
1515
#[cfg(any(target_arch = "aarch64"))]
1616
use kvm_bindings::KVM_VM_TYPE_ARM_IPA_SIZE_MASK;
1717
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
18-
use kvm_bindings::{CpuId, MsrList, KVM_MAX_MSR_ENTRIES};
18+
use kvm_bindings::{CpuId, MsrList, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES};
1919
use kvm_ioctls::*;
2020
use vmm_sys_util::errno;
2121
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -228,13 +228,18 @@ impl Kvm {
228228
}
229229

230230
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
231-
fn get_cpuid(&self, kind: u64, max_entries_count: usize) -> Result<CpuId> {
232-
let mut cpuid = CpuId::new(max_entries_count);
231+
fn get_cpuid(&self, kind: u64, num_entries: usize) -> Result<CpuId> {
232+
if num_entries > KVM_MAX_CPUID_ENTRIES {
233+
// Returns the same error the underlying `ioctl` would have sent.
234+
return Err(errno::Error::new(libc::ENOMEM));
235+
}
236+
237+
let mut cpuid = CpuId::new(num_entries);
233238

234239
let ret = unsafe {
235240
// ioctl is unsafe. The kernel is trusted not to write beyond the bounds of the memory
236241
// allocated for the struct. The limit is read from nent, which is set to the allocated
237-
// size(max_entries_count) above.
242+
// size(num_entries) above.
238243
ioctl_with_mut_ptr(self, kind, cpuid.as_mut_fam_struct_ptr())
239244
};
240245
if ret < 0 {
@@ -250,7 +255,7 @@ impl Kvm {
250255
///
251256
/// # Arguments
252257
///
253-
/// * `max_entries_count` - Maximum number of CPUID entries. This function can return less than
258+
/// * `num_entries` - Maximum number of CPUID entries. This function can return less than
254259
/// this when the hardware does not support so many CPUID entries.
255260
///
256261
/// # Example
@@ -267,8 +272,8 @@ impl Kvm {
267272
/// ```
268273
///
269274
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
270-
pub fn get_emulated_cpuid(&self, max_entries_count: usize) -> Result<CpuId> {
271-
self.get_cpuid(KVM_GET_EMULATED_CPUID(), max_entries_count)
275+
pub fn get_emulated_cpuid(&self, num_entries: usize) -> Result<CpuId> {
276+
self.get_cpuid(KVM_GET_EMULATED_CPUID(), num_entries)
272277
}
273278

274279
/// X86 specific call to get the system supported CPUID values.
@@ -277,7 +282,7 @@ impl Kvm {
277282
///
278283
/// # Arguments
279284
///
280-
/// * `max_entries_count` - Maximum number of CPUID entries. This function can return less than
285+
/// * `num_entries` - Maximum number of CPUID entries. This function can return less than
281286
/// this when the hardware does not support so many CPUID entries.
282287
///
283288
/// # Example
@@ -294,8 +299,8 @@ impl Kvm {
294299
/// ```
295300
///
296301
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
297-
pub fn get_supported_cpuid(&self, max_entries_count: usize) -> Result<CpuId> {
298-
self.get_cpuid(KVM_GET_SUPPORTED_CPUID(), max_entries_count)
302+
pub fn get_supported_cpuid(&self, num_entries: usize) -> Result<CpuId> {
303+
self.get_cpuid(KVM_GET_SUPPORTED_CPUID(), num_entries)
299304
}
300305

301306
/// X86 specific call to get list of supported MSRS
@@ -593,6 +598,10 @@ mod tests {
593598
let cpuid_entries = cpuid.as_mut_slice();
594599
assert!(!cpuid_entries.is_empty());
595600
assert!(cpuid_entries.len() <= KVM_MAX_CPUID_ENTRIES);
601+
602+
// Test case for more than MAX entries
603+
let cpuid_err = kvm.get_emulated_cpuid(KVM_MAX_CPUID_ENTRIES + 1 as usize);
604+
assert!(cpuid_err.is_err());
596605
}
597606

598607
#[test]
@@ -603,6 +612,10 @@ mod tests {
603612
let cpuid_entries = cpuid.as_mut_slice();
604613
assert!(!cpuid_entries.is_empty());
605614
assert!(cpuid_entries.len() <= KVM_MAX_CPUID_ENTRIES);
615+
616+
// Test case for more than MAX entries
617+
let cpuid_err = kvm.get_emulated_cpuid(KVM_MAX_CPUID_ENTRIES + 1 as usize);
618+
assert!(cpuid_err.is_err());
606619
}
607620

608621
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]

src/ioctls/vcpu.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
1212

1313
use ioctls::{KvmRunWrapper, Result};
1414
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
15-
use kvm_bindings::{CpuId, Msrs};
15+
use kvm_bindings::{CpuId, Msrs, KVM_MAX_CPUID_ENTRIES};
1616
use kvm_ioctls::*;
1717
use vmm_sys_util::errno;
1818
use vmm_sys_util::ioctl::{ioctl, ioctl_with_mut_ref, ioctl_with_ref};
@@ -376,6 +376,11 @@ impl VcpuFd {
376376
///
377377
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
378378
pub fn get_cpuid2(&self, num_entries: usize) -> Result<CpuId> {
379+
if num_entries > KVM_MAX_CPUID_ENTRIES {
380+
// Returns the same error the underlying `ioctl` would have sent.
381+
return Err(errno::Error::new(libc::ENOMEM));
382+
}
383+
379384
let mut cpuid = CpuId::new(num_entries);
380385
let ret = unsafe {
381386
// Here we trust the kernel not to read past the end of the kvm_cpuid2 struct.
@@ -1415,6 +1420,18 @@ mod tests {
14151420
}
14161421
}
14171422

1423+
#[cfg(target_arch = "x86_64")]
1424+
#[test]
1425+
fn test_get_cpuid_fail_num_entries_too_high() {
1426+
let kvm = Kvm::new().unwrap();
1427+
if kvm.check_extension(Cap::ExtCpuid) {
1428+
let vm = kvm.create_vm().unwrap();
1429+
let vcpu = vm.create_vcpu(0).unwrap();
1430+
let err_cpuid = vcpu.get_cpuid2(KVM_MAX_CPUID_ENTRIES + 1 as usize);
1431+
assert!(err_cpuid.is_err());
1432+
}
1433+
}
1434+
14181435
#[cfg(target_arch = "x86_64")]
14191436
#[test]
14201437
fn test_set_cpuid() {

0 commit comments

Comments
 (0)