mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-28 00:07:16 +00:00
Merge pull request #6295 from dborquez/add_kernel_module_checks_kvm
kata-ctl: checks for kvm, kvm_intel modules loaded
This commit is contained in:
commit
7fdaab49bc
@ -20,7 +20,7 @@ mod arch_specific {
|
|||||||
|
|
||||||
// List of check functions
|
// List of check functions
|
||||||
static CHECK_LIST: &[CheckItem] = &[CheckItem {
|
static CHECK_LIST: &[CheckItem] = &[CheckItem {
|
||||||
name: CheckType::CheckCpu,
|
name: CheckType::Cpu,
|
||||||
descr: "This parameter performs the host check",
|
descr: "This parameter performs the host check",
|
||||||
fp: check,
|
fp: check,
|
||||||
perm: PermissionType::NonPrivileged,
|
perm: PermissionType::NonPrivileged,
|
||||||
|
@ -60,7 +60,7 @@ mod arch_specific {
|
|||||||
|
|
||||||
// List of check functions
|
// List of check functions
|
||||||
static CHECK_LIST: &[CheckItem] = &[CheckItem {
|
static CHECK_LIST: &[CheckItem] = &[CheckItem {
|
||||||
name: CheckType::CheckCpu,
|
name: CheckType::Cpu,
|
||||||
descr: "This parameter performs the cpu check",
|
descr: "This parameter performs the cpu check",
|
||||||
fp: check,
|
fp: check,
|
||||||
perm: PermissionType::NonPrivileged,
|
perm: PermissionType::NonPrivileged,
|
||||||
|
@ -21,16 +21,43 @@ mod arch_specific {
|
|||||||
const CPUINFO_FLAGS_TAG: &str = "flags";
|
const CPUINFO_FLAGS_TAG: &str = "flags";
|
||||||
const CPU_FLAGS_INTEL: &[&str] = &["lm", "sse4_1", "vmx"];
|
const CPU_FLAGS_INTEL: &[&str] = &["lm", "sse4_1", "vmx"];
|
||||||
const CPU_ATTRIBS_INTEL: &[&str] = &["GenuineIntel"];
|
const CPU_ATTRIBS_INTEL: &[&str] = &["GenuineIntel"];
|
||||||
|
const VMM_FLAGS: &[&str] = &["hypervisor"];
|
||||||
|
|
||||||
pub const ARCH_CPU_VENDOR_FIELD: &str = check::GENERIC_CPU_VENDOR_FIELD;
|
pub const ARCH_CPU_VENDOR_FIELD: &str = check::GENERIC_CPU_VENDOR_FIELD;
|
||||||
pub const ARCH_CPU_MODEL_FIELD: &str = check::GENERIC_CPU_MODEL_FIELD;
|
pub const ARCH_CPU_MODEL_FIELD: &str = check::GENERIC_CPU_MODEL_FIELD;
|
||||||
|
|
||||||
// List of check functions
|
// List of check functions
|
||||||
static CHECK_LIST: &[CheckItem] = &[CheckItem {
|
static CHECK_LIST: &[CheckItem] = &[
|
||||||
name: CheckType::CheckCpu,
|
CheckItem {
|
||||||
descr: "This parameter performs the cpu check",
|
name: CheckType::Cpu,
|
||||||
fp: check_cpu,
|
descr: "This parameter performs the cpu check",
|
||||||
perm: PermissionType::NonPrivileged,
|
fp: check_cpu,
|
||||||
}];
|
perm: PermissionType::NonPrivileged,
|
||||||
|
},
|
||||||
|
CheckItem {
|
||||||
|
name: CheckType::KernelModules,
|
||||||
|
descr: "This parameter performs the kvm check",
|
||||||
|
fp: check_kernel_modules,
|
||||||
|
perm: PermissionType::NonPrivileged,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
static MODULE_LIST: &[KernelModule] = &[
|
||||||
|
KernelModule {
|
||||||
|
name: "kvm",
|
||||||
|
parameter: KernelParam {
|
||||||
|
name: "kvmclock_periodic_sync",
|
||||||
|
value: KernelParamType::Simple("Y"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
KernelModule {
|
||||||
|
name: "kvm_intel",
|
||||||
|
parameter: KernelParam {
|
||||||
|
name: "unrestricted_guest",
|
||||||
|
value: KernelParamType::Predicate(unrestricted_guest_param_check),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
pub fn get_checks() -> Option<&'static [CheckItem<'static>]> {
|
pub fn get_checks() -> Option<&'static [CheckItem<'static>]> {
|
||||||
Some(CHECK_LIST)
|
Some(CHECK_LIST)
|
||||||
@ -141,6 +168,120 @@ mod arch_specific {
|
|||||||
|
|
||||||
Ok(GuestProtection::NoProtection)
|
Ok(GuestProtection::NoProtection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn running_on_vmm() -> Result<bool> {
|
||||||
|
match check::get_single_cpu_info(check::PROC_CPUINFO, CPUINFO_DELIMITER) {
|
||||||
|
Ok(cpu_info) => {
|
||||||
|
// check if the 'hypervisor' flag exist in the cpu features
|
||||||
|
let missing_hypervisor_flag = check::check_cpu_attribs(&cpu_info, VMM_FLAGS)?;
|
||||||
|
|
||||||
|
if missing_hypervisor_flag.is_empty() {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Unable to determine if the OS is running on a VM: {}: {}",
|
||||||
|
e,
|
||||||
|
check::PROC_CPUINFO
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the host kernel parameter value is valid
|
||||||
|
// and check if we are running inside a VMM
|
||||||
|
fn unrestricted_guest_param_check(
|
||||||
|
module: &str,
|
||||||
|
param_name: &str,
|
||||||
|
param_value_host: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let expected_param_value: char = 'Y';
|
||||||
|
|
||||||
|
let running_on_vmm_alt = running_on_vmm()?;
|
||||||
|
|
||||||
|
if running_on_vmm_alt {
|
||||||
|
let msg = format!("You are running in a VM, where the kernel module '{}' parameter '{:}' has a value '{:}'. This causes conflict when running kata.",
|
||||||
|
module,
|
||||||
|
param_name,
|
||||||
|
param_value_host
|
||||||
|
);
|
||||||
|
return Err(anyhow!(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if param_value_host == expected_param_value.to_string() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let error_msg = format!(
|
||||||
|
"Kernel Module: '{:}' parameter '{:}' should have value '{:}', but found '{:}.'.",
|
||||||
|
module, param_name, expected_param_value, param_value_host
|
||||||
|
);
|
||||||
|
|
||||||
|
let action_msg = format!("Remove the '{:}' module using `rmmod` and then reload using `modprobe`, setting '{:}={:}'",
|
||||||
|
module,
|
||||||
|
param_name,
|
||||||
|
expected_param_value
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(anyhow!("{} {}", error_msg, action_msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_kernel_param(
|
||||||
|
module: &str,
|
||||||
|
param_name: &str,
|
||||||
|
param_value_host: &str,
|
||||||
|
param_type: KernelParamType,
|
||||||
|
) -> Result<()> {
|
||||||
|
match param_type {
|
||||||
|
KernelParamType::Simple(param_value_req) => {
|
||||||
|
if param_value_host != param_value_req {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Kernel module '{}': parameter '{}' should have value '{}', but found '{}'",
|
||||||
|
module,
|
||||||
|
param_name,
|
||||||
|
param_value_req,
|
||||||
|
param_value_host
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
KernelParamType::Predicate(pred_func) => {
|
||||||
|
pred_func(module, param_name, param_value_host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_kernel_modules(_args: &str) -> Result<()> {
|
||||||
|
println!("INFO: check kernel modules for: x86_64");
|
||||||
|
|
||||||
|
for module in MODULE_LIST {
|
||||||
|
let module_loaded =
|
||||||
|
check::check_kernel_module_loaded(module.name, module.parameter.name);
|
||||||
|
|
||||||
|
match module_loaded {
|
||||||
|
Ok(param_value_host) => {
|
||||||
|
let parameter_check = check_kernel_param(
|
||||||
|
module.name,
|
||||||
|
module.parameter.name,
|
||||||
|
¶m_value_host,
|
||||||
|
module.parameter.value.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
match parameter_check {
|
||||||
|
Ok(_v) => println!("{} Ok", module.name),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("WARNING {:}", err.replace('\n', ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
@ -9,6 +9,10 @@ use anyhow::{anyhow, Result};
|
|||||||
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
|
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64"))]
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||||
struct Release {
|
struct Release {
|
||||||
tag_name: String,
|
tag_name: String,
|
||||||
@ -17,6 +21,12 @@ struct Release {
|
|||||||
tarball_url: String,
|
tarball_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
const MODPROBE_PATH: &str = "/sbin/modprobe";
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
const MODINFO_PATH: &str = "/sbin/modinfo";
|
||||||
|
|
||||||
const KATA_GITHUB_RELEASE_URL: &str =
|
const KATA_GITHUB_RELEASE_URL: &str =
|
||||||
"https://api.github.com/repos/kata-containers/kata-containers/releases";
|
"https://api.github.com/repos/kata-containers/kata-containers/releases";
|
||||||
|
|
||||||
@ -29,6 +39,7 @@ const ERR_NO_CPUINFO: &str = "cpu_info string is empty";
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const GENERIC_CPU_VENDOR_FIELD: &str = "vendor_id";
|
pub const GENERIC_CPU_VENDOR_FIELD: &str = "vendor_id";
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const GENERIC_CPU_MODEL_FIELD: &str = "model name";
|
pub const GENERIC_CPU_MODEL_FIELD: &str = "model name";
|
||||||
|
|
||||||
@ -36,8 +47,8 @@ pub const GENERIC_CPU_MODEL_FIELD: &str = "model name";
|
|||||||
pub const PROC_CPUINFO: &str = "/proc/cpuinfo";
|
pub const PROC_CPUINFO: &str = "/proc/cpuinfo";
|
||||||
|
|
||||||
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
||||||
fn get_cpu_info(cpu_info_file: &str) -> Result<String> {
|
fn read_file_contents(file_path: &str) -> Result<String> {
|
||||||
let contents = std::fs::read_to_string(cpu_info_file)?;
|
let contents = std::fs::read_to_string(file_path)?;
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +56,7 @@ fn get_cpu_info(cpu_info_file: &str) -> Result<String> {
|
|||||||
// the specified cpuinfo file by parsing based on a specified delimiter
|
// the specified cpuinfo file by parsing based on a specified delimiter
|
||||||
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
||||||
pub fn get_single_cpu_info(cpu_info_file: &str, substring: &str) -> Result<String> {
|
pub fn get_single_cpu_info(cpu_info_file: &str, substring: &str) -> Result<String> {
|
||||||
let contents = get_cpu_info(cpu_info_file)?;
|
let contents = read_file_contents(cpu_info_file)?;
|
||||||
|
|
||||||
if contents.is_empty() {
|
if contents.is_empty() {
|
||||||
return Err(anyhow!(ERR_NO_CPUINFO));
|
return Err(anyhow!(ERR_NO_CPUINFO));
|
||||||
@ -57,7 +68,6 @@ pub fn get_single_cpu_info(cpu_info_file: &str, substring: &str) -> Result<Strin
|
|||||||
.ok_or("error splitting contents of cpuinfo")
|
.ok_or("error splitting contents of cpuinfo")
|
||||||
.map_err(|e| anyhow!(e))?
|
.map_err(|e| anyhow!(e))?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +80,7 @@ pub fn get_cpu_flags(cpu_info: &str, cpu_flags_tag: &str) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cpu_flags_tag.is_empty() {
|
if cpu_flags_tag.is_empty() {
|
||||||
return Err(anyhow!("cpu flags delimiter string is empty"));
|
return Err(anyhow!("cpu flags delimiter string is empty"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let subcontents: Vec<&str> = cpu_info.split('\n').collect();
|
let subcontents: Vec<&str> = cpu_info.split('\n').collect();
|
||||||
@ -222,6 +232,86 @@ pub fn check_official_releases() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64"))]
|
||||||
|
pub fn check_kernel_module_loaded(module: &str, parameter: &str) -> Result<String, String> {
|
||||||
|
const MODPROBE_PARAMETERS_DRY_RUN: &str = "--dry-run";
|
||||||
|
const MODPROBE_PARAMETERS_FIRST_TIME: &str = "--first-time";
|
||||||
|
const MODULES_PATH: &str = "/sys/module";
|
||||||
|
|
||||||
|
let status_modinfo_success;
|
||||||
|
|
||||||
|
// Partial check w/ modinfo
|
||||||
|
// verifies that the module exists
|
||||||
|
match Command::new(MODINFO_PATH)
|
||||||
|
.arg(module)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
Ok(v) => {
|
||||||
|
status_modinfo_success = v.status.success();
|
||||||
|
|
||||||
|
// The module is already not loaded.
|
||||||
|
if !status_modinfo_success {
|
||||||
|
let msg = String::from_utf8_lossy(&v.stderr).replace('\n', "");
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_e) => {
|
||||||
|
let msg = format!(
|
||||||
|
"Command {:} not found, verify that `kmod` package is already installed.",
|
||||||
|
MODINFO_PATH,
|
||||||
|
);
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Partial check w/ modprobe
|
||||||
|
// check that the module is already loaded
|
||||||
|
match Command::new(MODPROBE_PATH)
|
||||||
|
.arg(MODPROBE_PARAMETERS_DRY_RUN)
|
||||||
|
.arg(MODPROBE_PARAMETERS_FIRST_TIME)
|
||||||
|
.arg(module)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
Ok(v) => {
|
||||||
|
// a successful simulated modprobe insert, means the module is not already loaded
|
||||||
|
let status_modprobe_success = v.status.success();
|
||||||
|
|
||||||
|
if status_modprobe_success && status_modinfo_success {
|
||||||
|
// This condition is true in the case that the module exist, but is not already loaded
|
||||||
|
let msg = format!("The kernel module `{:}` exist but is not already loaded. Try reloading it using 'modprobe {:}=Y'",
|
||||||
|
module, module
|
||||||
|
);
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(_e) => {
|
||||||
|
let msg = format!(
|
||||||
|
"Command {:} not found, verify that `kmod` package is already installed.",
|
||||||
|
MODPROBE_PATH,
|
||||||
|
);
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let module_path = format!("{}/{}/parameters/{}", MODULES_PATH, module, parameter);
|
||||||
|
|
||||||
|
// Here the currently loaded kernel parameter value
|
||||||
|
// is retrieved and returned on success
|
||||||
|
match read_file_contents(&module_path) {
|
||||||
|
Ok(result) => Ok(result.replace('\n', "")),
|
||||||
|
Err(_e) => {
|
||||||
|
let msg = format!(
|
||||||
|
"'{:}' kernel module parameter `{:}` not found.",
|
||||||
|
module, parameter
|
||||||
|
);
|
||||||
|
Err(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -413,4 +503,64 @@ mod tests {
|
|||||||
assert!(!v.minor.to_string().is_empty());
|
assert!(!v.minor.to_string().is_empty());
|
||||||
assert!(!v.patch.to_string().is_empty());
|
assert!(!v.patch.to_string().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64"))]
|
||||||
|
#[test]
|
||||||
|
fn check_module_loaded() {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TestData<'a> {
|
||||||
|
module_name: &'a str,
|
||||||
|
param_name: &'a str,
|
||||||
|
param_value: &'a str,
|
||||||
|
result: Result<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = &[
|
||||||
|
// Failure scenarios
|
||||||
|
TestData {
|
||||||
|
module_name: "",
|
||||||
|
param_name: "",
|
||||||
|
param_value: "",
|
||||||
|
result: Err(anyhow!("modinfo: ERROR: Module {} not found.", "")),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
module_name: "kvm",
|
||||||
|
param_name: "",
|
||||||
|
param_value: "",
|
||||||
|
result: Err(anyhow!(
|
||||||
|
"'{:}' kernel module parameter `{:}` not found.",
|
||||||
|
"kvm",
|
||||||
|
""
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
// Success scenarios
|
||||||
|
TestData {
|
||||||
|
module_name: "kvm",
|
||||||
|
param_name: "kvmclock_periodic_sync",
|
||||||
|
param_value: "Y",
|
||||||
|
result: Ok("Y".to_string()),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, d) in tests.iter().enumerate() {
|
||||||
|
let msg = format!("test[{}]: {:?}", i, d);
|
||||||
|
let result = check_kernel_module_loaded(d.module_name, d.param_name);
|
||||||
|
let msg = format!("{}, result: {:?}", msg, result);
|
||||||
|
|
||||||
|
if d.result.is_ok() {
|
||||||
|
assert_eq!(
|
||||||
|
result.as_ref().unwrap(),
|
||||||
|
d.result.as_ref().unwrap(),
|
||||||
|
"{}",
|
||||||
|
msg
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let expected_error = format!("{}", &d.result.as_ref().unwrap_err());
|
||||||
|
let actual_error = result.unwrap_err().to_string();
|
||||||
|
assert!(actual_error == expected_error, "{}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,15 +73,18 @@ pub fn handle_check(checkcmd: CheckArgument) -> Result<()> {
|
|||||||
match command {
|
match command {
|
||||||
CheckSubCommand::All => {
|
CheckSubCommand::All => {
|
||||||
// run architecture-specific tests
|
// run architecture-specific tests
|
||||||
handle_builtin_check(CheckType::CheckCpu, "")?;
|
handle_builtin_check(CheckType::Cpu, "")?;
|
||||||
|
|
||||||
// run code that uses network checks
|
// run code that uses network checks
|
||||||
check::run_network_checks()?;
|
check::run_network_checks()?;
|
||||||
|
|
||||||
|
// run kernel module checks
|
||||||
|
handle_builtin_check(CheckType::KernelModules, "")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckSubCommand::NoNetworkChecks => {
|
CheckSubCommand::NoNetworkChecks => {
|
||||||
// run architecture-specific tests
|
// run architecture-specific tests
|
||||||
handle_builtin_check(CheckType::CheckCpu, "")?;
|
handle_builtin_check(CheckType::Cpu, "")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckSubCommand::CheckVersionOnly => {
|
CheckSubCommand::CheckVersionOnly => {
|
||||||
|
@ -12,8 +12,9 @@ pub type BuiltinCmdFp = fn(args: &str) -> Result<()>;
|
|||||||
// CheckType encodes the name of each check provided by kata-ctl.
|
// CheckType encodes the name of each check provided by kata-ctl.
|
||||||
#[derive(Debug, strum_macros::Display, EnumString, PartialEq)]
|
#[derive(Debug, strum_macros::Display, EnumString, PartialEq)]
|
||||||
pub enum CheckType {
|
pub enum CheckType {
|
||||||
CheckCpu,
|
Cpu,
|
||||||
CheckNetwork,
|
Network,
|
||||||
|
KernelModules,
|
||||||
}
|
}
|
||||||
|
|
||||||
// PermissionType is used to show whether a check needs to run with elevated (super-user)
|
// PermissionType is used to show whether a check needs to run with elevated (super-user)
|
||||||
@ -33,3 +34,39 @@ pub struct CheckItem<'a> {
|
|||||||
pub fp: BuiltinCmdFp,
|
pub fp: BuiltinCmdFp,
|
||||||
pub perm: PermissionType,
|
pub perm: PermissionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Builtin module parameter check handler type.
|
||||||
|
//
|
||||||
|
// BuiltinModuleParamFp represents a predicate function to determine if a
|
||||||
|
// kernel parameter _value_ is as expected. If not, the returned Error will
|
||||||
|
// explain what is wrong.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// - module: name of kernel module.
|
||||||
|
// - param: name of parameter for the kernel module.
|
||||||
|
// - value: value of the kernel parameter.
|
||||||
|
pub type BuiltinModuleParamFp = fn(module: &str, param: &str, value: &str) -> Result<()>;
|
||||||
|
|
||||||
|
// KernelParamType encodes the value and a handler
|
||||||
|
// function for kernel module parameters
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum KernelParamType<'a> {
|
||||||
|
Simple(&'a str),
|
||||||
|
Predicate(BuiltinModuleParamFp),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters is used to encode the module parameters
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct KernelParam<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub value: KernelParamType<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// KernelModule is used to describe a kernel module along with its required parameters.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct KernelModule<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub parameter: KernelParam<'a>,
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user