When -fcf-protection=branch is used, the compiler will generate jump tables where the indirect jump is prefixed with the NOTRACK prefix, so it can jump to non-ENDBR targets. Yet, for NOTRACK prefixes to work, the NOTRACK specific enable bit must be set, what renders the binary broken on any environment where this is not the case. In fact, having NOTRACK disabled was a design choice for the Linux kernel CET support.
Generate jump tables with ENDBR and skip the NOTRACK prefix for indirect jump. Document -mno-cet-switch to turn off CET instrumentation on jump tables for switch statements. gcc/ PR target/104816 * config/i386/i386.opt: Turn on -mcet-switch by default. * doc/invoke.texi: Document -mno-cet-switch. gcc/testsuite/ * gcc.target/i386/cet-switch-1.c: Add -mno-cet-switch. * gcc.target/i386/cet-switch-2.c: Remove -mcet-switch. * gcc.target/i386/cet-switch-3.c: Likewise. --- gcc/config/i386/i386.opt | 2 +- gcc/doc/invoke.texi | 9 ++++++++- gcc/testsuite/gcc.target/i386/cet-switch-1.c | 2 +- gcc/testsuite/gcc.target/i386/cet-switch-2.c | 2 +- gcc/testsuite/gcc.target/i386/cet-switch-3.c | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index a6b0e28f238..96b4a433e44 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1047,7 +1047,7 @@ Enable shadow stack built-in functions from Control-flow Enforcement Technology (CET). mcet-switch -Target Undocumented Var(flag_cet_switch) Init(0) +Target Var(flag_cet_switch) Init(1) Turn on CET instrumentation for switch statements that use a jump table and an indirect jump. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7a35d9613a4..8bb96c5938a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1420,7 +1420,8 @@ See RS/6000 and PowerPC Options. -msse4a -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop @gol -madx -mlzcnt -mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mhle -mlwp @gol -mmwaitx -mclzero -mpku -mthreads -mgfni -mvaes -mwaitpkg @gol --mshstk -mmanual-endbr -mforce-indirect-call -mavx512vbmi2 -mavx512bf16 -menqcmd @gol +-mshstk -mmanual-endbr -mno-cet-switch -mforce-indirect-call @gol +-mavx512vbmi2 -mavx512bf16 -menqcmd @gol -mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq @gol -mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid @gol -mrdseed -msgx -mavx512vp2intersect -mserialize -mtsxldtrk@gol @@ -32641,6 +32642,12 @@ function attribute. This is useful when used with the option @option{-fcf-protection=branch} to control ENDBR insertion at the function entry. +@item -mno-cet-switch +@opindex mno-cet-switch +@opindex mcet-switch +Turn off CET instrumentation for switch statements that use a jump table +and an indirect jump. The default is @option{mcet-switch}. + @item -mcall-ms2sysv-xlogues @opindex mcall-ms2sysv-xlogues @opindex mno-call-ms2sysv-xlogues diff --git a/gcc/testsuite/gcc.target/i386/cet-switch-1.c b/gcc/testsuite/gcc.target/i386/cet-switch-1.c index afe5adc2f3d..4931c3ad1d2 100644 --- a/gcc/testsuite/gcc.target/i386/cet-switch-1.c +++ b/gcc/testsuite/gcc.target/i386/cet-switch-1.c @@ -1,6 +1,6 @@ /* Verify that CET works. */ /* { dg-do compile } */ -/* { dg-options "-O -fcf-protection" } */ +/* { dg-options "-O -fcf-protection -mno-cet-switch" } */ /* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */ /* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */ /* { dg-final { scan-assembler-times "notrack jmp\[ \t]+\[*]" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/cet-switch-2.c b/gcc/testsuite/gcc.target/i386/cet-switch-2.c index 69ddc6fd5b7..11578d1a30c 100644 --- a/gcc/testsuite/gcc.target/i386/cet-switch-2.c +++ b/gcc/testsuite/gcc.target/i386/cet-switch-2.c @@ -1,6 +1,6 @@ /* Verify that CET works. */ /* { dg-do compile } */ -/* { dg-options "-O -fcf-protection -mcet-switch" } */ +/* { dg-options "-O -fcf-protection" } */ /* { dg-final { scan-assembler-times "endbr32" 12 { target ia32 } } } */ /* { dg-final { scan-assembler-times "endbr64" 12 { target { ! ia32 } } } } */ /* { dg-final { scan-assembler-times "\[ \t]+jmp\[ \t]+\[*]" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/cet-switch-3.c b/gcc/testsuite/gcc.target/i386/cet-switch-3.c index 0d9ed4488dd..a4e2e4dfc16 100644 --- a/gcc/testsuite/gcc.target/i386/cet-switch-3.c +++ b/gcc/testsuite/gcc.target/i386/cet-switch-3.c @@ -1,6 +1,6 @@ /* Verify that CET works. */ /* { dg-do compile } */ -/* { dg-options "-O -fcf-protection -mcet-switch" } */ +/* { dg-options "-O -fcf-protection" } */ /* { dg-final { scan-assembler-times "endbr32" 12 { target ia32 } } } */ /* { dg-final { scan-assembler-times "endbr64" 12 { target { ! ia32 } } } } */ /* { dg-final { scan-assembler-times "\[ \t]+jmp\[ \t]+\[*]" 1 } } */ -- 2.35.1