mirror of
https://github.com/ipxe/ipxe
synced 2025-12-25 09:01:24 +03:00
[efi] Enable stack protection where possible
Enable -fstack-protector for EFI builds, where binary size is less critical than for BIOS builds. The stack cookie must be constructed immediately on entry, which prohibits the use of any viable entropy source. Construct a cookie by XORing together various mildly random quantities to produce a value that will at least not be identical on each run. On detecting a stack corruption, attempt to call Exit() with an appropriate error. If that fails, then lock up the machine since there is no other safe action that can be taken. The old conditional check for support of -fno-stack-protector is omitted since this flag dates back to GCC 4.1. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -47,6 +47,16 @@ int efi_shutdown_in_progress;
|
||||
/** Event used to signal shutdown */
|
||||
static EFI_EVENT efi_shutdown_event;
|
||||
|
||||
/** Stack cookie */
|
||||
unsigned long __stack_chk_guard;
|
||||
|
||||
/** Exit function
|
||||
*
|
||||
* Cached to minimise external dependencies when a stack check
|
||||
* failure is triggered.
|
||||
*/
|
||||
static EFI_EXIT efi_exit;
|
||||
|
||||
/* Forward declarations */
|
||||
static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
|
||||
|
||||
@@ -87,6 +97,29 @@ static void * efi_find_table ( EFI_GUID *guid ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a stack cookie value
|
||||
*
|
||||
* @v handle Image handle
|
||||
* @ret cookie Stack cookie
|
||||
*/
|
||||
__attribute__ (( noinline )) unsigned long
|
||||
efi_stack_cookie ( EFI_HANDLE handle ) {
|
||||
|
||||
/* There is no viable source of entropy available at this
|
||||
* point. Construct a value that is at least likely to vary
|
||||
* between platforms and invocations.
|
||||
*
|
||||
* Ensure that the value contains a NUL byte, to act as a
|
||||
* runaway string terminator. Construct the NUL using a shift
|
||||
* rather than a mask, to avoid losing valuable entropy in the
|
||||
* low-order bits.
|
||||
*/
|
||||
return ( ( ( ( unsigned long ) handle ) ^
|
||||
( ( unsigned long ) &handle ) ^
|
||||
profile_timestamp() ^ build_id ) << 8 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise EFI environment
|
||||
*
|
||||
@@ -130,6 +163,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
|
||||
DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
|
||||
bs = systab->BootServices;
|
||||
|
||||
/* Store abort function pointer */
|
||||
efi_exit = bs->Exit;
|
||||
|
||||
/* Look up used protocols */
|
||||
for_each_table_entry ( prot, EFI_PROTOCOLS ) {
|
||||
if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
|
||||
@@ -240,3 +276,29 @@ static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort on stack check failure
|
||||
*
|
||||
*/
|
||||
__attribute__ (( noreturn )) void __stack_chk_fail ( void ) {
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
/* Report failure (when debugging) */
|
||||
DBGC ( efi_systab, "EFI stack check failed (cookie %#lx); aborting\n",
|
||||
__stack_chk_guard );
|
||||
|
||||
/* Attempt to exit cleanly with an error status */
|
||||
if ( efi_exit ) {
|
||||
efirc = efi_exit ( efi_image_handle, EFI_COMPROMISED_DATA,
|
||||
0, NULL );
|
||||
rc = -EEFI ( efirc );
|
||||
DBGC ( efi_systab, "EFI stack check exit failed: %s\n",
|
||||
strerror ( rc ) );
|
||||
}
|
||||
|
||||
/* If the exit fails for any reason, lock the system */
|
||||
while ( 1 ) {}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
|
||||
EFI_SYSTEM_TABLE *systab ) {
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Initialise stack cookie */
|
||||
efi_init_stack_guard ( image_handle );
|
||||
|
||||
/* Initialise EFI environment */
|
||||
if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
|
||||
return efirc;
|
||||
|
||||
@@ -41,6 +41,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
/* Initialise stack cookie */
|
||||
efi_init_stack_guard ( image_handle );
|
||||
|
||||
/* Initialise EFI environment */
|
||||
if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
|
||||
goto err_init;
|
||||
|
||||
Reference in New Issue
Block a user