diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index f5fff4ba06..d9bf095f5c 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -1133,6 +1133,14 @@ pub struct Hypervisor { /// Vendor customized runtime configuration. #[serde(default, flatten)] pub vendor: HypervisorVendor, + + /// Disable applying SELinux on the container process. + #[serde(default = "yes")] + pub disable_guest_selinux: bool, +} + +fn yes() -> bool { + true } impl Hypervisor { diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs b/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs index c00f3204fa..7fa49b96c0 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs @@ -176,6 +176,10 @@ impl Kernel { kernel_params.append(&mut KernelParams::from_string( &config.boot_info.kernel_params, )); + kernel_params.append(&mut KernelParams::from_string(&format!( + "selinux={}", + if config.disable_guest_selinux { 0 } else { 1 } + ))); Ok(Kernel { path: config.boot_info.kernel.clone(), diff --git a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs index d281403a79..486a882a5c 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs @@ -71,7 +71,7 @@ impl ShareVirtioFsStandalone { }) } - fn virtiofsd_args(&self, sock_path: &str) -> Result> { + fn virtiofsd_args(&self, sock_path: &str, disable_guest_selinux: bool) -> Result> { let source_path = get_host_ro_shared_path(&self.config.id); ensure_dir_exist(&source_path)?; let shared_dir = source_path @@ -96,12 +96,19 @@ impl ShareVirtioFsStandalone { args.append(&mut extra_args); } + if !disable_guest_selinux { + args.push(String::from("--xattr")); + } + Ok(args) } async fn setup_virtiofsd(&self, h: &dyn Hypervisor) -> Result<()> { let sock_path = generate_sock_path(&h.get_jailer_root().await?); - let args = self.virtiofsd_args(&sock_path).context("virtiofsd args")?; + let disable_guest_selinux = h.hypervisor_config().await.disable_guest_selinux; + let args = self + .virtiofsd_args(&sock_path, disable_guest_selinux) + .context("virtiofsd args")?; let mut cmd = Command::new(&self.config.virtio_fs_daemon); let child_cmd = cmd.args(&args).stderr(Stdio::piped()); diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs index 2cab538f70..8167f39faf 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs @@ -97,7 +97,23 @@ impl Container { let toml_config = self.resource_manager.config().await; let config = &self.config; let sandbox_pidns = is_pid_namespace_enabled(&spec); - amend_spec(&mut spec, toml_config.runtime.disable_guest_seccomp).context("amend spec")?; + let disable_guest_selinux = match toml_config + .hypervisor + .get(&toml_config.runtime.hypervisor_name) + { + Some(hypervisor_config) => hypervisor_config.disable_guest_selinux, + // This shouldn't happen due to how logic in the config crate works + // but we need to handle it anyway so we stick with the default + // value of disable_guest_selinux in configuration.toml which + // is 'true'. + None => true, + }; + amend_spec( + &mut spec, + toml_config.runtime.disable_guest_seccomp, + disable_guest_selinux, + ) + .context("amend spec")?; // get mutable root from oci spec let root = match spec.root_mut() { @@ -564,7 +580,11 @@ impl Container { } } -fn amend_spec(spec: &mut oci::Spec, disable_guest_seccomp: bool) -> Result<()> { +fn amend_spec( + spec: &mut oci::Spec, + disable_guest_seccomp: bool, + disable_guest_selinux: bool, +) -> Result<()> { // Only the StartContainer hook needs to be reserved for execution in the guest let start_container_hooks = if let Some(hooks) = spec.hooks().as_ref() { hooks.start_container().clone() @@ -609,6 +629,15 @@ fn amend_spec(spec: &mut oci::Spec, disable_guest_seccomp: bool) -> Result<()> { linux.set_namespaces(if ns.is_empty() { None } else { Some(ns) }); } + if disable_guest_selinux { + if let Some(ref mut process) = spec.process_mut() { + process.set_selinux_label(None); + } + if let Some(ref mut linux) = spec.linux_mut() { + linux.set_mount_label(None); + } + } + Ok(()) } @@ -645,14 +674,43 @@ mod tests { assert!(spec.linux().as_ref().unwrap().seccomp().is_some()); // disable_guest_seccomp = false - amend_spec(&mut spec, false).unwrap(); + amend_spec(&mut spec, false, false).unwrap(); assert!(spec.linux().as_ref().unwrap().seccomp().is_some()); // disable_guest_seccomp = true - amend_spec(&mut spec, true).unwrap(); + amend_spec(&mut spec, true, false).unwrap(); assert!(spec.linux().as_ref().unwrap().seccomp().is_none()); } + #[test] + fn test_amend_spec_disable_guest_selinux() { + let mut spec = oci::SpecBuilder::default() + .process( + oci::ProcessBuilder::default() + .selinux_label("xxx".to_owned()) + .build() + .unwrap(), + ) + .linux( + oci::LinuxBuilder::default() + .mount_label("yyy".to_owned()) + .build() + .unwrap(), + ) + .build() + .unwrap(); + + // disable_guest_selinux = false, selinux labels are left alone + amend_spec(&mut spec, false, false).unwrap(); + assert!(spec.process().as_ref().unwrap().selinux_label() == &Some("xxx".to_owned())); + assert!(spec.linux().as_ref().unwrap().mount_label() == &Some("yyy".to_owned())); + + // disable_guest_selinux = true, selinux labels are reset + amend_spec(&mut spec, false, true).unwrap(); + assert!(spec.process().as_ref().unwrap().selinux_label().is_none()); + assert!(spec.linux().as_ref().unwrap().mount_label().is_none()); + } + #[test] fn test_is_pid_namespace_enabled() { struct TestData<'a> {