Skip to content

Commit f46f134

Browse files
committed
sd-boot: Only use --random-seed flag on systemd >= 257
`bootctl install --random-seed no` is only available on systemd >= 257. Query the bootctl version and only pass the flag when supported. Signed-off-by: Peter Siegel <psiegel2000@icloud.com>
1 parent 85ad2f9 commit f46f134

1 file changed

Lines changed: 60 additions & 1 deletion

File tree

crates/lib/src/bootloader.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,16 @@ pub(crate) fn install_systemd_boot(
256256
];
257257

258258
if configopts.generic_image {
259-
bootctl_args.extend(["--random-seed", "no", "--no-variables"]);
259+
bootctl_args.push("--no-variables");
260+
// `--random-seed` was only added to `bootctl install` in systemd 257.
261+
let systemd_version = bootctl_systemd_version()?;
262+
if systemd_version >= BOOTCTL_RANDOM_SEED_MIN_VERSION {
263+
bootctl_args.extend(["--random-seed", "no"]);
264+
} else {
265+
tracing::debug!(
266+
"Skipping --random-seed: requires systemd >= {BOOTCTL_RANDOM_SEED_MIN_VERSION}, found {systemd_version}"
267+
);
268+
}
260269
}
261270

262271
Command::new("bootctl")
@@ -312,6 +321,28 @@ pub(crate) fn install_systemd_boot(
312321
Ok(())
313322
}
314323

324+
/// First systemd release whose `bootctl install` accepts `--random-seed`.
325+
/// See: <https://www.freedesktop.org/software/systemd/man/latest/bootctl.html>
326+
const BOOTCTL_RANDOM_SEED_MIN_VERSION: u32 = 257;
327+
328+
#[context("Querying bootctl version")]
329+
fn bootctl_systemd_version() -> Result<u32> {
330+
let out = Command::new("bootctl").arg("--version").run_get_string()?;
331+
parse_systemd_version(&out)
332+
}
333+
334+
/// Parse the systemd major version from `bootctl --version` output, whose first
335+
/// line looks like `systemd 259 (259.5-0ubuntu3)`.
336+
fn parse_systemd_version(output: &str) -> Result<u32> {
337+
output
338+
.split_whitespace()
339+
.nth(1)
340+
.and_then(|s| s.parse::<u32>().ok())
341+
.ok_or_else(|| {
342+
anyhow!("Could not parse systemd version from bootctl --version: {output:?}")
343+
})
344+
}
345+
315346
#[context("Installing bootloader using zipl")]
316347
pub(crate) fn install_via_zipl(device: &bootc_blockdev::Device, boot_uuid: &str) -> Result<()> {
317348
// Identify the target boot partition from UUID
@@ -389,3 +420,31 @@ pub(crate) fn install_via_zipl(device: &bootc_blockdev::Device, boot_uuid: &str)
389420
.log_debug()
390421
.run_inherited_with_cmd_context()
391422
}
423+
424+
#[cfg(test)]
425+
mod tests {
426+
use super::*;
427+
428+
#[test]
429+
fn test_parse_systemd_version() {
430+
// The first line of `bootctl --version`. the trailing feature line is ignored.
431+
let cases = [
432+
("systemd 259 (259.5-0ubuntu3)", 259),
433+
("systemd 257 (257-26.el10-g1d19ad5)", 257),
434+
("systemd 255 (255.4-1ubuntu8.16)", 255),
435+
];
436+
for (input, expected) in cases {
437+
assert_eq!(
438+
parse_systemd_version(input).unwrap(),
439+
expected,
440+
"input: {input:?}"
441+
);
442+
}
443+
for bad in ["", "systemd", "not a version string"] {
444+
assert!(
445+
parse_systemd_version(bad).is_err(),
446+
"should reject: {bad:?}"
447+
);
448+
}
449+
}
450+
}

0 commit comments

Comments
 (0)