forked from containers/bootc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Colin Walters <[email protected]>
- Loading branch information
Showing
13 changed files
with
328 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Enable fsverity at install time | ||
FROM localhost/bootc | ||
RUN <<EORUN | ||
set -xeuo pipefail | ||
mkdir -p /usr/lib/bootc/install | ||
cat > /usr/lib/bootc/install/30-fsverity.toml <<EOF | ||
[install] | ||
fsverity = "enabled" | ||
EOF | ||
EORUN |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
//! # Write deployments merging image with configmap | ||
//! | ||
//! Create a merged filesystem tree with the image and mounted configmaps. | ||
use std::os::fd::AsFd; | ||
use std::str::FromStr as _; | ||
|
||
use anyhow::Ok; | ||
use anyhow::{Context, Result}; | ||
use camino::Utf8PathBuf; | ||
use cap_std::fs::Dir; | ||
use cap_std_ext::cap_std; | ||
use fn_error_context::context; | ||
use ostree_ext::keyfileext::KeyFileExt; | ||
use ostree_ext::ostree; | ||
use rustix::io::Errno; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use crate::install::config::Tristate; | ||
use crate::store::{self, Storage}; | ||
|
||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub(crate) enum VerityState { | ||
Enabled, | ||
Disabled, | ||
Inconsistent, | ||
} | ||
|
||
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq)] | ||
pub(crate) struct FsckResult { | ||
pub(crate) errors: Vec<String>, | ||
pub(crate) verity: Option<VerityState>, | ||
} | ||
|
||
/// Check the fsverity state of all regular files in this object directory. | ||
#[context("Computing verity state")] | ||
fn verity_state_of_objects(d: &Dir) -> Result<(u64, u64)> { | ||
let mut enabled = 0; | ||
let mut disabled = 0; | ||
for ent in d.entries()? { | ||
let ent = ent?; | ||
if !ent.file_type()?.is_file() { | ||
continue; | ||
} | ||
let name = ent.file_name(); | ||
let name = name | ||
.into_string() | ||
.map(Utf8PathBuf::from) | ||
.map_err(|_| anyhow::anyhow!("Invalid UTF-8"))?; | ||
let Some("file") = name.extension() else { | ||
continue; | ||
}; | ||
let f = d | ||
.open(&name) | ||
.with_context(|| format!("Failed to open {name}"))?; | ||
let r: Option<composefs::fsverity::Sha256HashValue> = | ||
match composefs::fsverity::ioctl::fs_ioc_measure_verity(f.as_fd()) { | ||
Ok(r) => Some(r), | ||
Err(e) if matches!(e.downcast_ref::<Errno>(), Some(&Errno::NOSYS)) => None, | ||
Err(e) => return Err(e), | ||
}; | ||
drop(f); | ||
if r.is_some() { | ||
enabled += 1; | ||
} else { | ||
disabled += 1; | ||
} | ||
} | ||
Ok((enabled, disabled)) | ||
} | ||
|
||
async fn verity_state_of_all_objects(repo: &ostree::Repo) -> Result<(u64, u64)> { | ||
const MAX_CONCURRENT: usize = 3; | ||
|
||
let repo_config = repo.config(); | ||
let verity_state = { | ||
let (k, v) = store::REPO_VERITY_CONFIG.split_once('.').unwrap(); | ||
repo_config | ||
.optional_string(k, v)? | ||
.map(|v| Tristate::from_str(&v)) | ||
.transpose()? | ||
.unwrap_or_default() | ||
}; | ||
|
||
let repodir = Dir::reopen_dir(&repo.dfd_borrow())?; | ||
|
||
let mut joinset = tokio::task::JoinSet::new(); | ||
let mut results = Vec::new(); | ||
|
||
for ent in repodir.read_dir("objects")? { | ||
while joinset.len() >= MAX_CONCURRENT { | ||
results.push(joinset.join_next().await.unwrap()??); | ||
} | ||
let ent = ent?; | ||
if !ent.file_type()?.is_dir() { | ||
continue; | ||
} | ||
let objdir = ent.open_dir()?; | ||
joinset.spawn_blocking(move || verity_state_of_objects(&objdir)); | ||
} | ||
|
||
while let Some(output) = joinset.join_next().await { | ||
results.push(output??); | ||
} | ||
let r = results.into_iter().fold((0, 0), |mut acc, v| { | ||
acc.0 += v.0; | ||
acc.1 += v.1; | ||
acc | ||
}); | ||
Ok(r) | ||
} | ||
|
||
pub(crate) async fn fsck(storage: &Storage) -> Result<FsckResult> { | ||
let mut r = FsckResult::default(); | ||
r.verity = match verity_state_of_all_objects(&storage.repo()).await? { | ||
(0, 0) => None, | ||
(_, 0) => Some(VerityState::Enabled), | ||
(0, _) => Some(VerityState::Disabled), | ||
_ => Some(VerityState::Inconsistent), | ||
}; | ||
if matches!(&r.verity, &Some(VerityState::Inconsistent)) { | ||
r.errors.push("Inconsistent fsverity state".into()); | ||
} | ||
serde_json::to_writer(std::io::stdout().lock(), &r)?; | ||
Ok(r) | ||
} |
Oops, something went wrong.