Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-90378

Stack canary stored below RSP due to LTO-optimized cpp_error_at [clone .constprop.0] in arm-none-eabi-gcc-cs on EPEL 10

Linking RHIVOS CVEs to...Migration: Automation ...SWIFT: POC ConversionSync from "Extern...XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not a Bug
    • Icon: Normal Normal
    • None
    • CentOS Stream 10
    • gcc
    • None
    • No
    • Moderate
    • rhel-pt-gcc
    • ssg_platform_tools
    • None
    • False
    • False
    • Hide

      None

      Show
      None
    • None
    • None
    • None
    • None
    • Unspecified
    • Unspecified
    • Unspecified
    • x86_64
    • None

      Description of problem:

      In EPEL 10 (e.g., CentOS Stream 10), an EPEL package(arm-none-eabi-gcc-cs)'s multiple binaries(e.g. arm-none-eabi-cpp) share a function cpp_error_at whose stack canary is stored at [RSP - 0x60], which is outside the function's allocated stack frame. This layout violates standard ABI conventions and suggests an LTO-related misplacement.

      The issue does not occur in Fedora 40 and newer, where RPM_OPT_FLAGS includes -fno-omit-frame-pointer, causing the canary to be correctly stored relative to RBP. However, when the -fno-omit-frame-pointer flag is removed, even Fedora 40 reproduces the issue, indicating the root cause is LTO-triggered constant propagation.

      The faulty instruction (e.g., at 0x0016d130 in arm-none-eabi-cpp) appears in an optimized clone of the function:
      cpp_error_at(cpp_reader*, cpp_diagnostic_level, unsigned int, const char*, ...) [clone .constprop.0]

      Manual attempts to reproduce the bug by building errors.cc in isolation using the same compiler, flags, and environment failed to trigger the faulty code generation. However, analysis of build.log shows that the object file errors.o was later archived into libcpp.a with LTO enabled via liblto_plugin.so, and this static archive was further LTO-linked in later stages, which is the likely root cause.

      This behavior could lead to incorrect assumptions for stack analysis or static analysis tools, and violates the intended behavior of stack canary placement.

      Version-Release number of selected component (if applicable):

      arm-none-eabi-gcc-cs-14.1.0-1.el10_1.x86_64
      (issue also reproducible in older versions on EPEL 10)

      How reproducible:

      Always reproducible in EPEL 10 with default mock or local build using centos-stream-10.

      Steps to Reproduce:

      Build arm-none-eabi-gcc-cs(can be found via
      https://koji.fedoraproject.org/koji/buildinfo?buildID=2665566) in epel-10-x86_64 mock environment (or centos-stream-10).

      Extract binary /usr/bin/arm-none-eabi-cpp from resulting RPM.

      Disassemble it using any disassembler (e.g., Ghidra) and inspect cpp_error_at function.

      Actual results:

      Function cpp_error_at stores stack canary at [RSP - 0x60] outside the allocated stack frame.

      Expected results:

      Stack canary should be stored inside the allocated stack frame, usually at [RBP - offset] or [RSP + offset], following the ABI.

      Additional info:

      The affected function is an LTO-generated constant-propagation variant.

      Root cause seems to stem from cross-object inlining and aggressive constant propagation during static archive (libcpp.a) LTO.

      Removing -fno-omit-frame-pointer in Fedora 40 reproduces the same bug, indicating it is not EPEL-specific, but hidden due to default compiler flags.

      And Full assembly code for cpp_error_at is below:

      0x0016d130: ENDBR64
      0x0016d134: PUSH RAX
      0x0016d135: POP RAX
      0x0016d136: SUB RSP,0x60
      0x0016d13a: MOV qword ptr [RSP + -0x38],R8
      0x0016d13f: MOV qword ptr [RSP + -0x30],R9
      0x0016d144: TEST AL,AL
      0x0016d146: JZ 0x0016d178
      0x0016d148: VMOVAPS xmmword ptr [RSP + -0x28],XMM0
      0x0016d14e: VMOVAPS xmmword ptr [RSP + -0x18],XMM1
      0x0016d154: VMOVAPS xmmword ptr [RSP + -0x8],XMM2
      0x0016d15a: VMOVAPS xmmword ptr [RSP + 0x8],XMM3
      0x0016d160: VMOVAPS xmmword ptr [RSP + 0x18],XMM4
      0x0016d166: VMOVAPS xmmword ptr [RSP + 0x28],XMM5
      0x0016d16c: VMOVAPS xmmword ptr [RSP + 0x38],XMM6
      0x0016d172: VMOVAPS xmmword ptr [RSP + 0x48],XMM7
      0x0016d178: MOV RAX,qword ptr FS:[0x28]
      0x0016d181: MOV qword ptr [RSP + -0x60],RAX
      0x0016d186: XOR EAX,EAX
      0x0016d188: LEA RAX,[RSP + 0x68]
      0x0016d18d: MOV dword ptr [RSP + -0x78],0x20
      0x0016d195: MOV qword ptr [RSP + -0x70],RAX
      0x0016d19a: LEA RAX,[RSP + -0x58]
      0x0016d19f: MOV dword ptr [RSP + -0x74],0x30
      0x0016d1a7: MOV qword ptr [RSP + -0x68],RAX
      0x0016d1ac: MOV RAX,qword ptr [0x00000028]
      0x0016d1b4: UD2

              sst-pt-gcc-issues SST PT GCC Bot
              zjy-dev 景耀 张 (Inactive)
              SST PT GCC Bot SST PT GCC Bot
              Vaclav Kadlcik Vaclav Kadlcik
              Votes:
              0 Vote for this issue
              Watchers:
              9 Start watching this issue

                Created:
                Updated:
                Resolved: