From 136e695c3b6001f973779a1b34658ca9a2b54847 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 17 Jul 2024 11:45:17 -0400 Subject: [PATCH] install/baseline: use sfdisk, not lsblk I think this may also help with the install flake we've been seeing where we somehow get the partitions mixed up. - Use `sfdisk` in the baseline install because it's what we're switching to using anyways later on - Add some verification at least for the root and EFI partitions that we read back the expected type Signed-off-by: Colin Walters --- lib/src/blockdev.rs | 15 ++++++++++++ lib/src/install/baseline.rs | 49 ++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/src/blockdev.rs b/lib/src/blockdev.rs index 98eb30dd..c90df601 100644 --- a/lib/src/blockdev.rs +++ b/lib/src/blockdev.rs @@ -165,6 +165,21 @@ impl PartitionTable { pub(crate) fn path(&self) -> &Utf8Path { self.device.as_str().into() } + + // Find the partition with the given offset (starting at 1) + pub(crate) fn find_partno<'a>(&'a self, partno: u32) -> Result<&'a Partition> { + let r = self + .partitions + .get(partno.checked_sub(1).expect("1 based partition offset") as usize) + .ok_or_else(|| anyhow::anyhow!("Missing partition for index {partno}"))?; + Ok(r) + } +} + +impl Partition { + pub(crate) fn path(&self) -> &Utf8Path { + self.node.as_str().into() + } } #[context("Listing partitions of {dev}")] diff --git a/lib/src/install/baseline.rs b/lib/src/install/baseline.rs index 35e2c06d..931167d6 100644 --- a/lib/src/install/baseline.rs +++ b/lib/src/install/baseline.rs @@ -328,24 +328,18 @@ pub(crate) fn install_create_rootfs( // we're targeting, but this is a simple coarse hammer. crate::blockdev::udev_settle()?; - // Now inspect the partitioned device again so we can find the names of the child devices. - let device_partitions = crate::blockdev::list_dev(&devpath)? - .children - .ok_or_else(|| anyhow::anyhow!("Failed to find children after partitioning"))?; - // Given a partition number, return the path to its device. - let findpart = |idx: u32| -> Result { - // checked_sub is here because our partition numbers start at 1, but the vec starts at 0 - let devpath = device_partitions - .get(idx.checked_sub(1).unwrap() as usize) - .ok_or_else(|| anyhow::anyhow!("Missing partition for index {idx}"))? - .path(); - Ok(devpath) - }; - - let base_rootdev = findpart(rootpn)?; + // Re-read what we wrote into structured information + let base_partitions = &crate::blockdev::partitions_of(&devpath)?; + let root_partition = base_partitions.find_partno(rootpn)?; + if root_partition.parttype.as_str() != LINUX_PARTTYPE { + anyhow::bail!( + "root partition {partno} has type {}; expected {LINUX_PARTTYPE}", + root_partition.parttype.as_str() + ); + } let (rootdev, root_blockdev_kargs) = match block_setup { - BlockSetup::Direct => (base_rootdev, None), + BlockSetup::Direct => (root_partition.node.to_owned(), None), BlockSetup::Tpm2Luks => { let uuid = uuid::Uuid::new_v4().to_string(); // This will be replaced via --wipe-slot=all when binding to tpm below @@ -356,21 +350,23 @@ pub(crate) fn install_create_rootfs( let tmp_keyfile = tmp_keyfile.path(); let dummy_passphrase_input = Some(dummy_passphrase.as_bytes()); + let root_devpath = root_partition.path(); + Task::new("Initializing LUKS for root", "cryptsetup") .args(["luksFormat", "--uuid", uuid.as_str(), "--key-file"]) .args([tmp_keyfile]) - .args([base_rootdev.as_str()]) + .args([root_devpath]) .run()?; // The --wipe-slot=all removes our temporary passphrase, and binds to the local TPM device. // We also use .verbose() here as the details are important/notable. Task::new("Enrolling root device with TPM", "systemd-cryptenroll") .args(["--wipe-slot=all", "--tpm2-device=auto", "--unlock-key-file"]) .args([tmp_keyfile]) - .args([base_rootdev.as_str()]) + .args([root_devpath]) .verbose() .run_with_stdin_buf(dummy_passphrase_input)?; Task::new("Opening root LUKS device", "cryptsetup") - .args(["luksOpen", base_rootdev.as_str(), luks_name]) + .args(["luksOpen", root_devpath.as_str(), luks_name]) .run()?; let rootdev = format!("/dev/mapper/{luks_name}"); let kargs = vec![ @@ -383,12 +379,15 @@ pub(crate) fn install_create_rootfs( // Initialize the /boot filesystem let bootdev = if let Some(bootpn) = boot_partno { - Some(findpart(bootpn)?) + Some(base_partitions.find_partno(bootpn)?) } else { None }; let boot_uuid = if let Some(bootdev) = bootdev.as_deref() { - Some(mkfs(bootdev, root_filesystem, "boot", []).context("Initializing /boot")?) + Some( + mkfs(bootdev.node.as_str(), root_filesystem, "boot", []) + .context("Initializing /boot")?, + ) } else { None }; @@ -419,22 +418,22 @@ pub(crate) fn install_create_rootfs( // Create the underlying mount point directory, which should be labeled crate::lsm::ensure_dir_labeled(&target_rootfs, "boot", None, 0o755.into(), sepolicy)?; if let Some(bootdev) = bootdev.as_deref() { - mount::mount(bootdev, &bootfs)?; + mount::mount(bootdev.node.as_str(), &bootfs)?; } // And we want to label the root mount of /boot crate::lsm::ensure_dir_labeled(&target_rootfs, "boot", None, 0o755.into(), sepolicy)?; // Create the EFI system partition, if applicable if let Some(esp_partno) = esp_partno { - let espdev = &findpart(esp_partno)?; + let espdev = base_partitions.find_partno(esp_partno)?; Task::new("Creating ESP filesystem", "mkfs.fat") - .args([espdev.as_str(), "-n", "EFI-SYSTEM"]) + .args([espdev.node.as_str(), "-n", "EFI-SYSTEM"]) .verbose() .quiet_output() .run()?; let efifs_path = bootfs.join(crate::bootloader::EFI_DIR); std::fs::create_dir(&efifs_path).context("Creating efi dir")?; - mount::mount(espdev, &efifs_path)?; + mount::mount(espdev.node.as_str(), &efifs_path)?; } let luks_device = match block_setup {