Security Software

Deep Dive: Intel Analysis of Speculative Behavior of SWAPGS and Segment Registers

This technical deep dive expands on the information in the Speculative Behavior of SWAPGS and Segment Registers disclosure. 

Overview of SWAPGS

In the IA-32 architecture, memory segmentation is used in the formation of physical memory addresses. Segment descriptors specify a base address (along with other attributes) for each segment, on which the rest of the physical address is built. The segment information is stored in a table in memory, and the individual segments are referenced by selectors that act as indices into this table. The architecture defines a set of segment registers (CS, SS, DS, ES, FS, and GS) that can each hold one selector value. One of these registers is either implicitly or explicitly used for every effective address memory access. More information on segmentation can be found in the Intel® 64 and IA-32 Architectures Software Developer Manual, Volume 3a, Chapter 3, Protected Mode Memory Management.

Many operating systems use the GS segment register to reference application and kernel data that is specific to a thread or processor. In such cases, the operating system maintains both user space and kernel values of GS. The SWAPGS instruction is a privileged CPU instruction used to exchange the application and kernel values of GS.

If operating systems that use SWAPGS to switch the contents of the GS register on kernel entry have code paths that conditionally determine whether or not to execute the instruction and then also contain memory references offset from the register, those OSes may be vulnerable to malicious actors who can cause the SWAPGS instruction to be speculatively executed or bypassed. The CVE assigned to this vulnerability is CVE-2019-1125 (5.6 Medium CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N/E:P/RL:O/RC:C).

We can use the example code sequence below to illustrate both of these cases:

0			test 
1			je skip
2			swapgs
3			mov r10, qword ptr gs:[1000h]
4			mov rbx, [r10]
5			...
6	skip:
7			mov rcx, qword ptr gs:[2000h]
8			mov rbx, [rcx]
9			…

Speculatively missed SWAPGS

If GS holds the user space value on entry (for example, if this was part of a system call) and the branch is speculatively predicted to be taken, then the speculative execution path skips the SWAPGS instruction. The memory reference on line 7 would speculatively execute with the user space value of GS, and thus may load kernel data from an address specified by a malicious actor. The memory reference on line 8 would be based on the value loaded by line 7, which may affect the cache in a way that might be detectable by a malicious actor in user space.

Speculatively executed extra SWAPGS

In the other case, if GS holds the kernel value on entry (for example, if this code was part of an interrupt handler where interrupts could be generated from either kernel or user space) and the branch is speculatively predicted to not be taken, then the speculative execution path executes the SWAPGS instruction, switching to the user space value of GS. The memory reference on line 3 would speculatively execute with the user space value and thus may load kernel data from an address specified by a malicious actor. The memory reference on line 4 would be based on the value loaded by line 3, which would affect the cache in a way that might be detectable by a malicious actor in user space.

Note: Real software may not have sequences that are as simple as the example above.

Speculative Behavior of Segment Register Writes

Caching of segment descriptors

When converting an effective address into a linear address, the address generation hardware needs to know the base address and the limit of the applicable segment. When a segment register is written, these fields are cached within the processor in a microarchitectural structure called the segment register file.

Segment renaming and speculative execution

Register renaming is a microarchitectural technique that can improve performance by allowing an operation to execute and update a register before the processor knows whether older operations will cause a jump mispredict, trap, interrupt, or exception. For at least some types of register renaming, a renamed register file will have more physical entries than the number of architectural registers that software can specify and a mapping from each architectural register to each physical entry. When software writes one of these registers, the hardware picks a new physical register file entry, writes the result into it, and causes the architectural register to point to the physical register instead of overwriting the contents of the physical register that was previously used. If that operation retires (no older operation takes a jump mispredict, trap, interrupt, or exception) then the old (unused) physical register file entry is no longer needed and can be reclaimed. However, if the operation does not retire, then the old contents of that register can be restored by mapping the architectural register back to the old physical register file entry.

