Documentation / x86 / sgx.rst

Based on kernel version 6.3.13. Page generated on 2023-08-29 08:35 EST.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
.. SPDX-License-Identifier: GPL-2.0

Software Guard eXtensions (SGX)


Software Guard eXtensions (SGX) hardware enables for user space applications
to set aside private memory regions of code and data:

* Privileged (ring-0) ENCLS functions orchestrate the construction of the
* Unprivileged (ring-3) ENCLU functions allow an application to enter and
  execute inside the regions.

These memory regions are called enclaves. An enclave can be only entered at a
fixed set of entry points. Each entry point can hold a single hardware thread
at a time.  While the enclave is loaded from a regular binary file by using
ENCLS functions, only the threads inside the enclave can access its memory. The
region is denied from outside access by the CPU, and encrypted before it leaves
from LLC.

The support can be determined by

	``grep sgx /proc/cpuinfo``

SGX must both be supported in the processor and enabled by the BIOS.  If SGX
appears to be unsupported on a system which has hardware support, ensure
support is enabled in the BIOS.  If a BIOS presents a choice between "Enabled"
and "Software Enabled" modes for SGX, choose "Enabled".

Enclave Page Cache

SGX utilizes an *Enclave Page Cache (EPC)* to store pages that are associated
with an enclave. It is contained in a BIOS-reserved region of physical memory.
Unlike pages used for regular memory, pages can only be accessed from outside of
the enclave during enclave construction with special, limited SGX instructions.

Only a CPU executing inside an enclave can directly access enclave memory.
However, a CPU executing inside an enclave may access normal memory outside the

The kernel manages enclave memory similar to how it treats device memory.

Enclave Page Types

**SGX Enclave Control Structure (SECS)**
   Enclave's address range, attributes and other global data are defined
   by this structure.

**Regular (REG)**
   Regular EPC pages contain the code and data of an enclave.

**Thread Control Structure (TCS)**
   Thread Control Structure pages define the entry points to an enclave and
   track the execution state of an enclave thread.

**Version Array (VA)**
   Version Array pages contain 512 slots, each of which can contain a version
   number for a page evicted from the EPC.

Enclave Page Cache Map

The processor tracks EPC pages in a hardware metadata structure called the
*Enclave Page Cache Map (EPCM)*.  The EPCM contains an entry for each EPC page
which describes the owning enclave, access rights and page type among the other

EPCM permissions are separate from the normal page tables.  This prevents the
kernel from, for instance, allowing writes to data which an enclave wishes to
remain read-only.  EPCM permissions may only impose additional restrictions on
top of normal x86 page permissions.

For all intents and purposes, the SGX architecture allows the processor to
invalidate all EPCM entries at will.  This requires that software be prepared to
handle an EPCM fault at any time.  In practice, this can happen on events like
power transitions when the ephemeral key that encrypts enclave memory is lost.

Application interface

Enclave build functions

In addition to the traditional compiler and linker build process, SGX has a
separate enclave “build” process.  Enclaves must be built before they can be
executed (entered). The first step in building an enclave is opening the
**/dev/sgx_enclave** device.  Since enclave memory is protected from direct
access, special privileged instructions are then used to copy data into enclave
pages and establish enclave page permissions.

.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
   :functions: sgx_ioc_enclave_create

Enclave runtime management

Systems supporting SGX2 additionally support changes to initialized
enclaves: modifying enclave page permissions and type, and dynamically
adding and removing of enclave pages. When an enclave accesses an address
within its address range that does not have a backing page then a new
regular page will be dynamically added to the enclave. The enclave is
still required to run EACCEPT on the new page before it can be used.

.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
   :functions: sgx_ioc_enclave_restrict_permissions

Enclave vDSO

Entering an enclave can only be done through SGX-specific EENTER and ERESUME
functions, and is a non-trivial process.  Because of the complexity of
transitioning to and from an enclave, enclaves typically utilize a library to
handle the actual transitions.  This is roughly analogous to how glibc
implementations are used by most applications to wrap system calls.

Another crucial characteristic of enclaves is that they can generate exceptions
as part of their normal operation that need to be handled in the enclave or are
unique to SGX.

Instead of the traditional signal mechanism to handle these exceptions, SGX
can leverage special exception fixup provided by the vDSO.  The kernel-provided
vDSO function wraps low-level transitions to/from the enclave like EENTER and
ERESUME.  The vDSO function intercepts exceptions that would otherwise generate
a signal and return the fault information directly to its caller.  This avoids
the need to juggle signal handlers.

.. kernel-doc:: arch/x86/include/uapi/asm/sgx.h
   :functions: vdso_sgx_enter_enclave_t


SGX support includes a kernel thread called *ksgxd*.

EPC sanitization

ksgxd is started when SGX initializes.  Enclave memory is typically ready
for use when the processor powers on or resets.  However, if SGX has been in
use since the reset, enclave pages may be in an inconsistent state.  This might
occur after a crash and kexec() cycle, for instance.  At boot, ksgxd
reinitializes all enclave pages so that they can be allocated and re-used.

The sanitization is done by going through EPC address space and applying the
EREMOVE function to each physical page. Some enclave pages like SECS pages have
hardware dependencies on other pages which prevents EREMOVE from functioning.
Executing two EREMOVE passes removes the dependencies.

Page reclaimer

Similar to the core kswapd, ksgxd, is responsible for managing the
overcommitment of enclave memory.  If the system runs out of enclave memory,
*ksgxd* “swaps” enclave memory to normal memory.

