Repository navigation
composefs-boot: Make composefs integration optional #411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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,109 @@ | ||
| use std::ffi::OsStr; | ||
|
|
||
| use anyhow::Result; | ||
| use rustix::fd::AsFd; | ||
|
|
||
| use composefs::{fsverity::FsVerityHashValue, repository::Repository, tree::FileSystem}; | ||
|
|
||
| use crate::{ | ||
| bootloader::{BootEntry, get_boot_resources}, | ||
| selabel, | ||
| }; | ||
|
|
||
| /// These directories are required to exist in images. | ||
| /// They may have content in the container, but we don't | ||
| /// want to expose them in the final merged root. | ||
| /// | ||
| /// # /boot | ||
| /// | ||
| /// This is how sealed UKIs are handled; the UKI in /boot has the composefs | ||
| /// digest, so we can't include it in the rendered image. | ||
| /// | ||
| /// # /sysroot | ||
| /// | ||
| /// See https://github.com/containers/composefs-rs/issues/164 | ||
| /// Basically there is only content here in ostree-container cases, | ||
| /// and us traversing there for SELinux labeling will cause problems. | ||
| /// The ostree-container code special cases it in a different way, but | ||
| /// here we can just ignore it. | ||
| const REQUIRED_TOPLEVEL_TO_EMPTY_DIRS: &[&str] = &["boot", "sysroot"]; | ||
|
|
||
| /// Empty the required top-level directories and set their mtime to match /usr. | ||
| fn empty_toplevel_dirs<ObjectID: FsVerityHashValue>(fs: &mut FileSystem<ObjectID>) -> Result<()> { | ||
| let usr = fs.root.get_directory(OsStr::new("usr"))?; | ||
| let usr_mtime_stat_sec = usr.stat.st_mtim_sec; | ||
| let usr_mtime_stat_nsec = usr.stat.st_mtim_nsec; | ||
|
|
||
| for d in REQUIRED_TOPLEVEL_TO_EMPTY_DIRS { | ||
| let d = fs.root.get_directory_mut(d.as_ref())?; | ||
| d.stat.st_mtim_sec = usr_mtime_stat_sec; | ||
| d.stat.st_mtim_nsec = usr_mtime_stat_nsec; | ||
| d.clear(); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Trait for transforming filesystem images for boot scenarios. | ||
| /// | ||
| /// This trait provides functionality to prepare composefs filesystem images for booting by | ||
| /// extracting boot resources and applying necessary transformations like SELinux labeling. | ||
| pub trait BootOps<ObjectID: FsVerityHashValue> { | ||
| /// Transforms a filesystem image for boot by extracting boot entries and applying SELinux labels. | ||
| /// | ||
| /// This method extracts boot resources from the filesystem, empties required top-level | ||
| /// directories (/boot, /sysroot), and applies SELinux security contexts. | ||
| /// | ||
| /// # Arguments | ||
| /// | ||
| /// * `repo` - The composefs repository containing filesystem objects | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// A vector of boot entries extracted from the filesystem (Type 1 BLS entries, Type 2 UKIs, etc.) | ||
| fn transform_for_boot( | ||
| &mut self, | ||
| repo: &Repository<ObjectID>, | ||
| ) -> Result<Vec<BootEntry<ObjectID>>>; | ||
|
|
||
| /// Apply boot filesystem transformations using an on-disk directory for file content. | ||
| /// | ||
| /// This applies the same filesystem transformations as [`BootOps::transform_for_boot`] | ||
| /// (emptying /boot and /sysroot, SELinux relabeling) but reads SELinux policy files | ||
| /// directly from the on-disk filesystem via a directory fd rather than from the | ||
| /// composefs repository. | ||
| /// | ||
| /// This does not extract boot entries (Type 1 BLS entries, UKIs, etc.) since those | ||
| /// are only needed for writing to the boot partition, not for computing the composefs | ||
| /// digest. | ||
| /// | ||
| /// # Arguments | ||
| /// | ||
| /// * `rootfs` - A directory fd pointing to the root of the on-disk filesystem | ||
| fn transform_for_boot_from_dir(&mut self, rootfs: impl AsFd) -> Result<()>; | ||
| } | ||
|
|
||
| impl<ObjectID: FsVerityHashValue> BootOps<ObjectID> for FileSystem<ObjectID> { | ||
| fn transform_for_boot( | ||
| &mut self, | ||
| repo: &Repository<ObjectID>, | ||
| ) -> Result<Vec<BootEntry<ObjectID>>> { | ||
| let boot_entries = get_boot_resources(self, repo)?; | ||
| empty_toplevel_dirs(self)?; | ||
| // Compact the leaves table after clearing directories, so that leaves | ||
| // which were only referenced by /boot or /sysroot are removed and | ||
| // don't appear as orphans when the filesystem is validated. | ||
| self.compact(); | ||
| selabel::selabel(self, repo)?; | ||
|
|
||
| Ok(boot_entries) | ||
| } | ||
|
|
||
| fn transform_for_boot_from_dir(&mut self, rootfs: impl AsFd) -> Result<()> { | ||
| empty_toplevel_dirs(self)?; | ||
| // Same as above: compact to remove leaves orphaned by clearing dirs. | ||
| self.compact(); | ||
| selabel::selabel_from_dir(self, rootfs)?; | ||
| Ok(()) | ||
| } | ||
| } |
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, can be a followup though