Project

General

Profile

Actions

Bug #18061

open

Execshield test: libruby.so.N.N.N: FAIL: property-note test because no .note.gnu.property section found

Added by jaruga (Jun Aruga) 3 months ago. Updated 2 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:104774]

Description

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 cause the failure. Do you have any idea how to fix this? Thanks.


Files

Updated by jaruga (Jun Aruga) 3 months ago

Thanks for the patch! Let me check it.

Updated by jaruga (Jun Aruga) 2 months ago

I applied the patch for the Ruby 3.0.2 in RHEL 8, built. But I still see the failed message.

annocheck: Version 9.65.
Hardened: libruby.so.3.0.2: FAIL: property-note test because no .note.gnu.property section found
Hardened: Rerun annocheck with --verbose to see more information on the tests.

I also applied the patch to the Ruby on master branch 1cb5a669d39fe741388be7ac45fc88c336b097cf . But the message is same.

$ autoconf
$ ./configure --enable-shared
$ make

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

So, I don't think that adding the empty section works.

Updated by jaruga (Jun Aruga) 2 months ago

By the way, I found a case generating ".note.gnu.property section" in the OpenSSL project.
https://github.com/openssl/openssl/commit/51994e505dbb1cd0dd76869ec962e2948b77b585

The commit message explains how they verified the change. So in the case of Ruby, here is a way to verify?

I also applied the patch to the Ruby on master branch 1cb5a669d39fe741388be7ac45fc88c336b097cf .

On the above commit, I see an error because there is no .note.gnu.property non-empty section?

$ autoconf

$ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure --enable-shared

$ make
...
/bin/ld: coroutine/amd64/Context.o: error: missing IBT and SHSTK properties
/bin/ld: probes.o: error: missing IBT and SHSTK properties
collect2: error: ld returned 1 exit status
make: *** [Makefile:277: miniruby] Error 1

$ echo $?
2

Updated by jaruga (Jun Aruga) 2 months ago

It seems we can check if the .note.gnu.property exists in a binary file by the command readelf -S --wide <file>. The binary file ruby has it. But the file libruby.so.3.1.0 doesn't it.

$ readelf -S --wide ruby
There are 40 section headers, starting at offset 0x36038:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000400318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000400338 000338 000020 00   A  0   0  8
...
$ readelf -S --wide libruby.so.3.1.0
There are 42 section headers, starting at offset 0xc15a38:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.build-id NOTE            0000000000000270 000270 000024 00   A  0   0  4
  [ 2] .gnu.hash         GNU_HASH        0000000000000298 000298 0033e4 00   A  3   0  8
...

Updated by jaruga (Jun Aruga) 2 months ago

Thanks for the patch! Let me check it.

Updated by ioquatix (Samuel Williams) 2 months ago

On another side, we have an Intel CET [2], [3]:
"Control-flow Enforcement Technology (CET) provides the following capabilities to defend
against ROP/JOP style control-flow subversion attacks:
- Shadow Stack - return address protection to defend against Return Oriented Programming,
- Indirect branch tracking - free branch protection to defend against Jump/Call Oriented Programming.‚Äč"

Intel CET uses following processor-specific program property types in .note.gnu.property [3, p85, p87]:

* GNU_PROPERTY_X86_FEATURE_1_IBT This indicates that all executable sections are compatible
with IBT (see Section 13.1.1) when endbr64 instruction starts each valid target where an indirect
branch instruction can land. 8
* GNU_PROPERTY_X86_FEATURE_1_SHSTK This indicates that all executable sections are compatible
with SHSTK (see Section 13.1.2) where return address popped from shadow stack always matches
return address popped from normal stack.

We should confirm that coroutine stack swapping is compatible with GNU_PROPERTY_X86_FEATURE_1_SHSTK.

Updated by jaruga (Jun Aruga) 2 months ago

Thanks for the patch! Let me check it.

0001-Add-.note.gnu.property-sections.patch (3.69 KB)

I tried the 2nd patch on an older master commit 1cb5a669d39fe741388be7ac45fc88c336b097cf , as I couldn't build on the latest master commit due to #18072 . But I still see similar or same result.

$ gcc --version
gcc (GCC) 11.2.1 20210728 (Red Hat 11.2.1-1)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

With -Wl,-z,cet-report=error

$ autoconf
$ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure --enable-shared
$ make
...
vm_call_iseq_optimized.inc updated
generating vmtc.inc
compiling vm.c
compiling vm_backtrace.c
compiling vm_dump.c
compiling vm_sync.c
making trace_point.rbinc
compiling vm_trace.c
assembling coroutine/amd64/Context.S
processing probes in object files
compiling enc/ascii.c
compiling enc/us_ascii.c
compiling enc/unicode.c
compiling enc/utf_8.c
generating enc/trans/newline.c ...
compiling enc/trans/newline.c
compiling ./missing/setproctitle.c
compiling ./missing/strlcat.c
compiling ./missing/strlcpy.c
compiling addr2line.c
compiling dmyenc.c
linking miniruby
/bin/ld: probes.o: error: missing IBT and SHSTK properties
collect2: error: ld returned 1 exit status
make: *** [Makefile:277: miniruby] Error 1

Check by annocheck and readelf.

$ autoconf
$ ./configure --enable-shared
$ make
$ annocheck 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.

$ readelf -S --wide libruby.so.3.1.0
  => No .note.gnu.property section.
Actions #10

Updated by jaruga (Jun Aruga) 2 months ago

  • Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: UNKNOWN, 2.7: REQUIRED, 3.0: REQUIRED
Actions

Also available in: Atom PDF