mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 15:40:16 +00:00
fix(chainload): ensure that load options are always set, even if it is to an empty string
This commit is contained in:
@@ -53,30 +53,25 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
|
|||||||
let options =
|
let options =
|
||||||
utils::combine_options(configuration.options.iter().map(|item| context.stamp(item)));
|
utils::combine_options(configuration.options.iter().map(|item| context.stamp(item)));
|
||||||
|
|
||||||
// Pass the options to the image, if any are provided.
|
// Pass the load options to the image.
|
||||||
// The holder must drop at the end of this function to ensure the options are not leaked,
|
// If no options are provided, the resulting string will be empty.
|
||||||
// and the holder here ensures it outlives the if block here, as a pointer has to be
|
// The options are pinned and boxed to ensure that they are valid for the lifetime of this
|
||||||
// passed to the image.
|
// function, which ensures the lifetime of the options for the image runtime.
|
||||||
// SAFETY: The options outlive the usage of the image, and the image is not used after this.
|
let options = Box::pin(
|
||||||
let mut options_holder: Option<Box<CString16>> = None;
|
CString16::try_from(&options[..])
|
||||||
if !options.is_empty() {
|
.context("unable to convert chainloader options to CString16")?,
|
||||||
let options = Box::new(
|
);
|
||||||
CString16::try_from(&options[..])
|
|
||||||
.context("unable to convert chainloader options to CString16")?,
|
|
||||||
);
|
|
||||||
|
|
||||||
if options.num_bytes() > u32::MAX as usize {
|
if options.num_bytes() > u32::MAX as usize {
|
||||||
bail!("chainloader options too large");
|
bail!("chainloader options too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: option size is checked to validate it is safe to pass.
|
// SAFETY: option size is checked to validate it is safe to pass.
|
||||||
// Additionally, the pointer is allocated and retained on heap, which makes
|
// Additionally, the pointer is allocated and retained on heap, which makes
|
||||||
// passing the `options` pointer safe to the next image.
|
// passing the `options` pointer safe to the next image.
|
||||||
unsafe {
|
unsafe {
|
||||||
loaded_image_protocol
|
loaded_image_protocol
|
||||||
.set_load_options(options.as_ptr() as *const u8, options.num_bytes() as u32);
|
.set_load_options(options.as_ptr() as *const u8, options.num_bytes() as u32);
|
||||||
}
|
|
||||||
options_holder = Some(options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stamp the initrd path, if provided.
|
// Stamp the initrd path, if provided.
|
||||||
@@ -118,8 +113,9 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
|
|||||||
|
|
||||||
// Assert there was no error starting the image.
|
// Assert there was no error starting the image.
|
||||||
result.context("unable to start image")?;
|
result.context("unable to start image")?;
|
||||||
// Explicitly drop the option holder to clarify the lifetime.
|
|
||||||
drop(options_holder);
|
// Explicitly drop the options to clarify the lifetime.
|
||||||
|
drop(options);
|
||||||
|
|
||||||
// Return control to sprout.
|
// Return control to sprout.
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user