Skip to content

Commit

Permalink
fix(repair): Add plain option to cryptswaps in crypttab
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick committed Oct 21, 2020
1 parent 2736463 commit c668a15
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 13 deletions.
7 changes: 3 additions & 4 deletions src/release/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ impl DaemonRuntime {
self.terminate_background_applications();

let from_version = from.parse::<Version>().expect("invalid version");
let from_codename = Codename::try_from(from_version).expect("release doesn't have a codename");
let from_codename =
Codename::try_from(from_version).expect("release doesn't have a codename");

let lock_or = |ready, then: UpgradeEvent| {
(*logger)(if ready { then } else { UpgradeEvent::AptFilesLocked })
Expand All @@ -328,10 +329,8 @@ impl DaemonRuntime {

// Check the system and perform any repairs necessary for success.
(|| {
// Repair the fstab
repair::crypttab::repair().map_err(RepairError::Crypttab)?;
repair::fstab::repair().map_err(RepairError::Fstab)?;

// Try to fix any packaging errors
repair::packaging::repair().map_err(RepairError::Packaging)?;

Ok(())
Expand Down
74 changes: 74 additions & 0 deletions src/repair/crypttab.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use anyhow::Context;
use std::fs;
use std::path::Path;

const CRYPTTAB: &str = "/etc/crypttab";
const CRYPTTAB_TMP: &str = "/etc/crypttab.tmp";

pub fn repair() -> anyhow::Result<()> {
if !Path::new(CRYPTTAB).exists() {
return Ok(());
}

let contents = fs::read_to_string(CRYPTTAB).context("cannot read the crypttab file")?;

if let Some(new_contents) = cryptswap_plain_warning(&contents) {
fs::write(CRYPTTAB_TMP, new_contents.as_bytes()).context("failed to write new crypttab")?;

fs::rename(CRYPTTAB_TMP, CRYPTTAB).context("failed to overwrite crypttab")?;
}

Ok(())
}

fn cryptswap_plain_warning(input: &str) -> Option<String> {
let mut correction_needed = false;
let mut new = String::new();

for line in input.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
new.push_str(line);
new.push('\n');
continue;
}

if let Some(options) = line.split_ascii_whitespace().skip(3).next() {
let fields = options.split(',').collect::<Vec<_>>();
if fields.iter().any(|&e| e == "swap") && !fields.iter().any(|&e| e == "plain") {
new.push_str(&line.replace("swap,", "swap,plain,"));
new.push('\n');
correction_needed = true;
continue;
}
}

new.push_str(line);
new.push('\n');
}

if correction_needed {
Some(new)
} else {
None
}
}

#[cfg(test)]
mod tests {
use super::*;

const BAD: &str = r#"cryptdata UUID=ed9e7007-b02b-48a6-b4ce-2207ee5fefd6 none luks
cryptswap UUID=ed9e7007-b02b-48a6-b4ce-2207ee5fefd6 /dev/urandom swap,offset=1024,cipher=aes-xts-plain64,size=512
"#;

const GOOD: &str = r#"cryptdata UUID=ed9e7007-b02b-48a6-b4ce-2207ee5fefd6 none luks
cryptswap UUID=ed9e7007-b02b-48a6-b4ce-2207ee5fefd6 /dev/urandom swap,plain,offset=1024,cipher=aes-xts-plain64,size=512
"#;

#[test]
fn cryptswap() {
assert_eq!(None, cryptswap_plain_warning(GOOD));
assert_eq!(Some(GOOD.to_owned()), cryptswap_plain_warning(BAD));
}
}
29 changes: 20 additions & 9 deletions src/repair/mod.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
pub mod crypttab;
pub mod fstab;
pub mod misc;
pub mod packaging;

use self::fstab::FstabError;
use std::io;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum RepairError {
#[error(display = "packaging error: {}", _0)]
Packaging(anyhow::Error),
#[error(display = "error checking and fixing fstab: {}", _0)]
Fstab(FstabError),
#[error(display = "version is not an ubuntu codename: {}", _0)]
#[error("failed to correct errors in crypttab")]
Crypttab(#[source] anyhow::Error),

#[error("unable to apply dkms gcc9 fix")]
DkmsGcc9(#[source] io::Error),

#[error("error checking and fixing fstab")]
Fstab(#[source] FstabError),

#[error("version is not an ubuntu codename: {}", _0)]
InvalidVersion(String),
#[error(display = "unable to apply dkms gcc9 fix: {}", _0)]
DkmsGcc9(io::Error),
#[error(display = "failed to wipe pulseaudio settings for users: {}", _0)]
WipePulse(io::Error),

#[error("packaging error")]
Packaging(#[source] anyhow::Error),

#[error("failed to wipe pulseaudio settings for users")]
WipePulse(#[source] io::Error),
}

pub fn repair() -> Result<(), RepairError> {
info!("performing release repair");

crypttab::repair().map_err(RepairError::Crypttab)?;
fstab::repair().map_err(RepairError::Fstab)?;
packaging::repair().map_err(RepairError::Packaging)?;

Expand Down

0 comments on commit c668a15

Please sign in to comment.