mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-03 03:15:20 +00:00
vmm: make landlock configs VMM-level config
This requires stashing the config values in `struct Vmm`. The configs should be validated before before creating the VMM thread. Refactor the code and update documentation where necessary. The place where the rules are applied remain the same. Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
parent
8452edfcc7
commit
94929889ac
@ -30,10 +30,7 @@ Linux kernel confirms Landlock support with above message in dmesg.
|
|||||||
## Implementation Details
|
## Implementation Details
|
||||||
|
|
||||||
To enable Landlock, Cloud-Hypervisor process needs the full list of files it
|
To enable Landlock, Cloud-Hypervisor process needs the full list of files it
|
||||||
needs to access over its lifetime. Most of these files are received as VM
|
needs to access over its lifetime. Landlock is enabled in the `vm_create` stage.
|
||||||
Configuration (`struct VmConfig`). Landlock is enabled in `vm_create` stage, as
|
|
||||||
this is the earliest stage in guest boot sequence which has access to guest's
|
|
||||||
VM Configuration.
|
|
||||||
|
|
||||||
## Enable Landlock
|
## Enable Landlock
|
||||||
|
|
||||||
|
@ -190,8 +190,6 @@ impl RequestHandler for StubApiRequestHandler {
|
|||||||
platform: None,
|
platform: None,
|
||||||
tpm: None,
|
tpm: None,
|
||||||
preserved_fds: None,
|
preserved_fds: None,
|
||||||
landlock_enable: false,
|
|
||||||
landlock_config: None,
|
|
||||||
})),
|
})),
|
||||||
state: VmState::Running,
|
state: VmState::Running,
|
||||||
memory_actual_size: 0,
|
memory_actual_size: 0,
|
||||||
|
31
src/main.rs
31
src/main.rs
@ -285,14 +285,14 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
|
|||||||
)
|
)
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.default_value("false")
|
.default_value("false")
|
||||||
.group("vm-config"),
|
.group("vmm-config"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("landlock-rules")
|
Arg::new("landlock-rules")
|
||||||
.long("landlock-rules")
|
.long("landlock-rules")
|
||||||
.help(config::LandlockConfig::SYNTAX)
|
.help(config::LandlockConfig::SYNTAX)
|
||||||
.num_args(1..)
|
.num_args(1..)
|
||||||
.group("vm-config"),
|
.group("vmm-config"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("net")
|
Arg::new("net")
|
||||||
@ -657,7 +657,31 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
|
|||||||
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
|
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
|
||||||
|
|
||||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
||||||
|
|
||||||
let landlock_enable = cmd_arguments.get_flag("landlock");
|
let landlock_enable = cmd_arguments.get_flag("landlock");
|
||||||
|
let landlock_config_str_vec: Option<Vec<&str>> = cmd_arguments
|
||||||
|
.get_many::<String>("landlock-rules")
|
||||||
|
.map(|x| x.map(|y| y as &str).collect());
|
||||||
|
|
||||||
|
let landlock_config = if let Some(str_vec) = landlock_config_str_vec {
|
||||||
|
Some(
|
||||||
|
str_vec
|
||||||
|
.into_iter()
|
||||||
|
.map(config::LandlockConfig::parse)
|
||||||
|
.collect::<config::Result<Vec<config::LandlockConfig>>>()
|
||||||
|
.map_err(Error::ParsingConfig)?,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(lc) = landlock_config.as_ref() {
|
||||||
|
for c in lc.iter() {
|
||||||
|
c.validate()
|
||||||
|
.map_err(config::Error::Validation)
|
||||||
|
.map_err(Error::ParsingConfig)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut event_monitor = cmd_arguments
|
let mut event_monitor = cmd_arguments
|
||||||
@ -755,6 +779,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
|
|||||||
&seccomp_action,
|
&seccomp_action,
|
||||||
hypervisor,
|
hypervisor,
|
||||||
landlock_enable,
|
landlock_enable,
|
||||||
|
landlock_config,
|
||||||
)
|
)
|
||||||
.map_err(Error::StartVmmThread)?;
|
.map_err(Error::StartVmmThread)?;
|
||||||
|
|
||||||
@ -1065,8 +1090,6 @@ mod unit_tests {
|
|||||||
platform: None,
|
platform: None,
|
||||||
tpm: None,
|
tpm: None,
|
||||||
preserved_fds: None,
|
preserved_fds: None,
|
||||||
landlock_enable: false,
|
|
||||||
landlock_config: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(expected_vm_config, result_vm_config);
|
assert_eq!(expected_vm_config, result_vm_config);
|
||||||
|
@ -496,8 +496,6 @@ pub struct VmParams<'a> {
|
|||||||
pub igvm: Option<&'a str>,
|
pub igvm: Option<&'a str>,
|
||||||
#[cfg(feature = "sev_snp")]
|
#[cfg(feature = "sev_snp")]
|
||||||
pub host_data: Option<&'a str>,
|
pub host_data: Option<&'a str>,
|
||||||
pub landlock_enable: bool,
|
|
||||||
pub landlock_config: Option<Vec<&'a str>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmParams<'a> {
|
impl<'a> VmParams<'a> {
|
||||||
@ -563,10 +561,6 @@ impl<'a> VmParams<'a> {
|
|||||||
let igvm = args.get_one::<String>("igvm").map(|x| x as &str);
|
let igvm = args.get_one::<String>("igvm").map(|x| x as &str);
|
||||||
#[cfg(feature = "sev_snp")]
|
#[cfg(feature = "sev_snp")]
|
||||||
let host_data = args.get_one::<String>("host-data").map(|x| x as &str);
|
let host_data = args.get_one::<String>("host-data").map(|x| x as &str);
|
||||||
let landlock_enable = args.get_flag("landlock");
|
|
||||||
let landlock_config: Option<Vec<&str>> = args
|
|
||||||
.get_many::<String>("landlock-rules")
|
|
||||||
.map(|x| x.map(|y| y as &str).collect());
|
|
||||||
|
|
||||||
VmParams {
|
VmParams {
|
||||||
cpus,
|
cpus,
|
||||||
@ -605,8 +599,6 @@ impl<'a> VmParams<'a> {
|
|||||||
igvm,
|
igvm,
|
||||||
#[cfg(feature = "sev_snp")]
|
#[cfg(feature = "sev_snp")]
|
||||||
host_data,
|
host_data,
|
||||||
landlock_enable,
|
|
||||||
landlock_config,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2334,6 +2326,12 @@ impl TpmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
|
pub struct LandlockConfig {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub access: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl LandlockConfig {
|
impl LandlockConfig {
|
||||||
pub const SYNTAX: &'static str = "Landlock parameters \
|
pub const SYNTAX: &'static str = "Landlock parameters \
|
||||||
\"path=<path/to/{file/dir}>,access=[rw]\"";
|
\"path=<path/to/{file/dir}>,access=[rw]\"";
|
||||||
@ -2725,12 +2723,6 @@ impl VmConfig {
|
|||||||
.map(|p| p.iommu_segments.is_some())
|
.map(|p| p.iommu_segments.is_some())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if let Some(landlock_configs) = &self.landlock_config {
|
|
||||||
for landlock_config in landlock_configs {
|
|
||||||
landlock_config.validate()?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(id_list)
|
Ok(id_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2901,16 +2893,6 @@ impl VmConfig {
|
|||||||
#[cfg(feature = "guest_debug")]
|
#[cfg(feature = "guest_debug")]
|
||||||
let gdb = vm_params.gdb;
|
let gdb = vm_params.gdb;
|
||||||
|
|
||||||
let mut landlock_config: Option<Vec<LandlockConfig>> = None;
|
|
||||||
if let Some(ll_config) = vm_params.landlock_config {
|
|
||||||
landlock_config = Some(
|
|
||||||
ll_config
|
|
||||||
.iter()
|
|
||||||
.map(|rule| LandlockConfig::parse(rule))
|
|
||||||
.collect::<Result<Vec<LandlockConfig>>>()?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut config = VmConfig {
|
let mut config = VmConfig {
|
||||||
cpus: CpusConfig::parse(vm_params.cpus)?,
|
cpus: CpusConfig::parse(vm_params.cpus)?,
|
||||||
memory: MemoryConfig::parse(vm_params.memory, vm_params.memory_zones)?,
|
memory: MemoryConfig::parse(vm_params.memory, vm_params.memory_zones)?,
|
||||||
@ -2942,8 +2924,6 @@ impl VmConfig {
|
|||||||
platform,
|
platform,
|
||||||
tpm,
|
tpm,
|
||||||
preserved_fds: None,
|
preserved_fds: None,
|
||||||
landlock_enable: vm_params.landlock_enable,
|
|
||||||
landlock_config,
|
|
||||||
};
|
};
|
||||||
config.validate().map_err(Error::Validation)?;
|
config.validate().map_err(Error::Validation)?;
|
||||||
Ok(config)
|
Ok(config)
|
||||||
@ -3070,7 +3050,6 @@ impl Clone for VmConfig {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
// SAFETY: FFI call with valid FDs
|
// SAFETY: FFI call with valid FDs
|
||||||
.map(|fds| fds.iter().map(|fd| unsafe { libc::dup(*fd) }).collect()),
|
.map(|fds| fds.iter().map(|fd| unsafe { libc::dup(*fd) }).collect()),
|
||||||
landlock_config: self.landlock_config.clone(),
|
|
||||||
..*self
|
..*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3869,8 +3848,6 @@ mod tests {
|
|||||||
..net_fixture()
|
..net_fixture()
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
landlock_enable: false,
|
|
||||||
landlock_config: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let valid_config = RestoreConfig {
|
let valid_config = RestoreConfig {
|
||||||
@ -4059,8 +4036,6 @@ mod tests {
|
|||||||
platform: None,
|
platform: None,
|
||||||
tpm: None,
|
tpm: None,
|
||||||
preserved_fds: None,
|
preserved_fds: None,
|
||||||
landlock_enable: false,
|
|
||||||
landlock_config: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(valid_config.validate().is_ok());
|
assert!(valid_config.validate().is_ok());
|
||||||
|
298
vmm/src/lib.rs
298
vmm/src/lib.rs
@ -12,8 +12,11 @@ use crate::api::{
|
|||||||
ApiRequest, ApiResponse, RequestHandler, VmInfoResponse, VmReceiveMigrationData,
|
ApiRequest, ApiResponse, RequestHandler, VmInfoResponse, VmReceiveMigrationData,
|
||||||
VmSendMigrationData, VmmPingResponse,
|
VmSendMigrationData, VmmPingResponse,
|
||||||
};
|
};
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::config::DebugConsoleConfig;
|
||||||
use crate::config::{
|
use crate::config::{
|
||||||
add_to_config, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, RestoreConfig,
|
add_to_config, ConsoleConfig, DeviceConfig, DiskConfig, FsConfig, LandlockConfig,
|
||||||
|
MemoryZoneConfig, NetConfig, PayloadConfig, PmemConfig, RestoreConfig, RngConfig, TpmConfig,
|
||||||
UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
|
UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
|
||||||
};
|
};
|
||||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||||
@ -39,6 +42,7 @@ use serde::ser::{SerializeStruct, Serializer};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use signal_hook::iterator::{Handle, Signals};
|
use signal_hook::iterator::{Handle, Signals};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{stdout, Read, Write};
|
use std::io::{stdout, Read, Write};
|
||||||
@ -413,6 +417,7 @@ pub fn start_vmm_thread(
|
|||||||
seccomp_action: &SeccompAction,
|
seccomp_action: &SeccompAction,
|
||||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||||
landlock_enable: bool,
|
landlock_enable: bool,
|
||||||
|
landlock_config: Option<Vec<LandlockConfig>>,
|
||||||
) -> Result<VmmThreadHandle> {
|
) -> Result<VmmThreadHandle> {
|
||||||
#[cfg(feature = "guest_debug")]
|
#[cfg(feature = "guest_debug")]
|
||||||
let gdb_hw_breakpoints = hypervisor.get_guest_debug_hw_bps();
|
let gdb_hw_breakpoints = hypervisor.get_guest_debug_hw_bps();
|
||||||
@ -451,6 +456,8 @@ pub fn start_vmm_thread(
|
|||||||
vmm_seccomp_action,
|
vmm_seccomp_action,
|
||||||
hypervisor,
|
hypervisor,
|
||||||
exit_event,
|
exit_event,
|
||||||
|
landlock_enable,
|
||||||
|
landlock_config,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
vmm.setup_signal_handler(landlock_enable)?;
|
vmm.setup_signal_handler(landlock_enable)?;
|
||||||
@ -578,6 +585,8 @@ pub struct Vmm {
|
|||||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||||
console_resize_pipe: Option<File>,
|
console_resize_pipe: Option<File>,
|
||||||
console_info: Option<ConsoleInfo>,
|
console_info: Option<ConsoleInfo>,
|
||||||
|
landlock_enable: bool,
|
||||||
|
landlock_config: Option<Vec<LandlockConfig>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vmm {
|
impl Vmm {
|
||||||
@ -684,6 +693,8 @@ impl Vmm {
|
|||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
|
landlock_enable: bool,
|
||||||
|
landlock_config: Option<Vec<LandlockConfig>>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let mut epoll = EpollContext::new().map_err(Error::Epoll)?;
|
let mut epoll = EpollContext::new().map_err(Error::Epoll)?;
|
||||||
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||||
@ -730,6 +741,8 @@ impl Vmm {
|
|||||||
original_termios_opt: Arc::new(Mutex::new(None)),
|
original_termios_opt: Arc::new(Mutex::new(None)),
|
||||||
console_resize_pipe: None,
|
console_resize_pipe: None,
|
||||||
console_info: None,
|
console_info: None,
|
||||||
|
landlock_enable,
|
||||||
|
landlock_config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,15 +779,12 @@ impl Vmm {
|
|||||||
MigratableError::MigrateReceive(anyhow!("Error creating console devices: {:?}", e))
|
MigratableError::MigrateReceive(anyhow!("Error creating console devices: {:?}", e))
|
||||||
})?);
|
})?);
|
||||||
|
|
||||||
if self
|
if self.landlock_enable {
|
||||||
.vm_config
|
apply_landlock(
|
||||||
.as_ref()
|
&self.vm_config.as_ref().unwrap().clone(),
|
||||||
.unwrap()
|
&self.landlock_config,
|
||||||
.lock()
|
)
|
||||||
.unwrap()
|
.map_err(|e| {
|
||||||
.landlock_enable
|
|
||||||
{
|
|
||||||
apply_landlock(self.vm_config.as_ref().unwrap().clone()).map_err(|e| {
|
|
||||||
MigratableError::MigrateReceive(anyhow!("Error applying landlock: {:?}", e))
|
MigratableError::MigrateReceive(anyhow!("Error applying landlock: {:?}", e))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -1264,8 +1274,236 @@ impl Vmm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_landlock(vm_config: Arc<Mutex<VmConfig>>) -> result::Result<(), LandlockError> {
|
pub type LandlockResult<T> = result::Result<T, LandlockError>;
|
||||||
vm_config.lock().unwrap().apply_landlock()?;
|
/// Trait to apply Landlock on VmConfig elements
|
||||||
|
pub(crate) trait ApplyLandlock {
|
||||||
|
/// Apply Landlock rules to file paths
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for MemoryZoneConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
if let Some(file) = &self.file {
|
||||||
|
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for DiskConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
if let Some(path) = &self.path {
|
||||||
|
landlock.add_rule_with_access(path.to_path_buf(), "rw")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for RngConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
// Rng Path only need read access
|
||||||
|
landlock.add_rule_with_access(self.src.to_path_buf(), "r")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for FsConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for PmemConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.file.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for ConsoleConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
if let Some(file) = &self.file {
|
||||||
|
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
||||||
|
}
|
||||||
|
if let Some(socket) = &self.socket {
|
||||||
|
landlock.add_rule_with_access(socket.to_path_buf(), "rw")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
impl ApplyLandlock for DebugConsoleConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
if let Some(file) = &self.file {
|
||||||
|
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for DeviceConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
let device_path = fs::read_link(self.path.as_path()).map_err(LandlockError::OpenPath)?;
|
||||||
|
let iommu_group = device_path.file_name();
|
||||||
|
let iommu_group_str = iommu_group
|
||||||
|
.ok_or(LandlockError::InvalidPath)?
|
||||||
|
.to_str()
|
||||||
|
.ok_or(LandlockError::InvalidPath)?;
|
||||||
|
|
||||||
|
let vfio_group_path = "/dev/vfio/".to_owned() + iommu_group_str;
|
||||||
|
landlock.add_rule_with_access(vfio_group_path.into(), "rw")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for UserDeviceConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for VdpaConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.path.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for VsockConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for PayloadConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
// Payload only needs read access
|
||||||
|
if let Some(firmware) = &self.firmware {
|
||||||
|
landlock.add_rule_with_access(firmware.to_path_buf(), "r")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(kernel) = &self.kernel {
|
||||||
|
landlock.add_rule_with_access(kernel.to_path_buf(), "r")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(initramfs) = &self.initramfs {
|
||||||
|
landlock.add_rule_with_access(initramfs.to_path_buf(), "r")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "igvm")]
|
||||||
|
if let Some(igvm) = &self.igvm {
|
||||||
|
landlock.add_rule_with_access(igvm.to_path_buf(), "r")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for TpmConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplyLandlock for LandlockConfig {
|
||||||
|
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
||||||
|
landlock.add_rule_with_access(self.path.to_path_buf(), self.access.clone().as_str())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_landlock(
|
||||||
|
vm_config: &Arc<Mutex<VmConfig>>,
|
||||||
|
landlock_config: &Option<Vec<LandlockConfig>>,
|
||||||
|
) -> LandlockResult<()> {
|
||||||
|
let vm_config = vm_config.lock().unwrap();
|
||||||
|
let mut landlock = Landlock::new()?;
|
||||||
|
|
||||||
|
if let Some(mem_zones) = &vm_config.memory.zones {
|
||||||
|
for zone in mem_zones.iter() {
|
||||||
|
zone.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let disks = &vm_config.disks;
|
||||||
|
if let Some(disks) = disks {
|
||||||
|
for disk in disks.iter() {
|
||||||
|
disk.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_config.rng.apply_landlock(&mut landlock)?;
|
||||||
|
|
||||||
|
if let Some(fs_configs) = &vm_config.fs {
|
||||||
|
for fs_config in fs_configs.iter() {
|
||||||
|
fs_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pmem_configs) = &vm_config.pmem {
|
||||||
|
for pmem_config in pmem_configs.iter() {
|
||||||
|
pmem_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_config.console.apply_landlock(&mut landlock)?;
|
||||||
|
vm_config.serial.apply_landlock(&mut landlock)?;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
{
|
||||||
|
vm_config.debug_console.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(devices) = &vm_config.devices {
|
||||||
|
landlock.add_rule_with_access("/dev/vfio/vfio".into(), "rw")?;
|
||||||
|
|
||||||
|
for device in devices.iter() {
|
||||||
|
device.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user_devices) = &vm_config.user_devices {
|
||||||
|
for user_devices in user_devices.iter() {
|
||||||
|
user_devices.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(vdpa_configs) = &vm_config.vdpa {
|
||||||
|
for vdpa_config in vdpa_configs.iter() {
|
||||||
|
vdpa_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(vsock_config) = &vm_config.vsock {
|
||||||
|
vsock_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(payload) = &vm_config.payload {
|
||||||
|
payload.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tpm_config) = &vm_config.tpm {
|
||||||
|
tpm_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if vm_config.net.is_some() {
|
||||||
|
landlock.add_rule_with_access("/dev/net/tun".into(), "rw")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(landlock_configs) = landlock_config {
|
||||||
|
for landlock_config in landlock_configs.iter() {
|
||||||
|
landlock_config.apply_landlock(&mut landlock)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
landlock.restrict_self()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,16 +1516,12 @@ impl RequestHandler for Vmm {
|
|||||||
self.console_info =
|
self.console_info =
|
||||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||||
|
|
||||||
if self
|
if self.landlock_enable {
|
||||||
.vm_config
|
apply_landlock(
|
||||||
.as_ref()
|
&self.vm_config.as_ref().unwrap().clone(),
|
||||||
.unwrap()
|
&self.landlock_config,
|
||||||
.lock()
|
)
|
||||||
.unwrap()
|
.map_err(VmError::ApplyLandlock)?;
|
||||||
.landlock_enable
|
|
||||||
{
|
|
||||||
apply_landlock(self.vm_config.as_ref().unwrap().clone())
|
|
||||||
.map_err(VmError::ApplyLandlock)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -1472,16 +1706,12 @@ impl RequestHandler for Vmm {
|
|||||||
)?;
|
)?;
|
||||||
self.vm = Some(vm);
|
self.vm = Some(vm);
|
||||||
|
|
||||||
if self
|
if self.landlock_enable {
|
||||||
.vm_config
|
apply_landlock(
|
||||||
.as_ref()
|
&self.vm_config.as_ref().unwrap().clone(),
|
||||||
.unwrap()
|
&self.landlock_config,
|
||||||
.lock()
|
)
|
||||||
.unwrap()
|
.map_err(VmError::ApplyLandlock)?;
|
||||||
.landlock_enable
|
|
||||||
{
|
|
||||||
apply_landlock(self.vm_config.as_ref().unwrap().clone())
|
|
||||||
.map_err(VmError::ApplyLandlock)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can restore the rest of the VM.
|
// Now we can restore the rest of the VM.
|
||||||
@ -2195,6 +2425,8 @@ mod unit_tests {
|
|||||||
SeccompAction::Allow,
|
SeccompAction::Allow,
|
||||||
hypervisor::new().unwrap(),
|
hypervisor::new().unwrap(),
|
||||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||||
|
false,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
@ -2273,8 +2505,6 @@ mod unit_tests {
|
|||||||
platform: None,
|
platform: None,
|
||||||
tpm: None,
|
tpm: None,
|
||||||
preserved_fds: None,
|
preserved_fds: None,
|
||||||
landlock_enable: false,
|
|
||||||
landlock_config: None,
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,11 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
use crate::{landlock::LandlockError, Landlock};
|
|
||||||
use net_util::MacAddr;
|
use net_util::MacAddr;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fs, net::Ipv4Addr, path::PathBuf, result};
|
use std::{net::Ipv4Addr, path::PathBuf};
|
||||||
use virtio_devices::RateLimiterConfig;
|
use virtio_devices::RateLimiterConfig;
|
||||||
|
|
||||||
pub type LandlockResult<T> = result::Result<T, LandlockError>;
|
|
||||||
|
|
||||||
/// Trait to apply Landlock on VmConfig elements
|
|
||||||
pub(crate) trait ApplyLandlock {
|
|
||||||
/// Apply Landlock rules to file paths
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct CpuAffinity {
|
pub struct CpuAffinity {
|
||||||
pub vcpu: u8,
|
pub vcpu: u8,
|
||||||
@ -141,15 +132,6 @@ pub struct MemoryZoneConfig {
|
|||||||
pub prefault: bool,
|
pub prefault: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for MemoryZoneConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
if let Some(file) = &self.file {
|
|
||||||
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
|
||||||
pub enum HotplugMethod {
|
pub enum HotplugMethod {
|
||||||
#[default]
|
#[default]
|
||||||
@ -263,15 +245,6 @@ pub struct DiskConfig {
|
|||||||
pub queue_affinity: Option<Vec<VirtQueueAffinity>>,
|
pub queue_affinity: Option<Vec<VirtQueueAffinity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for DiskConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
if let Some(path) = &self.path {
|
|
||||||
landlock.add_rule_with_access(path.to_path_buf(), "rw")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const DEFAULT_DISK_NUM_QUEUES: usize = 1;
|
pub const DEFAULT_DISK_NUM_QUEUES: usize = 1;
|
||||||
|
|
||||||
pub fn default_diskconfig_num_queues() -> usize {
|
pub fn default_diskconfig_num_queues() -> usize {
|
||||||
@ -405,14 +378,6 @@ impl Default for RngConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for RngConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
// Rng Path only need read access
|
|
||||||
landlock.add_rule_with_access(self.src.to_path_buf(), "r")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct BalloonConfig {
|
pub struct BalloonConfig {
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
@ -446,13 +411,6 @@ pub fn default_fsconfig_queue_size() -> u16 {
|
|||||||
1024
|
1024
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for FsConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct PmemConfig {
|
pub struct PmemConfig {
|
||||||
pub file: PathBuf,
|
pub file: PathBuf,
|
||||||
@ -468,13 +426,6 @@ pub struct PmemConfig {
|
|||||||
pub pci_segment: u16,
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for PmemConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.file.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum ConsoleOutputMode {
|
pub enum ConsoleOutputMode {
|
||||||
Off,
|
Off,
|
||||||
@ -499,18 +450,6 @@ pub fn default_consoleconfig_file() -> Option<PathBuf> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for ConsoleConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
if let Some(file) = &self.file {
|
|
||||||
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
|
||||||
}
|
|
||||||
if let Some(socket) = &self.socket {
|
|
||||||
landlock.add_rule_with_access(socket.to_path_buf(), "rw")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct DebugConsoleConfig {
|
pub struct DebugConsoleConfig {
|
||||||
@ -531,15 +470,6 @@ impl Default for DebugConsoleConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
impl ApplyLandlock for DebugConsoleConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
if let Some(file) = &self.file {
|
|
||||||
landlock.add_rule_with_access(file.to_path_buf(), "rw")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct DeviceConfig {
|
pub struct DeviceConfig {
|
||||||
@ -554,22 +484,6 @@ pub struct DeviceConfig {
|
|||||||
pub x_nv_gpudirect_clique: Option<u8>,
|
pub x_nv_gpudirect_clique: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for DeviceConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
let device_path = fs::read_link(self.path.as_path()).map_err(LandlockError::OpenPath)?;
|
|
||||||
let iommu_group = device_path.file_name();
|
|
||||||
let iommu_group_str = iommu_group
|
|
||||||
.ok_or(LandlockError::InvalidPath)?
|
|
||||||
.to_str()
|
|
||||||
.ok_or(LandlockError::InvalidPath)?;
|
|
||||||
|
|
||||||
let vfio_group_path = "/dev/vfio/".to_owned() + iommu_group_str;
|
|
||||||
landlock.add_rule_with_access(vfio_group_path.into(), "rw")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct UserDeviceConfig {
|
pub struct UserDeviceConfig {
|
||||||
pub socket: PathBuf,
|
pub socket: PathBuf,
|
||||||
@ -579,13 +493,6 @@ pub struct UserDeviceConfig {
|
|||||||
pub pci_segment: u16,
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for UserDeviceConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct VdpaConfig {
|
pub struct VdpaConfig {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
@ -603,13 +510,6 @@ pub fn default_vdpaconfig_num_queues() -> usize {
|
|||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for VdpaConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.path.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct VsockConfig {
|
pub struct VsockConfig {
|
||||||
pub cid: u32,
|
pub cid: u32,
|
||||||
@ -622,13 +522,6 @@ pub struct VsockConfig {
|
|||||||
pub pci_segment: u16,
|
pub pci_segment: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for VsockConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct SgxEpcConfig {
|
pub struct SgxEpcConfig {
|
||||||
@ -682,30 +575,6 @@ pub struct PayloadConfig {
|
|||||||
pub host_data: Option<String>,
|
pub host_data: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for PayloadConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
// Payload only needs read access
|
|
||||||
if let Some(firmware) = &self.firmware {
|
|
||||||
landlock.add_rule_with_access(firmware.to_path_buf(), "r")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(kernel) = &self.kernel {
|
|
||||||
landlock.add_rule_with_access(kernel.to_path_buf(), "r")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(initramfs) = &self.initramfs {
|
|
||||||
landlock.add_rule_with_access(initramfs.to_path_buf(), "r")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "igvm")]
|
|
||||||
if let Some(igvm) = &self.igvm {
|
|
||||||
landlock.add_rule_with_access(igvm.to_path_buf(), "r")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn default_serial() -> ConsoleConfig {
|
pub fn default_serial() -> ConsoleConfig {
|
||||||
ConsoleConfig {
|
ConsoleConfig {
|
||||||
file: None,
|
file: None,
|
||||||
@ -729,26 +598,6 @@ pub struct TpmConfig {
|
|||||||
pub socket: PathBuf,
|
pub socket: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplyLandlock for TpmConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.socket.to_path_buf(), "rw")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
|
||||||
pub struct LandlockConfig {
|
|
||||||
pub path: PathBuf,
|
|
||||||
pub access: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ApplyLandlock for LandlockConfig {
|
|
||||||
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
|
|
||||||
landlock.add_rule_with_access(self.path.to_path_buf(), self.access.clone().as_str())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct VmConfig {
|
pub struct VmConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -796,94 +645,4 @@ pub struct VmConfig {
|
|||||||
// valid, and will be closed when the holding VmConfig instance is destroyed.
|
// valid, and will be closed when the holding VmConfig instance is destroyed.
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub preserved_fds: Option<Vec<i32>>,
|
pub preserved_fds: Option<Vec<i32>>,
|
||||||
#[serde(default)]
|
|
||||||
pub landlock_enable: bool,
|
|
||||||
pub landlock_config: Option<Vec<LandlockConfig>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VmConfig {
|
|
||||||
pub(crate) fn apply_landlock(&self) -> LandlockResult<()> {
|
|
||||||
let mut landlock = Landlock::new()?;
|
|
||||||
|
|
||||||
if let Some(mem_zones) = &self.memory.zones {
|
|
||||||
for zone in mem_zones.iter() {
|
|
||||||
zone.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let disks = &self.disks;
|
|
||||||
if let Some(disks) = disks {
|
|
||||||
for disk in disks.iter() {
|
|
||||||
disk.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.rng.apply_landlock(&mut landlock)?;
|
|
||||||
|
|
||||||
if let Some(fs_configs) = &self.fs {
|
|
||||||
for fs_config in fs_configs.iter() {
|
|
||||||
fs_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(pmem_configs) = &self.pmem {
|
|
||||||
for pmem_config in pmem_configs.iter() {
|
|
||||||
pmem_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.console.apply_landlock(&mut landlock)?;
|
|
||||||
self.serial.apply_landlock(&mut landlock)?;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
{
|
|
||||||
self.debug_console.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(devices) = &self.devices {
|
|
||||||
landlock.add_rule_with_access("/dev/vfio/vfio".into(), "rw")?;
|
|
||||||
|
|
||||||
for device in devices.iter() {
|
|
||||||
device.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(user_devices) = &self.user_devices {
|
|
||||||
for user_devices in user_devices.iter() {
|
|
||||||
user_devices.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(vdpa_configs) = &self.vdpa {
|
|
||||||
for vdpa_config in vdpa_configs.iter() {
|
|
||||||
vdpa_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(vsock_config) = &self.vsock {
|
|
||||||
vsock_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(payload) = &self.payload {
|
|
||||||
payload.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tpm_config) = &self.tpm {
|
|
||||||
tpm_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.net.is_some() {
|
|
||||||
landlock.add_rule_with_access("/dev/net/tun".into(), "rw")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(landlock_configs) = &self.landlock_config {
|
|
||||||
for landlock_config in landlock_configs.iter() {
|
|
||||||
landlock_config.apply_landlock(&mut landlock)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
landlock.restrict_self()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user