fix(chainload): release LoadedImage before starting the image

The chainload action held the child image's LoadedImage protocol open
exclusively while calling start_image. Any image that opens its own
LoadedImage protocol exclusively, such as another uefi-rs application
or Sprout itself, then failed with ACCESS_DENIED. Scope the protocol to
setting the load options.
This commit is contained in:
alex authored and Alex Zenla committed 2026-09-26 18:58:54 -07:00
1 parent bcfb7dc680
commit 9967a7ab80
1 file changed
+9 -5
+9 -5
View File
@@ -32,11 +32,6 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
// It will determine if the image needs to be loaded via the shim or can be loaded directly.
let image = ImageLoader::load(request)?;
// Open the LoadedImage protocol of the image to chainload.
let mut loaded_image_protocol =
uefi::boot::open_protocol_exclusive::<LoadedImage>(*image.handle())
.context("unable to open loaded image protocol")?;
// Stamp and combine the options to pass to the image.
let options = combine_options(context.stamp_iter(configuration.options.iter()));
@@ -54,6 +49,14 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
bail!("chainloader options too large");
}
// Open the LoadedImage protocol of the image to chainload to pass the load options.
// This is done in a block to release the protocol before the image is started, as the
// image may itself need to open its LoadedImage protocol exclusively.
{
let mut loaded_image_protocol =
uefi::boot::open_protocol_exclusive::<LoadedImage>(*image.handle())
.context("unable to open loaded image protocol")?;
// SAFETY: option size is checked to validate it is safe to pass.
// Additionally, the pointer is allocated and retained on heap, which makes
// passing the `options` pointer safe to the next image.
@@ -61,6 +64,7 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
loaded_image_protocol
.set_load_options(options.as_ptr() as *const u8, options.num_bytes() as u32);
}
}
// Stamp the initrd path, if provided.
let initrd = configuration