mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-10 13:54:12 +00:00
Merge pull request #6379 from cmaf/kata-ctl-check-kvm-1
kata-ctl: add generic kvm check & unit test
This commit is contained in:
commit
13f9ba2298
@ -13,7 +13,7 @@ mod arch_specific {
|
||||
use crate::check::{GuestProtection, ProtectionError};
|
||||
use crate::types::*;
|
||||
use crate::utils;
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use nix::unistd::Uid;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
@ -41,6 +41,12 @@ mod arch_specific {
|
||||
fp: check_kernel_modules,
|
||||
perm: PermissionType::NonPrivileged,
|
||||
},
|
||||
CheckItem {
|
||||
name: CheckType::KvmIsUsable,
|
||||
descr: "This parameter performs check to see if KVM is usable",
|
||||
fp: check_kvm_is_usable,
|
||||
perm: PermissionType::Privileged,
|
||||
},
|
||||
];
|
||||
|
||||
static MODULE_LIST: &[KernelModule] = &[
|
||||
@ -114,6 +120,15 @@ mod arch_specific {
|
||||
utils::get_generic_cpu_details(check::PROC_CPUINFO)
|
||||
}
|
||||
|
||||
// check if kvm is usable
|
||||
fn check_kvm_is_usable(_args: &str) -> Result<()> {
|
||||
println!("INFO: check if kvm is usable: x86_64");
|
||||
|
||||
let result = check::check_kvm_is_usable_generic();
|
||||
|
||||
result.context("KVM check failed")
|
||||
}
|
||||
|
||||
pub const TDX_SYS_FIRMWARE_DIR: &str = "/sys/firmware/tdx_seam/";
|
||||
pub const TDX_CPU_FLAG: &str = "tdx";
|
||||
pub const SEV_KVM_PARAMETER_PATH: &str = "/sys/module/kvm_amd/parameters/sev";
|
||||
|
@ -6,6 +6,10 @@
|
||||
// Contains checks that are not architecture-specific
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use nix::fcntl::{open, OFlag};
|
||||
use nix::sys::stat::Mode;
|
||||
use nix::unistd::close;
|
||||
use nix::{ioctl_write_int_bad, request_code_none};
|
||||
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -176,6 +180,65 @@ pub fn run_network_checks() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Set of basic checks for kvm. Architectures should implement more specific checks if needed
|
||||
#[allow(dead_code)]
|
||||
pub fn check_kvm_is_usable_generic() -> Result<()> {
|
||||
// check for root user
|
||||
if !nix::unistd::Uid::effective().is_root() {
|
||||
return Err(anyhow!("Will not perform kvm checks as non root user"));
|
||||
}
|
||||
|
||||
// we do not want to create syscalls to any device besides /dev/kvm
|
||||
const KVM_DEVICE: &str = "/dev/kvm";
|
||||
|
||||
// constants specific to kvm ioctls found in kvm.h
|
||||
const KVM_IOCTL_ID: u8 = 0xAE;
|
||||
const KVM_CREATE_VM: u8 = 0x01;
|
||||
const KVM_GET_API_VERSION: u8 = 0x00;
|
||||
// per kvm api documentation, this number should always be 12
|
||||
// https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-get-api-version
|
||||
const API_VERSION: i32 = 12;
|
||||
|
||||
// open kvm device
|
||||
// since file is not being created, mode argument is not relevant
|
||||
let mode = Mode::empty();
|
||||
let flags = OFlag::O_RDWR | OFlag::O_CLOEXEC;
|
||||
let fd = open(KVM_DEVICE, flags, mode)?;
|
||||
|
||||
// check kvm api version
|
||||
ioctl_write_int_bad!(
|
||||
kvm_api_version,
|
||||
request_code_none!(KVM_IOCTL_ID, KVM_GET_API_VERSION)
|
||||
);
|
||||
// 0 is not used but required to produce output
|
||||
let v = unsafe { kvm_api_version(fd, 0)? };
|
||||
if v != API_VERSION {
|
||||
return Err(anyhow!("KVM API version is not correct"));
|
||||
}
|
||||
|
||||
// check if you can create vm
|
||||
ioctl_write_int_bad!(
|
||||
kvm_create_vm,
|
||||
request_code_none!(KVM_IOCTL_ID, KVM_CREATE_VM)
|
||||
);
|
||||
// 0 is default machine type
|
||||
let vmfd = unsafe { kvm_create_vm(fd, 0) };
|
||||
let _vmfd = match vmfd {
|
||||
Ok(vm) => vm,
|
||||
Err(ref error) if error.to_string() == "EBUSY: Device or resource busy" => {
|
||||
return Err(anyhow!(
|
||||
"Another hypervisor is running. KVM_CREATE_VM error: {:?}",
|
||||
error
|
||||
))
|
||||
}
|
||||
Err(error) => return Err(anyhow!("Other KVM_CREATE_VM error: {:?}", error)),
|
||||
};
|
||||
|
||||
let _ = close(fd);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_kata_all_releases_by_url(url: &str) -> std::result::Result<Vec<Release>, reqwest::Error> {
|
||||
let releases: Vec<Release> = reqwest::blocking::Client::new()
|
||||
.get(url)
|
||||
@ -332,6 +395,7 @@ mod tests {
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use tempfile::tempdir;
|
||||
use test_utils::skip_if_root;
|
||||
|
||||
#[test]
|
||||
fn test_get_single_cpu_info() {
|
||||
@ -459,6 +523,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_kvm_is_usable_generic() {
|
||||
skip_if_root!();
|
||||
#[allow(dead_code)]
|
||||
let result = check_kvm_is_usable_generic();
|
||||
assert!(
|
||||
result.err().unwrap().to_string() == "Will not perform kvm checks as non root user"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_kata_all_releases_by_url() {
|
||||
#[derive(Debug)]
|
||||
|
@ -80,6 +80,9 @@ pub fn handle_check(checkcmd: CheckArgument) -> Result<()> {
|
||||
|
||||
// run kernel module checks
|
||||
handle_builtin_check(CheckType::KernelModules, "")?;
|
||||
|
||||
// run kvm checks
|
||||
handle_builtin_check(CheckType::KvmIsUsable, "")?;
|
||||
}
|
||||
|
||||
CheckSubCommand::NoNetworkChecks => {
|
||||
|
@ -15,6 +15,7 @@ pub enum CheckType {
|
||||
Cpu,
|
||||
Network,
|
||||
KernelModules,
|
||||
KvmIsUsable,
|
||||
}
|
||||
|
||||
// PermissionType is used to show whether a check needs to run with elevated (super-user)
|
||||
|
Loading…
Reference in New Issue
Block a user