[BRLY-2022-028]
Absence or incomplete applying the Return Stack Buffer (RSB) stuffing mitigation logic before resuming from SMM.
BINARLY efiXplorer team

Summary

BINARLY efiXplorer team discovered that most enterprise vendors are affected by not correctly applying the Return Stack Buffer (RSB) stuffing mitigation logic before resuming from SMM (RSM instruction).

Information

  • BINARLY internal identifier: BRLY-2022-028
  • FwHunt rule: BRLY-2022-028
  • CVSS v3.1 Score 5.5 Medium AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Affected products with confirmed impact by Binarly team

Incomplete list of affected devices can be found in our FirmwareBleed repository.

Potential impact

The impact is focused on disclosing the content from privileged memory (including protected by virtualization technologies) to obtain sensitive data from processes running on the same processor (CPU). Cloud environments can have a greater impact when a physical server can be shared by multiple users or legal entities.

Description

The main CPU cores may use branch predictors other than the Return Stack Buffer (RSB) when the RSB underflows. Basically, RSB predict the target of RET instructions but when RSB underflows happen some of the CPU cores could fall back to using other branch predictors.

The best mitigation practice introduced by Intel in 2018 to address RSB behavior in SMM runtime was to leverage CALL instructions before returning from SMM context to avoid interfering with non-SMM usage of the retpoline mitigations. Regardless of whether Windows and Linux operating systems retpoline or not, if the SMM (SMI handlers) in system firmware don't have mitigations in place, an attack window will be available by design.

The original patch with mitigation code has been pushed by Intel to EDKII github repository in August 2018 to PiSmmCpuDxeSmm module to mitigate CVE-2017-5715 by adding Return Stack Buffer stuffing logic before resuming from SMM.

On AMD and Intel processors based on EDKII system firmwares, the same mitigation logic applies and the same mistakes in implementation too.

As an example, most of the analyzed UEFI firmwares images (most recent versions) have multiple cases when Resume from SMM (RSM) in SmiEntry is not mitigated. In the code of the PiSmmCpuDxeSmm there are three RSM instructions and two RSB stuffing mitigations. However, the third one does not. Additionally, the first two (where RSB stuffing is present) are not used during exit from SMM. The following figure shows the correct applied RSB stuffing mitigation (StuffRsb EDKII macros):

.text:00000000000010C0 B8 10 00 00 00                  mov     eax, 10h
.text:00000000000010C5                               Unroll1:
.text:00000000000010C5 E8 07 00 00 00                  call    Unroll2
.text:00000000000010CA                               SpecTrap1:
.text:00000000000010CA F3 90                           pause
.text:00000000000010CC 0F AE E8                        lfence
.text:00000000000010CF EB F9                           jmp     short SpecTrap1
.text:00000000000010D1                               Unroll2:
.text:00000000000010D1 E8 07 00 00 00                  call    StuffLoop
.text:00000000000010D6                               SpecTrap2:
.text:00000000000010D6 F3 90                           pause
.text:00000000000010D8 0F AE E8                        lfence
.text:00000000000010DB EB F9                           jmp     short SpecTrap2
.text:00000000000010DD                               StuffLoop:
.text:00000000000010DD 48 FF C8                        dec     rax
.text:00000000000010E0 75 E3                           jnz     short Unroll1
.text:00000000000010E2 48 81 C4 00 01 00 00            add     rsp, 100h
.text:00000000000010E9 0F AA                           rsm

On the other hand, during our research we found places where RSB mitigations are missed before the RSM instruction is executed in SmiEntry routine.

Code snippet without StuffRsb mitigation before RSM in SmiEntry presented below:

