Skip to content

Commit 8898c74

Browse files
committed
uefi: process: Fixes from PR
- Update system table crc32 - Fix unsound use of Box - Free exit data Signed-off-by: Ayush Singh <[email protected]>
1 parent 1490a7d commit 8898c74

File tree

2 files changed

+83
-50
lines changed

2 files changed

+83
-50
lines changed

library/std/src/sys/pal/uefi/helpers.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,13 @@ impl Drop for DevicePath {
292292
}
293293
}
294294

295-
pub(crate) struct Protocol<T> {
295+
pub(crate) struct OwnedProtocol<T> {
296296
guid: r_efi::efi::Guid,
297297
handle: NonNull<crate::ffi::c_void>,
298298
protocol: Box<T>,
299299
}
300300

301-
impl<T> Protocol<T> {
301+
impl<T> OwnedProtocol<T> {
302302
const fn new(
303303
guid: r_efi::efi::Guid,
304304
handle: NonNull<crate::ffi::c_void>,
@@ -337,7 +337,7 @@ impl<T> Protocol<T> {
337337
}
338338
}
339339

340-
impl<T> Drop for Protocol<T> {
340+
impl<T> Drop for OwnedProtocol<T> {
341341
fn drop(&mut self) {
342342
if let Some(bt) = boot_services() {
343343
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
@@ -352,14 +352,8 @@ impl<T> Drop for Protocol<T> {
352352
}
353353
}
354354

355-
impl<T> AsRef<T> for Protocol<T> {
355+
impl<T> AsRef<T> for OwnedProtocol<T> {
356356
fn as_ref(&self) -> &T {
357357
&self.protocol
358358
}
359359
}
360-
361-
impl<T> AsMut<T> for Protocol<T> {
362-
fn as_mut(&mut self) -> &mut T {
363-
&mut self.protocol
364-
}
365-
}

library/std/src/sys/pal/uefi/process.rs

+79-40
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct StdioPipes {
3535
pub stderr: Option<AnonPipe>,
3636
}
3737

38+
#[derive(Copy, Clone)]
3839
pub enum Stdio {
3940
Inherit,
4041
Null,
@@ -96,14 +97,14 @@ impl Command {
9697

9798
fn create_pipe(
9899
s: Stdio,
99-
) -> io::Result<Option<helpers::Protocol<uefi_command_internal::PipeProtocol>>> {
100+
) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>>> {
100101
match s {
101-
Stdio::MakePipe => helpers::Protocol::create(
102+
Stdio::MakePipe => helpers::OwnedProtocol::create(
102103
uefi_command_internal::PipeProtocol::new(),
103104
simple_text_output::PROTOCOL_GUID,
104105
)
105106
.map(Some),
106-
Stdio::Null => helpers::Protocol::create(
107+
Stdio::Null => helpers::OwnedProtocol::create(
107108
uefi_command_internal::PipeProtocol::null(),
108109
simple_text_output::PROTOCOL_GUID,
109110
)
@@ -116,36 +117,38 @@ impl Command {
116117
let mut cmd = uefi_command_internal::Command::load_image(&self.prog)?;
117118

118119
/* Setup Stdout */
119-
let stdout: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
120-
match self.stdout.take() {
120+
let stdout: Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>> =
121+
match self.stdout {
121122
Some(s) => Self::create_pipe(s),
122-
None => helpers::Protocol::create(
123+
None => helpers::OwnedProtocol::create(
123124
uefi_command_internal::PipeProtocol::new(),
124125
simple_text_output::PROTOCOL_GUID,
125126
)
126127
.map(Some),
127128
}?;
128-
match stdout {
129-
Some(stdout) => cmd.stdout_init(stdout),
130-
None => cmd.stdout_inherit(),
129+
if let Some(con) = stdout {
130+
cmd.stdout_init(con)
131+
} else {
132+
cmd.stdout_inherit()
131133
};
132134

133135
/* Setup Stderr */
134-
let stderr: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
135-
match self.stderr.take() {
136+
let stderr: Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>> =
137+
match self.stderr {
136138
Some(s) => Self::create_pipe(s),
137-
None => helpers::Protocol::create(
139+
None => helpers::OwnedProtocol::create(
138140
uefi_command_internal::PipeProtocol::new(),
139141
simple_text_output::PROTOCOL_GUID,
140142
)
141143
.map(Some),
142144
}?;
143-
match stderr {
144-
Some(stderr) => cmd.stderr_init(stderr),
145-
None => cmd.stderr_inherit(),
145+
if let Some(con) = stderr {
146+
cmd.stderr_init(con)
147+
} else {
148+
cmd.stderr_inherit()
146149
};
147150

148-
/* No reason to set args if only program name is preset */
151+
// No reason to set args if only program name is preset
149152
if !self.args.is_empty() {
150153
let args = self.args.iter().fold(OsString::from(&self.prog), |mut acc, arg| {
151154
acc.push(" ");
@@ -341,8 +344,8 @@ mod uefi_command_internal {
341344

342345
pub struct Command {
343346
handle: NonNull<crate::ffi::c_void>,
344-
stdout: Option<helpers::Protocol<PipeProtocol>>,
345-
stderr: Option<helpers::Protocol<PipeProtocol>>,
347+
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
348+
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
346349
st: Box<r_efi::efi::SystemTable>,
347350
args: Option<Vec<u16>>,
348351
}
@@ -382,45 +385,52 @@ mod uefi_command_internal {
382385

383386
let loaded_image: NonNull<loaded_image::Protocol> =
384387
helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();
385-
let mut st: Box<r_efi::efi::SystemTable> =
388+
let st: Box<r_efi::efi::SystemTable> =
386389
Box::new(unsafe { crate::ptr::read((*loaded_image.as_ptr()).system_table) });
387390

388-
unsafe {
389-
(*loaded_image.as_ptr()).system_table = st.as_mut();
390-
}
391-
392391
Ok(Self::new(child_handle, st))
393392
}
394393
}
395394

396-
pub fn start_image(&self) -> io::Result<r_efi::efi::Status> {
395+
pub fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
396+
self.update_st_crc32()?;
397+
398+
// Use our system table instead of the default one
399+
let loaded_image: NonNull<loaded_image::Protocol> =
400+
helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
401+
unsafe {
402+
(*loaded_image.as_ptr()).system_table = self.st.as_mut();
403+
}
404+
397405
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
398406
.ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
399407
.cast();
400-
let mut exit_data_size: MaybeUninit<usize> = MaybeUninit::uninit();
408+
let mut exit_data_size: usize = 0;
401409
let mut exit_data: MaybeUninit<*mut u16> = MaybeUninit::uninit();
402410

403411
let r = unsafe {
404412
((*boot_services.as_ptr()).start_image)(
405413
self.handle.as_ptr(),
406-
exit_data_size.as_mut_ptr(),
414+
&mut exit_data_size,
407415
exit_data.as_mut_ptr(),
408416
)
409417
};
410418

411419
// Drop exitdata
412-
unsafe {
413-
exit_data_size.assume_init_drop();
414-
exit_data.assume_init_drop();
420+
if exit_data_size != 0 {
421+
unsafe {
422+
let exit_data = exit_data.assume_init();
423+
((*boot_services.as_ptr()).free_pool)(exit_data as *mut crate::ffi::c_void);
424+
}
415425
}
416426

417427
Ok(r)
418428
}
419429

420-
pub fn stdout_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
430+
pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
421431
self.st.console_out_handle = protocol.handle().as_ptr();
422432
self.st.con_out =
423-
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
433+
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol;
424434

425435
self.stdout = Some(protocol);
426436
}
@@ -432,10 +442,10 @@ mod uefi_command_internal {
432442
self.st.con_out = unsafe { (*st.as_ptr()).con_out };
433443
}
434444

435-
pub fn stderr_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
445+
pub fn stderr_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
436446
self.st.standard_error_handle = protocol.handle().as_ptr();
437447
self.st.std_err =
438-
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
448+
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol;
439449

440450
self.stderr = Some(protocol);
441451
}
@@ -476,6 +486,30 @@ mod uefi_command_internal {
476486

477487
self.args = Some(args);
478488
}
489+
490+
fn update_st_crc32(&mut self) -> io::Result<()> {
491+
let bt: NonNull<r_efi::efi::BootServices> = boot_services().unwrap().cast();
492+
let st_size = self.st.hdr.header_size as usize;
493+
let mut crc32: u32 = 0;
494+
495+
// Set crc to 0 before calcuation
496+
self.st.hdr.crc32 = 0;
497+
498+
let r = unsafe {
499+
((*bt.as_ptr()).calculate_crc32)(
500+
self.st.as_mut() as *mut r_efi::efi::SystemTable as *mut crate::ffi::c_void,
501+
st_size,
502+
&mut crc32,
503+
)
504+
};
505+
506+
if r.is_error() {
507+
Err(io::Error::from_raw_os_error(r.as_usize()))
508+
} else {
509+
self.st.hdr.crc32 = crc32;
510+
Ok(())
511+
}
512+
}
479513
}
480514

481515
impl Drop for Command {
@@ -501,13 +535,12 @@ mod uefi_command_internal {
501535
set_cursor_position: simple_text_output::ProtocolSetCursorPosition,
502536
enable_cursor: simple_text_output::ProtocolEnableCursor,
503537
mode: *mut simple_text_output::Mode,
504-
_mode: Box<simple_text_output::Mode>,
505538
_buffer: Vec<u16>,
506539
}
507540

508541
impl PipeProtocol {
509542
pub fn new() -> Self {
510-
let mut mode = Box::new(simple_text_output::Mode {
543+
let mode = Box::new(simple_text_output::Mode {
511544
max_mode: 0,
512545
mode: 0,
513546
attribute: 0,
@@ -525,14 +558,13 @@ mod uefi_command_internal {
525558
clear_screen: Self::clear_screen,
526559
set_cursor_position: Self::set_cursor_position,
527560
enable_cursor: Self::enable_cursor,
528-
mode: mode.as_mut(),
529-
_mode: mode,
561+
mode: Box::into_raw(mode),
530562
_buffer: Vec::new(),
531563
}
532564
}
533565

534566
pub fn null() -> Self {
535-
let mut mode = Box::new(simple_text_output::Mode {
567+
let mode = Box::new(simple_text_output::Mode {
536568
max_mode: 0,
537569
mode: 0,
538570
attribute: 0,
@@ -550,8 +582,7 @@ mod uefi_command_internal {
550582
clear_screen: Self::clear_screen,
551583
set_cursor_position: Self::set_cursor_position,
552584
enable_cursor: Self::enable_cursor,
553-
mode: mode.as_mut(),
554-
_mode: mode,
585+
mode: Box::into_raw(mode),
555586
_buffer: Vec::new(),
556587
}
557588
}
@@ -660,4 +691,12 @@ mod uefi_command_internal {
660691
r_efi::efi::Status::UNSUPPORTED
661692
}
662693
}
694+
695+
impl Drop for PipeProtocol {
696+
fn drop(&mut self) {
697+
unsafe {
698+
let _ = Box::from_raw(self.mode);
699+
}
700+
}
701+
}
663702
}

0 commit comments

Comments
 (0)