Skip to content

Commit a3bee28

Browse files
committed
Ensure ESP is mounted
Following coreos/fedora-coreos-config#794, the ESP will no longer be mounted by default in FCOS. Mount the ESP at a directory with a random name in bootupd's sandboxed /tmp ourselves before reading from/writing to it. Note that ESPs on redundant disks is not yet supported, this commit simply mounts the device with part-label `EFI-SYSTEM` if one exists. `ProtectClock=yes` in `bootupd.service` is preventing the ESP from being mounted, remove that for now.
1 parent 5a298e6 commit a3bee28

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

src/efi.rs

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use anyhow::{bail, Context, Result};
1414
use openat_ext::OpenatDirExt;
1515

1616
use chrono::prelude::*;
17+
use structopt::lazy_static::lazy_static;
1718

1819
use crate::component::*;
1920
use crate::filetree;
@@ -22,27 +23,64 @@ use crate::ostreeutil;
2223
use crate::util;
2324
use crate::util::CommandRunExt;
2425

25-
/// The path to the ESP mount
26-
pub(crate) const MOUNT_PATH: &str = "boot/efi";
26+
/// The ESP partition label
27+
pub(crate) const ESP_PART_LABEL: &str = "EFI-SYSTEM";
28+
29+
#[macro_use]
30+
lazy_static! {
31+
/// The path to a temporary ESP mount
32+
static ref MOUNT_PATH: PathBuf = {
33+
// Create new directory in /tmp with randomly generated name at runtime for ESP mount path.
34+
tempfile::tempdir_in("/tmp").expect("Failed to create temp dir for EFI mount").into_path()
35+
};
36+
}
2737

2838
#[derive(Default)]
2939
pub(crate) struct EFI {}
3040

3141
impl EFI {
3242
fn esp_path(&self) -> PathBuf {
33-
Path::new(MOUNT_PATH).join("EFI")
43+
Path::new(&*MOUNT_PATH).join("EFI")
44+
}
45+
46+
fn esp_device(&self) -> PathBuf {
47+
Path::new("/dev/disk/by-partlabel/").join(ESP_PART_LABEL)
3448
}
3549

3650
fn open_esp_optional(&self) -> Result<Option<openat::Dir>> {
51+
self.ensure_mounted_esp()?;
3752
let sysroot = openat::Dir::open("/")?;
3853
let esp = sysroot.sub_dir_optional(&self.esp_path())?;
3954
Ok(esp)
4055
}
4156
fn open_esp(&self) -> Result<openat::Dir> {
57+
self.ensure_mounted_esp()?;
4258
let sysroot = openat::Dir::open("/")?;
4359
let esp = sysroot.sub_dir(&self.esp_path())?;
4460
Ok(esp)
4561
}
62+
63+
fn ensure_mounted_esp(&self) -> Result<()> {
64+
let mount_point = &Path::new("/").join(&*MOUNT_PATH);
65+
let output = std::process::Command::new("mountpoint")
66+
.arg(mount_point)
67+
.output()?;
68+
if !output.status.success() {
69+
let esp_device = &self.esp_device();
70+
if !esp_device.exists() {
71+
log::error!("Single ESP device not found; ESP on multiple independent filesystems currently unsupported");
72+
anyhow::bail!("Could not find {:?}", esp_device);
73+
}
74+
let status = std::process::Command::new("mount")
75+
.arg(&self.esp_device())
76+
.arg(mount_point)
77+
.status()?;
78+
if !status.success() {
79+
anyhow::bail!("Failed to mount {:?}", esp_device);
80+
}
81+
};
82+
Ok(())
83+
}
4684
}
4785

4886
impl Component for EFI {
@@ -94,7 +132,6 @@ impl Component for EFI {
94132
let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?;
95133
// For adoption, we should only touch files that we know about.
96134
let diff = updatef.relative_diff_to(&esp)?;
97-
ensure_writable_efi()?;
98135
log::trace!("applying adoption diff: {}", &diff);
99136
filetree::apply_diff(&updated, &esp, &diff, None).context("applying filesystem changes")?;
100137
Ok(InstalledContent {
@@ -112,7 +149,8 @@ impl Component for EFI {
112149
};
113150
let srcdir_name = component_updatedirname(self);
114151
let ft = crate::filetree::FileTree::new_from_dir(&src_root.sub_dir(&srcdir_name)?)?;
115-
let destdir = Path::new(dest_root).join(MOUNT_PATH);
152+
self.ensure_mounted_esp()?;
153+
let destdir = Path::new(dest_root).join(&*MOUNT_PATH);
116154
{
117155
let destd = openat::Dir::open(&destdir)
118156
.with_context(|| format!("opening dest dir {}", destdir.display()))?;
@@ -151,10 +189,9 @@ impl Component for EFI {
151189
.context("opening update dir")?;
152190
let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?;
153191
let diff = currentf.diff(&updatef)?;
154-
let destdir = openat::Dir::open(&Path::new("/").join(MOUNT_PATH).join("EFI"))
155-
.context("opening EFI dir")?;
192+
self.ensure_mounted_esp()?;
193+
let destdir = self.open_esp().context("opening EFI dir")?;
156194
validate_esp(&destdir)?;
157-
ensure_writable_efi()?;
158195
log::trace!("applying diff: {}", &diff);
159196
filetree::apply_diff(&updated, &destdir, &diff, None)
160197
.context("applying filesystem changes")?;
@@ -256,7 +293,8 @@ impl Component for EFI {
256293
.filetree
257294
.as_ref()
258295
.ok_or_else(|| anyhow::anyhow!("No filetree for installed EFI found!"))?;
259-
let efidir = openat::Dir::open(&Path::new("/").join(MOUNT_PATH).join("EFI"))?;
296+
self.ensure_mounted_esp()?;
297+
let efidir = self.open_esp()?;
260298
let diff = currentf.relative_diff_to(&efidir)?;
261299
let mut errs = Vec::new();
262300
for f in diff.changes.iter() {
@@ -282,7 +320,3 @@ fn validate_esp(dir: &openat::Dir) -> Result<()> {
282320
};
283321
Ok(())
284322
}
285-
286-
fn ensure_writable_efi() -> Result<()> {
287-
util::ensure_writable_mount(&Path::new("/").join(MOUNT_PATH))
288-
}

systemd/bootupd.service

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ ProtectHome=yes
1919
ReadOnlyPaths=/usr
2020
PrivateTmp=yes
2121
PrivateNetwork=yes
22-
ProtectClock=yes
2322
ProtectHostname=yes
2423
ProtectControlGroups=yes
2524
RestrictSUIDSGID=yes

0 commit comments

Comments
 (0)