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

            Bug ID: 127949
           Summary: -fhardened overrides an explicit
                    -fno-stack-clash-protection
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mark at markesler dot com
  Target Milestone: ---

Created attachment 65873
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65873&action=edit
Fix: test OPTION_SET_P instead of the flag value

The manual says -fhardened "only enables a particular option if it wasn't
already specified anywhere on the command line." For -fstack-clash-protection
it does not: an explicit -fno-stack-clash-protection is ignored, in either
argument order, without a warning.

    $ cat t.c
    void g(volatile char *);
    void f(void) { volatile char big[1 << 20]; g(big); }
    $ gcc -O2 -fno-stack-clash-protection -S -o - t.c | grep -c 'orb.*(%rsp)'
    0
    $ gcc -O2 -fhardened -fno-stack-clash-protection -S -o - t.c | grep -c
'orb.*(%rsp)'
    1

t.c includes no headers, so it is its own preprocessed source.

Expected: no stack probes, as without -fhardened.
Actual: the probe loop (subq $4096, %rsp; orb $0, (%rsp)) is emitted.

This affects every release with -fhardened (GCC 14, 15 and 16) as well as
trunk, on x86_64 (also -m32, C++, -flto) and aarch64. Distributions that add
-fhardened by default leave packages no way to turn stack clash protection off.

The cause is in process_options (toplev.cc), which tests the flag's value
rather than whether it was given:

    if (!flag_stack_clash_protection
        && flag_stack_check == NO_STACK_CHECK)
      flag_stack_clash_protection = 1;

PR 114606 fixed the same pattern for -fcf-protection.

Attached are two patches. The first tests OPTION_SET_P
(flag_stack_clash_protection) instead, with three tests. The second adds the
-Whardened warning that -fno-stack-protector and
-ftrivial-auto-var-init=uninitialized already give, with two tests. Both were
bootstrapped and regression-tested on x86_64-pc-linux-gnu against d871a07, with
no new failures.

    $ gcc -v
    Using built-in specs.
    COLLECT_GCC=/data/gcc-trunk-d871a07/inst/bin/gcc
   
COLLECT_LTO_WRAPPER=/data/gcc-trunk-d871a07/inst/libexec/gcc/x86_64-pc-linux-gnu/17.0.0/lto-wrapper
    Target: x86_64-pc-linux-gnu
    Configured with: ../src/configure --prefix=/data/gcc-trunk-d871a07/inst
--disable-bootstrap --enable-languages=c,c++ --disable-multilib
    Thread model: posix
    Supported LTO compression algorithms: zlib zstd
    gcc version 17.0.0 20261015 (experimental) (GCC) 

Thanks.

Reply via email to