From: Mark Hatle <mark.ha...@amd.com>

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.

Signed-off-by: Mark Hatle <mark.ha...@amd.com>
Signed-off-by: Steve Sakoman <st...@sakoman.com>
---
 meta/recipes-devtools/gcc/gcc-13.2.inc        |   1 +
 .../gcc/gcc/CVE-2024-0151.patch               | 315 ++++++++++++++++++
 2 files changed, 316 insertions(+)
 create mode 100644 meta/recipes-devtools/gcc/gcc/CVE-2024-0151.patch

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} \
            file://CVE-2023-4039.patch \
            file://0026-aarch64-Fix-loose-ldpstp-check-PR111411.patch \
            file://0027-Fix-gcc-vect-module-testcases.patch \
+           file://CVE-2024-0151.patch \
 "
 SRC_URI[sha256sum] = 
"e275e76442a6067341a27f04c5c6b83d8613144004c0413528863dc6b5c743da"
 
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 @@
+arm: Zero/Sign extends for CMSE security
+
+This patch makes the following changes:
+
+1) When calling a secure function from non-secure code then any arguments
+   smaller than 32-bits that are passed in registers are zero- or 
sign-extended.
+2) After a non-secure function returns into secure code then any return value
+   smaller than 32-bits that is passed in a register is  zero- or 
sign-extended.
+
+This patch addresses the following CVE-2024-0151.
+
+gcc/ChangeLog:
+        PR target/114837
+        * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear):
+          Add zero/sign extend.
+        (arm_expand_prologue): Add zero/sign extend.
+
+gcc/testsuite/ChangeLog:
+
+        * gcc.target/arm/cmse/extend-param.c: New test.
+        * gcc.target/arm/cmse/extend-return.c: New test.
+
+CVE: CVE-2024-0151
+Upstream-Status: Backport 
[https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649973.html]
+Signed-off-by: Mark Hatle <mark.ha...@amd.com>
+
+diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
+index 
0217abc218d60956ce727e6d008d46b9176dddc5..ea0c963a4d67ecd70e1571624e84dfe46d757df9
 100644