This technique can also be applied to segment registers. A processor can maintain a renamed segment register file and keep updating the architectural segment register to point to the correct entry (reflecting the current architectural state) in the segment register file. This may be applicable to instructions which directly operate on segment bases, like WRGSBASE, as well.

The processor may speculatively execute instructions that perform writes to segment registers, and thus segment bases, in the segment register file. Since these operations happen under a speculative window, the processor may allocate an entry in the segment register file and update it with a new base address. Later, the processor may determine that this speculative execution path was wrong and thus will not update the architectural state. The architectural segment register would still point to the old entry and the old base. The entry allocated in the segment register file during the speculative window may retain its speculatively written value. For lack of other terminology, we can call this entry a stale segment register entry as it is not currently being used for the architectural segment register. If the processor determines that the speculative execution path was correct, then it will update the architectural state to the newly written value. In this case, the previously used entry that held the old base would become a stale segment register entry.

Fault on segment register write

If the segment register is loaded with a new selector value, a processor may perform the following operations:

  1. Read out the segment descriptor that is pointed to by the new selector value.
  2. Validate the segment descriptor, and pend a fault (to be taken when the segment write retires) if it is invalid.
  3. Allocate an entry in the segment register file to hold base, limit, etc. from the segment descriptor.
  4. If the segment descriptor is valid, write new values as read from the segment descriptor to the allocated entry in the segment register file.
  5. Update the architectural segment register file to point to the newly allocated entry.

On processors with segment renaming, step 5 may still occur when step 2 detects that the segment descriptor is not valid. If the descriptor is invalid, step 2 ensures the operation faults and the changes are never reflected in the architectural state. However, if dependent instructions consume the results of this segment write (for example, by reading it out through RDFSBASE), the dependent instructions may speculatively get the value from the newly allocated segment entry in the segment register file (from step 3). Some implementations will not write the segment register file when the segment descriptor is invalid, which can result in the value in the allocated segment entry being a stale value that was written by some previous segment write operation. Malicious actors may be able to reveal this stale value using a speculative execution disclosure gadget.

The affected CPUs have two dedicated segment register file entries for each architectural segment, one of which is currently used for the segment, while the other is currently unused at any particular time. These entries are not shared between logical processors (for example, no entry is sometimes used by hyperthread 0 and sometimes used by hyperthread 1 on the same physical core), nor are they shared between different architectural segment registers (for example, there is no segment register file entry that is sometimes allocated to GS and sometimes to FS).

Implications of speculative segment register writes

Observation of old segment bases

The values contained in a stale segment register file entry may belong to previously run software. It may be possible for a malicious actor to infer the value in the unused segment register file entry, thus inferring the segment base of that previously run software. This may apply to previously run applications, guests, kernels, or virtual machine managers (VMMs). Most software only uses non-zero segment bases for those segments used for thread local storage (FS and GS segments).

Segment bases as a covert channel

Malicious actors who are able to control victim execution (for example, through a lack of mitigations against branch target injection attacks (also known as Spectre variant 2)) may be able to induce the victim to speculatively execute a segment write with data desired by the malicious actor. This speculatively written data may go into the unused segment register file entry of the destination segment.

When the malicious code later runs on the same logical processor, the malicious actor may be able to recover this data from the unused segment register file entry using the aforementioned technique.

It is also possible for two pieces of software to intentionally pass data through the unused segment register file entry of a segment.

Mitigation

SWAPGS

After assessing this issue, industry partners determined that mitigations for this issue would be implemented by the operating system. For more details about these mitigations, refer to the Microsoft* security advisory for Windows* operating systems and the latest kernel.org documentation for Linux* operating systems.

Generically, the recommended mitigation for when SWAPGS is speculatively missed (as in the first example case above) is to add an LFENCE or serializing instruction before the first memory reference using GS (for example, between lines 6 and 7 in the example code) on all paths that can speculatively skip the SWAPGS instruction. This will create a speculation barrier that forces the conditional to be evaluated before the memory reference executes.

The mitigation for when an extra SWAPGS instruction is speculatively executed when it should not be (as in the second case above) is to add an LFENCE or serializing instruction after the SWAPGS instruction (for example, after line 2 in the example code).

