Merge pull request #161 from nix-community/safeguard-gc

tool: disable gc in the presence of malformed gens
This commit is contained in:
nikstur 2023-04-25 01:13:26 +02:00 committed by GitHub
commit b1101610f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 24 deletions

7
rust/tool/Cargo.lock generated
View File

@ -473,6 +473,12 @@ dependencies = [
"cxx-build", "cxx-build",
] ]
[[package]]
name = "indoc"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690"
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -541,6 +547,7 @@ dependencies = [
"fastrand", "fastrand",
"filetime", "filetime",
"goblin", "goblin",
"indoc",
"log", "log",
"nix", "nix",
"rand", "rand",

View File

@ -27,6 +27,7 @@ sha2 = "0.10.6"
fastrand = "1.9.0" fastrand = "1.9.0"
log = { version = "0.4.17", features = ["std"] } log = { version = "0.4.17", features = ["std"] }
stderrlog = "0.5.4" stderrlog = "0.5.4"
indoc = "2.0.1"
[dev-dependencies] [dev-dependencies]
assert_cmd = "2.0.11" assert_cmd = "2.0.11"

View File

@ -18,6 +18,7 @@ use crate::systemd::SystemdVersion;
use crate::utils::{file_hash, SecureTempDirExt}; use crate::utils::{file_hash, SecureTempDirExt};
pub struct Installer { pub struct Installer {
enable_gc: bool,
gc_roots: Roots, gc_roots: Roots,
lanzaboote_stub: PathBuf, lanzaboote_stub: PathBuf,
systemd: PathBuf, systemd: PathBuf,
@ -43,6 +44,7 @@ impl Installer {
gc_roots.extend(esp_paths.to_iter()); gc_roots.extend(esp_paths.to_iter());
Self { Self {
enable_gc: true,
gc_roots, gc_roots,
lanzaboote_stub, lanzaboote_stub,
systemd, systemd,
@ -85,6 +87,7 @@ impl Installer {
self.install_systemd_boot()?; self.install_systemd_boot()?;
if self.enable_gc {
log::info!("Collecting garbage..."); log::info!("Collecting garbage...");
// Only collect garbage in these two directories. This way, no files that do not belong to // Only collect garbage in these two directories. This way, no files that do not belong to
// the NixOS installation are deleted. Lanzatool takes full control over the esp/EFI/nixos // the NixOS installation are deleted. Lanzatool takes full control over the esp/EFI/nixos
@ -100,6 +103,18 @@ impl Installer {
.and_then(|n| n.to_str()) .and_then(|n| n.to_str())
.map_or(false, |n| n.starts_with("nixos-")) .map_or(false, |n| n.starts_with("nixos-"))
})?; })?;
} else {
// Garbage collection can only be disabled if there are malformed generations. If
// garbage collection can ever be disabled differently, the below log message most
// likely does not make sense anymore.
log::warn!(indoc::indoc! {"
Garbage collection is disabled because you have malformed NixOS generations that do
not contain a readable bootspec document.
Remove the malformed generations with `nix-env --delete-generations` to re-enable
garbage collection.
"})
};
log::info!("Successfully installed Lanzaboote."); log::info!("Successfully installed Lanzaboote.");
Ok(()) Ok(())
@ -171,15 +186,13 @@ impl Installer {
// Ignore failing to read a generation so that old malformed generations do not stop // Ignore failing to read a generation so that old malformed generations do not stop
// lzbt from working. // lzbt from working.
if let Err(e) = &generation_result { if generation_result.is_err() {
// Semantically, this message should be a warning. However, since users might // If there is ANY malformed generation present, completely disable all garbage
// have hundreds of old and thus malformed generations and can do little about // collection to protect the old generations from being deleted. The user has
// it, this should remain a debug message. This way the user is not spammed // to manually intervene by getting rid of the old generations to re-enable
// with no-op warnings while still enabling debugging. // garbage collection. This safeguard against catastrophic failure in case of
log::debug!( // unhandled upstream changes to NixOS.
"Ignoring generation {} because it's malformed: {e:#}", self.enable_gc = false;
link.version
);
} }
generation_result.ok() generation_result.ok()