composefs_boot/lib.rs
1//! Boot integration for composefs filesystem images.
2//!
3//! This crate provides functionality to transform composefs filesystem images for boot
4//! scenarios by extracting boot resources, applying SELinux labels, and preparing
5//! bootloader entries. It supports both Boot Loader Specification (Type 1) entries
6//! and Unified Kernel Images (Type 2) for UEFI boot.
7
8#![deny(missing_debug_implementations)]
9
10pub mod bootloader;
11pub mod cmdline;
12pub mod os_release;
13pub mod selabel;
14pub mod uki;
15pub mod write_boot;
16
17use anyhow::Result;
18
19use composefs::{fsverity::FsVerityHashValue, repository::Repository, tree::FileSystem};
20
21use crate::bootloader::{get_boot_resources, BootEntry};
22
23/// These directories are required to exist in images.
24/// They may have content in the container, but we don't
25/// want to expose them in the final merged root.
26///
27/// # /boot
28///
29/// This is how sealed UKIs are handled; the UKI in /boot has the composefs
30/// digest, so we can't include it in the rendered image.
31///
32/// # /sysroot
33///
34/// See https://github.com/containers/composefs-rs/issues/164
35/// Basically there is only content here in ostree-container cases,
36/// and us traversing there for SELinux labeling will cause problems.
37/// The ostree-container code special cases it in a different way, but
38/// here we can just ignore it.
39const REQUIRED_TOPLEVEL_TO_EMPTY_DIRS: &[&str] = &["boot", "sysroot"];
40
41/// Trait for transforming filesystem images for boot scenarios.
42///
43/// This trait provides functionality to prepare composefs filesystem images for booting by
44/// extracting boot resources and applying necessary transformations like SELinux labeling.
45pub trait BootOps<ObjectID: FsVerityHashValue> {
46 /// Transforms a filesystem image for boot by extracting boot entries and applying SELinux labels.
47 ///
48 /// This method extracts boot resources from the filesystem, empties required top-level
49 /// directories (/boot, /sysroot), and applies SELinux security contexts.
50 ///
51 /// # Arguments
52 ///
53 /// * `repo` - The composefs repository containing filesystem objects
54 ///
55 /// # Returns
56 ///
57 /// A vector of boot entries extracted from the filesystem (Type 1 BLS entries, Type 2 UKIs, etc.)
58 fn transform_for_boot(
59 &mut self,
60 repo: &Repository<ObjectID>,
61 ) -> Result<Vec<BootEntry<ObjectID>>>;
62}
63
64impl<ObjectID: FsVerityHashValue> BootOps<ObjectID> for FileSystem<ObjectID> {
65 fn transform_for_boot(
66 &mut self,
67 repo: &Repository<ObjectID>,
68 ) -> Result<Vec<BootEntry<ObjectID>>> {
69 let boot_entries = get_boot_resources(self, repo)?;
70 for d in REQUIRED_TOPLEVEL_TO_EMPTY_DIRS {
71 let d = self.root.get_directory_mut(d.as_ref())?;
72 d.stat.st_mtim_sec = 0;
73 d.clear();
74 }
75
76 selabel::selabel(self, repo)?;
77
78 Ok(boot_entries)
79 }
80}