summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/security/index.md4
-rw-r--r--Documentation/security/smm.md29
-rw-r--r--src/cpu/x86/smm/smihandler.c10
-rw-r--r--src/cpu/x86/smm/smm_module_handler.c9
-rw-r--r--src/include/cpu/x86/smm.h12
5 files changed, 63 insertions, 1 deletions
diff --git a/Documentation/security/index.md b/Documentation/security/index.md
index d5d4e2b93e..c9cb4a77de 100644
--- a/Documentation/security/index.md
+++ b/Documentation/security/index.md
@@ -13,3 +13,7 @@ This section describes documentation about the security architecture of coreboot
- [Intel TXT in general](intel/txt.md)
- [Intel TXT Initial Boot Block](intel/txt_ibb.md)
- [Intel Authenticated Code Modules](intel/acm.md)
+
+## SMM
+
+- [System Management Mode](smm.md)
diff --git a/Documentation/security/smm.md b/Documentation/security/smm.md
new file mode 100644
index 0000000000..4e95427b86
--- /dev/null
+++ b/Documentation/security/smm.md
@@ -0,0 +1,29 @@
+# x86 System Managment Mode
+
+## Introduction
+
+The code running in System Management Mode (SMM) provides runtime services
+to applications running in [ring0]. It has a higher privilege level than
+[ring0] and resides in the SMRAM region which cannot be accessed from [ring0].
+
+SMM can be entered by issuing System Managment Interrupts (SMIs).
+
+## Secure data exchange
+
+In order to not leak SMM internals or accidentally overwrite parts of SMM,
+[ring0] provided data (pointers, offsets, sizes, ...) must be checked before
+using them in SMM.
+
+There exist two methods to verify data:
+
+```C
+/* Returns true if the region overlaps with the SMM */
+bool smm_region_overlaps_handler(struct region *r);
+```
+
+```C
+/* Returns true if the memory pointed to overlaps with SMM reserved memory. */
+static inline bool smm_points_to_smram(const void *ptr, const size_t len);
+```
+
+[ring0]: https://en.wikipedia.org/wiki/Protection_ring
diff --git a/src/cpu/x86/smm/smihandler.c b/src/cpu/x86/smm/smihandler.c
index bb4689e24e..8fd95bb563 100644
--- a/src/cpu/x86/smm/smihandler.c
+++ b/src/cpu/x86/smm/smihandler.c
@@ -2,6 +2,7 @@
#include <arch/io.h>
#include <console/console.h>
+#include <commonlib/region.h>
#include <cpu/x86/smm.h>
#include <cpu/x86/smi_deprecated.h>
#include <cpu/amd/amd64_save_state.h>
@@ -119,6 +120,13 @@ static inline void *smm_save_state(uintptr_t base, int arch_offset, int node)
return (void *)base;
}
+bool smm_region_overlaps_handler(const struct region *r)
+{
+ const struct region r_smm = {SMM_BASE, SMM_DEFAULT_SIZE};
+
+ return region_overlap(&r_smm, r);
+}
+
/**
* @brief Interrupt handler for SMI#
*
@@ -129,7 +137,7 @@ void smi_handler(u32 smm_revision)
{
unsigned int node;
smm_state_save_area_t state_save;
- u32 smm_base = 0xa0000; /* ASEG */
+ u32 smm_base = SMM_BASE; /* ASEG */
/* Are we ok to execute the handler? */
if (!smi_obtain_lock()) {
diff --git a/src/cpu/x86/smm/smm_module_handler.c b/src/cpu/x86/smm/smm_module_handler.c
index 404b0ccdaa..37af199080 100644
--- a/src/cpu/x86/smm/smm_module_handler.c
+++ b/src/cpu/x86/smm/smm_module_handler.c
@@ -2,6 +2,7 @@
#include <arch/io.h>
#include <console/console.h>
+#include <commonlib/region.h>
#include <cpu/x86/smm.h>
#include <rmodule.h>
@@ -103,6 +104,14 @@ void *smm_get_save_state(int cpu)
return base;
}
+bool smm_region_overlaps_handler(const struct region *r)
+{
+ const struct region r_smm = {smm_runtime->smbase, smm_runtime->smm_size};
+ const struct region r_aseg = {SMM_BASE, SMM_DEFAULT_SIZE};
+
+ return region_overlap(&r_smm, r) || region_overlap(&r_aseg, r);
+}
+
asmlinkage void smm_handler_start(void *arg)
{
const struct smm_module_params *p;
diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h
index 75c19a5cd5..ca834743b5 100644
--- a/src/include/cpu/x86/smm.h
+++ b/src/include/cpu/x86/smm.h
@@ -4,6 +4,7 @@
#define CPU_X86_SMM_H
#include <arch/cpu.h>
+#include <commonlib/region.h>
#include <types.h>
#define SMM_DEFAULT_BASE 0x30000
@@ -93,6 +94,17 @@ asmlinkage void smm_handler_start(void *params);
* account CPUs which are configured to not save their state to RAM. */
void *smm_get_save_state(int cpu);
+/* Returns true if the region overlaps with the SMM */
+bool smm_region_overlaps_handler(const struct region *r);
+
+/* Returns true if the memory pointed to overlaps with SMM reserved memory. */
+static inline bool smm_points_to_smram(const void *ptr, const size_t len)
+{
+ const struct region r = {(uintptr_t)ptr, len};
+
+ return smm_region_overlaps_handler(&r);
+}
+
/* SMM Module Loading API */
/* The smm_loader_params structure provides direction to the SMM loader: