[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #10 from James Addison --- Hi folks, Re-stating and confirming the bugreport details here: both gcc-11 (11.3.0) and gcc-12 (12.2.0) emit bytecode instructions that aren't supported on all i686-architecture CPUs. This comment includes a demonstration/repro case to help verify the problem and potential fixes, along with a suggested remediation approach that is a small adjustment of Adrian's original suggestion. As a recap, partly for my own understanding: the 'endbr32' instruction required to implement Intel Control-flow Enforcement Technology (aka Intel CET) is a renaming and repurposing of an existing long-NOP (aka NOPL) instruction that was not documented in the original Pentium Pro specification and therefore is not supported on all i686-class CPUs. ### Version information $ gcc-11 --version gcc-11 (Debian 11.3.0-12) 11.3.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gcc-12 --version gcc-12 (Debian 12.2.0-14) 12.2.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ objdump --version GNU objdump (GNU Binutils for Debian) 2.40 Copyright (C) 2023 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) any later version. This program has absolutely no warranty. ### Replicating the problem $ cat repro.c int main() {} $ for prot in full branch return none check; do gcc-11 -m32 -march=i686 -fcf-protection=$prot -c repro.c -o gcc-11-$prot.o; gcc-12 -m32 -march=i686 -fcf-protection=$prot -c repro.c -o gcc-12-$prot.o; done; ### Checking the results $ for binary in gcc-*.o; do echo $binary; objdump -d $binary | grep -w endbr32 ; done; gcc-11-branch.o 0: f3 0f 1e fb endbr32 gcc-11-check.o gcc-11-full.o 0: f3 0f 1e fb endbr32 gcc-11-none.o gcc-11-return.o gcc-12-branch.o 0: f3 0f 1e fb endbr32 gcc-12-check.o gcc-12-full.o 0: f3 0f 1e fb endbr32 gcc-12-none.o gcc-12-return.o ### Remedy Please could GCC be updated to reject attempts to build binaries for the i686 architecture when fcf-protection is configured to -- or implied to include -- 'branch' protection? Values for the fcf-protection flag were sourced from the GCC documentation at: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fcf-protection (as noted: this does duplicate some of the original bugreport's suggestion, but is intended to be slightly more granular because I believe it's important to note that not all fcf-protection values are unsupported by the i686 architecture)
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 James Addison changed: What|Removed |Added CC||jay+g...@jp-hosting.net --- Comment #9 from James Addison --- (In reply to James Addison from comment #7) > Something that's unclear to me is whether fcf-protection requires NOPL > (multi-byte NOP). I understand that it requires endbr32. (and now I also understand that the endbr32 instruction is a repurposing of a previously-existing long-NOP - and that it's required to implement fcf-protection, aka Intel CET)
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #8 from James Addison --- (In reply to James Addison from comment #7) > (In reply to Adrian Bunk from comment #6) > > (In reply to James Addison from comment #5) > > > Could the findings indicate that there are two bugs here? > > > > > > - The Geode LX target capable of supporting fcf-protection but GCC-11 > > > currently rejects that architecture and flag combination > > > > The problem is the opposite. > > Ok, thank you. > > Something that's unclear to me is whether fcf-protection requires NOPL > (multi-byte NOP). I understand that it requires endbr32. > > Was my second statement (re: GCC-11 emitting NOPL for i686) correct? I haven't been able to replicate generation of NOPL instructions using GCC-11 (with GNU binutils); my apologies for the distraction.
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #7 from James Addison --- (In reply to Adrian Bunk from comment #6) > (In reply to James Addison from comment #5) > > Could the findings indicate that there are two bugs here? > > > > - The Geode LX target capable of supporting fcf-protection but GCC-11 > > currently rejects that architecture and flag combination > > The problem is the opposite. Ok, thank you. Something that's unclear to me is whether fcf-protection requires NOPL (multi-byte NOP). I understand that it requires endbr32. Was my second statement (re: GCC-11 emitting NOPL for i686) correct?
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #6 from Adrian Bunk --- (In reply to James Addison from comment #5) > Could the findings indicate that there are two bugs here? > > - The Geode LX target capable of supporting fcf-protection but GCC-11 > currently rejects that architecture and flag combination The problem is the opposite.
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 James Addison changed: What|Removed |Added CC||jay+g...@jp-hosting.net --- Comment #5 from James Addison --- Adrian wrote: > To support the Geode in OLPC, the toolchain definition of i686 does include > CMOV but it does not include multi-byte NOPs. ... > Sorry for being unclear, this is the historical reason why the binutils/gcc > definition of i686 does not include multi-byte NOPs. Jakub wrote: > Just build for those as -march=i586. preventing -fcf-protection with > -march=i686 would be a really bad idea, that would basically prevent all of > CET protection for 32-bit code, i686 is what is used as the supported lowest > common denominator of 32-bit code. Could the findings indicate that there are two bugs here? - The Geode LX target capable of supporting fcf-protection but GCC-11 currently rejects that architecture and flag combination (in the potentially-buggy code[1] that Adrian refers to) - Multi-byte NOPs are emitted for architecture i686 by GCC-11, despite some CPUs within that architecture lacking[2] support Also potentially relevant is bug 41989. [1] - https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/i386/i386-options.cc;h=805539364108eee07f5bda527acd6f39f3f7bf95;hb=HEAD#l2929 [2] - https://bugzilla.redhat.com/show_bug.cgi?id=579838#c32
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #4 from Adrian Bunk --- (In reply to Jakub Jelinek from comment #3) > Just build for those as -march=i586. There is no "for those" in Debian. There is one build of all packages for one i386 Debian release architecture. Building the Debian i386 architecture with -march=i586 would also remove CMOV support. > i686 is what is used as the supported lowest > common denominator of 32-bit code. This is not true. The lowest common denominator of 32-bit x86 code on Linux is -march=i486, since the 486 is the lowest supported CPU in the kernel. Distributions usually use various baselines higher than 486 for their 32-bit x86 ports. E.g. for distributions dropping support for actual 32-bit hardware (keeping only multiarch/multilib support), using -march=x86-64 (or whatever higher they are using for their 64bit x86) might make more sense since it also brings MMX/SSE/SSE2 which are not in -march=i686 (this also allows using SSE instead of the x87 FPU with its excess precision oddity). > preventing -fcf-protection with > -march=i686 would be a really bad idea, that would basically prevent all of > CET protection for 32-bit code, The toolchain emitting instructions not supported by the selected target is also a really bad idea. gcc rejecting -fcf-protection for < 686 indicates that this option was not intended to enable emitting instructions not already supported by the -march setting. The proper solution might be a -mmultibyte-nops option?
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #3 from Jakub Jelinek --- Just build for those as -march=i586. preventing -fcf-protection with -march=i686 would be a really bad idea, that would basically prevent all of CET protection for 32-bit code, i686 is what is used as the supported lowest common denominator of 32-bit code.
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #2 from Adrian Bunk --- (In reply to Andrew Pinski from comment #1) > Is OLPC really still around? I thought it died when Google came out with > their chrome books. Sorry for being unclear, this is the historical reason why the binutils/gcc definition of i686 does not include multi-byte NOPs. While all 32bit x86 hardware is pretty dated in the year 2022, there is still a surprisingly large number of users of 32bit x86 including like in the case of this Debian bug on a (likely non-OLPC) Geode. The Debian i386 port has the toolchain configured for i686, and it is therefore a problem that due to this gcc bug an autoconf test for -fcf-protection succeeds.
[Bug target/104713] gcc does not reject -march=i686 -fcf-protection
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104713 --- Comment #1 from Andrew Pinski --- Is OLPC really still around? I thought it died when Google came out with their chrome books.