aboutsummaryrefslogtreecommitdiff
path: root/src/interface
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface')
-rw-r--r--src/interface/efi/efi_init.c62
-rw-r--r--src/interface/efi/efidrvprefix.c3
-rw-r--r--src/interface/efi/efiprefix.c3
3 files changed, 68 insertions, 0 deletions
diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c
index ed9707f..df46bb1 100644
--- a/src/interface/efi/efi_init.c
+++ b/src/interface/efi/efi_init.c
@@ -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 );
@@ -88,6 +98,29 @@ static void * efi_find_table ( EFI_GUID *guid ) {
}
/**
+ * 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
*
* @v image_handle Image handle
@@ -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 ) {}
+
+}
diff --git a/src/interface/efi/efidrvprefix.c b/src/interface/efi/efidrvprefix.c
index 4fbb19f..f9bfa4c 100644
--- a/src/interface/efi/efidrvprefix.c
+++ b/src/interface/efi/efidrvprefix.c
@@ -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;
diff --git a/src/interface/efi/efiprefix.c b/src/interface/efi/efiprefix.c
index de3572c..2c5a5b3 100644
--- a/src/interface/efi/efiprefix.c
+++ b/src/interface/efi/efiprefix.c
@@ -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;