summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@amd.com>2024-05-24 14:12:14 -0600
committerSteve Sakoman <steve@sakoman.com>2024-06-05 05:57:12 -0700
commit59c0a35bb829217bf9b36d6a782ba88b344fed51 (patch)
treedd528f7b1d9394c1b2b77112f4f5bca91e84b929
parent96b48c195a60ef6de2a43a66a8fa61b6a4baff10 (diff)
downloadpoky-59c0a35bb829217bf9b36d6a782ba88b344fed51.tar.gz
gcc: Fix for CVE-2024-0151
Fix for insufficient argument checking in Secure state Entry functions in software using Cortex-M Security Extensions (CMSE), that has been compiled using toolchains that implement 'Arm v8-M Security Extensions Requirements on Development Tools' prior to version 1.4, allows an attacker to pass values to Secure state that are out of range for types smaller than 32-bits. Out of range values might lead to incorrect operations in secure state. (From OE-Core rev: 165a7007678c27b6c0a27cda25652a00768c2fee) Signed-off-by: Mark Hatle <mark.hatle@amd.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/gcc/gcc-13.2.inc1
-rw-r--r--meta/recipes-devtools/gcc/gcc/CVE-2024-0151.patch315
2 files changed, 316 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-13.2.inc b/meta/recipes-devtools/gcc/gcc-13.2.inc
index 603377a49a..abf177822b 100644
--- a/meta/recipes-devtools/gcc/gcc-13.2.inc
+++ b/meta/recipes-devtools/gcc/gcc-13.2.inc
@@ -68,6 +68,7 @@ SRC_URI = "${BASEURI} \
68 file://CVE-2023-4039.patch \ 68 file://CVE-2023-4039.patch \
69 file://0026-aarch64-Fix-loose-ldpstp-check-PR111411.patch \ 69 file://0026-aarch64-Fix-loose-ldpstp-check-PR111411.patch \
70 file://0027-Fix-gcc-vect-module-testcases.patch \ 70 file://0027-Fix-gcc-vect-module-testcases.patch \
71 file://CVE-2024-0151.patch \
71" 72"
72SRC_URI[sha256sum] = "e275e76442a6067341a27f04c5c6b83d8613144004c0413528863dc6b5c743da" 73SRC_URI[sha256sum] = "e275e76442a6067341a27f04c5c6b83d8613144004c0413528863dc6b5c743da"
73 74
diff --git a/meta/recipes-devtools/gcc/gcc/CVE-2024-0151.patch b/meta/recipes-devtools/gcc/gcc/CVE-2024-0151.patch
new file mode 100644
index 0000000000..12883388cb
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/CVE-2024-0151.patch
@@ -0,0 +1,315 @@
1arm: Zero/Sign extends for CMSE security
2
3This patch makes the following changes:
4
51) When calling a secure function from non-secure code then any arguments
6 smaller than 32-bits that are passed in registers are zero- or sign-extended.
72) After a non-secure function returns into secure code then any return value
8 smaller than 32-bits that is passed in a register is zero- or sign-extended.
9
10This patch addresses the following CVE-2024-0151.
11
12gcc/ChangeLog:
13 PR target/114837
14 * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear):
15 Add zero/sign extend.
16 (arm_expand_prologue): Add zero/sign extend.
17
18gcc/testsuite/ChangeLog:
19
20 * gcc.target/arm/cmse/extend-param.c: New test.
21 * gcc.target/arm/cmse/extend-return.c: New test.
22
23CVE: CVE-2024-0151
24Upstream-Status: Backport [https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649973.html]
25Signed-off-by: Mark Hatle <mark.hatle@amd.com>
26
27diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
28index 0217abc218d60956ce727e6d008d46b9176dddc5..ea0c963a4d67ecd70e1571624e84dfe46d757df9 100644
29--- a/gcc/config/arm/arm.cc
30+++ b/gcc/config/arm/arm.cc
31@@ -19210,6 +19210,30 @@ cmse_nonsecure_call_inline_register_clear (void)
32 end_sequence ();
33 emit_insn_before (seq, insn);
34
35+ /* The AAPCS requires the callee to widen integral types narrower
36+ than 32 bits to the full width of the register; but when handling
37+ calls to non-secure space, we cannot trust the callee to have
38+ correctly done so. So forcibly re-widen the result here. */
39+ tree ret_type = TREE_TYPE (fntype);
40+ if ((TREE_CODE (ret_type) == INTEGER_TYPE
41+ || TREE_CODE (ret_type) == ENUMERAL_TYPE
42+ || TREE_CODE (ret_type) == BOOLEAN_TYPE)
43+ && known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 4))
44+ {
45+ machine_mode ret_mode = TYPE_MODE (ret_type);
46+ rtx extend;
47+ if (TYPE_UNSIGNED (ret_type))
48+ extend = gen_rtx_ZERO_EXTEND (SImode,
49+ gen_rtx_REG (ret_mode, R0_REGNUM));
50+ else
51+ extend = gen_rtx_SIGN_EXTEND (SImode,
52+ gen_rtx_REG (ret_mode, R0_REGNUM));
53+ emit_insn_after (gen_rtx_SET (gen_rtx_REG (SImode, R0_REGNUM),
54+ extend), insn);
55+
56+ }
57+
58+
59 if (TARGET_HAVE_FPCXT_CMSE)
60 {
61 rtx_insn *last, *pop_insn, *after = insn;
62@@ -23652,6 +23676,51 @@ arm_expand_prologue (void)
63
64 ip_rtx = gen_rtx_REG (SImode, IP_REGNUM);
65
66+ /* The AAPCS requires the callee to widen integral types narrower
67+ than 32 bits to the full width of the register; but when handling
68+ calls to non-secure space, we cannot trust the callee to have
69+ correctly done so. So forcibly re-widen the result here. */
70+ if (IS_CMSE_ENTRY (func_type))
71+ {
72+ function_args_iterator args_iter;
73+ CUMULATIVE_ARGS args_so_far_v;
74+ cumulative_args_t args_so_far;
75+ bool first_param = true;
76+ tree arg_type;
77+ tree fndecl = current_function_decl;
78+ tree fntype = TREE_TYPE (fndecl);
79+ arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl);
80+ args_so_far = pack_cumulative_args (&args_so_far_v);
81+ FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
82+ {
83+ rtx arg_rtx;
84+
85+ if (VOID_TYPE_P (arg_type))
86+ break;
87+
88+ function_arg_info arg (arg_type, /*named=*/true);
89+ if (!first_param)
90+ /* We should advance after processing the argument and pass
91+ the argument we're advancing past. */
92+ arm_function_arg_advance (args_so_far, arg);
93+ first_param = false;
94+ arg_rtx = arm_function_arg (args_so_far, arg);
95+ gcc_assert (REG_P (arg_rtx));
96+ if ((TREE_CODE (arg_type) == INTEGER_TYPE
97+ || TREE_CODE (arg_type) == ENUMERAL_TYPE
98+ || TREE_CODE (arg_type) == BOOLEAN_TYPE)
99+ && known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 4))
100+ {
101+ if (TYPE_UNSIGNED (arg_type))
102+ emit_set_insn (gen_rtx_REG (SImode, REGNO (arg_rtx)),
103+ gen_rtx_ZERO_EXTEND (SImode, arg_rtx));
104+ else
105+ emit_set_insn (gen_rtx_REG (SImode, REGNO (arg_rtx)),
106+ gen_rtx_SIGN_EXTEND (SImode, arg_rtx));
107+ }
108+ }
109+ }
110+
111 if (IS_STACKALIGN (func_type))
112 {
113 rtx r0, r1;
114diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-param.c b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c
115new file mode 100644
116index 0000000000000000000000000000000000000000..01fac7862385f871f3ecc246ede95eea180be025
117--- /dev/null
118+++ b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c
119@@ -0,0 +1,96 @@
120+/* { dg-do compile } */
121+/* { dg-options "-mcmse" } */
122+/* { dg-final { check-function-bodies "**" "" "" } } */
123+
124+#include <arm_cmse.h>
125+#include <stdbool.h>
126+
127+#define ARRAY_SIZE (256)
128+char array[ARRAY_SIZE];
129+
130+enum offset
131+{
132+ zero = 0,
133+ one = 1,
134+ two = 2
135+};
136+
137+/*
138+**__acle_se_unsignSecureFunc:
139+** ...
140+** uxtb r0, r0
141+** ...
142+*/
143+__attribute__((cmse_nonsecure_entry)) char unsignSecureFunc (unsigned char index) {
144+ if (index >= ARRAY_SIZE)
145+ return 0;
146+ return array[index];
147+}
148+
149+/*
150+**__acle_se_signSecureFunc:
151+** ...
152+** sxtb r0, r0
153+** ...
154+*/
155+__attribute__((cmse_nonsecure_entry)) char signSecureFunc (signed char index) {
156+ if (index >= ARRAY_SIZE)
157+ return 0;
158+ return array[index];
159+}
160+
161+/*
162+**__acle_se_shortUnsignSecureFunc:
163+** ...
164+** uxth r0, r0
165+** ...
166+*/
167+__attribute__((cmse_nonsecure_entry)) char shortUnsignSecureFunc (unsigned short index) {
168+ if (index >= ARRAY_SIZE)
169+ return 0;
170+ return array[index];
171+}
172+
173+/*
174+**__acle_se_shortSignSecureFunc:
175+** ...
176+** sxth r0, r0
177+** ...
178+*/
179+__attribute__((cmse_nonsecure_entry)) char shortSignSecureFunc (signed short index) {
180+ if (index >= ARRAY_SIZE)
181+ return 0;
182+ return array[index];
183+}
184+
185+/*
186+**__acle_se_enumSecureFunc:
187+** ...
188+** uxtb r0, r0
189+** ...
190+*/
191+__attribute__((cmse_nonsecure_entry)) char enumSecureFunc (enum offset index) {
192+
193+ // Compiler may optimize away bounds check as value is an unsigned char.
194+
195+ // According to AAPCS caller will zero extend to ensure value is < 256.
196+
197+ if (index >= ARRAY_SIZE)
198+ return 0;
199+ return array[index];
200+
201+}
202+
203+/*
204+**__acle_se_boolSecureFunc:
205+** ...
206+** uxtb r0, r0
207+** ...
208+*/
209+__attribute__((cmse_nonsecure_entry)) char boolSecureFunc (bool index) {
210+
211+ if (index >= ARRAY_SIZE)
212+ return 0;
213+ return array[index];
214+
215+}
216\ No newline at end of file
217diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c
218new file mode 100644
219index 0000000000000000000000000000000000000000..cf731ed33df7e6dc101320c1970016f01b14c59a
220--- /dev/null
221+++ b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c
222@@ -0,0 +1,92 @@
223+/* { dg-do compile } */
224+/* { dg-options "-mcmse" } */
225+/* { dg-final { check-function-bodies "**" "" "" } } */
226+
227+#include <arm_cmse.h>
228+#include <stdbool.h>
229+
230+enum offset
231+{
232+ zero = 0,
233+ one = 1,
234+ two = 2
235+};
236+
237+typedef unsigned char __attribute__ ((cmse_nonsecure_call)) ns_unsign_foo_t (void);
238+typedef signed char __attribute__ ((cmse_nonsecure_call)) ns_sign_foo_t (void);
239+typedef unsigned short __attribute__ ((cmse_nonsecure_call)) ns_short_unsign_foo_t (void);
240+typedef signed short __attribute__ ((cmse_nonsecure_call)) ns_short_sign_foo_t (void);
241+typedef enum offset __attribute__ ((cmse_nonsecure_call)) ns_enum_foo_t (void);
242+typedef bool __attribute__ ((cmse_nonsecure_call)) ns_bool_foo_t (void);
243+
244+/*
245+**unsignNonsecure0:
246+** ...
247+** bl __gnu_cmse_nonsecure_call
248+** uxtb r0, r0
249+** ...
250+*/
251+unsigned char unsignNonsecure0 (ns_unsign_foo_t * ns_foo_p)
252+{
253+ return ns_foo_p ();
254+}
255+
256+/*
257+**signNonsecure0:
258+** ...
259+** bl __gnu_cmse_nonsecure_call
260+** sxtb r0, r0
261+** ...
262+*/
263+signed char signNonsecure0 (ns_sign_foo_t * ns_foo_p)
264+{
265+ return ns_foo_p ();
266+}
267+
268+/*
269+**shortUnsignNonsecure0:
270+** ...
271+** bl __gnu_cmse_nonsecure_call
272+** uxth r0, r0
273+** ...
274+*/
275+unsigned short shortUnsignNonsecure0 (ns_short_unsign_foo_t * ns_foo_p)
276+{
277+ return ns_foo_p ();
278+}
279+
280+/*
281+**shortSignNonsecure0:
282+** ...
283+** bl __gnu_cmse_nonsecure_call
284+** sxth r0, r0
285+** ...
286+*/
287+signed short shortSignNonsecure0 (ns_short_sign_foo_t * ns_foo_p)
288+{
289+ return ns_foo_p ();
290+}
291+
292+/*
293+**enumNonsecure0:
294+** ...
295+** bl __gnu_cmse_nonsecure_call
296+** uxtb r0, r0
297+** ...
298+*/
299+unsigned char __attribute__((noipa)) enumNonsecure0 (ns_enum_foo_t * ns_foo_p)
300+{
301+ return ns_foo_p ();
302+}
303+
304+/*
305+**boolNonsecure0:
306+** ...
307+** bl __gnu_cmse_nonsecure_call
308+** uxtb r0, r0
309+** ...
310+*/
311+unsigned char boolNonsecure0 (ns_bool_foo_t * ns_foo_p)
312+{
313+ return ns_foo_p ();
314+}
315\ No newline at end of file