aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cpu/x86/smm/smm_module_handler.c14
-rw-r--r--src/cpu/x86/smm/smm_stub.S13
-rw-r--r--src/include/cpu/x86/smm.h4
3 files changed, 29 insertions, 2 deletions
diff --git a/src/cpu/x86/smm/smm_module_handler.c b/src/cpu/x86/smm/smm_module_handler.c
index c2001ec9e2..6dff9411de 100644
--- a/src/cpu/x86/smm/smm_module_handler.c
+++ b/src/cpu/x86/smm/smm_module_handler.c
@@ -122,10 +122,13 @@ asmlinkage void smm_handler_start(void *arg)
const struct smm_module_params *p;
const struct smm_runtime *runtime;
int cpu;
+ uintptr_t actual_canary;
+ uintptr_t expected_canary;
p = arg;
runtime = p->runtime;
cpu = p->cpu;
+ expected_canary = (uintptr_t)p->canary;
/* Make sure to set the global runtime. It's OK to race as the value
* will be the same across CPUs as well as multiple SMIs. */
@@ -171,6 +174,17 @@ asmlinkage void smm_handler_start(void *arg)
smi_restore_pci_address();
+ actual_canary = *p->canary;
+
+ if (actual_canary != expected_canary) {
+ printk(BIOS_DEBUG, "canary 0x%lx != 0x%lx\n", actual_canary,
+ expected_canary);
+
+ // Don't die if we can't indicate an error.
+ if (IS_ENABLED(CONFIG_DEBUG_SMI))
+ die("SMM Handler caused a stack overflow\n");
+ }
+
smi_release_lock();
/* De-assert SMI# signal to allow another SMI */
diff --git a/src/cpu/x86/smm/smm_stub.S b/src/cpu/x86/smm/smm_stub.S
index ba66db9179..eb890df150 100644
--- a/src/cpu/x86/smm/smm_stub.S
+++ b/src/cpu/x86/smm/smm_stub.S
@@ -136,6 +136,11 @@ smm_trampoline32:
subl %eax, %ebx /* global_stack_top - offset = stack_top */
mov %ebx, %esp
+ /* Write canary to the bottom of the stack */
+ movl stack_size, %eax
+ subl %eax, %ebx /* %ebx(stack_top) - size = %ebx(stack_bottom) */
+ movl %ebx, (%ebx)
+
/* Create stack frame by pushing a NULL stack base pointer */
pushl $0x0
mov %esp, %ebp
@@ -166,14 +171,18 @@ smm_trampoline32:
fxsave (%edi)
1:
- /* Align stack to 16 bytes. Another 16 bytes are pushed below. */
+ /* Align stack to 16 bytes. Another 32 bytes are pushed below. */
andl $0xfffffff0, %esp
/* Call into the c-based SMM relocation function with the platform
* parameters. Equivalent to:
- * struct arg = { c_handler_params, cpu_num, smm_runtime };
+ * struct arg = { c_handler_params, cpu_num, smm_runtime, canary };
* c_handler(&arg)
*/
+ push $0x0 /* Padding */
+ push $0x0 /* Padding */
+ push $0x0 /* Padding */
+ push %ebx /* uintptr_t *canary */
push $(smm_runtime)
push %ecx /* int cpu */
push c_handler_arg /* void *arg */
diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h
index 7dcf4d70e2..9942772f0e 100644
--- a/src/include/cpu/x86/smm.h
+++ b/src/include/cpu/x86/smm.h
@@ -527,6 +527,10 @@ struct smm_module_params {
void *arg;
int cpu;
const struct smm_runtime *runtime;
+ /* A canary value that has been placed at the end of the stack.
+ * If (uintptr_t)canary != *canary then a stack overflow has occurred.
+ */
+ const uintptr_t *canary;
};
/* smm_handler_t is called with arg of smm_module_params pointer. */