diff --git a/nix/modules/lanzaboote.nix b/nix/modules/lanzaboote.nix index ad2942e..d9254c4 100644 --- a/nix/modules/lanzaboote.nix +++ b/nix/modules/lanzaboote.nix @@ -7,6 +7,12 @@ let }; configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit; + timeout = if config.boot.loader.timeout == null then 0 else config.boot.loader.timeout; + + systemdBootLoaderConfig = pkgs.writeText "loader.conf" '' + timeout ${toString timeout} + console-mode ${config.boot.loader.systemd-boot.consoleMode} + ''; in { options.boot.lanzaboote = { @@ -60,6 +66,7 @@ in ${cfg.package}/bin/lzbt install \ --systemd ${pkgs.systemd} \ + --systemd-boot-loader-config ${systemdBootLoaderConfig} \ --public-key ${cfg.publicKeyFile} \ --private-key ${cfg.privateKeyFile} \ --configuration-limit ${toString configurationLimit} \ diff --git a/nix/tests/lanzaboote.nix b/nix/tests/lanzaboote.nix index d9b6bee..06e9652 100644 --- a/nix/tests/lanzaboote.nix +++ b/nix/tests/lanzaboote.nix @@ -154,4 +154,21 @@ in machine.succeed("efibootmgr") ''; }; + + systemd-boot-loader-config = mkSecureBootTest { + name = "lanzaboote-systemd-boot-loader-config"; + machine = { + boot.loader.timeout = 0; + boot.loader.systemd-boot.consoleMode = "auto"; + }; + testScript = '' + machine.start() + + actual_loader_config = machine.succeed("cat /boot/loader/loader.conf") + expected_loader_config = "timeout 0\nconsole-mode auto\n" + + assert actual_loader_config == expected_loader_config, \ + f"Actual: '{actual_loader_config}' is not equal to expected: '{expected_loader_config}'" + ''; + }; } diff --git a/rust/tool/src/cli.rs b/rust/tool/src/cli.rs index e203805..852c594 100644 --- a/rust/tool/src/cli.rs +++ b/rust/tool/src/cli.rs @@ -23,6 +23,10 @@ struct InstallCommand { #[arg(long)] systemd: PathBuf, + /// Systemd-boot loader config + #[arg(long)] + systemd_boot_loader_config: PathBuf, + /// sbsign Public Key #[arg(long)] public_key: PathBuf, @@ -65,6 +69,7 @@ fn install(args: InstallCommand) -> Result<()> { install::Installer::new( PathBuf::from(lanzaboote_stub), args.systemd, + args.systemd_boot_loader_config, key_pair, args.configuration_limit, args.esp, diff --git a/rust/tool/src/esp.rs b/rust/tool/src/esp.rs index 36b5d58..9e50e64 100644 --- a/rust/tool/src/esp.rs +++ b/rust/tool/src/esp.rs @@ -15,6 +15,8 @@ pub struct EspPaths { pub efi_fallback: PathBuf, pub systemd: PathBuf, pub systemd_boot: PathBuf, + pub loader: PathBuf, + pub systemd_boot_loader_config: PathBuf, } impl EspPaths { @@ -25,6 +27,8 @@ impl EspPaths { let efi_linux = efi.join("Linux"); let efi_systemd = efi.join("systemd"); let efi_efi_fallback_dir = efi.join("BOOT"); + let loader = esp.join("loader"); + let systemd_boot_loader_config = loader.join("loader.conf"); Self { esp: esp.to_path_buf(), @@ -35,11 +39,13 @@ impl EspPaths { efi_fallback: efi_efi_fallback_dir.join("BOOTX64.EFI"), systemd: efi_systemd.clone(), systemd_boot: efi_systemd.join("systemd-bootx64.efi"), + loader, + systemd_boot_loader_config, } } /// Return the used file paths to store as garbage collection roots. - pub fn to_iter(&self) -> IntoIter<&PathBuf, 8> { + pub fn to_iter(&self) -> IntoIter<&PathBuf, 10> { [ &self.esp, &self.efi, @@ -49,6 +55,8 @@ impl EspPaths { &self.efi_fallback, &self.systemd, &self.systemd_boot, + &self.loader, + &self.systemd_boot_loader_config, ] .into_iter() } diff --git a/rust/tool/src/install.rs b/rust/tool/src/install.rs index 51dd8ae..33d2c59 100644 --- a/rust/tool/src/install.rs +++ b/rust/tool/src/install.rs @@ -19,6 +19,7 @@ pub struct Installer { gc_roots: Roots, lanzaboote_stub: PathBuf, systemd: PathBuf, + systemd_boot_loader_config: PathBuf, key_pair: KeyPair, configuration_limit: usize, esp_paths: EspPaths, @@ -29,6 +30,7 @@ impl Installer { pub fn new( lanzaboote_stub: PathBuf, systemd: PathBuf, + systemd_boot_loader_config: PathBuf, key_pair: KeyPair, configuration_limit: usize, esp: PathBuf, @@ -42,6 +44,7 @@ impl Installer { gc_roots, lanzaboote_stub, systemd, + systemd_boot_loader_config, key_pair, configuration_limit, esp_paths, @@ -221,6 +224,18 @@ impl Installer { .with_context(|| format!("Failed to install systemd-boot binary to: {to:?}"))?; } } + + install( + &self.systemd_boot_loader_config, + &self.esp_paths.systemd_boot_loader_config, + ) + .with_context(|| { + format!( + "Failed to install systemd-boot loader.conf to {:?}", + &self.esp_paths.systemd_boot_loader_config + ) + })?; + Ok(()) } } diff --git a/rust/tool/tests/common/mod.rs b/rust/tool/tests/common/mod.rs index 1872789..01aab3a 100644 --- a/rust/tool/tests/common/mod.rs +++ b/rust/tool/tests/common/mod.rs @@ -107,12 +107,18 @@ pub fn lanzaboote_install( let test_systemd = systemd_location_from_env()?; let test_systemd_stub = format!("{test_systemd}/lib/systemd/boot/efi/linuxx64.efi.stub"); + let test_loader_config_path = tempfile::NamedTempFile::new()?; + let test_loader_config = r"timeout 0\nconsole-mode 1\n"; + fs::write(test_loader_config_path.path(), test_loader_config)?; + let mut cmd = Command::cargo_bin("lzbt")?; let output = cmd .env("LANZABOOTE_STUB", test_systemd_stub) .arg("install") .arg("--systemd") .arg(test_systemd) + .arg("--systemd-boot-loader-config") + .arg(test_loader_config_path.path()) .arg("--public-key") .arg("tests/fixtures/uefi-keys/db.pem") .arg("--private-key") diff --git a/rust/tool/tests/gc.rs b/rust/tool/tests/gc.rs index ad9cfc6..e9dece6 100644 --- a/rust/tool/tests/gc.rs +++ b/rust/tool/tests/gc.rs @@ -61,9 +61,11 @@ fn keep_unrelated_files_on_esp() -> Result<()> { let output0 = common::lanzaboote_install(0, esp_mountpoint.path(), generation_links.clone())?; assert!(output0.status.success()); + let unrelated_loader_config = esp_mountpoint.path().join("loader/loader.conf"); let unrelated_uki = esp_mountpoint.path().join("EFI/Linux/ubuntu.efi"); let unrelated_os = esp_mountpoint.path().join("EFI/windows"); let unrelated_firmware = esp_mountpoint.path().join("dell"); + fs::File::create(&unrelated_loader_config)?; fs::File::create(&unrelated_uki)?; fs::create_dir(&unrelated_os)?; fs::create_dir(&unrelated_firmware)?; @@ -72,6 +74,7 @@ fn keep_unrelated_files_on_esp() -> Result<()> { let output1 = common::lanzaboote_install(2, esp_mountpoint.path(), generation_links)?; assert!(output1.status.success()); + assert!(unrelated_loader_config.exists()); assert!(unrelated_uki.exists()); assert!(unrelated_os.exists()); assert!(unrelated_firmware.exists());