diff --git a/lib/src/install.rs b/lib/src/install.rs index d4f70ee2..5004bd72 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -680,17 +680,25 @@ async fn initialize_ostree_root( ostree_ext::fsverity::ensure_verity(repo).await?; } - let stateroot_exists = rootfs_dir.try_exists(format!("ostree/deploy/{stateroot}"))?; - ensure!( - !stateroot_exists, - "Cannot redeploy over extant stateroot {stateroot}" - ); - sysroot - .init_osname(stateroot, cancellable) - .context("initializing stateroot")?; + if let Some(booted) = sysroot.booted_deployment() { + if stateroot == booted.stateroot() { + anyhow::bail!("Cannot redeploy over booted stateroot {stateroot}"); + } + } let sysroot_dir = crate::utils::sysroot_dir(&sysroot)?; + // init_osname fails when ostree/deploy/{stateroot} already exists + // the stateroot directory can be left over after a failed install attempt, + // so only create it via init_osname if it doesn't exist + // (ideally this would be handled by init_osname) + let stateroot_path = format!("ostree/deploy/{stateroot}"); + if !sysroot_dir.try_exists(stateroot_path)? { + sysroot + .init_osname(stateroot, cancellable) + .context("initializing stateroot")?; + } + state.tempdir.create_dir("temp-run")?; let temp_run = state.tempdir.open_dir("temp-run")?; diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index b86ae223..4a994b22 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -3,6 +3,7 @@ use std::env; use std::ops::Deref; use anyhow::{Context, Result}; +use cap_std_ext::cap_std; use cap_std_ext::cap_std::fs::Dir; use cap_std_ext::dirext::CapStdExtDirExt; use clap::ValueEnum; @@ -88,15 +89,18 @@ impl Storage { } let sysroot_dir = crate::utils::sysroot_dir(&self.sysroot)?; - if self.sysroot.booted_deployment().is_none() { - anyhow::bail!("Not a bootc system (this shouldn't be possible)"); - } - - // load the sepolicy from the booted ostree deployment so the imgstorage can be - // properly labeled with /var/lib/container/storage labels - let dep = self.sysroot.booted_deployment().unwrap(); - let dep_fs = deployment_fd(&self.sysroot, &dep)?; - let sepolicy = &ostree::SePolicy::new_at(dep_fs.as_raw_fd(), gio::Cancellable::NONE)?; + let sepolicy = if self.sysroot.booted_deployment().is_none() { + // fallback to policy from container root + // this should only happen during cleanup of a broken install + let container_root = Dir::open_ambient_dir("/", cap_std::ambient_authority())?; + &ostree::SePolicy::new_at(container_root.as_raw_fd(), gio::Cancellable::NONE)? + } else { + // load the sepolicy from the booted ostree deployment so the imgstorage can be + // properly labeled with /var/lib/container/storage labels + let dep = self.sysroot.booted_deployment().unwrap(); + let dep_fs = deployment_fd(&self.sysroot, &dep)?; + &ostree::SePolicy::new_at(dep_fs.as_raw_fd(), gio::Cancellable::NONE)? + }; let imgstore = crate::imgstorage::Storage::create(&sysroot_dir, &self.run, Some(sepolicy))?; Ok(self.imgstore.get_or_init(|| imgstore))