Bug 1794159
| Summary: | Annocheck fails on binary compiled with -fstack-clash-protection | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 8 | Reporter: | Alexandra Petlanová Hájková <ahajkova> | ||||
| Component: | gcc-toolset-9-annobin | Assignee: | Nick Clifton <nickc> | ||||
| Status: | CLOSED ERRATA | QA Contact: | Martin Cermak <mcermak> | ||||
| Severity: | unspecified | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | 8.2 | CC: | ahajkova, dsmith, fweimer, jakub, mpolacek, mprchlik, nickc | ||||
| Target Milestone: | rc | Keywords: | Triaged | ||||
| Target Release: | 8.0 | Flags: | pm-rhel:
mirror+
|
||||
| Hardware: | Unspecified | ||||||
| OS: | Unspecified | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | gcc-toolset-9-annobin-9.07-1.el8 | Doc Type: | No Doc Update | ||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | |||||||
| : | 1803173 (view as bug list) | Environment: | |||||
| Last Closed: | 2020-04-28 16:05:05 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: | |||||||
| Bug Depends On: | |||||||
| Bug Blocks: | 1803173, 1828797 | ||||||
| Attachments: |
|
||||||
Doesn't look like a gcc problem, at least the generated assembly is the same system RHEL 8 gcc v. GTS 9 gcc:
.globl main
.type main, @function
main:
.LFB40:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movq stat64@GOTPCREL(%rip), %rcx
movl $1, %edi
xorl %eax, %eax
movq stat@GOTPCREL(%rip), %rdx
leaq .LC0(%rip), %rsi
call __printf_chk@PLT
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE40:
.size main, .-main
but the .gnu.build.attributes sections created by the annobin plugin differ:
@@ -57,7 +48,7 @@
.dc.l 15
.dc.l 0
.dc.l 0x100
- .asciz "GA+stack_clash"
+ .asciz "GA!stack_clash"
.dc.b 0
.popsection
@@ -111,7 +102,7 @@
.dc.l 22
.dc.l 0
.dc.l 0x100
- .asciz "GA+omit_frame_pointer"
+ .asciz "GA!omit_frame_pointer"
.dc.b 0, 0
.popsection
plugin/annobin.cc has
static void
record_stack_clash_note (const char * start, const char * end, int type, const char * sec_name)
{
char buffer [128];
unsigned len = sprintf (buffer, "GA%cstack_clash",
flag_stack_clash_protection ? BOOL_T : BOOL_F);
annobin_output_static_note (buffer, len + 1, true, "bool: -fstack-clash-protection status",
start, end, type, sec_name);
}
so it just looks at flag_stack_clash_protection to determine if the stack-clash protection is on.
This works fine with gcc 9.2.1 from Fedora.
Nick, any ideas?
fstack-clash-protection Common Report Var(flag_stack_clash_protection) Optimization So, like many other options, it is a per-function flag rather than per-TU. > Nick, any ideas?
There appears to be a discrepancy in the versions of gcc used. The report shows gcc-9.2.1 being used but the annocheck output reports
"binary producer gcc version 8". But this may be because the crt0.o file was built with gcc-8 and this was the first object file encountered by annocheck when it was examining the binary.
Is the binary that is being tested - stat - part of glibc ? I seem to recall that the stat program was special in some way, but that could just be me mis-remembering.
Is the problem build architecture agnostic ? I ask because the report appears to imply that the build was for the s390x (the -march=z13 option) but Marek's tests look like they are for the x86_64.
Anyway, I am going to see if I can reproduce the problem locally and investigate further.
(In reply to Nick Clifton from comment #4) > There appears to be a discrepancy in the versions of gcc used. The report > shows gcc-9.2.1 being used but the annocheck output reports > "binary producer gcc version 8". Doh! Just noticed this in the output: Warning: Multiple versions of a tool were used to build this file (9 8) - using highest version. So that answers that question. (In reply to Jakub Jelinek from comment #3) > So, like many other options, it is a per-function flag rather than per-TU. Right - but this also means that there is a global setting for this flag, which can be overridden on a per-function basis. The annobin plugin knows about this. So it records: global_stack_clash_option = flag_stack_clash_protection; during startup and then for every function it checks to see if it has changed: if (force || global_stack_clash_option != flag_stack_clash_protection) { annobin_inform (INFORM_VERBOSE, "Recording stack clash protection status of %d for %s", flag_stack_clash_protection, func_name); record_stack_clash_note (start_sym, end_sym, FUNC, sec_name); (In reply to Nick Clifton from comment #4) > Is the binary that is being tested - stat - part of glibc ? Forget that - I have just seen that stat.c is attached to this BZ. Doh. Ok - I can now reproduce the problem with gcc-toolset-9 for RHEL-8.2. Interestingly the problem does not exist with gcc-toolset-9 for RHEL-8.1. My best guess at the moment is a discrepancy between the annobin plugin built for gcc-toolset-9 for RHEL-8.2 and the gcc that is part of gcc-toolset-9 for RHEL 8.2. (There is code in the plugin that is meant to detect this kind of discrepancy, but maybe it has failed). Investigating... Yes - this is a discrepancy problem. A rebuilt version of the annobin plugin does not have the bug. All we need to do now is work out how to rebuild annobin for gcc-toolset-9 for RHEL-8.2.0. Fixed in gcc-toolset-9-annobin-9.07-1.el8 Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2020:1754 |
Created attachment 1654667 [details] reproducer Description of problem: Annocheck fails on binary compiled with -fstack-clash-protection with the Hardened: ./stat: FAIL: Parts of the binary were compiled without stack clash protection. Hardened: ./stat: FAIL: Parts of the binary were compiled without suffcient stack protection. Version-Release number of selected component (if applicable): gcc-toolset-9-gcc-9.2.1-2.2.el8 gcc-toolset-9-annobin-8.79-2.el8 How reproducible: Steps to Reproduce: 1. scl enable gcc-toolset-9 bash 2.gcc -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=z13 -mtune=z14 -fasynchronous-unwind-tables -fstack-clash-protection -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld stat.c -o stat 3. annocheck ./stat -v Actual results: annocheck: Version 8.78. Hardened: ./stat: binary producer gcc version 8. Hardened: ./stat: Warning: Multiple versions of a tool were used to build this file (9 8) - using highest version. Hardened: ./stat: FAIL: (component: main): No stack protection enabled. Hardened: ./stat: FAIL: (component: main): Compiled without -fstack-clash-protection. Hardened: ./stat: Warning: Multiple versions of a tool were used to build this file (8 9) - using highest version. Hardened: ./stat: Warning: Multiple versions of a tool were used to build this file (8 9) - using highest version. Hardened: ./stat: Warning: Multiple versions of a tool were used to build this file (8 9) - using highest version. Hardened: ./stat: PASS: No gaps found. Hardened: ./stat: PASS: Linked with -Wl,-z,now. Hardened: ./stat: skip: Test for control flow protection. (Only supported on x86 binaries). Hardened: ./stat: PASS: One dynamic section/segment found. Hardened: ./stat: skip: Entry point instruction is ENDBR. (Not an x86 binary). Hardened: ./stat: PASS: Compiled with -D_FORTIFY_SOURCE=2. Hardened: ./stat: PASS: Compiled with -D_GLIBCXX_ASSERTIONS. Hardened: ./stat: PASS: Linked with -Wl,-z,relro. Hardened: ./stat: PASS: Stack not executable. Hardened: ./stat: PASS: Compiled with sufficient optimization. Hardened: ./stat: PASS: Compiled with PIC/PIE. Hardened: ./stat: PASS: Compiled as a position independent binary. Hardened: ./stat: skip: GNU Property note check. (Only useful on x86_64 binaries). Hardened: ./stat: PASS: DT_RPATH/DT_RUNPATH absent or rooted at /usr. Hardened: ./stat: PASS: No RWX segments found. Hardened: ./stat: PASS: Consistent use of the -fshort-enum option. Hardened: ./stat: FAIL: Parts of the binary were compiled without stack clash protection. Hardened: ./stat: FAIL: Parts of the binary were compiled without suffcient stack protection. Hardened: ./stat: skip: Test for stack realignment support. (Only needed on i686 binaries). Hardened: ./stat: PASS: No text relocations found. Hardened: ./stat: PASS: No thread cancellation problems. Hardened: ./stat: PASS: GOT/PLT relocations are read only. Expected results: with gcc-8.3.1-4.5.el8, annobin-8.78-1.el8 annocheck -v ./stat annocheck: Version 8.78. Hardened: ./stat: binary producer gcc version 8. Hardened: ./stat: PASS: No gaps found. Hardened: ./stat: PASS: Linked with -Wl,-z,now. Hardened: ./stat: skip: Test for control flow protection. (Only supported on x86 binaries). Hardened: ./stat: PASS: One dynamic section/segment found. Hardened: ./stat: skip: Entry point instruction is ENDBR. (Not an x86 binary). Hardened: ./stat: PASS: Compiled with -D_FORTIFY_SOURCE=2. Hardened: ./stat: PASS: Compiled with -D_GLIBCXX_ASSERTIONS. Hardened: ./stat: PASS: Linked with -Wl,-z,relro. Hardened: ./stat: PASS: Stack not executable. Hardened: ./stat: PASS: Compiled with sufficient optimization. Hardened: ./stat: PASS: Compiled with PIC/PIE. Hardened: ./stat: PASS: Compiled as a position independent binary. Hardened: ./stat: skip: GNU Property note check. (Only useful on x86_64 binaries). Hardened: ./stat: PASS: DT_RPATH/DT_RUNPATH absent or rooted at /usr. Hardened: ./stat: PASS: No RWX segments found. Hardened: ./stat: PASS: Consistent use of the -fshort-enum option. Hardened: ./stat: PASS: Compiled with -fstack-clash-protection. Hardened: ./stat: PASS: Compiled with sufficient stack protection. Hardened: ./stat: skip: Test for stack realignment support. (Only needed on i686 binaries). Hardened: ./stat: PASS: No text relocations found. Hardened: ./stat: PASS: No thread cancellation problems. Hardened: ./stat: PASS: GOT/PLT relocations are read only. Hardened: ./stat: PASS.