Skip to content
This repository was archived by the owner on Dec 18, 2025. It is now read-only.

Commit 88f2b4f

Browse files
RTX5: enhance stack overrun checking
1 parent dae8b25 commit 88f2b4f

18 files changed

Lines changed: 691 additions & 115 deletions

CMSIS/DoxyGen/RTOS2/src/history.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
<td>
104104
- CVE-2021-27431 vulnerability mitigation.
105105
- Added OS Initialization for IAR.
106+
- Enhanced stack overrun checking.
106107
- Reorganized and optimized IRQ modules.
107108
</td>
108109
</tr>

CMSIS/RTOS2/RTX/Config/RTX_Config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@
143143
#endif
144144

145145
// <q>Stack overrun checking
146-
// <i> Enables stack overrun check at thread switch.
146+
// <i> Enables stack overrun check at thread switch (requires RTX source variant).
147147
// <i> Enabling this option increases slightly the execution time of a thread switch.
148148
#ifndef OS_STACK_CHECK
149-
#define OS_STACK_CHECK 1
149+
#define OS_STACK_CHECK 0
150150
#endif
151151

152152
// <q>Stack usage watermark

CMSIS/RTOS2/RTX/Include/rtx_def.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
#define RTX_OBJ_MEM_USAGE
2424
#endif
2525

26+
#if (defined(OS_STACK_CHECK) && (OS_STACK_CHECK != 0))
27+
#define RTX_STACK_CHECK
28+
#endif
29+
2630
#ifdef RTE_CMSIS_RTOS2_RTX5_ARMV8M_NS
2731
#define DOMAIN_NS 1
2832
#endif

CMSIS/RTOS2/RTX/Source/ARM/irq_armv6m.s

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,16 @@
2424
; */
2525

2626

27+
IF :LNOT::DEF:RTX_STACK_CHECK
28+
RTX_STACK_CHECK EQU 0
29+
ENDIF
30+
2731
I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
2832
TCB_SP_OFS EQU 56 ; TCB.SP offset
2933

34+
osRtxErrorStackOverflow\
35+
EQU 1 ; Stack overflow
36+
3037

3138
PRESERVE8
3239
THUMB
@@ -44,6 +51,10 @@ SVC_Handler PROC
4451
EXPORT SVC_Handler
4552
IMPORT osRtxUserSVC
4653
IMPORT osRtxInfo
54+
IF RTX_STACK_CHECK != 0
55+
IMPORT osRtxThreadStackCheck
56+
IMPORT osRtxKernelErrorNotify
57+
ENDIF
4758

4859
MOV R0,LR
4960
LSRS R0,R0,#3 ; Determine return stack from EXC_RETURN bit 2
@@ -70,24 +81,44 @@ SVC_Context
7081
CMP R1,R2 ; Check if thread switch is required
7182
BEQ SVC_Exit ; Branch when threads are the same
7283

84+
SUBS R3,R3,#8 ; Adjust address
85+
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
7386
CMP R1,#0
74-
BEQ SVC_ContextSwitch ; Branch if running thread is deleted
87+
BEQ SVC_ContextRestore ; Branch if running thread is deleted
7588

