-
Notifications
You must be signed in to change notification settings - Fork 174
WIP: install: Add --no-bootloader to skip bootloader setup #1997
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
base: main
Are you sure you want to change the base?
WIP: install: Add --no-bootloader to skip bootloader setup #1997
Conversation
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.
Code Review
This pull request introduces a --no-bootloader flag to skip bootloader management during installation, which is a valuable feature for custom environments. However, the current implementation has significant security implications and logic errors. In the ostree installation path, using this flag unintentionally skips all post-deployment operations, including the installation of logically bound images which may contain critical security components, potentially leaving the system in an insecure or incomplete state. Furthermore, in the composefs installation path, the --no-bootloader flag is completely ignored, leading to unexpected bootloader installation. These issues need to be addressed to ensure the flag behaves as expected and doesn't leave the system in an insecure or inconsistent state. My review includes detailed comments on how to resolve these problems.
crates/lib/src/install.rs
Outdated
| if state.config_opts.no_bootloader { | ||
| tracing::info!("Skipping bootloader installation (--no-bootloader requested)"); | ||
| return Ok(()); | ||
| } |
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.
The early return when --no-bootloader is enabled causes the installer to skip all subsequent post-deployment operations, including the installation of logically bound images. This is a critical security concern as bound images often contain critical system components or security agents, and skipping their installation can leave the system in an insecure or incomplete state. Pulling bound images should be independent of bootloader installation. The check should be refactored to only wrap the bootloader installation logic, ensuring post-deployment operations are always executed. Consider wrapping only the bootloader installation logic in a conditional block, similar to:if !state.config_opts.no_bootloader { let postfetch = PostFetchState::new(state, &deployment_dir)?; if cfg!(target_arch = "s390x") { // ... bootloader logic ... } else { // ... bootloader logic ... } tracing::debug!("Installed bootloader");} else { tracing::info!("Skipping bootloader installation (--no-bootloader requested)");}// This will now run in both casestracing::debug!("Performing post-deployment operations");match bound_images { // ...}
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.
I agree here, we should ensure not make this return, but just skip the bootloater::install_xxx calls.
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.
Indeed, I've missed that. I changed now to not return early and just avoid calling to the crate::bootloader::install_via_*
| // This allows installing to a filesystem without boot and ESP partitions | ||
| #[clap(long)] | ||
| #[serde(default)] | ||
| pub(crate) no_bootloader: bool, |
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.
The no_bootloader flag is not respected in the composefs installation path. While it is used to skip bootloader setup in the ostree path, the setup_composefs_boot function (called when composefs_backend is enabled) does not check this flag and proceeds to install the bootloader via bootupd or systemd-boot. This can lead to unexpected modification of the system's bootloader, potentially overwriting a custom or secure bootloader that the user intended to preserve.
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.
Also skipping the crate::bootloader::install_* calls in setup_composefs_boot() if the --no-bootloader option is used.
680acbe to
854bcf4
Compare
When we're currently checking if /boot is a mountpoint we ware failing if /boot is missing. In the automotive usecase, with aboot, neither /boot or /boot/EFI are real partitions, so when bootc-image-builder runs there will be no mounts anywhere under /boot, which means bootc errors out with: ``` No /boot directory found in root; this is is currently required. ``` This isn't necessary, we can just continue on with boot_is_mount as false in this case. Note: Things later fail in bootupd, but that can be fixed separately. Signed-off-by: Alexander Larsson <alexl@redhat.com>
854bcf4 to
1d743c2
Compare
Currently, the bootc install workflow assumes that the bootloader must be managed by bootupd. This works well for server and edge environments, but it is too inflexible for embedded or custom platforms where the bootloader is managed externally (e.g., aboot for automotive use cases). In these scenarios, users want to install the filesystem content (OSTree commit, kernel, initramfs, etc) without bootc assuming that a boot or ESP partition exists and that bootupd must be invoked to update these. By adding a --no-bootloader option, users can have explicit control over how the boot loading is handled, without bootc or bootupd intervention. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
1d743c2 to
ea65bef
Compare
Implicitly assuming the installation target will manage its own bootloader is a bit risky. The lack of an EFI partition could be the result of a mistake which would result in an installation that is not bootable. So I think it'd be best to keep this as an explicit option. |
|
We already detect if bootupd is missing and assume systemd-boot (except for s390x). Arguably, we could extend that and just allow bootupd to be missing, and assume that bootloader state is handled after installation. But I dunno...
Also coreos/bootupd#766 is related here in that I think there's an argument that bootupd should gain support for other things. Anyways just for my understanding, we still relying on the ostree aboot backend (which isn't implemented for composefs), correct? To combine these two things, how about instead of |
IMHO bootupd should be able to support more things, like rpi firmware, etc. And, it should be made to handle the aboot case "cleanly". I.e. not fall over itself if there is no EFI in the system at all. However, in the short term I think it makes sense to just drop bootupd in the "pure aboot" case, as it has no current value, and the full solution is more long term.
Yes. However, note that there are two ways we can use the ostree aboot backend. Either with a "pure" android boot firmware, in which case there will be no EFI partition at all, or with ukiboot, which is an EFI implementation of aboot. In the ukiboot case we do have an EFI partition, and we will need bootupd to properly install and update ukiboot.efi.
So, this would be fine in the "pure aboot" case, but would not work with ukiboot. So the "detect the presence" case here need to be careful about this. |
That is fair. And what about using whether Yes, it could be a mistake and |
Not a huge deal but I prefer to limit the chances a user could end up with a non-bootable system that is difficult to troubleshoot, which could be the case if we just print a message that will likely be ignored. Ideally we would explicitly handle each bootloader we intend to support. |
Can't we detect ukiboot too? BTW one big picture thing here is that we must support configuring things via files in the container image (also supporting CLI args is fine too), but I think the former should be generally preferred. Previous relevant changes: etc. |
We could but IMO explicit is better than trying to come up with heuristics and make assumptions about this.
I see. Thanks a lot for the references! Any suggestions on how the file config option should be named? There's already a |
I think we could reasonably make the detection not feel heuristic though...but it would need some bikeshedding.
Well...at this point this has a very high overlap with the ostree "bootloader" backend right? I guess we could extend our |
Currently, the bootc install workflow assumes that the bootloader must be
managed by bootupd. This works well for server and edge environments, but
it is too inflexible for embedded or custom platforms where the bootloader
is managed externally (e.g., aboot for automotive use cases).
In these scenarios, users want to install the filesystem content (OSTree
commit, kernel, initramfs, etc) without bootc assuming that a boot or ESP
partition exists and that bootupd must be invoked to update these.
By adding a --no-bootloader option, users can have explicit control over
how the boot loading is handled, without bootc or bootupd intervention.
Note: This PR depends on @alexlarsson's #1996. If the approach is found to be
acceptable, a follow-up would be for
bootc install to-filesystemto infer if theoption has to be set implicitly. For example if neither boot nor EFI partition exist.