However, for optimal performance, each instance of SWAPGS should be evaluated to determine whether an LFENCE is actually needed. For instance, a potentially problematic code sequence might only speculatively execute without mappings of secret data, in which case the malicious actor would not have access to that data. In other cases, there may be some other serializing instruction before the memory accesses that would serve the same purpose as LFENCE. Writes to the CR3 register used to mitigate rogue data cache load (also known as Meltdown) are serializing instructions and can be utilized for serialization in lieu of LFENCE.

Speculative behavior of segment writes

Usage of segment registers as a channel

Many channels already exist that can be used for side channels. In general, the mitigations outlined above do not prevent the side channels, but rather prevent malicious actors from controlling speculation in order to put victim data into the channel in the first place. For example, a branch target injection attack that uses segment registers as a side channel (instead of using the data caches as the original branch target injection attack did) should be mitigated by preventing branch target injection attacks in general (for example, through retpoline or indirect branch restricted speculation (IBRS)) instead of attempting to address the specific channel (in this case, segment registers).

Observation of old segment bases

The unused segment register file entry may contain information from previously run applications or guests. Most segment bases are zero except for segments used for thread local storage (FS and GS). Intel does not believe that these segment bases are application secrets and does not recommend mitigating this information leakage.

The segment register file entries for a segment can be overwritten with the specified data by a pair of SWAPGS, MOV xS, selector, POP xS, or LFS/LGS instructions that write that segment on at least Intel® microarchitecture code name Sandy Bridge and later processors. Loading a null segment selector may be lower latency than loading a segment from a descriptor table.

Due to SWAPGS being executed after ring transitions, applications cannot observe the GS value from previous applications, but they may be able to infer the kernel GS base.

System Administrators

Intel recommends that you always keep your systems up to date with the latest security updates and guidance from your OS and VMM vendors.

Affected Processors

Intel expects the following products are potentially affected by these issues:

Processors affected
Family/Model Step Processor Families /
Processor Number Series
 
Segment Register Write SWAPGS
Missed (Spectre V1 Variant)
 
SWAPGS Extra
(Spectre V1 Variant)
 
