Thursday, December 18, 2014

[QPSIIR-80] Qualcomm TrustZone Integer Signedness bug

________________________________________________________________________
Summary:
Qualcomm TrustZone is prone to an integer signedness bug that may allow to write NULL words to barely controllable locations in memory.

The vulnerability can be triggered from Non-Secure World through the TrustZone call "tzbsp_smmu_fault_regs_dump".

This issue has been discovered in Samsung Galaxy S5 firmware, but other devices can be affected as well.
________________________________________________________________________
Details:
This vulnerability has been discovered in TrustZone binary of Samsung Galaxy S5 firmware, version 4.4.2.
The tzbsp_smmu_fault_regs_dump function can be called from Non-Secure World through the SMC instruction. It takes 4 arguments passed in R0-R3 registers.
When called with argument R0 > 1, nested function subfunc_1 is called with arguments (R0 = 0xFFFFFFFF, R1) :

FE84B9B6 tzbsp_smmu_fault_regs_dump FE84B9B6 PUSH.W {R4-R8,LR} FE84B9BA MOVS R6, R2 FE84B9BC MOV R8, R1 FE84B9BE MOV R7, R3 FE84B9C0 MOV.W R4, #0xFFFFFFFF FE84B9C4 MOV R5, #0xFFFFFFEE FE84B9C8 BEQ loc_FE84BA1A FE84B9CA CBZ R0, loc_FE84B9D2 ; R0 > 1 : branch not taken FE84B9CC CMP R0, #1 FE84B9CE BEQ loc_FE84B9D6 ; R0 > 1 : branch not taken FE84B9D0 B loc_FE84B9D8 ; branch FE84B9D2 ; --------------------------------------------------------- FE84B9D2 loc_FE84B9D2 ; if R0 == 0 FE84B9D2 MOVS R4, #1 FE84B9D4 B loc_FE84B9D8 FE84B9D6 ; --------------------------------------------------------- FE84B9D6 loc_FE84B9D6 ; if R0 == 1 FE84B9D6 MOVS R4, #0 FE84B9D8 FE84B9D8 loc_FE84B9D8 ; for any value of R0 FE84B9D8 MOVS R0, #1 FE84B9DA BL subfunc_0 ; kind of "is retail hardware?" test FE84B9DE CBZ R0, loc_FE84B9EE ; not taken FE84B9E0 MOV R1, R8 FE84B9E2 MOV R0, R4 ; R4 == #0xFFFFFFFF FE84B9E4 BL subfunc_1
FE84B9E8 [...]


Then subfunc_1 checks if R0 value is valid. It will Branch and return if R0 is Greater than or Equal to 2. However, BGE instruction operates on signed integers. So R0 == -1 < 2 will pass the test and the execution will continue :
FE853124 subfunc_1 FE853124 CMP R0, #2 ; R0 == #0xFFFFFFFF FE853126 BGE locret_FE85314C ; signed comparison :
FE853126 ; R0(-1) < 2 so branch not taken FE853128 MOVW R2, #0x9EE0 FE85312C ADD.W R3, R0, R0,LSL#1 FE853130 MOVT.W R2, #0xFE82 FE853134 ADD.W R0, R3, R0,LSL#3 FE853138 LDR R2, [R2,#(dword_FE829EE4 - 0xFE829EE0)] FE85313A ADD.W R0, R2, R0,LSL#4 FE85313E LDRB R2, [R0,#4] FE853140 CMP R2, R1 ; with R1 < R2 FE853142 BLS locret_FE85314C FE853144 LDR R0, [R0] FE853146 MOVS R2, #0
FE853148 B.W sub_FE856C84 ; write NULL DWORD to a barely arbitrary address (derived from R1 value) FE85314C [...]


Finally, the last nested function could allow to write NULL words to a limited range of memory locations.
________________________________________________________________________
Fix:
This bug is fixed in Lolipop version of the firmware. Several changes have been made. First, subfunc_1 function is not reachable anymore with an invalid R0 value:
FE84B970 tzbsp_smmu_fault_regs_dump
FE84B970 PUSH.W {R4-R8,LR} FE84B974 MOVS R6, R2 FE84B976 MOV R8, R1 FE84B978 MOV R7, R3 FE84B97A MOV R5, #0xFFFFFFEE FE84B97E BEQ loc_FE84B9D2 FE84B980 CBZ R0, loc_FE84B98A FE84B982 CMP R0, #1 FE84B984 BEQ loc_FE84B98E FE84B986 ADDS R0, R5, #2 FE84B988 B locret_FE84B7AA ; branch if R0 > 1 FE84B98A ; --------------------------------------------------------- FE84B98A loc_FE84B98A ; if R0 == 0 FE84B98A MOVS R4, #1 FE84B98C B loc_FE84B990 FE84B98E ; --------------------------------------------------------- FE84B98E loc_FE84B98E ; if R0 == 1 FE84B98E MOVS R4, #0 FE84B990 FE84B990 loc_FE84B990 ; if 0 <= R0 < 2 FE84B990 MOVS R0, #1 FE84B992 BL subfunc_0 ; kind of "is retail hardware?" test FE84B996 CBZ R0, loc_FE84B9A6 ; not taken FE84B998 MOV R1, R8 FE84B99A MOV R0, R4 ; R4 is either 0 or 1
FE84B99C BL subfunc_1 FE84B9A0 [...]

Then in (sub)subfunc_1, R0 value is now tested with an unsigned comparison:
FE852B94 (sub)subfunc_1 FE852B94 CMP R0, #2 FE852B96 BCS loc_FE852BBA ;unsigned comparison: branch if R0 > 1 FE852B98 MOVW R2, #0x9F38 FE852B9C [...]

The bug can no longer be triggered.
________________________________________________________________________ CVSS Version 2 Metrics: Access Vector: Local Access Complexity: High Authentication: Single Confidentiality Impact: Complete Integrity Impact: Complete Availability Impact: Complete ________________________________________________________________________ Disclosure Timeline: 2014-08-28 Intial vendor notification
2014-09-03 Vendor reply; severity of the issue rated as high 2014-00-00 Vendor has notified all OEMs 2014-12-18 Public advisory ________________________________________________________________________ References:
https://www.qualcomm.com/connect/contact/security/product-security/hall-of-fame
________________________________________________________________________

No comments:

Post a Comment