Skip to content

Commit 8908e56

Browse files
committed
Do larger rewrite
1 parent 2715149 commit 8908e56

File tree

1 file changed

+133
-64
lines changed

1 file changed

+133
-64
lines changed

docs/WhatAndWhy/enhancedmemoryprotection.md

Lines changed: 133 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -26,95 +26,145 @@ to be updated to adhere to these new requirements and our collective commitment
2626
to progress will pave the way to a more secure and resilient digital future.
2727
**Project Mu serves as a reference implementation for Enhanced Memory Protections.**
2828

29+
## Terminology
30+
31+
This document describes two states of memory protections: hardware state and
32+
software state. The hardware state is the state of the page table and the software
33+
state is the state of the Global Coherency Domain (GCD). These states need to
34+
be in sync with each other, but different architectures may implement the
35+
mapping from GCD state to page table state differently. This document uses the
36+
GCD terminology as it is universal. This section serves to define the expectations
37+
that this document makes when using the GCD terminology.
38+
39+
| Attribute | Description |
40+
|-------------------------------|--------------------------------------------------------------------------|
41+
| `EFI_MEMORY_XP` | Memory is non-executable. |
42+
| `EFI_MEMORY_RO` | Memory is read-only. |
43+
| `EFI_MEMORY_RP` | Memory is read-protected or unmapped. A CPU fault occurs if accessed. |
44+
2945
## Condensed Requirements List
3046

31-
1: The UEFI 2.10 Memory Attribute Protocol must be produced.
32-
2: No address range can be simultaneously readable, writable, and executable.
33-
3: Unallocated memory must be marked EFI_MEMORY_RP or be unmapped.
34-
4: Address space which is not present in the Global Coherency Domain must cause a
35-
CPU fault if accessed. This is a future requirement.
36-
5: Calls to EFI_BOOT_SERVICES.AllocatePages and EFI_BOOT_SERVICES.AllocatePool
47+
1: All memory available to the platform must be described in the GCD.
48+
2: No address range can be simultaneously readable, writable, and executable. This means every GCD entry must have at
49+
least one of EFI_MEMORY_XP, EFI_MEMORY_RO, or EFI_MEMORY_RP set.
50+
3: Loaded image sections marked with the data characteristic must be EFI_MEMORY_XP.
51+
4: Loaded image sections marked with the code characteristic must be EFI_MEMORY_RO.
52+
5: PE Loaders must check the NX_COMPAT flag of loaded images to determine
53+
compatibility with the above memory protection requirements.
54+
6: MMIO ranges must be marked EFI_MEMORY_XP.
55+
7: Unallocated memory must be marked EFI_MEMORY_RP.
56+
8: Address space which is not present in the Global Coherency Domain must cause a
57+
CPU fault if accessed.
58+
9: Calls to EFI_BOOT_SERVICES.AllocatePages and EFI_BOOT_SERVICES.AllocatePool
3759
must return memory with the EFI_MEMORY_XP attribute.
38-
6: Page 0 in physical system memory must be marked EFI_MEMORY_RP or be unmapped.
39-
7: AP and BSP stacks must be marked EFI_MEMORY_XP.
40-
8: AP and BSP stacks must have an EFI_MEMORY_RP page at the bottom to catch overflow.
41-
9: MMIO ranges must be marked EFI_MEMORY_XP.
42-
10: Loaded image sections marked with the data characteristic must be EFI_MEMORY_XP.
43-
11: Loaded image sections the code characteristic must be EFI_MEMORY_RO.
44-
12: PE Loaders must check the NX_COMPAT flag of loaded images to determine
45-
compatibility with the above memory protection requirements.
60+
10: AP and BSP stacks must be marked EFI_MEMORY_XP.
61+
11: AP and BSP stacks must have an EFI_MEMORY_RP page at the bottom to catch overflow.
62+
12: Page 0 in physical system memory must be marked EFI_MEMORY_RP.
63+
13: The UEFI 2.10 Memory Attribute Protocol must be produced.
4664

47-
## Runtime Configurable Protections
65+
## Expanded Requirements List
4866

49-
To enable memory protection in consumer shipped devices, runtime
50-
configurability options need to be present to respond to edge cases
51-
and accommodate non-compliant option ROMs. It is up to the platform
52-
developer to determine what levers will be available and how faults are handled.
67+
![Example Compliant Memory Range](../img/memory_range.png)
5368

54-
## Memory Attribute Protocol
69+
### All Memory is Described in the GCD
5570

56-
A necessity for increasing the security posture is the availability of
57-
the Memory Attribute Protocol. Added in UEFI Spec 2.10, the protocol
58-
enables setting and getting EFI memory attributes in the UEFI environment.
59-
Project Mu hosts an example implementation of this protocol.
71+
All memory that a platform can access, whether through MMIO, protocols like CXL, or directly attached, must be
72+
described in the GCD with an appropriate memory type. The GCD is UEFI's software state of memory. If memory is not
73+
described here, we cannot safely manage the security of that memory.
6074

