Skip to content

Commit e0a48c7

Browse files
committed
lint: Add an api-base-directories lint
Saw in the wild that someone accidentally did an `rm -rf /var`, and that only fails pretty late in the process. Add a lint that hard requires the "API filesystem" directory mount points, plus `/var` - that one is a requirement for ostree right now. Signed-off-by: Colin Walters <walters@verbum.org>
1 parent 190085d commit e0a48c7

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

lib/src/lints.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use serde::Serialize;
2525

2626
/// Reference to embedded default baseimage content that should exist.
2727
const BASEIMAGE_REF: &str = "usr/share/doc/bootc/baseimage/base";
28+
// https://systemd.io/API_FILE_SYSTEMS/ with /var added for us
29+
const API_DIRS: &[&str] = &["dev", "proc", "sys", "run", "tmp", "var"];
2830

2931
/// A lint check has failed.
3032
#[derive(thiserror::Error, Debug)]
@@ -375,6 +377,31 @@ fn check_prepareroot_composefs_norecurse(dir: &Dir) -> LintResult {
375377
lint_ok()
376378
}
377379

380+
#[distributed_slice(LINTS)]
381+
static LINT_API_DIRS: Lint = Lint::new_fatal(
382+
"api-base-directories",
383+
indoc! { r#"
384+
Verify that expected base API directories exist. For more information
385+
on these, see <https://systemd.io/API_FILE_SYSTEMS/>.
386+
387+
Note that in addition, bootc requires that `/var` exist as a directory.
388+
"#},
389+
check_api_dirs,
390+
);
391+
fn check_api_dirs(root: &Dir) -> LintResult {
392+
for d in API_DIRS {
393+
let Some(meta) = root.symlink_metadata_optional(d)? else {
394+
return lint_err(format!("Missing API filesystem base directory: /{d}"));
395+
};
396+
if !meta.is_dir() {
397+
return lint_err(format!(
398+
"Expected directory for API filesystem base directory: /{d}"
399+
));
400+
}
401+
}
402+
lint_ok()
403+
}
404+
378405
#[distributed_slice(LINTS)]
379406
static LINT_COMPOSEFS: Lint = Lint::new_warning(
380407
"baseimage-composefs",
@@ -645,6 +672,9 @@ mod tests {
645672

646673
fn passing_fixture() -> Result<cap_std_ext::cap_tempfile::TempDir> {
647674
let root = cap_std_ext::cap_tempfile::tempdir(cap_std::ambient_authority())?;
675+
for d in API_DIRS {
676+
root.create_dir(d)?;
677+
}
648678
root.create_dir_all("usr/lib/modules/5.7.2")?;
649679
root.write("usr/lib/modules/5.7.2/vmlinuz", "vmlinuz")?;
650680

@@ -674,6 +704,18 @@ mod tests {
674704
Ok(())
675705
}
676706

707+
#[test]
708+
fn test_api() -> Result<()> {
709+
let root = &passing_fixture()?;
710+
// This one should pass
711+
check_api_dirs(root).unwrap().unwrap();
712+
root.remove_dir("var")?;
713+
assert!(check_api_dirs(root).unwrap().is_err());
714+
root.write("var", "a file for var")?;
715+
assert!(check_api_dirs(root).unwrap().is_err());
716+
Ok(())
717+
}
718+
677719
#[test]
678720
fn test_lint_main() -> Result<()> {
679721
let root = &passing_fixture()?;

0 commit comments

Comments
 (0)