From 483f353fd089f7350558af721da50114b41277de Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 12 Jun 2023 15:32:25 -0600 Subject: [PATCH] backup luks headers --- backend/src/backup/backup_bulk.rs | 23 +++++++++++++++-- backend/src/disk/main.rs | 30 ++++++++++++++++++---- backend/src/os_install/mod.rs | 41 +++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/backend/src/backup/backup_bulk.rs b/backend/src/backup/backup_bulk.rs index 0f41b443d..9d560a46b 100644 --- a/backend/src/backup/backup_bulk.rs +++ b/backend/src/backup/backup_bulk.rs @@ -1,5 +1,5 @@ use std::collections::{BTreeMap, BTreeSet}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use chrono::Utc; use clap::ArgMatches; @@ -8,6 +8,7 @@ use helpers::AtomicFile; use patch_db::{DbHandle, LockType, PatchDbHandle}; use rpc_toolkit::command; use tokio::io::AsyncWriteExt; +use tokio::process::Command; use tracing::instrument; use super::target::BackupTargetId; @@ -23,8 +24,8 @@ use crate::disk::mount::guard::TmpMountGuard; use crate::notifications::NotificationLevel; use crate::s9pk::manifest::PackageId; use crate::status::MainStatus; -use crate::util::display_none; use crate::util::serde::IoFormat; +use crate::util::{display_none, Invoke}; use crate::version::VersionT; use crate::{Error, ErrorKind, ResultExt}; @@ -358,6 +359,24 @@ async fn perform_backup( .await .with_kind(ErrorKind::Filesystem)?; + let luks_folder_old = backup_guard.as_ref().join("luks.old"); + if tokio::fs::metadata(&luks_folder_old).await.is_ok() { + tokio::fs::remove_dir_all(&luks_folder_old).await?; + } + let luks_folder_bak = backup_guard.as_ref().join("luks"); + if tokio::fs::metadata(&luks_folder_bak).await.is_ok() { + tokio::fs::rename(&luks_folder_bak, &luks_folder_old).await?; + } + let luks_folder = Path::new("/media/embassy/config/luks"); + if tokio::fs::metadata(&luks_folder).await.is_ok() { + Command::new("cp") + .arg("-r") + .arg(&luks_folder) + .arg(&luks_folder_bak) + .invoke(ErrorKind::Filesystem) + .await?; + } + let timestamp = Some(Utc::now()); backup_guard.unencrypted_metadata.version = crate::version::Current::new().semver().into(); diff --git a/backend/src/disk/main.rs b/backend/src/disk/main.rs index f9ec4bf08..2ebfc7613 100644 --- a/backend/src/disk/main.rs +++ b/backend/src/disk/main.rs @@ -106,12 +106,13 @@ pub async fn create_fs>( .arg(guid) .invoke(crate::ErrorKind::DiskManagement) .await?; + let crypt_path = Path::new("/dev").join(guid).join(name); Command::new("cryptsetup") .arg("-q") .arg("luksFormat") .arg(format!("--key-file={}", PASSWORD_PATH)) .arg(format!("--keyfile-size={}", password.len())) - .arg(Path::new("/dev").join(guid).join(name)) + .arg(&crypt_path) .invoke(crate::ErrorKind::DiskManagement) .await?; Command::new("cryptsetup") @@ -119,7 +120,7 @@ pub async fn create_fs>( .arg("luksOpen") .arg(format!("--key-file={}", PASSWORD_PATH)) .arg(format!("--keyfile-size={}", password.len())) - .arg(Path::new("/dev").join(guid).join(name)) + .arg(&crypt_path) .arg(format!("{}_{}", guid, name)) .invoke(crate::ErrorKind::DiskManagement) .await?; @@ -265,17 +266,36 @@ pub async fn mount_fs>( tokio::fs::write(PASSWORD_PATH, password) .await .with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?; + let crypt_path = Path::new("/dev").join(guid).join(name); + let full_name = format!("{}_{}", guid, name); Command::new("cryptsetup") .arg("-q") .arg("luksOpen") .arg(format!("--key-file={}", PASSWORD_PATH)) .arg(format!("--keyfile-size={}", password.len())) - .arg(Path::new("/dev").join(guid).join(name)) - .arg(format!("{}_{}", guid, name)) + .arg(&crypt_path) + .arg(&full_name) .invoke(crate::ErrorKind::DiskManagement) .await?; - let mapper_path = Path::new("/dev/mapper").join(format!("{}_{}", guid, name)); + let mapper_path = Path::new("/dev/mapper").join(&full_name); let reboot = repair.e2fsck(&mapper_path).await?; + // Backup LUKS header if e2fsck succeeded + let luks_folder = Path::new("/media/embassy/config/luks"); + tokio::fs::create_dir_all(luks_folder).await?; + let tmp_luks_bak = luks_folder.join(format!(".{full_name}.luks.bak.tmp")); + if tokio::fs::metadata(&tmp_luks_bak).await.is_ok() { + tokio::fs::remove_file(&tmp_luks_bak).await?; + } + let luks_bak = luks_folder.join(format!("{full_name}.luks.bak")); + Command::new("cryptsetup") + .arg("-q") + .arg("luksHeaderBackup") + .arg("--header-backup-file") + .arg(&tmp_luks_bak) + .arg(&crypt_path) + .invoke(crate::ErrorKind::DiskManagement) + .await?; + tokio::fs::rename(&tmp_luks_bak, &luks_bak).await?; mount(&mapper_path, datadir.as_ref().join(name), ReadWrite).await?; tokio::fs::remove_file(PASSWORD_PATH) diff --git a/backend/src/os_install/mod.rs b/backend/src/os_install/mod.rs index f6e29903d..6ebd33aaf 100644 --- a/backend/src/os_install/mod.rs +++ b/backend/src/os_install/mod.rs @@ -10,7 +10,7 @@ use crate::context::InstallContext; use crate::disk::mount::filesystem::bind::Bind; use crate::disk::mount::filesystem::block_dev::BlockDev; use crate::disk::mount::filesystem::efivarfs::EfiVarFs; -use crate::disk::mount::filesystem::ReadWrite; +use crate::disk::mount::filesystem::{MountType, ReadWrite}; use crate::disk::mount::guard::{MountGuard, TmpMountGuard}; use crate::disk::util::{DiskInfo, PartitionTable}; use crate::disk::OsPartitionInfo; @@ -147,6 +147,34 @@ pub async fn execute( .invoke(crate::ErrorKind::DiskManagement) .await?; + if !overwrite { + if let Ok(guard) = + TmpMountGuard::mount(&BlockDev::new(part_info.root.clone()), MountType::ReadOnly).await + { + if let Err(e) = async { + // cp -r ${guard}/config /tmp/config + Command::new("cp") + .arg("-r") + .arg(guard.as_ref().join("config")) + .arg("/tmp/config.bak") + .invoke(crate::ErrorKind::Filesystem) + .await?; + if tokio::fs::metadata(guard.as_ref().join("config/upgrade")) + .await + .is_ok() + { + tokio::fs::remove_file(guard.as_ref().join("config/upgrade")).await?; + } + guard.unmount().await + } + .await + { + tracing::error!("Error recovering previous config: {e}"); + tracing::debug!("{e:?}"); + } + } + } + Command::new("mkfs.ext4") .arg(&part_info.root) .invoke(crate::ErrorKind::DiskManagement) @@ -158,7 +186,16 @@ pub async fn execute( .await?; let rootfs = TmpMountGuard::mount(&BlockDev::new(&part_info.root), ReadWrite).await?; - tokio::fs::create_dir(rootfs.as_ref().join("config")).await?; + if tokio::fs::metadata("/tmp/config.bak").await.is_ok() { + Command::new("cp") + .arg("-r") + .arg("/tmp/config.bak") + .arg(rootfs.as_ref().join("config")) + .invoke(crate::ErrorKind::Filesystem) + .await?; + } else { + tokio::fs::create_dir(rootfs.as_ref().join("config")).await?; + } tokio::fs::create_dir(rootfs.as_ref().join("next")).await?; let current = rootfs.as_ref().join("current"); tokio::fs::create_dir(¤t).await?;