+--- a/gcc/config/arm/arm.cc
++++ b/gcc/config/arm/arm.cc
+@@ -19210,6 +19210,30 @@ cmse_nonsecure_call_inline_register_clear (void)
+         end_sequence ();
+         emit_insn_before (seq, insn);
+ 
++        /* The AAPCS requires the callee to widen integral types narrower
++           than 32 bits to the full width of the register; but when handling
++           calls to non-secure space, we cannot trust the callee to have
++           correctly done so.  So forcibly re-widen the result here.  */
++        tree ret_type = TREE_TYPE (fntype);
++        if ((TREE_CODE (ret_type) == INTEGER_TYPE
++            || TREE_CODE (ret_type) == ENUMERAL_TYPE
++            || TREE_CODE (ret_type) == BOOLEAN_TYPE)
++            && known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 4))
++          {
++            machine_mode ret_mode = TYPE_MODE (ret_type);
++            rtx extend;
++            if (TYPE_UNSIGNED (ret_type))
++              extend = gen_rtx_ZERO_EXTEND (SImode,
++                                            gen_rtx_REG (ret_mode, 
R0_REGNUM));
++            else
++              extend = gen_rtx_SIGN_EXTEND (SImode,
++                                            gen_rtx_REG (ret_mode, 
R0_REGNUM));
++            emit_insn_after (gen_rtx_SET (gen_rtx_REG (SImode, R0_REGNUM),
++                                           extend), insn);
++
++          }
++
++
+         if (TARGET_HAVE_FPCXT_CMSE)
+           {
+             rtx_insn *last, *pop_insn, *after = insn;
+@@ -23652,6 +23676,51 @@ arm_expand_prologue (void)
+ 
+   ip_rtx = gen_rtx_REG (SImode, IP_REGNUM);
+ 
++  /* The AAPCS requires the callee to widen integral types narrower
++     than 32 bits to the full width of the register; but when handling
++     calls to non-secure space, we cannot trust the callee to have
++     correctly done so.  So forcibly re-widen the result here.  */
++  if (IS_CMSE_ENTRY (func_type))
++    {
++      function_args_iterator args_iter;
++      CUMULATIVE_ARGS args_so_far_v;
++      cumulative_args_t args_so_far;
++      bool first_param = true;
++      tree arg_type;
++      tree fndecl = current_function_decl;
++      tree fntype = TREE_TYPE (fndecl);
++      arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl);
++      args_so_far = pack_cumulative_args (&args_so_far_v);
++      FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
++      {
++        rtx arg_rtx;
++
++        if (VOID_TYPE_P (arg_type))
++          break;
++
++        function_arg_info arg (arg_type, /*named=*/true);
++        if (!first_param)
++          /* We should advance after processing the argument and pass
++             the argument we're advancing past.  */
++          arm_function_arg_advance (args_so_far, arg);
++        first_param = false;
++        arg_rtx = arm_function_arg (args_so_far, arg);
++        gcc_assert (REG_P (arg_rtx));
++        if ((TREE_CODE (arg_type) == INTEGER_TYPE
++            || TREE_CODE (arg_type) == ENUMERAL_TYPE
++            || TREE_CODE (arg_type) == BOOLEAN_TYPE)
++            && known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 4))
++          {
++            if (TYPE_UNSIGNED (arg_type))
++              emit_set_insn (gen_rtx_REG (SImode, REGNO (arg_rtx)),
++                             gen_rtx_ZERO_EXTEND (SImode, arg_rtx));
++            else
++              emit_set_insn (gen_rtx_REG (SImode, REGNO (arg_rtx)),
++                             gen_rtx_SIGN_EXTEND (SImode, arg_rtx));
++          }
++      }
++    }
++
+   if (IS_STACKALIGN (func_type))
+     {
+       rtx r0, r1;
+diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-param.c 
b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c
+new file mode 100644
+index 
0000000000000000000000000000000000000000..01fac7862385f871f3ecc246ede95eea180be025
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c
+@@ -0,0 +1,96 @@
++/* { dg-do compile } */
++/* { dg-options "-mcmse" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include <arm_cmse.h>
++#include <stdbool.h>
++
++#define ARRAY_SIZE (256)
++char array[ARRAY_SIZE];
++
++enum offset
++{
++    zero = 0,
++    one = 1,
++    two = 2
++};
++
++/*
++**__acle_se_unsignSecureFunc:
++**    ...
++**    uxtb    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char unsignSecureFunc (unsigned char 
index) {
++    if (index >= ARRAY_SIZE)
++      return 0;
++    return array[index];
++}
++
++/*
++**__acle_se_signSecureFunc:
++**    ...
++**    sxtb    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char signSecureFunc (signed char index) 
{
++    if (index >= ARRAY_SIZE)
++      return 0;
++    return array[index];
++}
++
++/*
++**__acle_se_shortUnsignSecureFunc:
++**    ...
++**    uxth    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char shortUnsignSecureFunc (unsigned 
short index) {
++    if (index >= ARRAY_SIZE)
++      return 0;
++    return array[index];
++}
++
++/*
++**__acle_se_shortSignSecureFunc:
++**    ...
++**    sxth    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char shortSignSecureFunc (signed short 
index) {
++    if (index >= ARRAY_SIZE)
++      return 0;
++    return array[index];
++}
++
++/*
++**__acle_se_enumSecureFunc:
++**    ...
++**    uxtb    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char enumSecureFunc (enum offset index) 
{
++
++  // Compiler may optimize away bounds check as value is an unsigned char.
++
++  // According to AAPCS caller will zero extend to ensure value is < 256.
++
++  if (index >= ARRAY_SIZE)
++    return 0;
++  return array[index];
++
++}
++
++/*
++**__acle_se_boolSecureFunc:
++**    ...
++**    uxtb    r0, r0
++**    ...
++*/
++__attribute__((cmse_nonsecure_entry)) char boolSecureFunc (bool index) {
++
++  if (index >= ARRAY_SIZE)
++    return 0;
++  return array[index];
++
++}
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c 
b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c
+new file mode 100644
+index 
0000000000000000000000000000000000000000..cf731ed33df7e6dc101320c1970016f01b14c59a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c
+@@ -0,0 +1,92 @@
++/* { dg-do compile } */
++/* { dg-options "-mcmse" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include <arm_cmse.h>
++#include <stdbool.h>
++
++enum offset
++{
++    zero = 0,
++    one = 1,
++    two = 2
++};
++
++typedef unsigned char __attribute__ ((cmse_nonsecure_call)) ns_unsign_foo_t 
(void);
++typedef signed char __attribute__ ((cmse_nonsecure_call)) ns_sign_foo_t 
(void);
++typedef unsigned short __attribute__ ((cmse_nonsecure_call)) 
ns_short_unsign_foo_t (void);
++typedef signed short __attribute__ ((cmse_nonsecure_call)) 
ns_short_sign_foo_t (void);
++typedef enum offset __attribute__ ((cmse_nonsecure_call)) ns_enum_foo_t 
(void);
++typedef bool __attribute__ ((cmse_nonsecure_call)) ns_bool_foo_t (void);
++
++/*
++**unsignNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    uxtb    r0, r0
++**    ...
++*/
++unsigned char unsignNonsecure0 (ns_unsign_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
++
++/*
++**signNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    sxtb    r0, r0
++**    ...
++*/
++signed char signNonsecure0 (ns_sign_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
++
++/*
++**shortUnsignNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    uxth    r0, r0
++**    ...
++*/
++unsigned short shortUnsignNonsecure0 (ns_short_unsign_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
++
++/*
++**shortSignNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    sxth    r0, r0
++**    ...
++*/
++signed short shortSignNonsecure0 (ns_short_sign_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
++
++/*
++**enumNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    uxtb    r0, r0
++**    ...
++*/
++unsigned char __attribute__((noipa)) enumNonsecure0 (ns_enum_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
++
++/*
++**boolNonsecure0:
++**    ...
++**    bl      __gnu_cmse_nonsecure_call
++**    uxtb    r0, r0
++**    ...
++*/
++unsigned char boolNonsecure0 (ns_bool_foo_t * ns_foo_p)
++{
++  return ns_foo_p ();
++}
+\ No newline at end of file
-- 
2.34.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#200104): 
https://lists.openembedded.org/g/openembedded-core/message/200104
Mute This Topic: https://lists.openembedded.org/mt/106425339/21656
Group Owner: openembedded-core+ow...@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to