From 1bd5ac70bdcb8b000ed92f4a7863c07b9566de1b Mon Sep 17 00:00:00 2001 From: martynas Date: Tue, 14 Jan 2014 02:03:57 +0000 Subject: [PATCH] Add a new option "-fstack-protector-strong" for GCC4. This includes additional functions to be protected --- those that have local array definitions, or have references to local frame addresses. Note 1: Han explicitly licensed this under GPLv2 for us. Note 2: Do *not* use this anywhere in "src" Makefiles, as the other GCC doesn't have this option yet (but I'm working on it). --- gnu/gcc/gcc/c-cppbuiltin.c | 4 +- gnu/gcc/gcc/cfgexpand.c | 82 +++++++++++++++++++++++++++++++++---- gnu/gcc/gcc/common.opt | 4 ++ gnu/gcc/gcc/doc/cpp.texi | 4 ++ gnu/gcc/gcc/doc/gcc.1 | 7 +++- gnu/gcc/gcc/doc/invoke.texi | 7 +++- gnu/gcc/gcc/gcc.c | 2 +- 7 files changed, 99 insertions(+), 11 deletions(-) diff --git a/gnu/gcc/gcc/c-cppbuiltin.c b/gnu/gcc/gcc/c-cppbuiltin.c index 0d2a53c959b..84b99ac2963 100644 --- a/gnu/gcc/gcc/c-cppbuiltin.c +++ b/gnu/gcc/gcc/c-cppbuiltin.c @@ -546,7 +546,9 @@ 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 == 2) + if (flag_stack_protect == 3) + cpp_define (pfile, "__SSP_STRONG__=3"); + else if (flag_stack_protect == 2) cpp_define (pfile, "__SSP_ALL__=2"); else if (flag_stack_protect == 1) cpp_define (pfile, "__SSP__=1"); diff --git a/gnu/gcc/gcc/cfgexpand.c b/gnu/gcc/gcc/cfgexpand.c index b688917cc72..ccb534f0e18 100644 --- a/gnu/gcc/gcc/cfgexpand.c +++ b/gnu/gcc/gcc/cfgexpand.c @@ -810,6 +810,12 @@ clear_tree_used (tree block) clear_tree_used (t); } +enum { + SPCT_FLAG_DEFAULT = 1, + SPCT_FLAG_ALL = 2, + SPCT_FLAG_STRONG = 3 +}; + /* Examine TYPE and determine a bit mask of the following features. */ #define SPCT_HAS_LARGE_CHAR_ARRAY 1 @@ -879,7 +885,8 @@ stack_protect_decl_phase (tree decl) if (bits & SPCT_HAS_SMALL_CHAR_ARRAY) has_short_buffer = true; - if (flag_stack_protect == 2) + if (flag_stack_protect == SPCT_FLAG_ALL + || flag_stack_protect == SPCT_FLAG_STRONG) { if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY)) && !(bits & SPCT_HAS_AGGREGATE)) @@ -947,12 +954,36 @@ create_stack_guard (void) cfun->stack_protect_guard = guard; } +/* Helper routine to check if a record or union contains an array field. */ + +static int +record_or_union_type_has_array_p (tree tree_type) +{ + tree fields = TYPE_FIELDS (tree_type); + tree f; + + for (f = fields; f; f = TREE_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + tree field_type = TREE_TYPE (f); + if ((TREE_CODE (field_type) == RECORD_TYPE + || TREE_CODE (field_type) == UNION_TYPE + || TREE_CODE (field_type) == QUAL_UNION_TYPE) + && record_or_union_type_has_array_p (field_type)) + return 1; + if (TREE_CODE (field_type) == ARRAY_TYPE) + return 1; + } + return 0; +} + /* Expand all variables used in the function. */ static void expand_used_vars (void) { tree t, outer_block = DECL_INITIAL (current_function_decl); + bool gen_stack_protect_signal = false; /* Compute the phase of the stack frame for this function. */ { @@ -972,6 +1003,29 @@ expand_used_vars (void) has_protected_decls = false; has_short_buffer = false; + if (flag_stack_protect == SPCT_FLAG_STRONG) + for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t)) + { + tree var = TREE_VALUE (t); + if (!is_global_var (var)) + { + tree var_type = TREE_TYPE (var); + /* Examine local referenced variables that have their addresses + * taken, contain an array, or are arrays. */ + if (TREE_CODE (var) == VAR_DECL + && (TREE_CODE (var_type) == ARRAY_TYPE + || TREE_ADDRESSABLE (var) + || ((TREE_CODE (var_type) == RECORD_TYPE + || TREE_CODE (var_type) == UNION_TYPE + || TREE_CODE (var_type) == QUAL_UNION_TYPE) + && record_or_union_type_has_array_p (var_type)))) + { + gen_stack_protect_signal = true; + break; + } + } + } + /* At this point all variables on the unexpanded_var_list with TREE_USED set are not associated with any block scope. Lay them out. */ for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t)) @@ -1032,12 +1086,26 @@ expand_used_vars (void) dump_stack_var_partition (); } - /* There are several conditions under which we should create a - stack guard: protect-all, alloca used, protected decls present. */ - if (flag_stack_protect == 2 - || (flag_stack_protect - && (current_function_calls_alloca || has_protected_decls))) - create_stack_guard (); + switch (flag_stack_protect) + { + case SPCT_FLAG_ALL: + create_stack_guard (); + break; + + case SPCT_FLAG_STRONG: + if (gen_stack_protect_signal + || current_function_calls_alloca || has_protected_decls) + create_stack_guard (); + break; + + case SPCT_FLAG_DEFAULT: + if (current_function_calls_alloca || has_protected_decls) + create_stack_guard(); + break; + + default: + ; + } /* Assign rtl to each variable based on these partitions. */ if (stack_vars_num > 0) diff --git a/gnu/gcc/gcc/common.opt b/gnu/gcc/gcc/common.opt index 66499639fc2..de1ae3c59a4 100644 --- a/gnu/gcc/gcc/common.opt +++ b/gnu/gcc/gcc/common.opt @@ -870,6 +870,10 @@ fstack-protector-all Common Report RejectNegative Var(flag_stack_protect, 2) VarExists Use a stack protection method for every function +fstack-protector-strong +Common Report RejectNegative Var(flag_stack_protect, 3) +Use a smart stack protection method for certain functions + fstrength-reduce Common Does nothing. Preserved for backward compatibility. diff --git a/gnu/gcc/gcc/doc/cpp.texi b/gnu/gcc/gcc/doc/cpp.texi index 2a2deaa6e04..a7fef582a33 100644 --- a/gnu/gcc/gcc/doc/cpp.texi +++ b/gnu/gcc/gcc/doc/cpp.texi @@ -2145,6 +2145,10 @@ use. This macro is defined, with value 2, when @option{-fstack-protector-all} is in use. +@item __SSP_STRONG__ +This macro is defined, with value 3, when @option{-fstack-protector-strong} is +in use. + @item __TIMESTAMP__ This macro expands to a string constant that describes the date and time of the last modification of the current source file. The string constant diff --git a/gnu/gcc/gcc/doc/gcc.1 b/gnu/gcc/gcc/doc/gcc.1 index b095c87656e..2e5543e8994 100644 --- a/gnu/gcc/gcc/doc/gcc.1 +++ b/gnu/gcc/gcc/doc/gcc.1 @@ -355,7 +355,7 @@ in the following sections. \&\fB\-fsched2\-use\-superblocks \&\-fsched2\-use\-traces \-fsee \-freschedule\-modulo\-scheduled\-loops \&\-fsection\-anchors \-fsignaling\-nans \-fsingle\-precision\-constant -\&\-fstack\-protector \-fstack\-protector\-all +\&\-fstack\-protector \-fstack\-protector\-all \-fstack\-protector\-strong \&\-fstrict\-aliasing \-fstrict\-overflow \-ftracer \-fthread\-jumps \&\-funroll\-all\-loops \-funroll\-loops \-fpeel\-loops \&\-fsplit\-ivs\-in\-unroller \-funswitch\-loops @@ -5489,6 +5489,11 @@ If a guard check fails, an error message is printed and the program exits. .IP "\fB\-fstack\-protector\-all\fR" 4 .IX Item "-fstack-protector-all" Like \fB\-fstack\-protector\fR except that all functions are protected. +.IP "\fB\-fstack\-protector\-strong\fR" 4 +.IX Item "-fstack-protector-strong" +Like \fB\-fstack\-protector\fR but includes additional functions to +be protected \-\-\- those that have local array definitions, or have +references to local frame addresses. .IP "\fB\-fsection\-anchors\fR" 4 .IX Item "-fsection-anchors" Try to reduce the number of symbolic address calculations by using diff --git a/gnu/gcc/gcc/doc/invoke.texi b/gnu/gcc/gcc/doc/invoke.texi index 56db460d71c..60bc49cb343 100644 --- a/gnu/gcc/gcc/doc/invoke.texi +++ b/gnu/gcc/gcc/doc/invoke.texi @@ -336,7 +336,7 @@ Objective-C and Objective-C++ Dialects}. -fsched2-use-superblocks @gol -fsched2-use-traces -fsee -freschedule-modulo-scheduled-loops @gol -fsection-anchors -fsignaling-nans -fsingle-precision-constant @gol --fstack-protector -fstack-protector-all @gol +-fstack-protector -fstack-protector-all -fstack-protector-strong @gol -fstrict-aliasing -fstrict-overflow -ftracer -fthread-jumps @gol -funroll-all-loops -funroll-loops -fpeel-loops @gol -fsplit-ivs-in-unroller -funswitch-loops @gol @@ -5936,6 +5936,11 @@ If a guard check fails, an error message is printed and the program exits. @item -fstack-protector-all Like @option{-fstack-protector} except that all functions are protected. +@item -fstack-protector-strong +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 -fsection-anchors @opindex fsection-anchors Try to reduce the number of symbolic address calculations by using diff --git a/gnu/gcc/gcc/gcc.c b/gnu/gcc/gcc/gcc.c index 07ed21ebae3..c466fee4689 100644 --- a/gnu/gcc/gcc/gcc.c +++ b/gnu/gcc/gcc/gcc.c @@ -678,7 +678,7 @@ proper position among the other output files. */ #ifdef TARGET_LIBC_PROVIDES_SSP #define LINK_SSP_SPEC "%{fstack-protector:}" #else -#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}" +#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}" #endif #endif -- 2.20.1