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

            Bug ID: 128282
           Summary: cfgexpand: expand_stack_vars omits ASan redzone and
                    shadow poisoning for over-aligned fixed-size locals
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: 220255623 at seu dot edu.cn, dodji at gcc dot gnu.org,
                    dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org,
                    jianhao.xu at seu dot edu.cn, kcc at gcc dot gnu.org
  Target Milestone: ---
            Target: aarch64-*-*, riscv64-*-*, loongarch64-*-*

Summary
-------
Under `-fsanitize=address`, fixed-size local variables whose alignment exceeds
`MAX_SUPPORTED_STACK_ALIGNMENT` (16 bytes on AArch64, RISC-V, and LoongArch)
receive no ASan redzone padding and no shadow-memory poisoning.

In `gcc/cfgexpand.cc:1525-1648` (`expand_stack_vars`), when
`alignb * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT`, the variable is
allocated via the `large_alloc` arm (`allocate_dynamic_stack_space`). While
HWASan explicitly hooks this arm (`hwasan_record_stack_var` at line 1626),
ASan has no hook in this branch: the variable is never pushed onto
`data->asan_vec` or `data->asan_decl_vec`.

Consequently, any local buffer declared with `alignas(32)` or
`__attribute__((aligned(64)))` on AArch64, RISC-V, or LoongArch has all of its
stack shadow bytes left at `0` (addressable), and stack buffer overflows out of
that buffer are silently missed at runtime.

Reproducer
----------
$ cat trigger.c
__attribute__((noinline)) void over_aligned(int i) {
    volatile char buf[64] __attribute__((aligned(64)));
    buf[i] = 0x41;
}

__attribute__((noinline)) void normal(int i) {
    volatile char buf[64];
    buf[i] = 0x41;
}

Compile flag: aarch64-linux-gnu-gcc -O1 -fsanitize=address -S trigger.c

$ cat trigger.s
over_aligned:
        stp     x29, x30, [sp, -16]!
        mov     x29, sp
        sub     sp, sp, #128
        add     x1, sp, 63
        and     x1, x1, -64             # dynamically aligned in frame, ZERO
shadow poisoning!
        ...
        strb    w2, [x1]
        mov     sp, x29
        ldp     x29, x30, [sp], 16
        ret

normal:
        ...
        mov     w4, -235802127          # 0xf1f1f1f1 left redzone poisoned
        mov     w3, -202116109          # 0xf3f3f3f3 right redzone poisoned

Suggested Fix
-------------
Record over-aligned fixed-size locals for ASan redzone allocation and shadow
poisoning in the `alignb * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT` arm
of `expand_stack_vars` (`gcc/cfgexpand.cc:1602-1648`), mirroring
`hwasan_record_stack_var`.

Reply via email to