From 36367a3bb5e0ff699a2c6b26d282f0bd7cb212d6 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 21 Nov 2025 16:41:05 -0500 Subject: [PATCH] virtiofs: Set SELinux context on readonly mounts Apply system_u:object_r:usr_t:s0 context to readonly virtiofs mounts to avoid SELinux denials when accessing them as container storage. This allows readonly bind mounts to work correctly with podman. The function was renamed from generate_mount_unit to generate_virtiofs_mount_unit for clarity. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters --- crates/kit/src/credentials.rs | 19 +++++++++++++++---- crates/kit/src/libvirt/run.rs | 9 ++++++--- crates/kit/src/run_ephemeral.rs | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/crates/kit/src/credentials.rs b/crates/kit/src/credentials.rs index 961540d..c66f86b 100644 --- a/crates/kit/src/credentials.rs +++ b/crates/kit/src/credentials.rs @@ -45,8 +45,19 @@ pub fn guest_path_to_unit_name(guest_path: &str) -> String { /// Note: systemd automatically creates mount point directories, so DirectoryMode is not needed /// /// Returns the complete unit file content as a string -pub fn generate_mount_unit(virtiofs_tag: &str, guest_path: &str, readonly: bool) -> String { - let options = if readonly { "Options=ro" } else { "Options=rw" }; +pub fn generate_virtiofs_mount_unit( + virtiofs_tag: &str, + guest_path: &str, + readonly: bool, +) -> String { + let options = if readonly { + // Default readonly mounts to usr_t - this helps avoid SELinux + // issues when accessing them as container storage for example. + // TODO don't hardcode this, detect from the environment + "ro,context=system_u:object_r:usr_t:s0" + } else { + "rw" + }; format!( "[Unit]\n\ @@ -61,7 +72,7 @@ pub fn generate_mount_unit(virtiofs_tag: &str, guest_path: &str, readonly: bool) What={tag}\n\ Where={path}\n\ Type=virtiofs\n\ - {options}\n", + Options={options}\n", tag = virtiofs_tag, path = guest_path, options = options @@ -82,7 +93,7 @@ pub fn smbios_creds_for_mount_unit( readonly: bool, ) -> Result> { let unit_name = guest_path_to_unit_name(guest_path); - let mount_unit_content = generate_mount_unit(virtiofs_tag, guest_path, readonly); + let mount_unit_content = generate_virtiofs_mount_unit(virtiofs_tag, guest_path, readonly); let encoded_mount = data_encoding::BASE64.encode(mount_unit_content.as_bytes()); let mount_cred = diff --git a/crates/kit/src/libvirt/run.rs b/crates/kit/src/libvirt/run.rs index 9f8321e..16d16fa 100644 --- a/crates/kit/src/libvirt/run.rs +++ b/crates/kit/src/libvirt/run.rs @@ -882,8 +882,11 @@ fn process_bind_mounts( // Generate SMBIOS credential for mount unit (without dropin) let unit_name = crate::credentials::guest_path_to_unit_name(&bind_mount.guest_path); - let mount_unit_content = - crate::credentials::generate_mount_unit(&tag, &bind_mount.guest_path, readonly); + let mount_unit_content = crate::credentials::generate_virtiofs_mount_unit( + &tag, + &bind_mount.guest_path, + readonly, + ); let encoded_mount = data_encoding::BASE64.encode(mount_unit_content.as_bytes()); let mount_cred = format!("io.systemd.credential.binary:systemd.extra-unit.{unit_name}={encoded_mount}"); @@ -1211,7 +1214,7 @@ fn create_libvirt_domain_from_disk( let guest_mount_path = "/run/host-container-storage"; let unit_name = crate::credentials::guest_path_to_unit_name(guest_mount_path); let mount_unit_content = - crate::credentials::generate_mount_unit("hoststorage", guest_mount_path, true); + crate::credentials::generate_virtiofs_mount_unit("hoststorage", guest_mount_path, true); let encoded_mount = data_encoding::BASE64.encode(mount_unit_content.as_bytes()); let mount_cred = format!("io.systemd.credential.binary:systemd.extra-unit.{unit_name}={encoded_mount}"); diff --git a/crates/kit/src/run_ephemeral.rs b/crates/kit/src/run_ephemeral.rs index e9db17b..64d90ae 100644 --- a/crates/kit/src/run_ephemeral.rs +++ b/crates/kit/src/run_ephemeral.rs @@ -915,7 +915,7 @@ pub(crate) async fn run_impl(opts: RunEphemeralOpts) -> Result<()> { let mount_point = format!("/run/virtiofs-mnt-{}", mount_name_str); let unit_name = crate::credentials::guest_path_to_unit_name(&mount_point); let mount_unit_content = - crate::credentials::generate_mount_unit(&tag, &mount_point, is_readonly); + crate::credentials::generate_virtiofs_mount_unit(&tag, &mount_point, is_readonly); let encoded_mount = data_encoding::BASE64.encode(mount_unit_content.as_bytes()); // Create SMBIOS credential for the mount unit