Skip to content

Commit 4c3e68f

Browse files
henrywangcgwalters
authored andcommitted
Fix: Avoid a hard panic and use a recoverable error instead
Issue: Arch Linux container build where pacman -Syu in a downstream stage installs a newer kernel version (with nativevmlinuz in /usr/lib/modules/<kver>/) but no corresponding initramfs. UsrLibModulesVmlinuz::load_all calls self.initramfs.unwrap() which panics instead of returning an error when a kernel directory has vmlinuz but no initramfs fix: change unwrap() to ok_or_else(|| anyhow!("no initramfs for kernel {kver}")) and propagate Two tests: - test_into_type1_with_initramfs — verifies the right path produces entries with the correct vmlinuz and initramfs - test_into_type1_without_initramfs_returns_error — verifies None initramfs returns an error containing "no initramfs" rather than panic Signed-off-by: Xiaofeng Wang <henrywangxf@me.com>
1 parent ed0da92 commit 4c3e68f

2 files changed

Lines changed: 56 additions & 9 deletions

File tree

crates/composefs-boot/src/bootloader.rs

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -457,10 +457,18 @@ impl<ObjectID: FsVerityHashValue> UsrLibModulesVmlinuz<ObjectID> {
457457
///
458458
/// # Returns
459459
///
460-
/// A Type1Entry with generated BLS configuration
461-
pub fn into_type1(self, entry_id: Option<&str>) -> Type1Entry<ObjectID> {
460+
/// A Type1Entry with generated BLS configuration, or an error if initramfs is missing.
461+
pub fn into_type1(self, entry_id: Option<&str>) -> Result<Type1Entry<ObjectID>> {
462462
let id = entry_id.unwrap_or(&self.kver);
463463

464+
let initramfs = self.initramfs.ok_or_else(|| {
465+
anyhow::anyhow!(
466+
"kernel {} has no initramfs.img in /usr/lib/modules/{}",
467+
self.kver,
468+
self.kver
469+
)
470+
})?;
471+
464472
let title = "todoOS";
465473
let version = "0-todo";
466474
let entry = BootLoaderEntryFile::new(&format!(
@@ -474,17 +482,14 @@ initrd /{id}/initramfs.img
474482

475483
let filename = Box::from(format!("{id}.conf").as_ref());
476484

477-
Type1Entry {
485+
Ok(Type1Entry {
478486
filename,
479487
entry,
480488
files: HashMap::from([
481489
(Box::from(format!("/{id}/vmlinuz")), self.vmlinuz),
482-
(
483-
Box::from(format!("/{id}/initramfs.img")),
484-
self.initramfs.unwrap(),
485-
),
490+
(Box::from(format!("/{id}/initramfs.img")), initramfs),
486491
]),
487-
}
492+
})
488493
}
489494

490495
/// Loads all vmlinuz entries from /usr/lib/modules.
@@ -580,6 +585,48 @@ pub fn get_boot_resources<ObjectID: FsVerityHashValue>(
580585
#[cfg(test)]
581586
mod tests {
582587
use super::*;
588+
use composefs::{fsverity::Sha256HashValue, tree::RegularFile};
589+
590+
fn fake_file() -> RegularFile<Sha256HashValue> {
591+
RegularFile::Inline(Default::default())
592+
}
593+
594+
#[test]
595+
fn test_into_type1_with_initramfs() {
596+
let entry = UsrLibModulesVmlinuz::<Sha256HashValue> {
597+
kver: "6.9.0-arch1-1".into(),
598+
vmlinuz: fake_file(),
599+
initramfs: Some(fake_file()),
600+
os_release: None,
601+
};
602+
let t1 = entry
603+
.into_type1(None)
604+
.expect("should succeed with initramfs");
605+
let keys: Vec<&str> = t1.files.keys().map(|k| k.as_ref()).collect();
606+
assert!(
607+
keys.contains(&"/6.9.0-arch1-1/vmlinuz"),
608+
"missing vmlinuz key, got: {keys:?}"
609+
);
610+
assert!(
611+
keys.contains(&"/6.9.0-arch1-1/initramfs.img"),
612+
"missing initramfs key, got: {keys:?}"
613+
);
614+
}
615+
616+
#[test]
617+
fn test_into_type1_without_initramfs_returns_error() {
618+
let entry = UsrLibModulesVmlinuz::<Sha256HashValue> {
619+
kver: "6.9.0-arch1-1".into(),
620+
vmlinuz: fake_file(),
621+
initramfs: None,
622+
os_release: None,
623+
};
624+
let err = entry.into_type1(None).unwrap_err();
625+
assert!(
626+
err.to_string().contains("no initramfs"),
627+
"unexpected error message: {err}"
628+
);
629+
}
583630

584631
#[test]
585632
fn test_bootloader_entry_file_new() {

crates/composefs-boot/src/write_boot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub fn write_boot_simple<ObjectID: FsVerityHashValue>(
164164
write_t2_simple(t2, boot_partition, root_id, repo)?;
165165
}
166166
BootEntry::UsrLibModulesVmLinuz(entry) => {
167-
let mut t1 = entry.into_type1(entry_id);
167+
let mut t1 = entry.into_type1(entry_id)?;
168168
if let Some(name) = entry_id {
169169
t1.relocate(boot_subdir, name);
170170
}

0 commit comments

Comments
 (0)