diff --git a/docs/landlock.md b/docs/landlock.md index 4067151c7..9d0ad4edc 100644 --- a/docs/landlock.md +++ b/docs/landlock.md @@ -30,10 +30,7 @@ Linux kernel confirms Landlock support with above message in dmesg. ## Implementation Details 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 -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. +needs to access over its lifetime. Landlock is enabled in the `vm_create` stage. ## Enable Landlock diff --git a/fuzz/fuzz_targets/http_api.rs b/fuzz/fuzz_targets/http_api.rs index 553c338d5..a3f328630 100644 --- a/fuzz/fuzz_targets/http_api.rs +++ b/fuzz/fuzz_targets/http_api.rs @@ -190,8 +190,6 @@ impl RequestHandler for StubApiRequestHandler { platform: None, tpm: None, preserved_fds: None, - landlock_enable: false, - landlock_config: None, })), state: VmState::Running, memory_actual_size: 0, diff --git a/src/main.rs b/src/main.rs index 451c9985c..a724de52d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -285,14 +285,14 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String ) .action(ArgAction::SetTrue) .default_value("false") - .group("vm-config"), + .group("vmm-config"), ) .arg( Arg::new("landlock-rules") .long("landlock-rules") .help(config::LandlockConfig::SYNTAX) .num_args(1..) - .group("vm-config"), + .group("vmm-config"), ) .arg( Arg::new("net") @@ -657,7 +657,31 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result, Error> { let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?; let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?; + let landlock_enable = cmd_arguments.get_flag("landlock"); + let landlock_config_str_vec: Option> = cmd_arguments + .get_many::("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::>>() + .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)] let mut event_monitor = cmd_arguments @@ -755,6 +779,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result, Error> { &seccomp_action, hypervisor, landlock_enable, + landlock_config, ) .map_err(Error::StartVmmThread)?; @@ -1065,8 +1090,6 @@ mod unit_tests { platform: None, tpm: None, preserved_fds: None, - landlock_enable: false, - landlock_config: None, }; assert_eq!(expected_vm_config, result_vm_config); diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 6a9665e66..e54fdd938 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -496,8 +496,6 @@ pub struct VmParams<'a> { pub igvm: Option<&'a str>, #[cfg(feature = "sev_snp")] pub host_data: Option<&'a str>, - pub landlock_enable: bool, - pub landlock_config: Option>, } impl<'a> VmParams<'a> { @@ -563,10 +561,6 @@ impl<'a> VmParams<'a> { let igvm = args.get_one::("igvm").map(|x| x as &str); #[cfg(feature = "sev_snp")] let host_data = args.get_one::("host-data").map(|x| x as &str); - let landlock_enable = args.get_flag("landlock"); - let landlock_config: Option> = args - .get_many::("landlock-rules") - .map(|x| x.map(|y| y as &str).collect()); VmParams { cpus, @@ -605,8 +599,6 @@ impl<'a> VmParams<'a> { igvm, #[cfg(feature = "sev_snp")] 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 { pub const SYNTAX: &'static str = "Landlock parameters \ \"path=,access=[rw]\""; @@ -2725,12 +2723,6 @@ impl VmConfig { .map(|p| p.iommu_segments.is_some()) .unwrap_or_default(); - if let Some(landlock_configs) = &self.landlock_config { - for landlock_config in landlock_configs { - landlock_config.validate()?; - } - } - Ok(id_list) } @@ -2901,16 +2893,6 @@ impl VmConfig { #[cfg(feature = "guest_debug")] let gdb = vm_params.gdb; - let mut landlock_config: Option> = None; - if let Some(ll_config) = vm_params.landlock_config { - landlock_config = Some( - ll_config - .iter() - .map(|rule| LandlockConfig::parse(rule)) - .collect::>>()?, - ); - } - let mut config = VmConfig { cpus: CpusConfig::parse(vm_params.cpus)?, memory: MemoryConfig::parse(vm_params.memory, vm_params.memory_zones)?, @@ -2942,8 +2924,6 @@ impl VmConfig { platform, tpm, preserved_fds: None, - landlock_enable: vm_params.landlock_enable, - landlock_config, }; config.validate().map_err(Error::Validation)?; Ok(config) @@ -3070,7 +3050,6 @@ impl Clone for VmConfig { .as_ref() // SAFETY: FFI call with valid FDs .map(|fds| fds.iter().map(|fd| unsafe { libc::dup(*fd) }).collect()), - landlock_config: self.landlock_config.clone(), ..*self } } @@ -3869,8 +3848,6 @@ mod tests { ..net_fixture() }, ]), - landlock_enable: false, - landlock_config: None, }; let valid_config = RestoreConfig { @@ -4059,8 +4036,6 @@ mod tests { platform: None, tpm: None, preserved_fds: None, - landlock_enable: false, - landlock_config: None, }; assert!(valid_config.validate().is_ok()); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 8a65e5e57..871cd91ef 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -12,8 +12,11 @@ use crate::api::{ ApiRequest, ApiResponse, RequestHandler, VmInfoResponse, VmReceiveMigrationData, VmSendMigrationData, VmmPingResponse, }; +#[cfg(target_arch = "x86_64")] +use crate::config::DebugConsoleConfig; 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, }; #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] @@ -39,6 +42,7 @@ use serde::ser::{SerializeStruct, Serializer}; use serde::{Deserialize, Serialize}; use signal_hook::iterator::{Handle, Signals}; use std::collections::HashMap; +use std::fs; use std::fs::File; use std::io; use std::io::{stdout, Read, Write}; @@ -413,6 +417,7 @@ pub fn start_vmm_thread( seccomp_action: &SeccompAction, hypervisor: Arc, landlock_enable: bool, + landlock_config: Option>, ) -> Result { #[cfg(feature = "guest_debug")] let gdb_hw_breakpoints = hypervisor.get_guest_debug_hw_bps(); @@ -451,6 +456,8 @@ pub fn start_vmm_thread( vmm_seccomp_action, hypervisor, exit_event, + landlock_enable, + landlock_config, )?; vmm.setup_signal_handler(landlock_enable)?; @@ -578,6 +585,8 @@ pub struct Vmm { original_termios_opt: Arc>>, console_resize_pipe: Option, console_info: Option, + landlock_enable: bool, + landlock_config: Option>, } impl Vmm { @@ -684,6 +693,8 @@ impl Vmm { seccomp_action: SeccompAction, hypervisor: Arc, exit_evt: EventFd, + landlock_enable: bool, + landlock_config: Option>, ) -> Result { let mut epoll = EpollContext::new().map_err(Error::Epoll)?; 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)), console_resize_pipe: None, console_info: None, + landlock_enable, + landlock_config, }) } @@ -766,15 +779,12 @@ impl Vmm { MigratableError::MigrateReceive(anyhow!("Error creating console devices: {:?}", e)) })?); - if self - .vm_config - .as_ref() - .unwrap() - .lock() - .unwrap() - .landlock_enable - { - apply_landlock(self.vm_config.as_ref().unwrap().clone()).map_err(|e| { + if self.landlock_enable { + apply_landlock( + &self.vm_config.as_ref().unwrap().clone(), + &self.landlock_config, + ) + .map_err(|e| { MigratableError::MigrateReceive(anyhow!("Error applying landlock: {:?}", e)) })?; } @@ -1264,8 +1274,236 @@ impl Vmm { } } -fn apply_landlock(vm_config: Arc>) -> result::Result<(), LandlockError> { - vm_config.lock().unwrap().apply_landlock()?; +pub type LandlockResult = result::Result; +/// 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>, + landlock_config: &Option>, +) -> 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(()) } @@ -1278,16 +1516,12 @@ impl RequestHandler for Vmm { self.console_info = Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?); - if self - .vm_config - .as_ref() - .unwrap() - .lock() - .unwrap() - .landlock_enable - { - apply_landlock(self.vm_config.as_ref().unwrap().clone()) - .map_err(VmError::ApplyLandlock)?; + if self.landlock_enable { + apply_landlock( + &self.vm_config.as_ref().unwrap().clone(), + &self.landlock_config, + ) + .map_err(VmError::ApplyLandlock)?; } Ok(()) } else { @@ -1472,16 +1706,12 @@ impl RequestHandler for Vmm { )?; self.vm = Some(vm); - if self - .vm_config - .as_ref() - .unwrap() - .lock() - .unwrap() - .landlock_enable - { - apply_landlock(self.vm_config.as_ref().unwrap().clone()) - .map_err(VmError::ApplyLandlock)?; + if self.landlock_enable { + apply_landlock( + &self.vm_config.as_ref().unwrap().clone(), + &self.landlock_config, + ) + .map_err(VmError::ApplyLandlock)?; } // Now we can restore the rest of the VM. @@ -2195,6 +2425,8 @@ mod unit_tests { SeccompAction::Allow, hypervisor::new().unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(), + false, + None, ) .unwrap() } @@ -2273,8 +2505,6 @@ mod unit_tests { platform: None, tpm: None, preserved_fds: None, - landlock_enable: false, - landlock_config: None, })) } diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index 51de9af05..1f323df06 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -2,20 +2,11 @@ // // SPDX-License-Identifier: Apache-2.0 // -use crate::{landlock::LandlockError, Landlock}; use net_util::MacAddr; use serde::{Deserialize, Serialize}; -use std::{fs, net::Ipv4Addr, path::PathBuf, result}; +use std::{net::Ipv4Addr, path::PathBuf}; use virtio_devices::RateLimiterConfig; -pub type LandlockResult = result::Result; - -/// 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)] pub struct CpuAffinity { pub vcpu: u8, @@ -141,15 +132,6 @@ pub struct MemoryZoneConfig { 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)] pub enum HotplugMethod { #[default] @@ -263,15 +245,6 @@ pub struct DiskConfig { pub queue_affinity: Option>, } -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 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)] pub struct BalloonConfig { pub size: u64, @@ -446,13 +411,6 @@ pub fn default_fsconfig_queue_size() -> u16 { 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)] pub struct PmemConfig { pub file: PathBuf, @@ -468,13 +426,6 @@ pub struct PmemConfig { 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)] pub enum ConsoleOutputMode { Off, @@ -499,18 +450,6 @@ pub fn default_consoleconfig_file() -> Option { 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")] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 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)] pub struct DeviceConfig { @@ -554,22 +484,6 @@ pub struct DeviceConfig { pub x_nv_gpudirect_clique: Option, } -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)] pub struct UserDeviceConfig { pub socket: PathBuf, @@ -579,13 +493,6 @@ pub struct UserDeviceConfig { 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)] pub struct VdpaConfig { pub path: PathBuf, @@ -603,13 +510,6 @@ pub fn default_vdpaconfig_num_queues() -> usize { 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)] pub struct VsockConfig { pub cid: u32, @@ -622,13 +522,6 @@ pub struct VsockConfig { 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")] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct SgxEpcConfig { @@ -682,30 +575,6 @@ pub struct PayloadConfig { pub host_data: Option, } -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 { ConsoleConfig { file: None, @@ -729,26 +598,6 @@ pub struct TpmConfig { 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)] pub struct VmConfig { #[serde(default)] @@ -796,94 +645,4 @@ pub struct VmConfig { // valid, and will be closed when the holding VmConfig instance is destroyed. #[serde(skip)] pub preserved_fds: Option>, - #[serde(default)] - pub landlock_enable: bool, - pub landlock_config: Option>, -} - -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(()) - } }