61-
## Exception Handling
75+
### No R/W/X Regions
6276

63-
Increasing the security posture of UEFI implementations will increase the
64-
frequency of access violations. Exceptions should either cause a reset or
65-
transition the memory protection state into compatibility mode. Platform
66-
developers should also take care to ensure their exception handling logic
67-
provides enough data to distinguish between fault types and root cause
68-
failures. These access violations are often helpful for identifying programmer
69-
errors and rooting out critical bugs before they become CVEs.
77+
This has been a system software requirement for decades at this point and should be self-explanatory. Self-modifying
78+
executable regions are an easy attack vector for a bad actor. As such, all memory in the GCD must have one or more of
79+
EFI_MEMORY_XP, EFI_MEMORY_RO, and EFI_MEMORY_RP set.
7080

71-
## Memory Management
81+
### Image Data Sections Must Be EFI_MEMORY_XP
7282

73-
### General Memory Management
83+
Image data sections must be read from at a minimum and often need to be written to. They must not contain any
84+
executable code. Executable code must be in an image section marked with the code characteristic. It is appropriate
85+
to mark some image data sections EFI_MEMORY_RO in addition to EFI_MEMORY_XP, if they are read-only sections. All image
86+
data sections must be marked EFI_MEMORY_XP to prevent execution from occuring from these regions. This is a requirement
87+
to fulfill the No R/W/X Regions requirement and prevents common attack vectors for bad actors writing attack code to
88+
a memory region and forcing the processor to execute it.
7489

75-
![Example Compliant Memory Range](../img/memory_range.png)
90+
### Image Code Sections Must Be EFI_MEMORY_RO
7691

77-
At no point during boot should any addressable memory be readable, writable,
78-
and executable. To reach this heightened security bar, all unallocated memory
79-
should be marked EFI_MEMORY_RP or be unmapped. Addressable memory ranges which
80-
are not present in the Global Coherency Domain should also be read-protected or
81-
unmapped. When a module makes a call to allocate a buffer (even if that buffer
82-
is of type EfiBootServicesCode, EfiRuntimeServicesCode, or EfiLoaderCode),
83-
the returned page/pool must be non-executable. The module which called for the
84-
allocation will be expected to utilize the Memory Attribute Protocol to
85-
manipulate the attributes of the buffer to be either writable or executable
86-
but not both.
92+
Image code sections must be read and executed, but must not be writeable. This is a requirement to fulfill the No
93+
R/W/X Regions requirement and prevents the same problem of bad actors editing a running drivers memory to cause it
94+
to execute malicious code.
8795

88-
#### Special Memory Ranges
96+
### MMIO Ranges Must Be EFI_MEMORY_XP
8997

90-
* UEFI must apply EFI_MEMORY_RP to the NULL page or don't map it to help guard against NULL dereferences.
91-
* AP and BSP stacks must be marked EFI_MEMORY_XP to prevent execution from the stack with
92-
a page marked EFI_MEMORY_RP at the base of the stack to prevent stack overflow.
93-
* MMIO ranges should be marked EFI_MEMORY_XP.
98+
All devices connected to a system should be considered untrusted and must not be allowed to execute code. This is also
99+
a common attack vector for a bad actor to connect a compromised device and force the host system to execute malicious
100+
code from it.
94101

95-
## PE Loader
102+
### Unallocated Memory Must Be EFI_MEMORY_RP
96103

97-
![Example of Loaded Image Ranges](../img/loaded_images.png)
104+
This is a safety as well as security requirement. By marking unallocated memory EFI_MEMORY_RP, any access outside of
105+
legitimately allocated memory will cause a CPU fault, catching a large set of buffer under/overflows and use-after-free
106+
cases, which are both functional concerns as well as attack vectors.
98107

99-
On loading and prior to execution of an EFI image, the PE loader must apply
100-
EFI_MEMORY_XP to sections marked with the data characteristic and EFI_MEMORY_RO
101-
to sections marked with the code characteristic. Applying these page protections
102-
requires loaded images to meet the following criteria:
108+
This adds a new potential crash to code that may have "just worked" before, but it allows a platform to discover the
109+
safety and security issues pre-production and enforces defined behavior where before there was undefined behavior.
103110

