Skip to content

Commit 996abdb

Browse files
pratlucasvhscampos
andauthored
Add new requirements to code generation of CMSE Entry function and Non-secure calls (#319)
* Add new requirements to code generation of CMSE Entry function and Non-secure calls This addresses the vulnerability described in CVE-2024-0151. Patch by Victor Campos. Co-authored-by: Victor Campos <[email protected]>
1 parent 255e9fb commit 996abdb

File tree

2 files changed

+115
-19
lines changed

2 files changed

+115
-19
lines changed

cmse/cmse.md

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
title: Arm®v8-M Security Extensions <br /> Requirements on Development Tools
3-
version: 1.3
4-
date-of-issue: 04 August 2023
3+
version: 1.4
4+
date-of-issue: 05 April 2024
55
set-quote-highlight: true
66
# LaTeX specific variables
7-
copyright-text: Copyright 2019, 2021-2023 Arm Limited and/or its affiliates <[email protected]>.
8-
draftversion: false
7+
copyright-text: Copyright 2019, 2021-2024 Arm Limited and/or its affiliates <[email protected]>.
8+
draftversion: true
99
# Jekyll specific variables
1010
header_counter: true
1111
toc: true
@@ -155,6 +155,13 @@ Copyright 2019, 2021-2023 Arm Limited and/or its affiliates <open-source-office@
155155
[Non-secure function pointers](#non-secure-function-pointer).
156156
* Fixed typos.
157157

158+
#### Changes for next release
159+
160+
* Added [Requirement #47](#requirement-47) to address a security issue in the
161+
handling of arguments to CMSE Entry functions.
162+
* Added [Requirement #58](#requirement-58) to address a security issue in the
163+
handling of return values from CMSE Non-secure calls.
164+
158165
## References
159166

160167
This document refers to the following documents.
@@ -1138,9 +1145,51 @@ caller stack frame](#figure5).
11381145
11391146
![<span id="figure5" class="citation-label">**Entry function's caller stack frame**</span>](stack-frame-entry.svg)
11401147
1141-
### Return from an entry function
1148+
Calls from Non-secure state follow the [[AAPCS]](#AAPCS), which states that the
1149+
caller is responsible for zero- or sign-extending arguments of integral
1150+
Fundamental Data Types smaller than a word to 4 bytes. An Entry function must
1151+
not assume that callers follow this rule, that is, it cannot presume that
1152+
integral parameters will have been zero- or sign-extended to 4 bytes. For
1153+
example, an attacker might create code that passes arguments out of their
1154+
declared type's range in an attempt to cause out-of-bounds memory accesses.
11421155
11431156
<span id="requirement-47" class="requirement-box"></span>
1157+
> A compiler generating code for an entry function must, for each parameter
1158+
> that is an integral Fundamental Data Type smaller than a word, make no
1159+
> assumptions about the value of the padding bits, even when the value of
1160+
> those bits are defined by the AAPCS.
1161+
1162+
A possible implementation is shown below:
1163+
1164+
```c
1165+
int array[256];
1166+
1167+
__attribute__((cmse_nonsecure_entry))
1168+
int func(unsigned char idx) {
1169+
return array[idx];
1170+
}
1171+
```
1172+
1173+
```c
1174+
__acle_se_func:
1175+
func:
1176+
...
1177+
@ narrow 'idx' to 8 bits before first use
1178+
uxtb r0, r0
1179+
movw r1, :lower16:array
1180+
movt r1, :upper16:array
1181+
ldr.w r0, [r1, r0, lsl #2]
1182+
...
1183+
bxns lr
1184+
```
1185+
1186+
We recommend that function parameters with integral types smaller than 4
1187+
bytes should be avoided. This recommendation extends to underlying types of
1188+
`enum` used as parameters.
1189+
1190+
### Return from an entry function
1191+
1192+
<span id="requirement-48" class="requirement-box"></span>
11441193
11451194
> An entry function must use the BXNS instruction to return to its
11461195
> non-secure caller.
@@ -1153,7 +1202,7 @@ To prevent information leakage when an entry function returns, you must clear th
11531202
registers that contain secret information
11541203
([Information leakage](#information-leakage)).
11551204
1156-
<span id="requirement-48" class="requirement-box"></span>
1205+
<span id="requirement-49" class="requirement-box"></span>
11571206
11581207
> The code sequence directly preceding the `BXNS` instruction that transitions
11591208
> to non-secure code must:
@@ -1186,7 +1235,7 @@ difficult.
11861235
An entry function can be called from secure or non-secure state. Software needs
11871236
to distinguish between these cases.
11881237
1189-
<span id="requirement-49" class="requirement-box"></span>
1238+
<span id="requirement-50" class="requirement-box"></span>
11901239
11911240
> The following intrinsic function must be provided if bit 1 of macro
11921241
> `__ARM_FEATURE_CMSE` is set:
@@ -1212,12 +1261,12 @@ only happen via function pointers. This is a consequence of separating
12121261
secure and non-secure code into separate executable files as described
12131262
in [Executable files](#executable-files).
12141263
1215-
<span id="requirement-50" class="requirement-box"></span>
1264+
<span id="requirement-51" class="requirement-box"></span>
12161265
12171266
> A non-secure function type must be declared using the function attribute
12181267
> `__attribute__((cmse_nonsecure_call))`.
12191268
1220-
<span id="requirement-51" class="requirement-box"></span>
1269+
<span id="requirement-52" class="requirement-box"></span>
12211270
12221271
> A non-secure function type must only be used as a base type of a pointer.
12231272
@@ -1226,7 +1275,7 @@ executable file only contains secure function definitions.
12261275
12271276
### Performing a call
12281277
1229-
<span id="requirement-52" class="requirement-box"></span>
1278+
<span id="requirement-53" class="requirement-box"></span>
12301279
12311280
> A function call through a pointer with a non-secure function type as its
12321281
> base type must switch to the non-secure state.
@@ -1245,7 +1294,7 @@ that contain values that are used after the non-secure function call
12451294
must be restored after the call returns. Secure code cannot depend on
12461295
the non-secure state to restore these registers.
12471296
1248-
<span id="requirement-53" class="requirement-box"></span>
1297+
<span id="requirement-54" class="requirement-box"></span>
12491298
12501299
> The code sequence directly preceding the `BLXNS` instruction that
12511300
> transitions to non-secure code must:
@@ -1263,7 +1312,7 @@ the non-secure state to restore these registers.
12631312
A toolchain could provide you with the means to specify that some
12641313
types of variables never hold secret information.
12651314
1266-
<span id="requirement-54" class="requirement-box"></span>
1315+
<span id="requirement-55" class="requirement-box"></span>
12671316
12681317
> When the non-secure function call returns, caller- and callee-saved
12691318
> registers saved before the call must be restored. This includes bits [27:0]
@@ -1290,7 +1339,7 @@ usage is required according to [[AAPCS]](#AAPCS), the non-secure state expects
12901339
the arguments on the non-secure stack and writes the return value to non-secure
12911340
memory.
12921341
1293-
<span id="requirement-55" class="requirement-box"></span>
1342+
<span id="requirement-56" class="requirement-box"></span>
12941343
12951344
> To avoid using the non-secure stack, a toolchain may constrain the
12961345
> following, for a non-secure function type:
@@ -1299,7 +1348,7 @@ memory.
12991348
> * The type of each parameter.
13001349
> * The return type.
13011350
1302-
<span id="requirement-56" class="requirement-box"></span>
1351+
<span id="requirement-57" class="requirement-box"></span>
13031352
13041353
> A compiler compiling a call to a non-secure function must do either of the
13051354
> following:
@@ -1335,6 +1384,51 @@ The stack usage during a non-secure function call is shown in figure
13351384
13361385
![<span id="figure6" class="citation-label">**Caller's stack frame of a non-secure function call**</span>](stack-frame-non-secure.svg)
13371386
1387+
The return of values from Non-secure function calls follows the
1388+
[[AAPCS]](#AAPCS), which states that the callee is responsible for zero- or
1389+
sign-extending return values of integral Fundamental Data Types smaller than a
1390+
word to 4 bytes. A Secure function must not assume that Non-secure callees
1391+
follow this rule, that is, it cannot presume that integral returned values will
1392+
have been zero- or sign-extended to 4 bytes. For example, an attacker might
1393+
create code that returns values out of their declared type's range in an
1394+
attempt to cause out-of-bounds memory accesses.
1395+
1396+
<span id="requirement-58" class="requirement-box"></span>
1397+
> A compiler generating code for a Non-secure function call must, for each
1398+
> returned value that is an integral Fundamental Data Type smaller than a word,
1399+
> make no assumptions about the value of the padding bits, even when the value
1400+
> of those bits are defined by the AAPCS.
1401+
1402+
A possible implementation is shown below:
1403+
1404+
```c
1405+
__attribute__((cmse_nonsecure_call))
1406+
unsigned short (*nonsecurefunc)(void);
1407+
1408+
void securefunc(int *array) {
1409+
unsigned short idx = nonsecurefunc();
1410+
print(array[idx]);
1411+
}
1412+
```
1413+
1414+
```c
1415+
securefunc:
1416+
...
1417+
@ r1 has the address of 'nonsecurefunc'
1418+
@ r2 has 'array'
1419+
@ non-secure function call
1420+
blxns r1
1421+
@ narrow 'idx' (returned value in r0) to a 16-bit value
1422+
uxth r0, r0
1423+
ldr.w r0, [r2, r0, lsl #2]
1424+
bl print
1425+
...
1426+
```
1427+
1428+
We recommend that function return values with integral types smaller than 4
1429+
bytes should be avoided. This recommendation extends to underlying types of
1430+
`enum` used as return values.
1431+
13381432
## Non-secure function pointer
13391433
13401434
A function pointer that has its LSB unset is a non-secure function
@@ -1399,7 +1493,7 @@ void call_callback(void) {
13991493
This is just an optimisation technique and hence it is not required for the
14001494
correct usage of non-secure function pointers.
14011495
1402-
<span id="requirement-57" class="requirement-box"></span>
1496+
<span id="requirement-59" class="requirement-box"></span>
14031497
14041498
> The following intrinsics are defined if bit 1 of macro
14051499
> `__ARM_FEATURE_CMSE` is set:
@@ -1428,12 +1522,12 @@ A non-secure callable function is a function that is expected to be placed in an
14281522
NSC region. Its functionality is identical to an entry function, but instead of
14291523
a secure gateway veneer the function starts with the `SG` instruction.
14301524
1431-
<span id="requirement-58" class="requirement-box"></span>
1525+
<span id="requirement-60" class="requirement-box"></span>
14321526
14331527
> A non-secure callable function must be declared by using the attribute
14341528
> `__attribute__((cmse_nonsecure_callable))` on a function declaration.
14351529
1436-
<span id="requirement-59" class="requirement-box"></span>
1530+
<span id="requirement-61" class="requirement-box"></span>
14371531
14381532
> A non-secure callable function is identical to an entry function except that:
14391533
>
@@ -1449,7 +1543,7 @@ Toolchain support is needed to prevent inadvertent secure gateways
14491543
from occurring ([Inadverted secure
14501544
gataway](#inadvertent-secure-gateway)).
14511545
1452-
<span id="requirement-60" class="requirement-box"></span>
1546+
<span id="requirement-62" class="requirement-box"></span>
14531547
14541548
> A toolchain must provide a way for the programmer to guarantee that a
14551549
> non-secure callable function does not contain an inadvertent `SG` instruction
@@ -1465,7 +1559,7 @@ non-secure state, but cannot be called by the non-secure state. An example use
14651559
would be to provide tail-calls from an entry function to non-secure returning
14661560
functions.
14671561
1468-
<span id="requirement-61" class="requirement-box"></span>
1562+
<span id="requirement-63" class="requirement-box"></span>
14691563
14701564
> A non-secure returning function must be declared by using the attribute
14711565
> `__attribute__((cmse_nonsecure_return))` on a function declaration.

main/acle.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ Armv8.4-A [[ARMARMv84]](#ARMARMv84). Support is added for the Dot Product intrin
389389

390390

391391
#### Changes for next release
392+
* Added new content for the handling of arguments in CMSE Entry functions and
393+
return values of CMSE Non-secure calls in order to address security issues.
392394

393395
* Added [**Alpha**](#current-status-and-anticipated-changes)
394396
support for SVE2.1 (FEAT_SVE2p1).

0 commit comments

Comments
 (0)