From: "vo.x (Vit Ondruch) via ruby-core" Date: 2024-07-01T16:37:02+00:00 Subject: [ruby-core:118405] [Ruby master Bug#18061] Execshield test: libruby.so.N.N.N: FAIL: property-note test because no .note.gnu.property section found Issue #18061 has been updated by vo.x (Vit Ondruch). So I am experimenting with this simple patch: ~~~patch diff --git a/coroutine/amd64/Context.S b/coroutine/amd64/Context.S index fcc4b67bdc..b364fc06a1 100644 --- a/coroutine/amd64/Context.S +++ b/coroutine/amd64/Context.S @@ -4,6 +4,8 @@ ## Created by Samuel Williams on 10/5/2018. ## Copyright, 2018, by Samuel Williams. ## + +#include #define TOKEN_PASTE(x,y) x##y #define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) @@ -12,6 +14,8 @@ .globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): + + _CET_ENDBR # Make space on the stack for 6 registers: subq $48, %rsp ~~~ However, the patch alone is not enough, because there needs to be also the `-fcf-protection` propagated into the compiler. That can be workarounded by `export ASFLAGS='-fcf-protection'`. With these bits in place, I can pass the `annocheck`: ~~~ sh-5.2$ annocheck -v ./coroutine/amd64/Context.o annocheck: Version 12.59. Hardened: ./coroutine/amd64/Context.o: info: No matching profile found. Hardened: ./coroutine/amd64/Context.o: PASS: pie test because the ELF file header has the correct type Hardened: ./coroutine/amd64/Context.o: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: ./coroutine/amd64/Context.o: PASS: gnu-stack test because non-executable .note.GNU-stack section found Hardened: ./coroutine/amd64/Context.o: skip: gaps test because no notes found - therefore there are no gaps! Hardened: ./coroutine/amd64/Context.o: MAYB: test: notes, reason: annobin notes not found Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-notes.html Hardened: ./coroutine/amd64/Context.o: skip: bind-now test because only needed for executables Hardened: ./coroutine/amd64/Context.o: skip: branch-protection test because not an AArch64 binary Hardened: ./coroutine/amd64/Context.o: PASS: dynamic-segment test Hardened: ./coroutine/amd64/Context.o: skip: dynamic-tags test because AArch64 specific Hardened: ./coroutine/amd64/Context.o: PASS: entry test Hardened: ./coroutine/amd64/Context.o: PASS: fast test Hardened: ./coroutine/amd64/Context.o: skip: fips test because not a GO binary Hardened: ./coroutine/amd64/Context.o: skip: fortify test because no compiled C/C++ code found Hardened: ./coroutine/amd64/Context.o: skip: glibcxx-assertions test because no compiled C/C++ code found Hardened: ./coroutine/amd64/Context.o: skip: gnu-relro test because not needed in object files Hardened: ./coroutine/amd64/Context.o: skip: go-revision test because no GO compiled code found Hardened: ./coroutine/amd64/Context.o: skip: implicit-values test because These tests are only relevent to C source code Hardened: ./coroutine/amd64/Context.o: PASS: instrumentation test Hardened: ./coroutine/amd64/Context.o: skip: lto test because not compiled from C/C++ code Hardened: ./coroutine/amd64/Context.o: PASS: openssl-engine test Hardened: ./coroutine/amd64/Context.o: MAYB: test: optimization, reason: could not determine how the code was created Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-optimization.html Hardened: ./coroutine/amd64/Context.o: WARN: This can happen if the program is compiled from a language unknown to annocheck Hardened: ./coroutine/amd64/Context.o: WARN: or because there are no annobin build notes (could they be in a separate file ?) Hardened: ./coroutine/amd64/Context.o: WARN: For more details see https://sourceware.org/annobin/annobin.html/Absence-of-compiled-code.html Hardened: ./coroutine/amd64/Context.o: MAYB: test: pic, reason: no valid notes found regarding this test Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-pic.html Hardened: ./coroutine/amd64/Context.o: PASS: production test Hardened: ./coroutine/amd64/Context.o: skip: property-note test because property notes not needed in object files Hardened: ./coroutine/amd64/Context.o: PASS: run-path test Hardened: ./coroutine/amd64/Context.o: PASS: rwx-seg test Hardened: ./coroutine/amd64/Context.o: PASS: short-enums test Hardened: ./coroutine/amd64/Context.o: MAYB: test: stack-clash, reason: could not determine how the code was created Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-stack-clash.html Hardened: ./coroutine/amd64/Context.o: WARN: This can happen if the program is compiled from a language unknown to annocheck Hardened: ./coroutine/amd64/Context.o: WARN: or because there are no annobin build notes (could they be in a separate file ?) Hardened: ./coroutine/amd64/Context.o: WARN: For more details see https://sourceware.org/annobin/annobin.html/Absence-of-compiled-code.html Hardened: ./coroutine/amd64/Context.o: MAYB: test: stack-prot, reason: could not determine how the code was created Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-stack-prot.html Hardened: ./coroutine/amd64/Context.o: WARN: This can happen if the program is compiled from a language unknown to annocheck Hardened: ./coroutine/amd64/Context.o: WARN: or because there are no annobin build notes (could they be in a separate file ?) Hardened: ./coroutine/amd64/Context.o: WARN: For more details see https://sourceware.org/annobin/annobin.html/Absence-of-compiled-code.html Hardened: ./coroutine/amd64/Context.o: skip: stack-realign test because not an i686 executable Hardened: ./coroutine/amd64/Context.o: PASS: textrel test Hardened: ./coroutine/amd64/Context.o: PASS: threads test Hardened: ./coroutine/amd64/Context.o: PASS: unicode test Hardened: ./coroutine/amd64/Context.o: skip: warnings test because no compiled C/C++ code found Hardened: ./coroutine/amd64/Context.o: PASS: writable-got test Hardened: ./coroutine/amd64/Context.o: Overall: FAIL (due to MAYB results). sh-5.2$ annocheck -v mini miniinit.o miniruby sh-5.2$ annocheck -v miniruby annocheck: Version 12.59. Hardened: miniruby: info: No matching profile found. Hardened: miniruby: PASS: pie test because the ELF file header has the correct type Hardened: miniruby: info: written in C (source: DW_AT_language string). Hardened: miniruby: PASS: pic test because option found in DW_AT_producer string Hardened: miniruby: PASS: stack-prot test because option found in DW_AT_producer string Hardened: miniruby: PASS: optimization test because option found in DW_AT_producer string Hardened: miniruby: PASS: lto test because detected in DW_AT_producer string Hardened: miniruby: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: miniruby: PASS: writable-got test Hardened: miniruby: PASS: dynamic-segment test Hardened: miniruby: PASS: bind-now test Hardened: miniruby: PASS: notes test because annobin notes found in the .annobin.notes section Hardened: miniruby: skip: fast test because function ../sysdeps/x86/abi-note.c is part of the C library's static code and does use math functions Hardened: miniruby: skip: lto test because function ../sysdeps/x86/abi-note.c is part of the C library which is deliberately built without LTO Hardened: miniruby: PASS: implicit-values test because -Wimplicit-int and -Wimplicit-function-decalration enabled Hardened: miniruby: PASS: stack-clash test because compiled with -fstack-clash-protection Hardened: miniruby: skip: fortify test because function ../sysdeps/x86/abi-note.c is part of the C library, and as such it does not need fortification Hardened: miniruby: PASS: glibcxx-assertions test Hardened: miniruby: skip: warnings test because LTO compilation discards preprocessor options Hardened: miniruby: skip: implicit-values test because -Wimplicit-int setting is hidden by LTO Hardened: miniruby: PASS: entry test Hardened: miniruby: PASS: gnu-stack test because stack segment exists with the correct permissions Hardened: miniruby: PASS: gnu-relro test Hardened: miniruby: skip: gaps test because string notes imply full coverage Hardened: miniruby: skip: branch-protection test because not an AArch64 binary Hardened: miniruby: skip: dynamic-tags test because AArch64 specific Hardened: miniruby: skip: fips test because not a GO binary Hardened: miniruby: skip: go-revision test because no GO compiled code found Hardened: miniruby: PASS: instrumentation test Hardened: miniruby: PASS: openssl-engine test Hardened: miniruby: PASS: production test Hardened: miniruby: PASS: property-note test because CET enabled property note found Hardened: miniruby: PASS: run-path test Hardened: miniruby: PASS: rwx-seg test Hardened: miniruby: PASS: short-enums test Hardened: miniruby: skip: stack-realign test because not an i686 executable Hardened: miniruby: PASS: textrel test Hardened: miniruby: PASS: threads test Hardened: miniruby: PASS: unicode test Hardened: miniruby: Overall: PASS. sh-5.2$ annocheck -v libruby.so.3.3.2 annocheck: Version 12.59. Hardened: libruby.so.3.3.2: info: No matching profile found. Hardened: libruby.so.3.3.2: PASS: pie test because the ELF file header has the correct type Hardened: libruby.so.3.3.2: info: written in C (source: DW_AT_language string). Hardened: libruby.so.3.3.2: PASS: pic test because option found in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: stack-prot test because option found in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: optimization test because option found in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: lto test because detected in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: libruby.so.3.3.2: PASS: writable-got test Hardened: libruby.so.3.3.2: PASS: dynamic-segment test Hardened: libruby.so.3.3.2: PASS: bind-now test Hardened: libruby.so.3.3.2: PASS: notes test because annobin notes found in the .annobin.notes section Hardened: libruby.so.3.3.2: skip: warnings test because LTO compilation discards preprocessor options Hardened: libruby.so.3.3.2: skip: implicit-values test because -Wimplicit-int setting is hidden by LTO Hardened: libruby.so.3.3.2: skip: fortify test because LTO compilation discards preprocessor options Hardened: libruby.so.3.3.2: PASS: glibcxx-assertions test Hardened: libruby.so.3.3.2: PASS: stack-clash test because compiled with -fstack-clash-protection Hardened: libruby.so.3.3.2: skip: entry test because shared libraries do not use entry points Hardened: libruby.so.3.3.2: PASS: gnu-stack test because stack segment exists with the correct permissions Hardened: libruby.so.3.3.2: PASS: gnu-relro test Hardened: libruby.so.3.3.2: skip: gaps test because string notes imply full coverage Hardened: libruby.so.3.3.2: skip: branch-protection test because not an AArch64 binary Hardened: libruby.so.3.3.2: skip: dynamic-tags test because AArch64 specific Hardened: libruby.so.3.3.2: PASS: fast test Hardened: libruby.so.3.3.2: skip: fips test because not a GO binary Hardened: libruby.so.3.3.2: skip: go-revision test because no GO compiled code found Hardened: libruby.so.3.3.2: PASS: instrumentation test Hardened: libruby.so.3.3.2: PASS: openssl-engine test Hardened: libruby.so.3.3.2: PASS: production test Hardened: libruby.so.3.3.2: PASS: property-note test because CET enabled property note found Hardened: libruby.so.3.3.2: PASS: run-path test Hardened: libruby.so.3.3.2: PASS: rwx-seg test Hardened: libruby.so.3.3.2: PASS: short-enums test Hardened: libruby.so.3.3.2: skip: stack-realign test because not an i686 executable Hardened: libruby.so.3.3.2: PASS: textrel test Hardened: libruby.so.3.3.2: PASS: threads test Hardened: libruby.so.3.3.2: PASS: unicode test Hardened: libruby.so.3.3.2: Overall: PASS. ~~~ and this is the diff to version without the steps above: ~~~ --- +++ @@ -2,14 +2,13 @@ annocheck: Version 12.59. Hardened: ./coroutine/amd64/Context.o: info: No matching profile found. Hardened: ./coroutine/amd64/Context.o: PASS: pie test because the ELF file header has the correct type +Hardened: ./coroutine/amd64/Context.o: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: ./coroutine/amd64/Context.o: PASS: gnu-stack test because non-executable .note.GNU-stack section found Hardened: ./coroutine/amd64/Context.o: skip: gaps test because no notes found - therefore there are no gaps! Hardened: ./coroutine/amd64/Context.o: MAYB: test: notes, reason: annobin notes not found Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-notes.html Hardened: ./coroutine/amd64/Context.o: skip: bind-now test because only needed for executables Hardened: ./coroutine/amd64/Context.o: skip: branch-protection test because not an AArch64 binary -Hardened: ./coroutine/amd64/Context.o: FAIL: cf-protection test because no .note.gnu.property section = no control flow information -Hardened: ./coroutine/amd64/Context.o: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html Hardened: ./coroutine/amd64/Context.o: PASS: dynamic-segment test Hardened: ./coroutine/amd64/Context.o: skip: dynamic-tags test because AArch64 specific Hardened: ./coroutine/amd64/Context.o: PASS: entry test @@ -51,7 +50,9 @@ Hardened: ./coroutine/amd64/Context.o: PASS: unicode test Hardened: ./coroutine/amd64/Context.o: skip: warnings test because no compiled C/C++ code found Hardened: ./coroutine/amd64/Context.o: PASS: writable-got test -Hardened: ./coroutine/amd64/Context.o: Overall: FAIL. +Hardened: ./coroutine/amd64/Context.o: Overall: FAIL (due to MAYB results). + sh-5.2$ annocheck -v mini +miniinit.o miniruby sh-5.2$ annocheck -v miniruby annocheck: Version 12.59. Hardened: miniruby: info: No matching profile found. @@ -61,6 +62,7 @@ Hardened: miniruby: PASS: stack-prot test because option found in DW_AT_producer string Hardened: miniruby: PASS: optimization test because option found in DW_AT_producer string Hardened: miniruby: PASS: lto test because detected in DW_AT_producer string +Hardened: miniruby: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: miniruby: PASS: writable-got test Hardened: miniruby: PASS: dynamic-segment test Hardened: miniruby: PASS: bind-now test @@ -78,16 +80,13 @@ Hardened: miniruby: PASS: gnu-relro test Hardened: miniruby: skip: gaps test because string notes imply full coverage Hardened: miniruby: skip: branch-protection test because not an AArch64 binary -Hardened: miniruby: FAIL: cf-protection test because no .note.gnu.property section = no control flow information -Hardened: miniruby: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html Hardened: miniruby: skip: dynamic-tags test because AArch64 specific Hardened: miniruby: skip: fips test because not a GO binary Hardened: miniruby: skip: go-revision test because no GO compiled code found Hardened: miniruby: PASS: instrumentation test Hardened: miniruby: PASS: openssl-engine test Hardened: miniruby: PASS: production test -Hardened: miniruby: FAIL: property-note test because a property note was found but it shows that cf-protection is not enabled -Hardened: miniruby: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-property-note.html +Hardened: miniruby: PASS: property-note test because CET enabled property note found Hardened: miniruby: PASS: run-path test Hardened: miniruby: PASS: rwx-seg test Hardened: miniruby: PASS: short-enums test @@ -95,7 +94,7 @@ Hardened: miniruby: PASS: textrel test Hardened: miniruby: PASS: threads test Hardened: miniruby: PASS: unicode test -Hardened: miniruby: Overall: FAIL. +Hardened: miniruby: Overall: PASS. sh-5.2$ annocheck -v libruby.so.3.3.2 annocheck: Version 12.59. Hardened: libruby.so.3.3.2: info: No matching profile found. @@ -105,6 +104,7 @@ Hardened: libruby.so.3.3.2: PASS: stack-prot test because option found in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: optimization test because option found in DW_AT_producer string Hardened: libruby.so.3.3.2: PASS: lto test because detected in DW_AT_producer string +Hardened: libruby.so.3.3.2: PASS: cf-protection test because correct flags found in .note.gnu.property note Hardened: libruby.so.3.3.2: PASS: writable-got test Hardened: libruby.so.3.3.2: PASS: dynamic-segment test Hardened: libruby.so.3.3.2: PASS: bind-now test @@ -119,8 +119,6 @@ Hardened: libruby.so.3.3.2: PASS: gnu-relro test Hardened: libruby.so.3.3.2: skip: gaps test because string notes imply full coverage Hardened: libruby.so.3.3.2: skip: branch-protection test because not an AArch64 binary -Hardened: libruby.so.3.3.2: FAIL: cf-protection test because no .note.gnu.property section = no control flow information -Hardened: libruby.so.3.3.2: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html Hardened: libruby.so.3.3.2: skip: dynamic-tags test because AArch64 specific Hardened: libruby.so.3.3.2: PASS: fast test Hardened: libruby.so.3.3.2: skip: fips test because not a GO binary @@ -128,8 +126,7 @@ Hardened: libruby.so.3.3.2: PASS: instrumentation test Hardened: libruby.so.3.3.2: PASS: openssl-engine test Hardened: libruby.so.3.3.2: PASS: production test -Hardened: libruby.so.3.3.2: FAIL: property-note test because a property note was found but it shows that cf-protection is not enabled -Hardened: libruby.so.3.3.2: info: For more information visit: https://sourceware.org/annobin/annobin.html/Test-property-note.html +Hardened: libruby.so.3.3.2: PASS: property-note test because CET enabled property note found Hardened: libruby.so.3.3.2: PASS: run-path test Hardened: libruby.so.3.3.2: PASS: rwx-seg test Hardened: libruby.so.3.3.2: PASS: short-enums test @@ -137,4 +134,4 @@ Hardened: libruby.so.3.3.2: PASS: textrel test Hardened: libruby.so.3.3.2: PASS: threads test Hardened: libruby.so.3.3.2: PASS: unicode test -Hardened: libruby.so.3.3.2: Overall: FAIL. +Hardened: libruby.so.3.3.2: Overall: PASS. ~~~ ---------------------------------------- Bug #18061: Execshield test: libruby.so.N.N.N: FAIL: property-note test because no .note.gnu.property section found https://bugs.ruby-lang.org/issues/18061#change-108922 * Author: jaruga (Jun Aruga) * Status: Open * Assignee: kjtsanaktsidis (KJ Tsanaktsidis) * Backport: 2.6: UNKNOWN, 2.7: REQUIRED, 3.0: REQUIRED ---------------------------------------- I found an issue in our company's internal test called "execshield" by a security tool annobin - annocheck command [1][2]. ``` Hardened: libruby.so.2.7.4: FAIL: property-note test because no .note.gnu.property section found ``` Here is the reproducer on the upstream latest master, commit is 5f2987d6c2ae9ace3178ac3e1bbb4ac7079101eb, ``` $ autoconf $ ./configure --enable-shared $ make $ ls libruby.so.3.1.0 libruby.so.3.1.0* ``` If you are using Red Hat based Linux distro, it's easy to install by the RPM package like this. ``` $ sudo dnf -y install annobin-annocheck ``` ``` $ sudo yum -y install annobin-annocheck ``` Then ``` $ annocheck libruby.so.3.1.0 ``` If you are using other Linux distros such as Ubuntu, you can use it by a container I prepared. Prepare the following `Dockerfile`. ``` $ cat Dockerfile FROM docker.io/fedora:34 RUN cat /etc/fedora-release RUN dnf -y install annobin-annocheck WORKDIR /work ``` Then build the container image with the `Dockerfile` and run the annocheck command for the `libruby.so.3.1.0` on your host environment. The `-v` is an option for bind mount between host and container environment. ``` $ docker build --rm -t fedora-annocheck . $ docker run --rm -t -v $(pwd):/work fedora-annocheck annocheck /work/libruby.so.3.1.0 annocheck: Version 9.79. Hardened: libruby.so.3.1.0: FAIL: bind-now test because not linked with -Wl,-z,now Hardened: libruby.so.3.1.0: FAIL: notes test because gaps were detected in the annobin coverage Hardened: libruby.so.3.1.0: FAIL: cf-protection test because no .note.gnu.property section = no control flow information Hardened: libruby.so.3.1.0: FAIL: property-note test because no .note.gnu.property section found Hardened: Rerun annocheck with --verbose to see more information on the tests. ``` The message `Hardened: libruby.so.3.1.0: FAIL: property-note test because no .note.gnu.property section found` is what I found in our internal test. For other FAIL messages, maybe it can be fixed by changing how to build. Asking a colleague, I was told that the `coroutine/*/Context.S` files such as [coroutine/x86/Context.S](https://github.com/ruby/ruby/blob/master/coroutine/x86/Context.S) cause the failure. Do you have any idea how to fix this? Thanks. * [1] https://sourceware.org/annobin/ * [2] You can see `man annocheck` or https://www.mankier.com/1/annocheck . ---Files-------------------------------- 0001-Add-.note.gnu.property-sections.patch (2.64 KB) 0001-Add-.note.gnu.property-sections.patch (3.69 KB) config-pie.log (11.4 KB) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/