Bug 71585 - Cannot selectively disable stack protector with LTO
Summary: Cannot selectively disable stack protector with LTO
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 6.1.1
: P3 normal
Target Milestone: ---
Assignee: Martin Liška
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-06-19 19:00 UTC by Julian Stecklina
Modified: 2016-06-30 08:50 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-06-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julian Stecklina 2016-06-19 19:00:20 UTC
The following code includes a function that is intended to not be compiled with a stack canary. This is a reduced example from an embedded project, where this function is the function that actually sets the __stack_chk_guard variable.

The code is this:

#pragma GCC push_options
#pragma GCC optimize ("-fno-stack-protector")

__attribute__((constructor)) void foo()
{
  asm ("");
}

#pragma GCC pop_options

int main() { return 0; }

When compiled without LTO ( gcc -fstack-protector-all -O2  -o main lto-func-attr.c ), it correctly emits a non-stack-protected function foo():

00000000004004c0 <foo>:
  4004c0:       c3                      ret    

When compiled with LTO ( gcc -fstack-protector-all -flto -O2  -o main lto-func-attr.c ), it incorrectly emits a stack canary check:

00000000004004a0 <foo>:
  4004a0:       48 83 ec 18             sub    rsp,0x18
  4004a4:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  4004ab:       00 00 
  4004ad:       48 89 44 24 08          mov    QWORD PTR [rsp+0x8],rax
  4004b2:       31 c0                   xor    eax,eax
  4004b4:       48 8b 44 24 08          mov    rax,QWORD PTR [rsp+0x8]
  4004b9:       64 48 33 04 25 28 00    xor    rax,QWORD PTR fs:0x28
  4004c0:       00 00 
  4004c2:       75 05                   jne    4004c9 <foo+0x29>
  4004c4:       48 83 c4 18             add    rsp,0x18
  4004c8:       c3                      ret    
  4004c9:       e8 72 ff ff ff          call   400440 <__stack_chk_fail@plt>


The expected behavior is that even with LTO, no stack canary check is emitted.

I am using gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) running on Fedora 23 x86_64.
Comment 1 Andrew Pinski 2016-06-19 19:07:38 UTC
This might be fixed already in 6.1.
Comment 2 Julian Stecklina 2016-06-19 22:34:06 UTC
I can reproduce this on Fedora 24 with GCC 6.1:

gcc (GCC) 6.1.1 20160510 (Red Hat 6.1.1-2)
Comment 3 Julian Stecklina 2016-06-23 20:05:09 UTC
Is there the hope of having at least workaround here?
Comment 4 Martin Liška 2016-06-24 17:19:37 UTC
Hello

The problem can be seen on both GCC 6.x and current trunk, where we show following warning message:

pr71585.c:2:9: warning: bad option ‘-fno-stack-protector’ to pragma ‘optimize’ [-Wpragmas]
 #pragma GCC optimize ("-fno-stack-protector")
         ^~~
pr71585.c:7:1: warning: bad option ‘-fno-stack-protector’ to attribute ‘optimize’ [-Wattributes]
 {
 ^

The problem is that '-fstack-protect' is not marked as Optimize option.

Following patch fixed that:

diff --git a/gcc/common.opt b/gcc/common.opt
index 5d90385..a7c5125 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2221,19 +2221,19 @@ Common RejectNegative Joined Var(common_deferred_options) Defer
 -fstack-limit-symbol=<name>	Trap if the stack goes past symbol <name>.
 
 fstack-protector
-Common Report Var(flag_stack_protect, 1) Init(-1)
+Common Report Var(flag_stack_protect, 1) Init(-1) Optimization
 Use propolice as a stack protection method.
 
 fstack-protector-all
-Common Report RejectNegative Var(flag_stack_protect, 2) Init(-1)
+Common Report RejectNegative Var(flag_stack_protect, 2) Init(-1) Optimization
 Use a stack protection method for every function.
 
 fstack-protector-strong
-Common Report RejectNegative Var(flag_stack_protect, 3) Init(-1)
+Common Report RejectNegative Var(flag_stack_protect, 3) Init(-1) Optimization
 Use a smart stack protection method for certain functions.
 
 fstack-protector-explicit
-Common Report RejectNegative Var(flag_stack_protect, 4)
+Common Report RejectNegative Var(flag_stack_protect, 4) Optimization
 Use stack protection method only for functions with the stack_protect attribute.

The only question is whether we can add the flag to optimize flags? If so, I'll send the patch to mailing list.
Btw. I've come to a misleading hint related to the option: PR69265 and accidentally I hit also this: PR71652.

Another possible problem I can see is that some i386 target attributes are not handled,
for instance:

pr71585.c:3:9: error: attribute(target("stack-protector-guard=tls")) is unknown
 #pragma GCC target ("stack-protector-guard=tls")
         ^~~

Following hunk is necessary to enable the parsing:

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f7944f9..73f2149 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6458,6 +6458,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
 
     /* enum options */
     IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
+    IX86_ATTR_ENUM ("stack-protector-guard=", OPT_mstack_protector_guard_),
 
     /* string options */
     IX86_ATTR_STR ("arch=",    IX86_FUNCTION_SPECIFIC_ARCH),

I'll write a test-case for that.

Martin
Comment 5 Martin Liška 2016-06-24 17:20:57 UTC
> The only question is whether we can add the flag to optimize flags? If so,
> I'll send the patch to mailing list.
> Btw. I've come to a misleading hint related to the option: PR69265 and
> accidentally I hit also this: PR71652.

Sorry, the first link should be: PR71651.
Comment 6 Martin Liška 2016-06-29 12:13:28 UTC
Author: marxin
Date: Wed Jun 29 12:12:56 2016
New Revision: 237845

URL: https://gcc.gnu.org/viewcvs?rev=237845&root=gcc&view=rev
Log:
Mark -fstack-protect as optimization flag.

	PR middle-end/71585
	* common.opt (flag_stack_protect): Mark the flag as optimization
	flag.
	* ipa-inline-transform.c (inline_call): Remove unnecessary call
	of build_optimization_node.
	* gcc.dg/pr71585.c: New test.
	* gcc.dg/pr71585-2.c: New test.
	* gcc.dg/pr71585-3.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/pr71585-2.c
    trunk/gcc/testsuite/gcc.dg/pr71585-3.c
    trunk/gcc/testsuite/gcc.dg/pr71585.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/common.opt
    trunk/gcc/ipa-inline-transform.c
    trunk/gcc/testsuite/ChangeLog
Comment 7 Martin Liška 2016-06-29 12:32:02 UTC
Fixed on trunk.
Comment 8 Martin Liška 2016-06-30 08:50:45 UTC
Hunk in ipa-inline-transform.c has been backported to GCC-6 branch.