From b58828d4bd120814fd5de461795ca4883cdafac1 Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 8 May 2011 01:49:32 +0000 Subject: [PATCH] Add a no_stack_protector function attribute to localize the effect of disabling stack protection on a function-by-function level, as opposed to per source file. --- gnu/dist/gcc4/gcc/c-common.c | 30 ++++++++++++++++++++++++++++++ gnu/dist/gcc4/gcc/cfgexpand.c | 12 +++++++++--- gnu/dist/gcc4/gcc/tree.h | 6 ++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/gnu/dist/gcc4/gcc/c-common.c b/gnu/dist/gcc4/gcc/c-common.c index 03c855fa0d70..f50a37aab5e0 100644 --- a/gnu/dist/gcc4/gcc/c-common.c +++ b/gnu/dist/gcc4/gcc/c-common.c @@ -529,6 +529,8 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int, bool *); static tree handle_no_instrument_function_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_stack_protector_function_attribute (tree *, tree, + tree, int, bool *); static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); static tree handle_no_limit_stack_attribute (tree *, tree, tree, int, @@ -608,6 +610,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_weakref_attribute }, { "no_instrument_function", 0, 0, true, false, false, handle_no_instrument_function_attribute }, + { "no_stack_protector", 0, 0, true, false, false, + handle_no_stack_protector_function_attribute }, { "malloc", 0, 0, true, false, false, handle_malloc_attribute }, { "returns_twice", 0, 0, true, false, false, @@ -5051,6 +5055,32 @@ handle_no_instrument_function_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "no_instrument_function" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_stack_protector_function_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error ("%J%qE attribute applies only to functions", decl, name); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error ("%Jcan%'t set %qE attribute after definition", decl, name); + *no_add_attrs = true; + } + else + DECL_NO_STACK_PROTECTOR_FUNCTION (decl) = 1; + + return NULL_TREE; +} /* Handle a "malloc" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gnu/dist/gcc4/gcc/cfgexpand.c b/gnu/dist/gcc4/gcc/cfgexpand.c index 6fde1e36046c..be678aba89a9 100644 --- a/gnu/dist/gcc4/gcc/cfgexpand.c +++ b/gnu/dist/gcc4/gcc/cfgexpand.c @@ -862,6 +862,9 @@ stack_protect_decl_phase (tree decl) unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl)); int ret = 0; + if (DECL_NO_STACK_PROTECTOR_FUNCTION(decl)) + return ret; + if (bits & SPCT_HAS_SMALL_CHAR_ARRAY) has_short_buffer = true; @@ -939,6 +942,7 @@ static void expand_used_vars (void) { tree t, outer_block = DECL_INITIAL (current_function_decl); + bool stack_protect_func = !DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl); /* Compute the phase of the stack frame for this function. */ { @@ -1008,7 +1012,7 @@ 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 && stack_protect_func) add_stack_protection_conflicts (); /* Now that we have collected all stack variables, and have computed a @@ -1020,7 +1024,8 @@ expand_used_vars (void) /* There are several conditions under which we should create a stack guard: protect-all, alloca used, protected decls present. */ - if (flag_stack_protect == 2 + if (stack_protect_func) + if (flag_stack_protect == 2 || (flag_stack_protect && (current_function_calls_alloca || has_protected_decls))) create_stack_guard (); @@ -1595,7 +1600,8 @@ tree_expand_cfg (void) expand_used_vars (); /* Honor stack protection warnings. */ - if (warn_stack_protect) + if (warn_stack_protect && + !DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl)) { if (current_function_calls_alloca) warning (0, "not protecting local variables: variable length buffer"); diff --git a/gnu/dist/gcc4/gcc/tree.h b/gnu/dist/gcc4/gcc/tree.h index 96bbfaffba33..087fac4db041 100644 --- a/gnu/dist/gcc4/gcc/tree.h +++ b/gnu/dist/gcc4/gcc/tree.h @@ -2680,6 +2680,11 @@ struct tree_decl_non_common GTY(()) #define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) \ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_instrument_function_entry_exit) +/* Used in FUNCTION_DECLs to indicate that the function should not be stack + protected */ +#define DECL_NO_STACK_PROTECTOR_FUNCTION(NODE) \ + (FUNCTION_DECL_CHECK (NODE)->function_decl.no_stack_protector_function) + /* Used in FUNCTION_DECLs to indicate that limit-stack-* should be disabled in this function. */ #define DECL_NO_LIMIT_STACK(NODE) \ @@ -2746,6 +2751,7 @@ struct tree_function_decl GTY(()) unsigned regdecl_flag : 1; unsigned inline_flag : 1; unsigned no_instrument_function_entry_exit : 1; + unsigned no_stack_protector_function : 1; unsigned no_limit_stack : 1; ENUM_BITFIELD(built_in_class) built_in_class : 2;