7689
SVC_ContextSave
7790
MRS R0,PSP ; Get PSP
7891
SUBS R0,R0,#32 ; Calculate SP: space for R4..R11
7992
STR R0,[R1,#TCB_SP_OFS] ; Store SP
93+
94+
IF RTX_STACK_CHECK != 0
95+
96+
PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next
97+
MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr
98+
BL osRtxThreadStackCheck ; Check if thread stack is overrun
99+
POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next
100+
CMP R0,#0
101+
BNE SVC_ContextSaveRegs ; Branch when stack check is ok
102+
103+
MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id
104+
BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify
105+
LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run
106+
LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next
107+
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
108+
B SVC_ContextRestore ; Branch to context restore handling
109+
110+
SVC_ContextSaveRegs
111+
LDR R0,[R1,#TCB_SP_OFS] ; Load SP
112+
113+
ENDIF
114+
80115
STMIA R0!,{R4-R7} ; Save R4..R7
81116
MOV R4,R8
82117
MOV R5,R9
83118
MOV R6,R10
84119
MOV R7,R11
85120
STMIA R0!,{R4-R7} ; Save R8..R11
86121

87-
SVC_ContextSwitch
88-
SUBS R3,R3,#8 ; Adjust address
89-
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
90-
91122
SVC_ContextRestore
92123
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
93124
ADDS R0,R0,#16 ; Adjust address

CMSIS/RTOS2/RTX/Source/ARM/irq_armv7m.s

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
; */
2525

2626

27+
IF :LNOT::DEF:RTX_STACK_CHECK
28+
RTX_STACK_CHECK EQU 0
29+
ENDIF
30+
2731
IF ({FPU}="FPv4-SP")
2832
FPU_USED EQU 1
2933
ELSE
@@ -36,6 +40,10 @@ TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
3640

3741
FPCCR EQU 0xE000EF34 ; FPCCR Address
3842

43+
osRtxErrorStackOverflow\
44+
EQU 1 ; Stack overflow
45+
46+
3947
PRESERVE8
4048
THUMB
4149

@@ -52,6 +60,10 @@ SVC_Handler PROC
5260
EXPORT SVC_Handler
5361
IMPORT osRtxUserSVC
5462
IMPORT osRtxInfo
63+
IF RTX_STACK_CHECK != 0
64+
IMPORT osRtxThreadStackCheck
65+
IMPORT osRtxKernelErrorNotify
66+
ENDIF
5567

5668
TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2
5769
ITE EQ
@@ -60,7 +72,8 @@ SVC_Handler PROC
6072

6173
LDR R1,[R0,#24] ; Load saved PC from stack
6274
LDRB R1,[R1,#-2] ; Load SVC number
63-
CBNZ R1,SVC_User ; Branch if not SVC 0
75+
CMP R1,#0 ; Check SVC number
76+
BNE SVC_User ; Branch if not SVC 0
6477

6578
PUSH {R0,LR} ; Save SP and EXC_RETURN
6679
LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
@@ -75,31 +88,73 @@ SVC_Context
7588
IT EQ
7689
BXEQ LR ; Exit when threads are the same
7790

91+
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
92+
7893
IF FPU_USED != 0
7994
CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted
95+
SVC_FP_LazyState
8096
TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
81-
BNE SVC_ContextSwitch ; Branch if not extended stack frame
97+
BNE SVC_ContextRestore ; Branch if not extended stack frame
8298
LDR R3,=FPCCR ; FPCCR Address
8399
LDR R0,[R3] ; Load FPCCR
84100
BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation)
85101
STR R0,[R3] ; Store FPCCR
86-
B SVC_ContextSwitch ; Branch to context switch handling
102+
B SVC_ContextRestore ; Branch to context restore handling
87103
ELSE
88-
CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted
104+
CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted
89105
ENDIF
90106

91107
SVC_ContextSave
92-
STMDB R12!,{R4-R11} ; Save R4..R11
108+
IF RTX_STACK_CHECK != 0
109+
SUB R12,R12,#32 ; Calculate SP: space for R4..R11
93110
IF FPU_USED != 0
94111
TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
95112
IT EQ ; If extended stack frame
96-
VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31
113+
SUBEQ R12,R12,#64 ; Additional space for S16..S31
97114
STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
98115
ENDIF
99116
STR R12,[R1,#TCB_SP_OFS] ; Store SP
100117

101-
SVC_ContextSwitch
118+
PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next
119+
MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr
120+
BL osRtxThreadStackCheck ; Check if thread stack is overrun
121+
POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next
122+
CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok
123+
124+
IF FPU_USED != 0
125+
MOV R4,R1 ; Save osRtxInfo.thread.run.curr
126+
ENDIF
127+
MOV R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id
128+
BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify
129+
LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run
130+
LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next
102131
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
132+
IF FPU_USED != 0
133+
LDRB LR,[R4,#TCB_SF_OFS] ; Load stack frame information
134+
B SVC_FP_LazyState ; Branch to FP lazy state handling
135+
ELSE
136+
B SVC_ContextRestore ; Branch to context restore handling
137+
ENDIF
138+
139+
SVC_ContextSaveRegs
140+
LDR R12,[R1,#TCB_SP_OFS] ; Load SP
141+
IF FPU_USED != 0
142+
LDRB LR, [R1,#TCB_SF_OFS] ; Load stack frame information
143+
TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
144+
IT EQ ; If extended stack frame
145+
VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31
146+
ENDIF
147+
STM R12,{R4-R11} ; Save R4..R11
148+
ELSE
149+
STMDB R12!,{R4-R11} ; Save R4..R11
150+
IF FPU_USED != 0
151+
TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
152+
IT EQ ; If extended stack frame
153+
VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31
154+
STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
155+
ENDIF
156+
STR R12,[R1,#TCB_SP_OFS] ; Store SP
157+
ENDIF
103158

104159
SVC_ContextRestore
105160
LDR R0,[R2,#TCB_SP_OFS] ; Load SP

CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mbl.s

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
; */
2525

2626

27+
IF :LNOT::DEF:RTX_STACK_CHECK
28+
RTX_STACK_CHECK EQU 0
29+
ENDIF
30+
2731
IF :LNOT::DEF:DOMAIN_NS
2832
DOMAIN_NS EQU 0
2933
ENDIF
@@ -34,6 +38,9 @@ TCB_SP_OFS EQU 56 ; TCB.SP offset
3438
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
3539
TCB_TZM_OFS EQU 64 ; TCB.tz_memory offset
3640

41+
osRtxErrorStackOverflow\
42+
EQU 1 ; Stack overflow
43+
3744

3845
PRESERVE8
3946
THUMB
@@ -51,6 +58,10 @@ SVC_Handler PROC
5158
EXPORT SVC_Handler
5259
IMPORT osRtxUserSVC
5360
IMPORT osRtxInfo
61+
IF RTX_STACK_CHECK != 0
62+
IMPORT osRtxThreadStackCheck
63+
IMPORT osRtxKernelErrorNotify
64+
ENDIF
5465
IF DOMAIN_NS != 0
5566
IMPORT TZ_LoadContext_S
5667
IMPORT TZ_StoreContext_S
@@ -81,7 +92,9 @@ SVC_Context
8192
CMP R1,R2 ; Check if thread switch is required
8293
BEQ SVC_Exit ; Branch when threads are the same
8394

84-
CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted
95+
SUBS R3,R3,#8 ; Adjust address
96+
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
97+
CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted
8598

8699
SVC_ContextSave
87100
IF DOMAIN_NS != 0
@@ -102,6 +115,46 @@ SVC_ContextSave_NS
102115
BMI SVC_ContextSaveSP ; Branch if secure
103116
ENDIF
104117

118+
IF RTX_STACK_CHECK != 0
119+
SUBS R0,R0,#32 ; Calculate SP: space for R4..R11
120+
121+
SVC_ContextSaveSP
122+
STR R0,[R1,#TCB_SP_OFS] ; Store SP
123+
MOV R3,LR ; Get EXC_RETURN
124+
MOV R0,R1 ; osRtxInfo.thread.run.curr
125+
ADDS R0,R0,#TCB_SF_OFS ; Adjust address
126+
STRB R3,[R0] ; Store stack frame information
127+
128+
PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next
129+
MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr
130+
BL osRtxThreadStackCheck ; Check if thread stack is overrun
131+
POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next
132+
CMP R0,#0
133+
BNE SVC_ContextSaveRegs ; Branch when stack check is ok
134+
135+
MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id
136+
BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify
137+
LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run
138+
LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next
139+
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
140+
B SVC_ContextRestore ; Branch to context restore handling
141+
142+
SVC_ContextSaveRegs
143+
IF DOMAIN_NS != 0
144+
MOV R0,R1 ; osRtxInfo.thread.run.curr
145+
ADDS R0,R0,#TCB_SF_OFS ; Adjust address
146+
LDRB R3,[R0] ; Load stack frame information
147+
LSLS R3,R3,#25 ; Check domain of interrupted thread
148+
BMI SVC_ContextRestore ; Branch if secure
149+
ENDIF
150+
LDR R0,[R1,#TCB_SP_OFS] ; Load SP
151+
STMIA R0!,{R4-R7} ; Save R4..R7
152+
MOV R4,R8
153+
MOV R5,R9
154+
MOV R6,R10
155+
MOV R7,R11
156+
STMIA R0!,{R4-R7} ; Save R8..R11
157+
ELSE
105158
SUBS R0,R0,#32 ; Calculate SP: space for R4..R11
106159
STMIA R0!,{R4-R7} ; Save R4..R7
107160
MOV R4,R8
@@ -115,10 +168,7 @@ SVC_ContextSaveSP
115168
MOV R0,LR ; Get EXC_RETURN
116169
ADDS R1,R1,#TCB_SF_OFS ; Adjust address
117170
STRB R0,[R1] ; Store stack frame information
118-
119-
SVC_ContextSwitch
120-
SUBS R3,R3,#8 ; Adjust address
121-
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
171+
ENDIF
122172

123173
SVC_ContextRestore
124174
IF DOMAIN_NS != 0

0 commit comments

Comments
 (0)