06_2EH All Intel® Xeon® processor 7500, 6500 series (Nehalem-EX) Yes Yes Yes
06_1EH
06_1FH
All Intel® Core™ i7 and i5 Processors (Nehalem, Nehalem-G) Yes Yes Yes
06_1AH All Intel® Core™ i7 Processor, Intel Xeon processor 3400, 3500, 5500 series (Nehalem-EP) Yes Yes Yes
06_2FH All Intel® Xeon®  Processor E7 Family (Westmere-EX) Yes Yes Yes
06_25H
06_2CH
All Intel® Xeon®  processors 3600, 5600 series, Intel® Core™ i7, i5 and i3 Processors (Westmere, Westmere-EP) Yes Yes Yes
06_2DH All Intel® Xeon®  processor E5 Family based on Intel microarchitecture code name Sandy Bridge, Intel® Core™ i7-39xx Processor Extreme Edition Yes Yes Yes
06_2AH All Intel® Xeon® processor E3-1200 product family; 2nd Generation Intel® Core™ i7, i5, i3 Processors 2xxx Series (Sandy Bridge) Yes Yes Yes
06_3EH All Intel® Xeon® processor E7-8800/4800/2800 v2 product families based on Ivy Bridge-E microarchitecture Yes Yes Yes
06_3EH All Intel® Xeon® processor E5-2600/1600 v2 product families and Intel® Xeon® processor E5-2400 v2 product family based on Ivy Bridge-E microarchitecture, Intel® Core™ i7-49xx Processor Extreme Edition Yes Yes Yes
06_3AH All 3rd Generation Intel® Core™ Processor and Intel® Xeon® processor E3-1200 v2 product family based on Ivy Bridge microarchitecture Yes Yes Yes
06_3FH All Intel® Xeon® processor E5-4600/2600/1600 v3 product families, Intel® Xeon® processor E7 v3 product families based on Haswell-E microarchitecture, Intel® Core™ i7-59xx Processor Extreme Edition Yes Yes Yes
06_3CH
06_45H
06_46H
All 4th Generation Intel® Core™ processor and Intel® Xeon® processor E3-1200 v3 product family based on Haswell microarchitecture Yes Yes Yes
06_56H All Intel® Xeon® processor D-1500 product family based on Broadwell microarchitecture Yes Yes Yes
06_4FH All Intel® Xeon® processor E5 v4 Family based on Broadwell microarchitecture, Intel® Xeon® processor E7 v4 Family, Intel® Core™ i7-69xx Processor Extreme Edition Yes Yes Yes
06_47H All 5th generation Intel® Core™ processors, Intel® Xeon® processor E3-1200 v4 product family based on Broadwell microarchitecture Yes Yes Yes
06_3DH All Intel® Core™ M-5xxx Processor, 5th generation Intel® Core™ processors based on Broadwell microarchitecture Yes Yes Yes
06_55H <=4 Intel® Xeon® Processor Scalable Family based on Skylake microarchitecture  Yes Yes Yes
06_4EH
06_5EH
All 6th generation Intel® Core™ processors and Intel® Xeon® processor E3-1500m v5 product family and E3- 1200 v5 product family based on Skylake microarchitecture Yes Yes Yes
06_8EH <=A 7th/8th generation Intel® Core™ processors based on Kaby/Coffee Lake microarchitecture Yes Yes Yes
06_9EH <=B 7th/8th generation Intel® Core™ processors based on Kaby/Coffee Lake microarchitecture Yes Yes Yes
06_9E 0xC 8th generation Intel® Core™ processors based on Coffee Lake microarchitecture Yes Yes Yes
06_8E 0xB Whiskey Lake(ULT) Yes Yes Yes
06_8E 0xC Whiskey Lake (ULT refresh) Yes Yes Yes
06_9E 0xD Whiskey Lake (Desktop Yes Yes Yes
06_55H 5 2nd Generation Intel® Xeon® Scalable Processors based on Cascade Lake microarchitecture Yes Yes Yes
06_55H 6, 7 2nd Generation Intel® Xeon® Scalable Processors based on Cascade Lake microarchitecture Yes Yes Yes
06_37H
06_4AH,
06_4CH
06_4DH
06_5AH
06_5DH
06_6EH
06_65H
06_75H
06_1CH
06_26H
06_27H
06_35H
06_36H
06_36H
06_7AH
 
All Intel Atom® processors based on the Bonnell, Saltwell, Silvermont, Airmont, Goldmont, and GoldmontPlus microarchitectures No Yes No
06_57H
06_85H
All Intel® Xeon Phi™ processors based on the Knights Mill, Knights Landing, and Knights Corner microarchitectures No Yes No

References

Acknowledgements

Intel thanks the Linux kernel community and other industry partners who have contributed significantly to mitigations for speculative execution side channel methods, and recognizes the following people for their development efforts and dedication to software security:

  • Andrew Cooper
  • Thomas Gleixner
  • Tyler Hicks
  • Ben Hutchings
  • Greg KH
  • Jiri Kosina
  • Josh Poimboeuf

Was this article helpful?YesNo
0% of users found this helpful

Intel technologies’ features and benefits depend on system configuration and may require enabled hardware, software, or service activation. Performance varies depending on system configuration. Check with your system manufacturer or retailer or learn more at www.intel.com.

All information provided here is subject to change without notice. Contact your Intel representative to obtain the latest Intel product specifications and roadmaps.

The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request.

Intel provides these materials as-is, with no express or implied warranties.

No product or component can be absolutely secure.

Intel, the Intel logo, Intel Core, Intel Atom, Intel Xeon, Intel Xeon Phi, Intel® C Compiler, Intel Software Guard Extensions, and Intel® Trusted Execution Engine are trademarks of Intel Corporation in the U.S. and/or other countries.

*Other names and brands may be claimed as the property of others.