From 5434dc0730795cf6a2ef8a9fe20e4dcc9cd077be Mon Sep 17 00:00:00 2001 From: Marcos Diaz Date: Thu, 15 Jan 2015 05:29:12 +0000 Subject: [PATCH] common.opt: New option -fstack-protector-explicit. 2015-01-14 Marcos Diaz * common.opt: New option -fstack-protector-explicit. * cfgexpand.c (SPCT_FLAG_EXPLICIT): New enum. (stack_protect_decl_phase): Handle stack_protect attribute for explicit stack protection requests. (expand_used_vars): Similarly. * doc/cpp.texi (__SSP_EXPLICIT__): Document predefined macro. * doc/extend.texi: Add documentation for "stack_protect" attribute. * doc/invoke.texi: Add documentation for -fstack-protector-explicit. * c-cppbuiltin.c (c_cpp_builtins): New cpp define __SSP_EXPLICIT__ for the new option fstack-protector_explicit. * c-common.c (c_common_attribute_table): Add stack_protect attribute. (handle_stack_protect_attribute): New function. * gcc.dg/stackprotectexplicit1.c: New test. * g++.dg/stackprotectexplicit2.c: New test. From-SVN: r219633 --- gcc/ChangeLog | 11 +++++++ gcc/c-family/ChangeLog | 7 +++++ gcc/c-family/c-common.c | 22 +++++++++++++ gcc/c-family/c-cppbuiltin.c | 2 ++ gcc/cfgexpand.c | 33 ++++++++++++++++---- gcc/common.opt | 4 +++ gcc/doc/cpp.texi | 4 +++ gcc/doc/extend.texi | 8 ++++- gcc/doc/invoke.texi | 10 ++++-- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/stackprotectexplicit2.C | 27 ++++++++++++++++ gcc/testsuite/gcc.dg/stackprotectexplicit1.c | 23 ++++++++++++++ 12 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/stackprotectexplicit2.C create mode 100644 gcc/testsuite/gcc.dg/stackprotectexplicit1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e959c20f98..701c6c6734a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-01-14 Marcos Diaz + + * common.opt: New option -fstack-protector-explicit. + * cfgexpand.c (SPCT_FLAG_EXPLICIT): New enum. + (stack_protect_decl_phase): Handle stack_protect attribute for + explicit stack protection requests. + (expand_used_vars): Similarly. + * doc/cpp.texi (__SSP_EXPLICIT__): Document predefined macro. + * doc/extend.texi: Add documentation for "stack_protect" attribute. + * doc/invoke.texi: Add documentation for -fstack-protector-explicit. + 2015-01-14 Oleg Endo PR target/53988 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1efb75ac13c..976404579d2 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2015-01-14 Marcos Diaz + + * c-cppbuiltin.c (c_cpp_builtins): New cpp define __SSP_EXPLICIT__ + for the new option fstack-protector_explicit. + * c-common.c (c_common_attribute_table): Add stack_protect attribute. + (handle_stack_protect_attribute): New function. + 2015-01-13 Martin Uecker * c.opt: New option -Warray-bounds=. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 29cab015a1e..054f5a0e94a 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -327,6 +327,7 @@ static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree, int, bool *); static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int, bool *); +static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); static tree handle_noclone_attribute (tree *, tree, tree, int, bool *); static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); @@ -657,6 +658,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_noreturn_attribute, false }, { "volatile", 0, 0, true, false, false, handle_noreturn_attribute, false }, + { "stack_protect", 0, 0, true, false, false, + handle_stack_protect_attribute, false }, { "noinline", 0, 0, true, false, false, handle_noinline_attribute, false }, { "noclone", 0, 0, true, false, false, @@ -6769,6 +6772,25 @@ handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int, return NULL_TREE; } +/* Handle a "stack_protect" attribute; arguments as in + struct attribute_spec.handler. */ +static tree +handle_stack_protect_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + else + DECL_ATTRIBUTES (*node) + = tree_cons (get_identifier ("stack_protect"), + NULL_TREE, DECL_ATTRIBUTES (*node)); + + return NULL_TREE; +} + /* Handle a "noinline" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 229a316a886..0b00d59fd36 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1212,6 +1212,8 @@ c_cpp_builtins (cpp_reader *pfile) /* Make the choice of the stack protector runtime visible to source code. The macro names and values here were chosen for compatibility with an earlier implementation, i.e. ProPolice. */ + if (flag_stack_protect == 4) + cpp_define (pfile, "__SSP_EXPLICIT__=4"); if (flag_stack_protect == 3) cpp_define (pfile, "__SSP_STRONG__=3"); if (flag_stack_protect == 2) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 8926e8f64c9..c92c786ea38 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1411,7 +1411,8 @@ clear_tree_used (tree block) enum { SPCT_FLAG_DEFAULT = 1, SPCT_FLAG_ALL = 2, - SPCT_FLAG_STRONG = 3 + SPCT_FLAG_STRONG = 3, + SPCT_FLAG_EXPLICIT = 4 }; /* Examine TYPE and determine a bit mask of the following features. */ @@ -1484,7 +1485,10 @@ stack_protect_decl_phase (tree decl) has_short_buffer = true; if (flag_stack_protect == SPCT_FLAG_ALL - || flag_stack_protect == SPCT_FLAG_STRONG) + || flag_stack_protect == SPCT_FLAG_STRONG + || (flag_stack_protect == SPCT_FLAG_EXPLICIT + && lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl)))) { if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY)) && !(bits & SPCT_HAS_AGGREGATE)) @@ -1859,7 +1863,11 @@ expand_used_vars (void) /* If stack protection is enabled, we don't share space between vulnerable data and non-vulnerable data. */ - if (flag_stack_protect) + if (flag_stack_protect != 0 + && (flag_stack_protect != SPCT_FLAG_EXPLICIT + || (flag_stack_protect == SPCT_FLAG_EXPLICIT + && lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))))) add_stack_protection_conflicts (); /* Now that we have collected all stack variables, and have computed a @@ -1877,15 +1885,24 @@ expand_used_vars (void) case SPCT_FLAG_STRONG: if (gen_stack_protect_signal - || cfun->calls_alloca || has_protected_decls) + || cfun->calls_alloca || has_protected_decls + || lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))) create_stack_guard (); break; case SPCT_FLAG_DEFAULT: - if (cfun->calls_alloca || has_protected_decls) + if (cfun->calls_alloca || has_protected_decls + || lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))) create_stack_guard (); break; + case SPCT_FLAG_EXPLICIT: + if (lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))) + create_stack_guard (); + break; default: ; } @@ -1911,7 +1928,11 @@ expand_used_vars (void) expand_stack_vars (stack_protect_decl_phase_1, &data); /* Phase 2 contains other kinds of arrays. */ - if (flag_stack_protect == 2) + if (flag_stack_protect == SPCT_FLAG_ALL + || flag_stack_protect == SPCT_FLAG_STRONG + || (flag_stack_protect == SPCT_FLAG_EXPLICIT + && lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl)))) expand_stack_vars (stack_protect_decl_phase_2, &data); } diff --git a/gcc/common.opt b/gcc/common.opt index 3d1987559a8..c3219604836 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2093,6 +2093,10 @@ fstack-protector-strong Common Report RejectNegative Var(flag_stack_protect, 3) Use a smart stack protection method for certain functions +fstack-protector-explicit +Common Report RejectNegative Var(flag_stack_protect, 4) +Use stack protection method only for functions with the stack_protect attribute + fstack-usage Common RejectNegative Var(flag_stack_usage) Output stack usage information on a per-function basis diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index e94bdf74e11..10b72e7e61b 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -2351,6 +2351,10 @@ in use. This macro is defined, with value 3, when @option{-fstack-protector-strong} is in use. +@item __SSP_EXPLICIT__ +This macro is defined, with value 4, when @option{-fstack-protector-explicit} is +in use. + @item __SANITIZE_ADDRESS__ This macro is defined, with value 1, when @option{-fsanitize=address} or @option{-fsanitize=kernel-address} are in use. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 942a6bc8715..bf6d7102147 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2207,7 +2207,7 @@ attributes are currently defined for functions on all targets: @code{no_sanitize_address}, @code{no_address_safety_analysis}, @code{no_sanitize_thread}, @code{no_sanitize_undefined}, @code{no_reorder}, @code{bnd_legacy}, -@code{bnd_instrument}, +@code{bnd_instrument}, @code{stack_protect}, @code{error} and @code{warning}. Several other attributes are defined for functions on particular target systems. Other attributes, including @code{section} are @@ -3444,6 +3444,12 @@ prologue which decides whether to split the stack. Functions with the @code{no_split_stack} attribute do not have that prologue, and thus may run with only a small amount of stack space available. +@item stack_protect +@cindex @code{stack_protect} function attribute +This function attribute make a stack protection of the function if +flags @option{fstack-protector} or @option{fstack-protector-strong} +or @option{fstack-protector-explicit} are set. + @item noinline @cindex @code{noinline} function attribute This function attribute prevents a function from being considered for diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 748c70a158c..638ed9ac0e1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -428,8 +428,9 @@ Objective-C and Objective-C++ Dialects}. -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol -fsemantic-interposition @gol -fshrink-wrap -fsignaling-nans -fsingle-precision-constant @gol --fsplit-ivs-in-unroller -fsplit-wide-types -fssa-phiopt -fstack-protector @gol --fstack-protector-all -fstack-protector-strong -fstrict-aliasing @gol +-fsplit-ivs-in-unroller -fsplit-wide-types -fssa-phiopt @gol +-fstack-protector -fstack-protector-all -fstack-protector-strong @gol +-fstack-protector-explicit -fstrict-aliasing @gol -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol -ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol @@ -9838,6 +9839,11 @@ Like @option{-fstack-protector} but includes additional functions to be protected --- those that have local array definitions, or have references to local frame addresses. +@item -fstack-protector-explicit +@opindex fstack-protector-explicit +Like @option{-fstack-protector} but only protects those functions which +have the @code{stack_protect} attribute + @item -fsection-anchors @opindex fsection-anchors Try to reduce the number of symbolic address calculations by using diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4be48a15f21..1c53160960f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-01-14 Marcos Diaz + + * gcc.dg/stackprotectexplicit1.c: New test. + * g++.dg/stackprotectexplicit2.c: New test. + 2015-01-14 Jerry DeLisle PR target/61933 diff --git a/gcc/testsuite/g++.dg/stackprotectexplicit2.C b/gcc/testsuite/g++.dg/stackprotectexplicit2.C new file mode 100644 index 00000000000..9cf9ab909c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/stackprotectexplicit2.C @@ -0,0 +1,27 @@ +/* Test that stack protection is done on chosen functions. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fstack-protector-explicit" } */ + +int A() +{ + int A[23]; + char b[22]; +} + +int __attribute__((stack_protect)) B() +{ + int a; + int b; + return a+b; +} + +int __attribute__((stack_protect)) c() +{ + int a; + char b[34]; + return 0; +} + + +/* { dg-final { scan-assembler-times "stack_chk_fail" 2 } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/stackprotectexplicit1.c b/gcc/testsuite/gcc.dg/stackprotectexplicit1.c new file mode 100644 index 00000000000..658c297d9f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/stackprotectexplicit1.c @@ -0,0 +1,23 @@ +/* { dg-do run { target native } } */ +/* { dg-options "-fstack-protector-explicit" } */ +/* { dg-require-effective-target fstack_protector } */ + +#include + +void +__stack_chk_fail (void) +{ + exit (0); /* pass */ +} + +int __attribute__((stack_protect)) main () +{ + int i; + char foo[255]; + + // smash stack + for (i = 0; i <= 400; i++) + foo[i] = 42; + + return 1; /* fail */ +} -- 2.30.2