Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

install/baseline: use sfdisk, not lsblk #698

Merged
merged 2 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(&self, partno: u32) -> Result<&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}")]
Expand Down
57 changes: 29 additions & 28 deletions lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use crate::task::Task;
// This ensures we end up under 512 to be small-sized.
pub(crate) const BOOTPN_SIZE_MB: u32 = 510;
pub(crate) const EFIPN_SIZE_MB: u32 = 512;
/// The GPT type for "linux"
pub(crate) const LINUX_PARTTYPE: &str = "0FC63DAF-8483-4772-8E79-3D69D8477DE4";

#[derive(clap::ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
Expand Down Expand Up @@ -307,7 +309,7 @@ pub(crate) fn install_create_rootfs(
rootpn,
root_size,
"root",
Some("0FC63DAF-8483-4772-8E79-3D69D8477DE4"),
Some(LINUX_PARTTYPE),
);
sgdisk.run().context("Failed to run sgdisk")?;
tracing::debug!("Created partition table");
Expand All @@ -326,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<String> {
// 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
Expand All @@ -354,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![
Expand All @@ -381,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")?)
let boot_uuid = if let Some(bootdev) = bootdev {
Some(
mkfs(bootdev.node.as_str(), root_filesystem, "boot", [])
.context("Initializing /boot")?,
)
} else {
None
};
Expand Down Expand Up @@ -416,23 +417,23 @@ pub(crate) fn install_create_rootfs(
let bootfs = rootfs.join("boot");
// 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)?;
if let Some(bootdev) = bootdev {
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 {
Expand Down