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}