104-
1. Section flags must not combine IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE for any
105-
given section.
106-
2. The PE image sections are aligned to page granularity.
107-
3. The PE image must not contain any self-modifying code.
111+
### Memory Not in the GCD Must Cause a CPU Fault on Access
112+
113+
This is a converse of the requirement that all memory that a platform can access is described in the GCD: everything
114+
else must, therefore, cause a fault when accessed, because it is not memory a platform can access.
115+
116+
### AllocatePages and AllocatePool Must Return Memory with EFI_MEMORY_XP
117+
118+
DXE Core cannot rely on drivers to set the correct attributes. Most memory allocations occur without the consumer
119+
setting any attributes on the memory region. Furthermore, it is unsafe for pool allocations not in a multiple of the
120+
EFI_PAGE_SIZE to attempt to set attributes, there are other consumers using this pool space. If the core does not set
121+
the attributes, the attributes will not be set.
122+
123+
EFI_MEMORY_XP is the attribute that must be set because it is the general case: most memory will be marked
124+
EFI_MEMORY_XP. Even memory that will be used for an image code section must be marked EFI_MEMORY_XP originally,
125+
because the PE loader must write the code section to that memory before it marks it EFI_MEMORY_RO and removes
126+
EFI_MEMORY_XP.
127+
128+
### AP/BSP Stacks Must Be EFI_MEMORY_XP
129+
130+
This continues the requirement that non-code sections must be marked EFI_MEMORY_XP. This closes a common attacker
131+
scenario to put code on the stack and then force the processor to execute from it.
132+
133+
### AP/BSP Stacks Must Have EFI_MEMORY_RP Page at the Bottom
134+
135+
Commonly known as Stack Guard, this feature places a guard page marked EFI_MEMORY_RP at the bottom of the stack. This
136+
catches stack overflows by causing a CPU fault if this guard page is read from or written to. Stack overflows are both
137+
common attack vectors and common programming errors that require being caught during development.
108138

109-
## NX_COMPAT Characteristic
139+
This also adds a new potential crash during execution in code that may have "just worked" before, but similarly allows
140+
these problems to be solved pre-production and enforces defined behavior instead of undefined.
141+
142+
### EFI Memory Attributes Protocol Must Be Installed
143+
144+
The Memory Attributes Protocol, added in UEFI spec 2.10, provides a method for bootloaders to interact with UEFI's page
145+
tables before they create their own page tables. This allows them to enforce memory protections on their own images and
146+
allocations, closing further attack vectors.
147+
148+
### PE Loaders Must Check the NX_COMPAT Flag for Compatibility
110149

111150
Many bootloaders and OPROMs will not have implemented support for enhanced protections on
112151
image memory, allocated buffers, and other memory ranges. To indicate support for enhanced
113152
protections, the PE/COFF IMAGE_DLLCHARACTERISTICS_NX_COMPAT DLL characteristic will be used.
114153
Modules with this characteristic are expected to be compliant with enhanced memory protection
115154
and should utilize the Memory Attribute Protocol to manipulate the attributes of memory they
116155
allocate. If a module is loaded without this characteristic, the platform should enter
117-
compatibility mode.
156+
[compatibility mode](#compatibility-mode) if the platform chooses to support compatibility
157+
mode.
158+
159+
![Example of Loaded Image Ranges](../img/loaded_images.png)
160+
161+
Applying these page protections requires loaded images to meet the following criteria, signified by setting the
162+
NX_COMPAT characteristic:
163+
164+
1. Section flags must not combine IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE for any
165+
given section.
166+
2. The PE image sections are aligned to page granularity.
167+
3. The PE image must not contain any self-modifying code.
118168

119169
## Compatibility Mode
120170

@@ -127,9 +177,9 @@ deviations from the enhanced memory protection definition:
127177
2. All images loaded from the start of compatibility mode will no longer have
128178
restrictive access attributes applied to the memory ranges in which they are loaded.
129179
3. The Memory Attribute Protocol will be uninstalled.
130-
4. Page zero will be mapped.
180+
4. Page zero will be mapped if it resides in system memory.
131181
5. Legacy BIOS memory (the lower 640K range) will be mapped as readable, writable, and
132-
executable.
182+
executable on AMD64 systems.
133183

134184
### A Note on User Notification of Compatibility Mode
135185

@@ -141,6 +191,25 @@ platform. In the future, platform developers should consider adding a TPM (Trust
141191
Platform Module) measurement when the system enters compatibility mode to have platform
142192
enforcement of memory protections.
143193

194+
## Additional Considerations
195+
196+
## Runtime Configurable Protections
197+
198+
To enable memory protection in consumer shipped devices, runtime
199+
configurability options need to be present to respond to edge cases
200+
and accommodate non-compliant option ROMs. It is up to the platform
201+
developer to determine what levers will be available and how faults are handled.
202+
203+
## Exception Handling
204+
205+
Increasing the security posture of UEFI implementations will increase the
206+
frequency of access violations. Exceptions should either cause a reset or
207+
transition the memory protection state into compatibility mode. Platform
208+
developers should also take care to ensure their exception handling logic
209+
provides enough data to distinguish between fault types and root cause
210+
failures. These access violations are often helpful for identifying programmer
211+
errors and rooting out critical bugs before they become CVEs.
212+
144213
## Closing
145214

146215
It will take substantial work to update legacy code to adhere to these new security

0 commit comments

Comments
 (0)