Skip to content

Commit dba837b

Browse files
committed
feat: Add dive.sh for quick chrooting, Properly handle FDE in fstab and systemd-cryptsetup-generator
1 parent 749d5c7 commit dba837b

File tree

5 files changed

+303
-56
lines changed

5 files changed

+303
-56
lines changed

scripts/dive.sh

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/bin/bash
2+
3+
CHROOT_DIR="/mnt/custom"
4+
: ${DIVE_EXEC:="dive"}
5+
6+
# $1 will be the loop device path
7+
8+
usage() {
9+
echo "Usage: $0 <loop device path>"
10+
exit 1
11+
}
12+
13+
if [ -z "$1" ]; then
14+
usage
15+
fi
16+
17+
if [ ! -b "$1" ]; then
18+
echo "Error: $1 is not a block device"
19+
usage
20+
fi
21+
22+
DISK="$1"
23+
24+
# Check if the chroot directory exists
25+
26+
is_luks() {
27+
if sudo cryptsetup isLuks "$1"; then
28+
return 0
29+
else
30+
return 1
31+
fi
32+
}
33+
34+
EFI_PART="${DISK}p1"
35+
XBOOT_PART="${DISK}p2"
36+
ROOT_PART="${DISK}p3"
37+
ROOT_DEV="$ROOT_PART"
38+
# ROOT_PART="${DISK}p3"
39+
40+
if is_luks "$ROOT_PART"; then
41+
echo "Unlocking the root partition"
42+
sudo cryptsetup open "$ROOT_PART" root
43+
export ROOT_DEV="/dev/mapper/root"
44+
else
45+
export ROOT_DEV="$ROOT_DISK"
46+
fi
47+
48+
if [ ! -d "$CHROOT_DIR" ]; then
49+
echo "Creating the chroot directory"
50+
sudo mkdir -p "$CHROOT_DIR"
51+
fi
52+
53+
echo "Mounting the root partition"
54+
sudo mount "$ROOT_DEV" "$CHROOT_DIR"
55+
56+
echo "Mounting the boot partition"
57+
sudo mount "$XBOOT_PART" "$CHROOT_DIR/boot"
58+
59+
echo "Mounting the EFI partition"
60+
sudo mount "$EFI_PART" "$CHROOT_DIR/boot/efi"
61+
62+
echo "Chrooting into the system"
63+
sudo $DIVE_EXEC $CHROOT_DIR
64+
65+
66+
echo "Cleaning up"
67+
68+
sudo umount -Rv "$CHROOT_DIR"
69+
70+
if is_luks "$ROOT_PART"; then
71+
echo "Closing the root partition"
72+
sudo cryptsetup close $ROOT_DEV
73+
fi

src/backend/install.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use crate::{
3030
stage, util,
3131
};
3232

33+
use super::repart_output::CryptData;
34+
3335
pub static IPC_CHANNEL: OnceLock<Mutex<IpcSender<InstallationMessage>>> = OnceLock::new();
3436

3537
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
@@ -193,20 +195,18 @@ impl InstallationState {
193195
}
194196
}
195197

196-
197198
/// Copies the current config into a temporary directory, allowing them to be modified without
198199
/// affecting the original templates :D
199200
fn layer_configdir(&self, cfg_dir: &Path) -> Result<PathBuf> {
200-
201201
// /run/readymade-install
202202
let new_path = PathBuf::from("/run").join("readymade-install");
203203
std::fs::create_dir_all(&new_path)?;
204204
// Copy the contents of the cfg_dir to the new path
205205
util::fs::copy_dir(cfg_dir, "/run/readymade-install")?;
206-
206+
207207
Ok(new_path)
208208
}
209-
209+
210210
#[allow(clippy::unwrap_in_result)]
211211
#[tracing::instrument]
212212
pub fn install(&self) -> Result<()> {
@@ -220,9 +220,8 @@ impl InstallationState {
220220
let blockdev = &(self.destination_disk.as_ref())
221221
.expect("A valid destination device should be set before calling install()")
222222
.devpath;
223-
224-
// let cfgdir = inst_type.cfgdir();
225-
223+
224+
tracing::info!("Layering repart templates");
226225
let cfgdir = self.layer_configdir(&inst_type.cfgdir())?;
227226

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

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

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

265-
let crypttab = output.generate_crypttab();
268+
let crypt_data = output.generate_cryptdata()?;
266269

267-
container.run(|| self._inner_sys_setup(fstab, crypttab, esp_node, &xbootldr_node))??;
270+
container.run(|| self._inner_sys_setup(fstab, crypt_data, esp_node, &xbootldr_node))??;
268271

269272
Ok(())
270273
}
@@ -274,7 +277,7 @@ impl InstallationState {
274277
pub fn _inner_sys_setup(
275278
&self,
276279
fstab: String,
277-
crypttab: Option<String>,
280+
crypt_data: Option<CryptData>,
278281
esp_node: Option<String>,
279282
xbootldr_node: &str,
280283
) -> Result<()> {
@@ -285,12 +288,16 @@ impl InstallationState {
285288
esp_partition: esp_node,
286289
xbootldr_partition: xbootldr_node.to_owned(),
287290
lang: self.langlocale.clone().unwrap_or_else(|| "C.UTF-8".into()),
291+
crypt_data: crypt_data.clone(),
288292
};
289293

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

292-
if let Some(crypttab) = crypttab {
293-
std::fs::write("/etc/crypttab", crypttab).wrap_err("cannot write to /etc/crypttab")?;
297+
if let Some(data) = crypt_data {
298+
tracing::info!("Writing /etc/crypttab...");
299+
std::fs::write("/etc/crypttab", data.crypttab)
300+
.wrap_err("cannot write to /etc/crypttab")?;
294301
}
295302

296303
for module in &self.postinstall {
@@ -393,9 +400,9 @@ impl InstallationState {
393400
#[allow(clippy::unwrap_in_result)]
394401
#[tracing::instrument]
395402
/// Enable encryption on the root partition config
396-
///
403+
///
397404
/// This method will modify the root partition config file to enable encryption
398-
///
405+
///
399406
/// Please use [`Self::layer_configdir`] before calling this method to avoid modifying the original config files
400407
fn enable_encryption(&self, cfgdir: &Path) -> Result<()> {
401408
if !self.encrypt {
@@ -405,10 +412,10 @@ impl InstallationState {
405412
let f = std::fs::read_to_string(&root_file)?;
406413
let f = Self::set_encrypt_to_file(&f, self.tpm);
407414
// We're gonna write directly to the file.
408-
//
415+
//
409416
// Warning: Please don't use this method unless you're using layer_configdir
410417
std::fs::write(&root_file, f)?;
411-
418+
412419
// TODO: somehow actually use this config file
413420
Ok(())
414421
}

src/backend/postinstall/grub2.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,21 @@ pub struct GRUB2;
126126
impl PostInstallModule for GRUB2 {
127127
fn run(&self, context: &Context) -> Result<()> {
128128
stage!("Generating system grub defaults" {
129-
let defaults = Grub2Defaults::default();
129+
let mut defaults = Grub2Defaults::default();
130+
131+
// Now, let's add extra boot opts if they exist
132+
if let Some(crypt_data) = &context.crypt_data {
133+
// prepend
134+
let current_value = defaults.cmdline_linux.clone();
135+
136+
// this is a mess.
137+
// todo: In the event someone thinks this code stinks, please please PLEASE refactor it for us.
138+
139+
let joined_cmdline = crypt_data.cmdline_opts.join(" ");
140+
tracing::info!("Adding cryptsetup cmdline options: {}", joined_cmdline);
141+
defaults.cmdline_linux = format!("{} {}", joined_cmdline, current_value);
142+
}
143+
130144
let defaults_str = defaults.generate();
131145
std::fs::write("/etc/default/grub", defaults_str)?;
132146
});

src/backend/postinstall/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use selinux::SELinux;
1313
use serde::{Deserialize, Serialize};
1414
use std::path::PathBuf;
1515

16+
use super::repart_output::CryptData;
17+
1618
pub mod cleanup_boot;
1719
pub mod dracut;
1820
pub mod efi_stub;
@@ -31,6 +33,7 @@ pub struct Context {
3133
// Installs should always have an xbootldr partition
3234
pub xbootldr_partition: String,
3335
pub lang: String,
36+
pub crypt_data: Option<CryptData>,
3437
}
3538

3639
#[enum_dispatch(Module)]

0 commit comments

Comments
 (0)