Skip to content

Commit

Permalink
feat: Add dive.sh for quick chrooting, Properly handle FDE in fstab a…
Browse files Browse the repository at this point in the history
…nd systemd-cryptsetup-generator
  • Loading branch information
korewaChino committed Feb 13, 2025
1 parent 749d5c7 commit dba837b
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 56 deletions.
73 changes: 73 additions & 0 deletions scripts/dive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

CHROOT_DIR="/mnt/custom"
: ${DIVE_EXEC:="dive"}

# $1 will be the loop device path

usage() {
echo "Usage: $0 <loop device path>"
exit 1
}

if [ -z "$1" ]; then
usage
fi

if [ ! -b "$1" ]; then
echo "Error: $1 is not a block device"
usage
fi

DISK="$1"

# Check if the chroot directory exists

is_luks() {
if sudo cryptsetup isLuks "$1"; then
return 0
else
return 1
fi
}

EFI_PART="${DISK}p1"
XBOOT_PART="${DISK}p2"
ROOT_PART="${DISK}p3"
ROOT_DEV="$ROOT_PART"
# ROOT_PART="${DISK}p3"

if is_luks "$ROOT_PART"; then
echo "Unlocking the root partition"
sudo cryptsetup open "$ROOT_PART" root
export ROOT_DEV="/dev/mapper/root"
else
export ROOT_DEV="$ROOT_DISK"
fi

if [ ! -d "$CHROOT_DIR" ]; then
echo "Creating the chroot directory"
sudo mkdir -p "$CHROOT_DIR"
fi

echo "Mounting the root partition"
sudo mount "$ROOT_DEV" "$CHROOT_DIR"

echo "Mounting the boot partition"
sudo mount "$XBOOT_PART" "$CHROOT_DIR/boot"

echo "Mounting the EFI partition"
sudo mount "$EFI_PART" "$CHROOT_DIR/boot/efi"

echo "Chrooting into the system"
sudo $DIVE_EXEC $CHROOT_DIR


echo "Cleaning up"

sudo umount -Rv "$CHROOT_DIR"

if is_luks "$ROOT_PART"; then
echo "Closing the root partition"
sudo cryptsetup close $ROOT_DEV
fi
39 changes: 23 additions & 16 deletions src/backend/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use crate::{
stage, util,
};

use super::repart_output::CryptData;

pub static IPC_CHANNEL: OnceLock<Mutex<IpcSender<InstallationMessage>>> = OnceLock::new();

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -193,20 +195,18 @@ impl InstallationState {
}
}


/// Copies the current config into a temporary directory, allowing them to be modified without
/// affecting the original templates :D
fn layer_configdir(&self, cfg_dir: &Path) -> Result<PathBuf> {

// /run/readymade-install
let new_path = PathBuf::from("/run").join("readymade-install");
std::fs::create_dir_all(&new_path)?;
// Copy the contents of the cfg_dir to the new path
util::fs::copy_dir(cfg_dir, "/run/readymade-install")?;

Ok(new_path)
}

