public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Implement no_stack_protect attribute.
@ 2020-05-18 10:37 Martin Liška
  2020-05-18 10:41 ` Jakub Jelinek
                   ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Martin Liška @ 2020-05-18 10:37 UTC (permalink / raw)
  To: GCC Patches, Nick Desaulniers

[-- Attachment #1: Type: text/plain, Size: 502 bytes --]

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

[-- Attachment #2: 0002-Implement-no_stack_protect-attribute.patch --]
[-- Type: text/x-patch, Size: 13581 bytes --]

From 6b3e9d32150fe17acb271b7bedee7dc95cad7dc8 Mon Sep 17 00:00:00 2001
From: Martin Liska <mliska@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  <mliska@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  <mliska@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  <mliska@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  <mliska@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


[-- Attachment #3: 0001-Come-up-with-stack_protector-enum.patch --]
[-- Type: text/x-patch, Size: 3244 bytes --]

From 2465dd4f502824548472a4c303cde25c157215ef Mon Sep 17 00:00:00 2001
From: Martin Liska <mliska@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  <mliska@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  <mliska@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


^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2020-10-22 10:02 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-18 10:37 [PATCH] Implement no_stack_protect attribute Martin Liška
2020-05-18 10:41 ` Jakub Jelinek
2020-05-18 11:00   ` Martin Liška
2020-05-18 11:03     ` Jakub Jelinek
2020-05-18 11:07       ` Jakub Jelinek
2020-05-18 11:49         ` Richard Biener
2020-05-21 10:09           ` Martin Liška
2020-05-22 10:51             ` Richard Biener
2020-05-25  9:27               ` Martin Liška
2020-05-25 11:55                 ` Richard Biener
2020-05-18 11:44 ` Florian Weimer
2020-05-18 13:56   ` Michael Matz
2020-05-18 15:01     ` Florian Weimer
2020-05-18 15:52       ` Michael Matz
2020-05-18 15:56         ` Florian Weimer
2020-05-18 16:21           ` Michael Matz
2020-05-18 16:58           ` Andreas Schwab
2020-05-21 11:26           ` Martin Liška
2020-05-18 20:37 ` Martin Sebor
2020-05-21 11:28   ` Martin Liška
2020-05-21 14:53     ` Martin Sebor
2020-05-25 13:10       ` Martin Liška
2020-06-10  8:12         ` Martin Liška
2020-06-10 14:47           ` Martin Sebor
2020-06-24  9:09           ` Martin Liška
2020-07-23 11:10             ` Martin Liška
2020-08-17 12:35               ` Martin Liška
2020-08-25 14:46                 ` Nick Desaulniers
2020-08-26  9:11                   ` Martin Liška
2020-10-20 11:22                 ` Martin Liška
2020-10-20 12:19                   ` Richard Biener
2020-10-21 21:04                     ` Nick Desaulniers
2020-10-21 21:13                       ` Jakub Jelinek
2020-10-21 21:33                         ` Nick Desaulniers
2020-10-21 22:05                           ` Nick Desaulniers
2020-10-22 10:02                     ` Martin Liška

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).