Launch Control

SGX provides a launch control mechanism. After all enclave pages have been
copied, kernel executes EINIT function, which initializes the enclave. Only after
this the CPU can execute inside the enclave.

EINIT function takes an RSA-3072 signature of the enclave measurement.  The function
checks that the measurement is correct and signature is signed with the key
hashed to the four **IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}** MSRs representing the
SHA256 of a public key.

Those MSRs can be configured by the BIOS to be either readable or writable.
Linux supports only writable configuration in order to give full control to the
kernel on launch control policy. Before calling EINIT function, the driver sets
the MSRs to match the enclave's signing key.

Encryption engines

In order to conceal the enclave data while it is out of the CPU package, the
memory controller has an encryption engine to transparently encrypt and decrypt
enclave memory.

In CPUs prior to Ice Lake, the Memory Encryption Engine (MEE) is used to
encrypt pages leaving the CPU caches. MEE uses a n-ary Merkle tree with root in
SRAM to maintain integrity of the encrypted data. This provides integrity and
anti-replay protection but does not scale to large memory sizes because the time
required to update the Merkle tree grows logarithmically in relation to the
memory size.

CPUs starting from Icelake use Total Memory Encryption (TME) in the place of
MEE. TME-based SGX implementations do not have an integrity Merkle tree, which
means integrity and replay-attacks are not mitigated.  B, it includes
additional changes to prevent cipher text from being returned and SW memory
aliases from being created.

DMA to enclave memory is blocked by range registers on both MEE and TME systems
(SDM section 41.10).

Usage Models

Shared Library

Sensitive data and the code that acts on it is partitioned from the application
into a separate library. The library is then linked as a DSO which can be loaded
into an enclave. The application can then make individual function calls into
the enclave through special SGX instructions. A run-time within the enclave is
configured to marshal function parameters into and out of the enclave and to
call the correct library function.

Application Container

An application may be loaded into a container enclave which is specially
configured with a library OS and run-time which permits the application to run.
The enclave run-time and library OS work together to execute the application
when a thread enters the enclave.

Impact of Potential Kernel SGX Bugs

EPC leaks

When EPC page leaks happen, a WARNING like this is shown in dmesg:

"EREMOVE returned ... and an EPC page was leaked.  SGX may become unusable..."

This is effectively a kernel use-after-free of an EPC page, and due
to the way SGX works, the bug is detected at freeing. Rather than
adding the page back to the pool of available EPC pages, the kernel
intentionally leaks the page to avoid additional errors in the future.

When this happens, the kernel will likely soon leak more EPC pages, and
SGX will likely become unusable because the memory available to SGX is
limited. However, while this may be fatal to SGX, the rest of the kernel
is unlikely to be impacted and should continue to work.

As a result, when this happpens, user should stop running any new
SGX workloads, (or just any new workloads), and migrate all valuable
workloads. Although a machine reboot can recover all EPC memory, the bug
should be reported to Linux developers.

Virtual EPC

The implementation has also a virtual EPC driver to support SGX enclaves
in guests. Unlike the SGX driver, an EPC page allocated by the virtual
EPC driver doesn't have a specific enclave associated with it. This is
because KVM doesn't track how a guest uses EPC pages.

As a result, the SGX core page reclaimer doesn't support reclaiming EPC
pages allocated to KVM guests through the virtual EPC driver. If the
user wants to deploy SGX applications both on the host and in guests
on the same machine, the user should reserve enough EPC (by taking out
total virtual EPC size of all SGX VMs from the physical EPC size) for
host SGX applications so they can run with acceptable performance.

Architectural behavior is to restore all EPC pages to an uninitialized
state also after a guest reboot.  Because this state can be reached only
through the privileged ``ENCLS[EREMOVE]`` instruction, ``/dev/sgx_vepc``
provides the ``SGX_IOC_VEPC_REMOVE_ALL`` ioctl to execute the instruction
on all pages in the virtual EPC.

``EREMOVE`` can fail for three reasons.  Userspace must pay attention
to expected failures and handle them as follows:

1. Page removal will always fail when any thread is running in the
   enclave to which the page belongs.  In this case the ioctl will
   return ``EBUSY`` independent of whether it has successfully removed
   some pages; userspace can avoid these failures by preventing execution
   of any vcpu which maps the virtual EPC.

2. Page removal will cause a general protection fault if two calls to
   ``EREMOVE`` happen concurrently for pages that refer to the same
   "SECS" metadata pages.  This can happen if there are concurrent
   invocations to ``SGX_IOC_VEPC_REMOVE_ALL``, or if a ``/dev/sgx_vepc``
   file descriptor in the guest is closed at the same time as
   ``SGX_IOC_VEPC_REMOVE_ALL``; it will also be reported as ``EBUSY``.
   This can be avoided in userspace by serializing calls to the ioctl()
   and to close(), but in general it should not be a problem.

3. Finally, page removal will fail for SECS metadata pages which still
   have child pages.  Child pages can be removed by executing
   ``SGX_IOC_VEPC_REMOVE_ALL`` on all ``/dev/sgx_vepc`` file descriptors
   mapped into the guest.  This means that the ioctl() must be called
   twice: an initial set of calls to remove child pages and a subsequent
   set of calls to remove SECS pages.  The second set of calls is only
   required for those mappings that returned a nonzero value from the
   first call.  It indicates a bug in the kernel or the userspace client
   if any of the second round of ``SGX_IOC_VEPC_REMOVE_ALL`` calls has
   a return code other than 0.