#[allow(clippy::unwrap_in_result)]
#[tracing::instrument]
pub fn install(&self) -> Result<()> {
Expand All @@ -220,9 +220,8 @@ impl InstallationState {
let blockdev = &(self.destination_disk.as_ref())
.expect("A valid destination device should be set before calling install()")
.devpath;

// let cfgdir = inst_type.cfgdir();


tracing::info!("Layering repart templates");
let cfgdir = self.layer_configdir(&inst_type.cfgdir())?;

// Let's write the encryption key to the keyfile
Expand Down Expand Up @@ -252,6 +251,10 @@ impl InstallationState {

#[tracing::instrument]
fn setup_system(&self, output: RepartOutput, passphrase: Option<&str>) -> Result<()> {
// XXX: This is a bit hacky, but this function should be called before output.generate_fstab() for
// the fstab generator to be correct, IF we're using encryption
//
// todo: Unfuck this
let mut container = output.to_container(passphrase)?;

let fstab = output.generate_fstab()?;
Expand All @@ -262,9 +265,9 @@ impl InstallationState {
.get_xbootldr_partition()
.context("No xbootldr partition found")?;

let crypttab = output.generate_crypttab();
let crypt_data = output.generate_cryptdata()?;

container.run(|| self._inner_sys_setup(fstab, crypttab, esp_node, &xbootldr_node))??;
container.run(|| self._inner_sys_setup(fstab, crypt_data, esp_node, &xbootldr_node))??;

Ok(())
}
Expand All @@ -274,7 +277,7 @@ impl InstallationState {
pub fn _inner_sys_setup(
&self,
fstab: String,
crypttab: Option<String>,
crypt_data: Option<CryptData>,
esp_node: Option<String>,
xbootldr_node: &str,
) -> Result<()> {
Expand All @@ -285,12 +288,16 @@ impl InstallationState {
esp_partition: esp_node,
xbootldr_partition: xbootldr_node.to_owned(),
lang: self.langlocale.clone().unwrap_or_else(|| "C.UTF-8".into()),
crypt_data: crypt_data.clone(),
};

tracing::info!("Writing /etc/fstab...");
std::fs::write("/etc/fstab", fstab).wrap_err("cannot write to /etc/fstab")?;

if let Some(crypttab) = crypttab {
std::fs::write("/etc/crypttab", crypttab).wrap_err("cannot write to /etc/crypttab")?;
if let Some(data) = crypt_data {
tracing::info!("Writing /etc/crypttab...");
std::fs::write("/etc/crypttab", data.crypttab)
.wrap_err("cannot write to /etc/crypttab")?;
}

for module in &self.postinstall {
Expand Down Expand Up @@ -393,9 +400,9 @@ impl InstallationState {
#[allow(clippy::unwrap_in_result)]
#[tracing::instrument]
/// Enable encryption on the root partition config
///
///
/// This method will modify the root partition config file to enable encryption
///
///
/// Please use [`Self::layer_configdir`] before calling this method to avoid modifying the original config files
fn enable_encryption(&self, cfgdir: &Path) -> Result<()> {
if !self.encrypt {
Expand All @@ -405,10 +412,10 @@ impl InstallationState {
let f = std::fs::read_to_string(&root_file)?;
let f = Self::set_encrypt_to_file(&f, self.tpm);
// We're gonna write directly to the file.
//
//
// Warning: Please don't use this method unless you're using layer_configdir
std::fs::write(&root_file, f)?;

// TODO: somehow actually use this config file
Ok(())
}
Expand Down
16 changes: 15 additions & 1 deletion src/backend/postinstall/grub2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,21 @@ pub struct GRUB2;
impl PostInstallModule for GRUB2 {
fn run(&self, context: &Context) -> Result<()> {
stage!("Generating system grub defaults" {
let defaults = Grub2Defaults::default();
let mut defaults = Grub2Defaults::default();

// Now, let's add extra boot opts if they exist
if let Some(crypt_data) = &context.crypt_data {
// prepend
let current_value = defaults.cmdline_linux.clone();

// this is a mess.
// todo: In the event someone thinks this code stinks, please please PLEASE refactor it for us.

let joined_cmdline = crypt_data.cmdline_opts.join(" ");
tracing::info!("Adding cryptsetup cmdline options: {}", joined_cmdline);
defaults.cmdline_linux = format!("{} {}", joined_cmdline, current_value);
}

let defaults_str = defaults.generate();
std::fs::write("/etc/default/grub", defaults_str)?;
});
Expand Down
3 changes: 3 additions & 0 deletions src/backend/postinstall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use selinux::SELinux;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

use super::repart_output::CryptData;

pub mod cleanup_boot;
pub mod dracut;
pub mod efi_stub;
Expand All @@ -31,6 +33,7 @@ pub struct Context {
// Installs should always have an xbootldr partition
pub xbootldr_partition: String,
pub lang: String,
pub crypt_data: Option<CryptData>,
}

#[enum_dispatch(Module)]
Expand Down
Loading

0 comments on commit dba837b

Please sign in to comment.