Bug 1228800

Summary: x86_64-linux-gnu-gcc generated stack protector code unsuitable for kernel
Product: [Fedora] Fedora Reporter: Michal Schmidt <mschmidt>
Component: cross-gccAssignee: David Howells <dhowells>
Status: CLOSED CURRENTRELEASE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 22CC: dan, dhowells, ivecera
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: cross-gcc-5.1.1-3.fc22 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-07-20 19:33:48 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Michal Schmidt 2015-06-05 19:30:33 UTC
Description of problem:
I'd like to be able to cross-compile the Linux kernel on ppc64 for x86_64.
The cross-compiler for the x86_64 target is unable to compile a kernel with CONFIG_CC_STACKPROTECTOR=y.

Version-Release number of selected component (if applicable):
gcc-x86_64-linux-gnu-5.1.1-2.fc22

How reproducible:
always

Steps to Reproduce:
1. Run the test the Linux kernel build uses to detect the compiler's ability
   to generate stack protector code:

 echo "int foo(void) { char X[200]; return 3; }" |
 x86_64-linux-gnu-gcc -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o -

Actual results:
The generated code refers to __stack_chk_guard:
        ...
        movq    __stack_chk_guard(%rip), %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movl    $3, %eax
        movq    -8(%rbp), %rdx
        xorq    __stack_chk_guard(%rip), %rdx
        je      .L3
        call    __stack_chk_fail
        ...

Expected results:
It should use the %gs segment register to access the canary:
        ...
        movq    %gs:40, %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movl    $3, %eax
        movq    -8(%rbp), %rdx
        xorq    %gs:40, %rdx
        je      .L3
        call    __stack_chk_fail
        ...

Additional info:
I looked into how cross-gcc is built and the problem seems to be this:
gcc is configured with "--without-headers". The configure script checks for whether the target libc provides SSP (TARGET_LIBC_PROVIDES_SSP). In this case it will be false.
The definition of TARGET_THREAD_SSP_OFFSET is conditional under "#ifdef TARGET_LIBC_PROVIDES_SSP" (in gcc/config/i386/gnu-user64.h), so it will not be defined.
config/i386/i386.md describes how to generate stack protector code. It will use TLS canary only if "#ifdef TARGET_THREAD_SSP_OFFSET".

Possible solutions:
A) Add a hack to cross-gcc.spec to convince the configure script that
   the target libc does indeed provide SSP. Ugly, but easy:
   ./configure [...] gcc_cv_libc_provides_ssp=yes
B) Build cross-gcc against glibc headers. Complicated.
   (http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/)
C) Treat it as an upstream gcc bug that even with "-mcmodel=kernel" it
   generates different code based on what it thinks it knows about the
   target libc.

Comment 1 David Howells 2015-06-10 13:31:52 UTC
(In reply to Michal Schmidt from comment #0)
> B) Build cross-gcc against glibc headers. Complicated.
>    (http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/)

Yeah, complicated.  If I do it for one arch, I really have to do it for all.  However, this leads to a multiplicative effect on those arches that support multiple different configurations (including things like LE/BE variations).  Further, not all arches support glibc, so I'd have to build some against uClibc instead or as well (FRV, for example, does not support glibc in conjunction with nommu subarches).

Comment 2 David Howells 2015-06-10 15:44:58 UTC
(In reply to Michal Schmidt from comment #0)
> C) Treat it as an upstream gcc bug that even with "-mcmodel=kernel" it
>    generates different code based on what it thinks it knows about the
>    target libc.

Okay, I think I prefer this.  Raised against gcc as:

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66491

Comment 3 David Howells 2015-06-11 15:19:12 UTC
(In reply to Michal Schmidt from comment #0)
> A) Add a hack to cross-gcc.spec to convince the configure script that
>    the target libc does indeed provide SSP. Ugly, but easy:
>    ./configure [...] gcc_cv_libc_provides_ssp=yes

This works, but the qualifier needs to be passed to make rather than configure as it's not used by the base configure.

Comment 4 Fedora Update System 2015-07-03 20:34:36 UTC
cross-gcc-5.1.1-3.fc22 has been submitted as an update for Fedora 22.
https://admin.fedoraproject.org/updates/cross-gcc-5.1.1-3.fc22

Comment 5 Fedora Update System 2015-07-23 08:59:22 UTC
cross-gcc-5.1.1-3.fc22 has been pushed to the Fedora 22 stable repository.  If problems still persist, please make note of it in this bug report.