Hi. The patch adds new no_stack_protect attribute. The change is requested from kernel folks and is direct equivalent of Clang's no_stack_protector. Unlike Clang, I chose to name it no_stack_protect because we already have stack_protect attribute (used with -fstack-protector-explicit).
First part of the patch contains a small refactoring of an enum, second implements the functionality. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin
>From 6b3e9d32150fe17acb271b7bedee7dc95cad7dc8 Mon Sep 17 00:00:00 2001 From: Martin Liska <mli...@suse.cz> Date: Fri, 15 May 2020 14:42:12 +0200 Subject: [PATCH 2/2] Implement no_stack_protect attribute. gcc/ChangeLog: 2020-05-18 Martin Liska <mli...@suse.cz> PR c/94722 * cfgexpand.c (stack_protect_decl_phase): Guard with lookup_attribute("no_stack_protect") at various places. (expand_used_vars): Likewise here. * doc/extend.texi: Document no_stack_protect attribute. gcc/ada/ChangeLog: 2020-05-18 Martin Liska <mli...@suse.cz> PR c/94722 * gcc-interface/utils.c (handle_no_stack_protect_attribute): New. (handle_stack_protect_attribute): Add error message for a no_stack_protect function. gcc/c-family/ChangeLog: 2020-05-18 Martin Liska <mli...@suse.cz> PR c/94722 * c-attribs.c (handle_no_stack_protect_function_attribute): New. (handle_stack_protect_attribute): Add error message for a no_stack_protect function. gcc/testsuite/ChangeLog: 2020-05-18 Martin Liska <mli...@suse.cz> PR c/94722 * g++.dg/no-stack-protect-attr-2.C: New test. * g++.dg/no-stack-protect-attr-3.C: New test. * g++.dg/no-stack-protect-attr.C: New test. --- gcc/ada/gcc-interface/utils.c | 32 ++++++++ gcc/c-family/c-attribs.c | 33 ++++++++ gcc/cfgexpand.c | 82 ++++++++++--------- gcc/doc/extend.texi | 4 + .../g++.dg/no-stack-protect-attr-2.C | 7 ++ .../g++.dg/no-stack-protect-attr-3.C | 23 ++++++ gcc/testsuite/g++.dg/no-stack-protect-attr.C | 16 ++++ 7 files changed, 158 insertions(+), 39 deletions(-) create mode 100644 gcc/testsuite/g++.dg/no-stack-protect-attr-2.C create mode 100644 gcc/testsuite/g++.dg/no-stack-protect-attr-3.C create mode 100644 gcc/testsuite/g++.dg/no-stack-protect-attr.C diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 1527be4f6d1..144afe37d78 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -91,6 +91,7 @@ static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_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_noicf_attribute (tree *, tree, tree, int, bool *); @@ -141,6 +142,8 @@ const struct attribute_spec gnat_internal_attribute_table[] = handle_noreturn_attribute, NULL }, { "stack_protect",0, 0, true, false, false, false, handle_stack_protect_attribute, NULL }, + { "no_stack_protect",0, 0, true, false, false, false, + handle_no_stack_protect_attribute, NULL }, { "noinline", 0, 0, true, false, false, false, handle_noinline_attribute, NULL }, { "noclone", 0, 0, true, false, false, false, @@ -6523,10 +6526,39 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int, warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } + else if (lookup_attribute ("no_stack_protect", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with %qs attribute", name, "no_stack_protect"); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no_stack_protect" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_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 if (lookup_attribute ("stack_protect", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with %qs attribute", name, "stack_protect"); + *no_add_attrs = true; + } return NULL_TREE; } + /* Handle a "noinline" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 7a6fb9af6da..3c22576035b 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -63,6 +63,8 @@ static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int, static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *); static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_stack_protect_function_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_nocf_check_attribute (tree *, tree, tree, int, bool *); @@ -273,6 +275,9 @@ const struct attribute_spec c_common_attribute_table[] = handle_noreturn_attribute, NULL }, { "stack_protect", 0, 0, true, false, false, false, handle_stack_protect_attribute, NULL }, + { "no_stack_protect", 0, 0, true, false, false, false, + handle_no_stack_protect_function_attribute, + NULL }, { "noinline", 0, 0, true, false, false, false, handle_noinline_attribute, attr_noinline_exclusions }, @@ -1017,6 +1022,34 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int, warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } + else if (lookup_attribute ("no_stack_protect", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with %qs attribute", name, "no_stack_protect"); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no_stack_protect" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_stack_protect_function_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 if (lookup_attribute ("stack_protect", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with %qs attribute", name, "stack_protect"); + *no_add_attrs = true; + } return NULL_TREE; } diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index b66c3e5f7af..6e8687c392c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1831,11 +1831,12 @@ stack_protect_decl_phase (tree decl) if (bits & SPCT_HAS_SMALL_CHAR_ARRAY) has_short_buffer = true; - 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)))) + tree attribs = DECL_ATTRIBUTES (current_function_decl); + if (!lookup_attribute ("no_stack_protect", attribs) + && (flag_stack_protect == SPCT_FLAG_ALL + || flag_stack_protect == SPCT_FLAG_STRONG + || (flag_stack_protect == SPCT_FLAG_EXPLICIT + && lookup_attribute ("stack_protect", attribs)))) { if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY)) && !(bits & SPCT_HAS_AGGREGATE)) @@ -2136,6 +2137,7 @@ expand_used_vars (void) set are actually used by the optimized function. Lay them out. */ expand_used_vars_for_block (outer_block, true); + tree attribs = DECL_ATTRIBUTES (current_function_decl); if (stack_vars_num > 0) { bool has_addressable_vars = false; @@ -2145,10 +2147,10 @@ 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 != 0 + && !lookup_attribute ("no_stack_protect", attribs) && (flag_stack_protect != SPCT_FLAG_EXPLICIT || (flag_stack_protect == SPCT_FLAG_EXPLICIT - && lookup_attribute ("stack_protect", - DECL_ATTRIBUTES (current_function_decl))))) + && lookup_attribute ("stack_protect", attribs)))) has_addressable_vars = add_stack_protection_conflicts (); if (flag_stack_protect == SPCT_FLAG_STRONG && has_addressable_vars) @@ -2161,38 +2163,40 @@ expand_used_vars (void) dump_stack_var_partition (); } - switch (flag_stack_protect) - { - case SPCT_FLAG_ALL: - create_stack_guard (); - break; - case SPCT_FLAG_STRONG: - if (gen_stack_protect_signal - || cfun->calls_alloca - || has_protected_decls - || lookup_attribute ("stack_protect", - DECL_ATTRIBUTES (current_function_decl))) + if (!lookup_attribute ("no_stack_protect", attribs)) + switch (flag_stack_protect) + { + case SPCT_FLAG_ALL: create_stack_guard (); - break; + break; - case SPCT_FLAG_DEFAULT: - if (cfun->calls_alloca - || has_protected_decls - || lookup_attribute ("stack_protect", - DECL_ATTRIBUTES (current_function_decl))) - create_stack_guard (); - break; + case SPCT_FLAG_STRONG: + if (gen_stack_protect_signal + || 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; + case SPCT_FLAG_DEFAULT: + if (cfun->calls_alloca + || has_protected_decls + || lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))) + create_stack_guard (); + break; - default: - break; - } + case SPCT_FLAG_EXPLICIT: + if (lookup_attribute ("stack_protect", + DECL_ATTRIBUTES (current_function_decl))) + create_stack_guard (); + break; + + default: + break; + } /* Assign rtl to each variable based on these partitions. */ if (stack_vars_num > 0) @@ -2213,11 +2217,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 == SPCT_FLAG_ALL - || flag_stack_protect == SPCT_FLAG_STRONG - || (flag_stack_protect == SPCT_FLAG_EXPLICIT - && lookup_attribute ("stack_protect", - DECL_ATTRIBUTES (current_function_decl)))) + if (!lookup_attribute ("no_stack_protect", attribs) + && (flag_stack_protect == SPCT_FLAG_ALL + || flag_stack_protect == SPCT_FLAG_STRONG + || (flag_stack_protect == SPCT_FLAG_EXPLICIT + && lookup_attribute ("stack_protect", attribs)))) expand_stack_vars (stack_protect_decl_phase_2, &data); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c80848e9061..604bf37e916 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3671,6 +3671,10 @@ This attribute adds stack protection code to the function if flags @option{-fstack-protector}, @option{-fstack-protector-strong} or @option{-fstack-protector-explicit} are set. +@item no_stack_protect +@cindex @code{no_stack_protect} function attribute +This attribute prevents stack protection code for the function. + @item target (@var{string}, @dots{}) @cindex @code{target} function attribute Multiple target back ends implement the @code{target} attribute diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C b/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C new file mode 100644 index 00000000000..dcac6f9d389 --- /dev/null +++ b/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C @@ -0,0 +1,7 @@ +/* PR c/94722 */ +/* { dg-do compile } */ + +int __attribute__((no_stack_protect, stack_protect)) c() /* { dg-warning "'stack_protect' attribute ignored due to conflict with 'no_stack_protect' attribute" } */ +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C b/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C new file mode 100644 index 00000000000..a6b702ba5ea --- /dev/null +++ b/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C @@ -0,0 +1,23 @@ +/* PR c/94722 */ +/* Test that stack protection is disabled via no_stack_protect attribute. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fstack-protector-explicit" } */ + +/* { dg-do compile } */ + +int __attribute__((no_stack_protect)) foo() +{ + int a; + char b[34]; + return 0; +} + +int __attribute__((stack_protect)) bar() +{ + int a; + char b[34]; + return 0; +} + +/* { dg-final { scan-assembler-times "stack_chk_fail" 1 } } */ diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr.C b/gcc/testsuite/g++.dg/no-stack-protect-attr.C new file mode 100644 index 00000000000..8332e5b276d --- /dev/null +++ b/gcc/testsuite/g++.dg/no-stack-protect-attr.C @@ -0,0 +1,16 @@ +/* PR c/94722 */ +/* Test that stack protection is disabled via no_stack_protect attribute. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fstack-protector-all" } */ + +/* { dg-do compile } */ + +int __attribute__((no_stack_protect)) c() +{ + int a; + char b[34]; + return 0; +} + +/* { dg-final { scan-assembler-not "stack_chk_fail" } } */ -- 2.26.2
>From 2465dd4f502824548472a4c303cde25c157215ef Mon Sep 17 00:00:00 2001 From: Martin Liska <mli...@suse.cz> Date: Fri, 15 May 2020 14:51:24 +0200 Subject: [PATCH 1/2] Come up with stack_protector enum. gcc/ChangeLog: 2020-05-15 Martin Liska <mli...@suse.cz> * cfgexpand.c: Move the enum to ... * coretypes.h (enum stack_protector): ... here. * function.c (assign_parm_adjust_stack_rtl): Use the stack_protector enum. gcc/c-family/ChangeLog: 2020-05-15 Martin Liska <mli...@suse.cz> * c-cppbuiltin.c (c_cpp_builtins): Use the stack_protector enum. --- gcc/c-family/c-cppbuiltin.c | 8 ++++---- gcc/cfgexpand.c | 7 ------- gcc/coretypes.h | 8 ++++++++ gcc/function.c | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index a7d65d63934..9164400a046 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1425,13 +1425,13 @@ 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) + if (flag_stack_protect == SPCT_FLAG_EXPLICIT) cpp_define (pfile, "__SSP_EXPLICIT__=4"); - if (flag_stack_protect == 3) + if (flag_stack_protect == SPCT_FLAG_STRONG) cpp_define (pfile, "__SSP_STRONG__=3"); - if (flag_stack_protect == 2) + if (flag_stack_protect == SPCT_FLAG_ALL) cpp_define (pfile, "__SSP_ALL__=2"); - else if (flag_stack_protect == 1) + else if (flag_stack_protect == SPCT_FLAG_DEFAULT) cpp_define (pfile, "__SSP__=1"); if (flag_openacc) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 2f6ec97ed04..b66c3e5f7af 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1762,13 +1762,6 @@ clear_tree_used (tree block) clear_tree_used (t); } -enum { - SPCT_FLAG_DEFAULT = 1, - SPCT_FLAG_ALL = 2, - SPCT_FLAG_STRONG = 3, - SPCT_FLAG_EXPLICIT = 4 -}; - /* Examine TYPE and determine a bit mask of the following features. */ #define SPCT_HAS_LARGE_CHAR_ARRAY 1 diff --git a/gcc/coretypes.h b/gcc/coretypes.h index cda22697cc3..323b1cf0f1e 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -219,6 +219,14 @@ enum profile_reproducibility { PROFILE_REPRODUCIBILITY_MULTITHREADED }; +/* Type of -fstack-protector-*. */ +enum stack_protector { + SPCT_FLAG_DEFAULT = 1, + SPCT_FLAG_ALL = 2, + SPCT_FLAG_STRONG = 3, + SPCT_FLAG_EXPLICIT = 4 +}; + /* Types of unwind/exception handling info that can be generated. */ enum unwind_info_type diff --git a/gcc/function.c b/gcc/function.c index 9eee9b59bfd..fe5c91809f3 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2841,7 +2841,7 @@ assign_parm_adjust_stack_rtl (struct assign_parm_data_one *data) /* If stack protection is in effect for this function, don't leave any pointers in their passed stack slots. */ else if (crtl->stack_protect_guard - && (flag_stack_protect == 2 + && (flag_stack_protect == SPCT_FLAG_ALL || data->arg.pass_by_reference || POINTER_TYPE_P (data->nominal_type))) stack_parm = NULL; -- 2.26.2