https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102926

            Bug ID: 102926
           Summary: TLS register value is spilled to the stack instead of
                    reloaded from the system register
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ardb at kernel dot org
  Target Milestone: ---
            Target: ARM

The code below uses the hardware TLS register on ARM, and instead of reloading
its value directly from the system register, it spills its value to the stack.
This is suboptimal, and given that the TLS register is being proposed as an
alternative reference for the stack protector canary, it is also a security
concern, as an attacker that controls the stack may be able to control both
sides of the equation in the stack protector check occurring at the end of the
function.

Instead, I would expect any subsequent uses of the thread pointer to simply
issue the MRC again, which doesn't touch memory.

$ cat /tmp/spill.c 

    int foo(int);
    int bar(void)
    {
        int *l = __builtin_thread_pointer();

        return foo(l[0]) + l[1];
    }

$ arm-linux-gnueabihf-gcc -o - -S /tmp/spill.c -O3 -mtp=cp15 -ffixed-r4
-ffixed-r5 -ffixed-r6 -ffixed-r7 -ffixed-r8 -ffixed-r9 -ffixed-r10
-fno-omit-frame-pointer
        .cpu arm10tdmi
        .arch armv5t
        .fpu softvfp
        .eabi_attribute 20, 1
        .eabi_attribute 21, 1
        .eabi_attribute 23, 3
        .eabi_attribute 24, 1
        .eabi_attribute 25, 1
        .eabi_attribute 26, 2
        .eabi_attribute 30, 2
        .eabi_attribute 34, 0
        .eabi_attribute 18, 4
        .file   "spill.c"
        .text
        .align  2
        .global bar
        .syntax unified
        .arm
        .type   bar, %function
bar:
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        push    {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #8
        mrc     p15, 0, r3, c13, c0, 3  @ load_tp_hard
        ldr     r0, [r3]
        str     r3, [fp, #-8]
        bl      foo
        ldr     r3, [fp, #-8]
        ldr     r3, [r3, #4]
        add     r0, r0, r3
        sub     sp, fp, #4
        @ sp needed
        pop     {fp, pc}
        .size   bar, .-bar
        .ident  "GCC: (GNU) 12.0.0 20211024 (experimental)"
        .section        .note.GNU-stack,"",%progbits

Reply via email to