Skip to content

Commit

Permalink
Ensure mount points writable before updating
Browse files Browse the repository at this point in the history
The /boot and /boot/efi mount points may be read-only, so remount
them as read-write if necessary when writing.
  • Loading branch information
kelvinfan001 committed Dec 1, 2020
1 parent 0be1b27 commit b89fc14
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/bootupd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::coreos;
use crate::efi;
use crate::model::{ComponentStatus, ComponentUpdatable, ContentMetadata, SavedState, Status};
use crate::{component, ipc};
use crate::util;
use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
Expand Down Expand Up @@ -93,6 +94,10 @@ pub(crate) enum ComponentUpdateResult {
},
}

fn ensure_writable_boot() -> Result<()> {
util::ensure_writable_mount("/boot")
}

/// daemon implementation of component update
pub(crate) fn update(name: &str) -> Result<ComponentUpdateResult> {
let mut state = SavedState::load_from_disk("/")?.unwrap_or_default();
Expand All @@ -109,6 +114,8 @@ pub(crate) fn update(name: &str) -> Result<ComponentUpdateResult> {
_ => return Ok(ComponentUpdateResult::AtLatestVersion),
};

ensure_writable_boot()?;

let mut pending_container = state.pending.take().unwrap_or_default();
let interrupted = pending_container.get(component.name()).cloned();
pending_container.insert(component.name().into(), update.clone());
Expand Down Expand Up @@ -140,6 +147,9 @@ pub(crate) fn adopt_and_update(name: &str) -> Result<ContentMetadata> {
if state.installed.get(name).is_some() {
anyhow::bail!("Component {} is already installed", name);
};

ensure_writable_boot()?;

let update = if let Some(update) = component.query_update(&sysroot)? {
update
} else {
Expand Down
6 changes: 6 additions & 0 deletions src/efi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl Component for EFI {
let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?;
// For adoption, we should only touch files that we know about.
let diff = updatef.relative_diff_to(&esp)?;
ensure_writable_efi()?;
log::trace!("applying adoption diff: {}", &diff);
filetree::apply_diff(&updated, &esp, &diff, None).context("applying filesystem changes")?;
Ok(InstalledContent {
Expand Down Expand Up @@ -153,6 +154,7 @@ impl Component for EFI {
let destdir = openat::Dir::open(&Path::new("/").join(MOUNT_PATH).join("EFI"))
.context("opening EFI dir")?;
validate_esp(&destdir)?;
ensure_writable_efi()?;
log::trace!("applying diff: {}", &diff);
filetree::apply_diff(&updated, &destdir, &diff, None)
.context("applying filesystem changes")?;
Expand Down Expand Up @@ -280,3 +282,7 @@ fn validate_esp(dir: &openat::Dir) -> Result<()> {
};
Ok(())
}

fn ensure_writable_efi() -> Result<()> {
util::ensure_writable_mount(&Path::new("/").join(MOUNT_PATH))
}
18 changes: 18 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use anyhow::{bail, Result};
use openat_ext::OpenatDirExt;

use std::process::Command;
use std::path::Path;

pub(crate) trait CommandRunExt {
fn run(&mut self) -> Result<()>;
Expand Down Expand Up @@ -65,3 +66,20 @@ pub(crate) fn filenames(dir: &openat::Dir) -> Result<HashSet<String>> {
}
Ok(ret)
}

pub(crate) fn ensure_writable_mount<P: AsRef<Path>>(p: P) -> Result<()> {
use nix::sys::statvfs;
let p = p.as_ref();
let stat = statvfs::statvfs(p)?;
if !stat.flags().contains(statvfs::FsFlags::ST_RDONLY) {
return Ok(());
}
let status = std::process::Command::new("mount")
.args(&["-o", "remount,rw"])
.arg(p)
.status()?;
if !status.success() {
anyhow::bail!("Failed to remount {:?} writable", p);
}
Ok(())
}

0 comments on commit b89fc14

Please sign in to comment.