.text:0000000000002345 8A 00                           mov     al, [rax]
.text:0000000000002347 3C 00                           cmp     al, 0
.text:0000000000002349 74 0B                           jz      short loc_2356
.text:000000000000234B B9 A2 06 00 00                  mov     ecx, 6A2h
.text:0000000000002350 89 D8                           mov     eax, ebx
.text:0000000000002352 31 D2                           xor     edx, edx
.text:0000000000002354 0F 30                           wrmsr
.text:0000000000002356 0F AA                           rsm

This code pattern was obtained from Intel NUC M15.

On the another Intel-powered platforms, we also found alternate code patterns. Below is the similar code to SmiEntry from EDKII without RSB stuffing:

.text:000000000000224E 48 8B 5C 24 08                  mov     rbx, [rsp+8]
.text:0000000000002253 48 81 EC 00 02 00 00            sub     rsp, 200h
.text:000000000000225A 48 0F AE 04 24                  fxsave64 qword ptr [rsp]
.text:000000000000225F 48 83 C4 E0                     add     rsp, 0FFFFFFFFFFFFFFE0h
.text:0000000000002263 48 89 D9                        mov     rcx, rbx
.text:0000000000002266 E8 9D 25 00 00                  call    nullsub_1
.text:000000000000226B 48 89 D9                        mov     rcx, rbx
.text:000000000000226E E8 99 25 00 00                  call    sub_480C
.text:0000000000002273 48 89 D9                        mov     rcx, rbx
.text:0000000000002276 E8 8D 25 00 00                  call    nullsub_1
.text:000000000000227B 48 83 C4 20                     add     rsp, 20h
.text:000000000000227F 48 0F AE 0C 24                  fxrstor64 qword ptr [rsp]
.text:0000000000002284 48 81 C4 00 02 00 00            add     rsp, 200h
.text:000000000000228B 48 8D 05 5E 00 00 00            lea     rax, dword_22F0
.text:0000000000002292 48 31 DB                        xor     rbx, rbx
.text:0000000000002295 8B 18                           mov     ebx, [rax]
.text:0000000000002297 48 8D 04 24                     lea     rax, [rsp]
.text:000000000000229B 48 05 00 10 00 00               add     rax, 1000h
.text:00000000000022A1 48 25 00 F0 FF FF               and     rax, 0FFFFFFFFFFFFF000h
.text:00000000000022A7 48 29 D8                        sub     rax, rbx
.text:00000000000022AA 48 8D 0C 24                     lea     rcx, [rsp]
.text:00000000000022AE 48 29 C1                        sub     rcx, rax
.text:00000000000022B1 48 8D 7C 24 FF                  lea     rdi, [rsp-1]
.text:00000000000022B6 48 31 C0                        xor     rax, rax
.text:00000000000022B9 FD                              std
.text:00000000000022BA F3 AA                           rep stosb
.text:00000000000022BC FC                              cld
.text:00000000000022BD 48 8D 05 B9 FE FF FF            lea     rax, byte_217D
.text:00000000000022C4 8A 00                           mov     al, [rax]
.text:00000000000022C6 3C 00                           cmp     al, 0
.text:00000000000022C8 74 16                           jz      short loc_22E0
.text:00000000000022CA 5A                              pop     rdx
.text:00000000000022CB F7 C2 04 00 00 00               test    edx, 4
.text:00000000000022D1 74 0D                           jz      short loc_22E0
.text:00000000000022D3 B9 A0 01 00 00                  mov     ecx, 1A0h
.text:00000000000022D8 0F 32                           rdmsr
.text:00000000000022DA 66 83 CA 04                     or      dx, 4
.text:00000000000022DE 0F 30                           wrmsr
.text:00000000000022E0 0F AA                           rsm

Applying the RSB stuffing mitigation incorrectly can lead to the following security issues:

  • UEFI firmware does not have any RSB mitigations
  • UEFI firmware has RSB migitations in some places, but the code flow exposed to the operating system is not mitigated

Recomendations

The Binarly team recommends applying mitigation code before every RSM instruction that can be executed during runtime.

Acknowledgements

BINARLY efiXplorer team

References