Skip to content

Commit

Permalink
vmm: make landlock configs VMM-level config
Browse files Browse the repository at this point in the history
Treat them like seccomp.

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 <[email protected]>
  • Loading branch information
liuw committed Jul 2, 2024
1 parent feeaaab commit f8a439a
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 315 deletions.
5 changes: 1 addition & 4 deletions docs/landlock.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
31 changes: 27 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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 exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;

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)]
let mut event_monitor = cmd_arguments
Expand Down Expand Up @@ -755,6 +779,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
&seccomp_action,
hypervisor,
landlock_enable,
landlock_config,
)
.map_err(Error::StartVmmThread)?;

Expand Down Expand Up @@ -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);
Expand Down
37 changes: 6 additions & 31 deletions vmm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<&'a str>>,
}

impl<'a> VmParams<'a> {
Expand Down Expand Up @@ -563,10 +561,6 @@ impl<'a> VmParams<'a> {
let igvm = args.get_one::<String>("igvm").map(|x| x as &str);
#[cfg(feature = "sev_snp")]
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 {
cpus,
Expand Down Expand Up @@ -605,8 +599,6 @@ impl<'a> VmParams<'a> {
igvm,
#[cfg(feature = "sev_snp")]
host_data,
landlock_enable,
landlock_config,
}
}
}
Expand Down Expand Up @@ -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=<path/to/{file/dir}>,access=[rw]\"";
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -2901,16 +2893,6 @@ impl VmConfig {
#[cfg(feature = "guest_debug")]
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 {
cpus: CpusConfig::parse(vm_params.cpus)?,
memory: MemoryConfig::parse(vm_params.memory, vm_params.memory_zones)?,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
}
Expand Down Expand Up @@ -3869,8 +3848,6 @@ mod tests {
..net_fixture()
},
]),
landlock_enable: false,
landlock_config: None,
};

let valid_config = RestoreConfig {
Expand Down Expand Up @@ -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());
Expand Down
Loading

0 comments on commit f8a439a

Please sign in to comment.