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 | ||||||
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.