diff options
-rw-r--r-- | gcc/config/i386/i386.c | 47 | ||||
-rw-r--r-- | gcc/config/i386/i386.opt | 4 | ||||
-rw-r--r-- | gcc/config/i386/linux-common.h | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-1.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-2.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-3.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-4.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-5.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81842-6.c | 9 |
9 files changed, 203 insertions, 3 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 35037434bf5..feeb533056e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2679,6 +2679,39 @@ rest_of_insert_endbranch (void) return 0; } +/* Check if FNDECL is a ucontext function. */ + +void +ix86_check_ucontext_function_reference (location_t loc, + tree fndecl) +{ + if (!ix86_check_ucontext_functions + || !TARGET_SHSTK + || !DECL_FILE_SCOPE_P (fndecl) + || !TREE_PUBLIC (fndecl)) + return; + + /* For instrumentation clones, we want to derive flags from the + original name. */ + cgraph_node *node = cgraph_node::get (fndecl); + if (node && node->instrumentation_clone) + fndecl = node->orig_decl; + + tree name_decl = DECL_NAME (fndecl); + if (name_decl + && (IDENTIFIER_LENGTH (name_decl) == 10 + || IDENTIFIER_LENGTH (name_decl) == 11)) + { + const char *name = IDENTIFIER_POINTER (name_decl); + + if (! strcmp (name, "getcontext") + || ! strcmp (name, "setcontext") + || ! strcmp (name, "makecontext") + || ! strcmp (name, "swapcontext")) + error_at (loc, "%qE cannot be used with -mshstk", fndecl); + } +} + namespace { const pass_data pass_data_insert_endbranch = @@ -18117,10 +18150,18 @@ ix86_print_operand (FILE *file, rtx x, int code) } if (CONST_INT_P (x)) fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); - else if (flag_pic || MACHOPIC_INDIRECT) - output_pic_addr_const (file, x, code); else - output_addr_const (file, x); + { + if (GET_CODE (x) == SYMBOL_REF + && SYMBOL_REF_DECL (x) + && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL) + ix86_check_ucontext_function_reference (input_location, + SYMBOL_REF_DECL (x)); + if (flag_pic || MACHOPIC_INDIRECT) + output_pic_addr_const (file, x, code); + else + output_addr_const (file, x); + } } } diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 04e391d311d..13b9697ba7e 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1005,6 +1005,10 @@ Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags2) Save Specifically enables an shadow stack support feature from Control-flow Enforcment Technology (CET). +mcheck-ucontext-functions +Target Report Var(ix86_check_ucontext_functions) Init(1) +Check references to ucontext functions. + mcet-switch Target Report Undocumented Var(flag_cet_switch) Init(0) Turn on CET instrumentation for switch statements, which use jump table and diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h index 6613807180e..5dff543ab76 100644 --- a/gcc/config/i386/linux-common.h +++ b/gcc/config/i386/linux-common.h @@ -126,3 +126,20 @@ extern void file_end_indicate_exec_stack_and_cet (void); #undef TARGET_ASM_FILE_END #define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet + +#if !defined USED_FOR_TARGET && !defined GENERATOR_FILE +#include "input.h" + +extern void ix86_check_ucontext_function_reference (location_t, tree); + +#undef ASM_OUTPUT_EXTERNAL +#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ + do \ + { \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + ix86_check_ucontext_function_reference (UNKNOWN_LOCATION,\ + DECL); \ + default_elf_asm_output_external (FILE, DECL, NAME); \ + } \ + while (0) +#endif diff --git a/gcc/testsuite/gcc.target/i386/pr81842-1.c b/gcc/testsuite/gcc.target/i386/pr81842-1.c new file mode 100644 index 00000000000..bd6bf775625 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet" } */ + +#include <ucontext.h> + +int +func1 (ucontext_t *ucp) +{ + return getcontext (ucp); /* { dg-error "'getcontext' cannot be used with -mshstk" } */ +} + +int +func2 (const ucontext_t *ucp) +{ + return setcontext (ucp); /* { dg-error "'setcontext' cannot be used with -mshstk" } */ +} + +int +func3 (ucontext_t *oucp, const ucontext_t *ucp) +{ + return swapcontext (oucp, ucp); /* { dg-error "'swapcontext' cannot be used with -mshstk" } */ +} + +void +func4 (ucontext_t *ucp, void (*func) (void)) +{ + makecontext (ucp, func, 0); /* { dg-error "'makecontext' cannot be used with -mshstk" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr81842-2.c b/gcc/testsuite/gcc.target/i386/pr81842-2.c new file mode 100644 index 00000000000..202b1aa1888 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-2.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */ + +#include <ucontext.h> + +int +func1 (ucontext_t *ucp) +{ + return getcontext (ucp); +} + +int +func2 (const ucontext_t *ucp) +{ + return setcontext (ucp); +} + +int +func3 (ucontext_t *oucp, const ucontext_t *ucp) +{ + return swapcontext (oucp, ucp); +} + +void +func4 (ucontext_t *ucp, void (*func) (void)) +{ + makecontext (ucp, func, 0); +} diff --git a/gcc/testsuite/gcc.target/i386/pr81842-3.c b/gcc/testsuite/gcc.target/i386/pr81842-3.c new file mode 100644 index 00000000000..f98a8b56a71 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-3.c @@ -0,0 +1,32 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet" } */ + +#include <ucontext.h> + +void * +func1 (void) +{ + return getcontext; +} + +void * +func2 (void) +{ + return setcontext; +} + +void * +func3 (void) +{ + return swapcontext; +} + +void * +func4 (void) +{ + return makecontext; +} +/* { dg-error "'getcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'setcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'swapcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'makecontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81842-4.c b/gcc/testsuite/gcc.target/i386/pr81842-4.c new file mode 100644 index 00000000000..d4d1dce1311 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-4.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */ + +#include <ucontext.h> + +void * +func1 (void) +{ + return getcontext; +} + +void * +func2 (void) +{ + return setcontext; +} + +void * +func3 (void) +{ + return swapcontext; +} + +void * +func4 (void) +{ + return makecontext; +} diff --git a/gcc/testsuite/gcc.target/i386/pr81842-5.c b/gcc/testsuite/gcc.target/i386/pr81842-5.c new file mode 100644 index 00000000000..b9acf7a2e07 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet" } */ + +#include <ucontext.h> + +void *p1 = getcontext; +void *p2 = setcontext; +void *p3 = swapcontext; +void *p4 = makecontext; +/* { dg-error "'getcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'setcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'swapcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ +/* { dg-error "'makecontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81842-6.c b/gcc/testsuite/gcc.target/i386/pr81842-6.c new file mode 100644 index 00000000000..01d5a3ddf8f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81842-6.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */ + +#include <ucontext.h> + +void *p1 = getcontext; +void *p2 = setcontext; +void *p3 = swapcontext; +void *p4 = makecontext; |