Skip to content

Conversation

fanquake
Copy link
Member

@fanquake fanquake commented Feb 2, 2023

glibc 2.33 introduced a new fortification level, _FORTIFY_SOURCE=3. It improves the coverage of cases where _FORTIFY_SOURCE can use _chk functions.

For example, using GCC 13 and glibc 2.36 (Fedora Rawhide), compiling master:

nm -C src/bitcoind | grep _chk
                 U __fprintf_chk@GLIBC_2.17
                 U __memcpy_chk@GLIBC_2.17
                 U __snprintf_chk@GLIBC_2.17
                 U __sprintf_chk@GLIBC_2.17
                 U __stack_chk_fail@GLIBC_2.17
                 U __stack_chk_guard@GLIBC_2.17
                 U __vsnprintf_chk@GLIBC_2.17

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
33

vs this branch:

nm -C src/bitcoind | grep _chk
                 U __fprintf_chk@GLIBC_2.17
                 U __memcpy_chk@GLIBC_2.17
                 U __memset_chk@GLIBC_2.17
                 U __snprintf_chk@GLIBC_2.17
                 U __sprintf_chk@GLIBC_2.17
                 U __stack_chk_fail@GLIBC_2.17
                 U __stack_chk_guard@GLIBC_2.17
                 U __vsnprintf_chk@GLIBC_2.17

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
61

Usage of level 3 requires LLVM/Clang 9+, or GCC 12+. Older compilers/glibc will still use _FORTIFY_SOURCE=2. For example, in the glibc we currently use for Linux release builds (2.24), __USE_FORTIFY_LEVEL is determined using the following:

#if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0
# if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0
#  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
# elif !__GNUC_PREREQ (4, 1)
#  warning _FORTIFY_SOURCE requires GCC 4.1 or later
# elif _FORTIFY_SOURCE > 1
#  define __USE_FORTIFY_LEVEL 2
# else
#  define __USE_FORTIFY_LEVEL 1
# endif
#endif
#ifndef __USE_FORTIFY_LEVEL
# define __USE_FORTIFY_LEVEL 0
#endif

so any value > 1 will turn on _FORTIFY_SOURCE=2. This value detection logic has become slightly more complex in later versions of glibc.

https://sourceware.org/pipermail/libc-alpha/2021-February/122207.html
https://developers.redhat.com/blog/2021/04/16/broadening-compiler-checks-for-buffer-overflows-in-_fortify_source

@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 2, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK theuni
Concept ACK john-moffett, TheCharlatan

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@hebasto
Copy link
Member

hebasto commented Feb 2, 2023

https://sourceware.org/pipermail/libc-alpha/2021-February/122207.html:

At this level, glibc may use additional checks that may have an additional performance overhead.

Any estimations of the mentioned "additional performance overhead" for our binaries?

@theuni
Copy link
Member

theuni commented Feb 2, 2023

Hahaha, I was just poking at this myself today.

FYI support has been recently proposed to mingw as well: https://sourceforge.net/p/mingw-w64/mailman/message/37772473/

At this level, glibc may use additional checks that may have an additional performance overhead.

Any estimations of the mentioned "additional performance overhead" for our binaries?

This was my hesitation as well. It'd be nice to have a before/after for our benches at least.

Edit: Concept ACK, btw. And ACK after a quick bench shows it doesn't tank performace.

@john-moffett
Copy link
Contributor

john-moffett commented Feb 2, 2023

Concept ACK

Yeah, I ran the benchmarks before and after with both a Linux (GCC) and macOS (Clang) build and couldn’t see a significant change, not that I was expecting it on macOS at least. I may try more extensive measurements soon.

@theuni
Copy link
Member

theuni commented Feb 3, 2023

In order to test this, I decided to try out the recommended fortify metrics plugin for gcc.

I spent all day tracking down a bug in the plugin (PR'd what I believe to be the fix here). Next week I'll use it to gather some statistics on _FORTIFY_SOURCE=2 vs =3.

It will also be usable to test how much additional fortification we'd get if we built depends that way as well.

@fanquake
Copy link
Member Author

fanquake commented Feb 5, 2023

Hahaha, I was just poking at this myself today.

heh. I had just sent a doc change up to glibc before opening: bminor/glibc@1423a26.

FYI support has been recently proposed to mingw as well:

Looks like this has gone in mirror/mingw-w64@e34c747.

Note I've also opened #27038 to add a sanity check that foritification (like other haardneing) is being used in the release binaries.

@TheCharlatan
Copy link
Contributor

Concept ACK

Ran this on Ubuntu 22.04 with glibc 2.35 and clang 14. Also did not observe a significant slowdown of the benchmarks.
On master:

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
...
36

This branch:

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
...
76

glibc 2.33 introduced a new fortification level, _FORTIFY_SOURCE=3.
Which improves the coverage of cases where _FORTIFY_SOURCE can use _chk
functions. For example, using GCC 13 and glibc 2.36 (Fedora Rawhide),
compiling master:
```bash
nm -C src/bitcoind | grep _chk
                 U __fprintf_chk@GLIBC_2.17
                 U __memcpy_chk@GLIBC_2.17
                 U __snprintf_chk@GLIBC_2.17
                 U __sprintf_chk@GLIBC_2.17
                 U __stack_chk_fail@GLIBC_2.17
                 U __stack_chk_guard@GLIBC_2.17
                 U __vsnprintf_chk@GLIBC_2.17

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
33
```

vs this branch:
```bash
nm -C src/bitcoind | grep _chk
                 U __fprintf_chk@GLIBC_2.17
                 U __memcpy_chk@GLIBC_2.17
                 U __memset_chk@GLIBC_2.17
                 U __snprintf_chk@GLIBC_2.17
                 U __sprintf_chk@GLIBC_2.17
                 U __stack_chk_fail@GLIBC_2.17
                 U __stack_chk_guard@GLIBC_2.17
                 U __vsnprintf_chk@GLIBC_2.17

objdump -d src/bitcoind | grep "_chk@plt" | wc -l
61
```

Usage of level 3 requires LLVM/Clang 9+, or GCC 12+. Older
compilers/glibc will still use _FORTIFY_SOURCE=2. For example, in the
glibc we currently use for Linux release builds (2.24), FORTIFY_LEVEL is
determined using the following:
```c
```
so any value > 1 will turn on _FORTIFY_SOURCE=2.

https://sourceware.org/pipermail/libc-alpha/2021-February/122207.html
https://developers.redhat.com/blog/2021/04/16/broadening-compiler-checks-for-buffer-overflows-in-_fortify_source
@theuni
Copy link
Member

theuni commented Feb 17, 2023

ACK 4faa4e3. After playing with this quite a bit I didn't observe any noticeable pitfalls.

I'd expect this to matter more in low-level code, so I'm interested to see how much #27118 affects the numbers.

@fanquake fanquake merged commit 0561f34 into bitcoin:master Feb 20, 2023
@fanquake fanquake deleted the fortify_source_3 branch February 20, 2023 16:36
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 25, 2023
4faa4e3 build: use _FORTIFY_SOURCE=3 (fanquake)

Pull request description:

  [glibc 2.33](https://sourceware.org/pipermail/libc-alpha/2021-February/122207.html) introduced a new fortification level, `_FORTIFY_SOURCE=3`. It improves the coverage of cases where `_FORTIFY_SOURCE` can use `_chk` functions.

  For example, using GCC 13 and glibc 2.36 (Fedora Rawhide), compiling master:
  ```bash
  nm -C src/bitcoind | grep _chk
                   U __fprintf_chk@GLIBC_2.17
                   U __memcpy_chk@GLIBC_2.17
                   U __snprintf_chk@GLIBC_2.17
                   U __sprintf_chk@GLIBC_2.17
                   U __stack_chk_fail@GLIBC_2.17
                   U __stack_chk_guard@GLIBC_2.17
                   U __vsnprintf_chk@GLIBC_2.17

  objdump -d src/bitcoind | grep "_chk@plt" | wc -l
  33
  ```

  vs this branch:
  ```bash
  nm -C src/bitcoind | grep _chk
                   U __fprintf_chk@GLIBC_2.17
                   U __memcpy_chk@GLIBC_2.17
                   U __memset_chk@GLIBC_2.17
                   U __snprintf_chk@GLIBC_2.17
                   U __sprintf_chk@GLIBC_2.17
                   U __stack_chk_fail@GLIBC_2.17
                   U __stack_chk_guard@GLIBC_2.17
                   U __vsnprintf_chk@GLIBC_2.17

  objdump -d src/bitcoind | grep "_chk@plt" | wc -l
  61
  ```

  Usage of level 3 requires LLVM/Clang 9+, or GCC 12+. Older compilers/glibc will still use _FORTIFY_SOURCE=2. For example, in the glibc we currently use for Linux release builds (2.24), `__USE_FORTIFY_LEVEL` is determined using the following:
  ```c
  #if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0
  # if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0
  #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
  # elif !__GNUC_PREREQ (4, 1)
  #  warning _FORTIFY_SOURCE requires GCC 4.1 or later
  # elif _FORTIFY_SOURCE > 1
  #  define __USE_FORTIFY_LEVEL 2
  # else
  #  define __USE_FORTIFY_LEVEL 1
  # endif
  #endif
  #ifndef __USE_FORTIFY_LEVEL
  # define __USE_FORTIFY_LEVEL 0
  #endif
  ```
  so any value > 1 will turn on `_FORTIFY_SOURCE=2`. This value detection logic has become slightly more complex in later versions of glibc.

  https://sourceware.org/pipermail/libc-alpha/2021-February/122207.html
  https://developers.redhat.com/blog/2021/04/16/broadening-compiler-checks-for-buffer-overflows-in-_fortify_source

ACKs for top commit:
  theuni:
    ACK 4faa4e3. After playing with this quite a bit I didn't observe any noticeable pitfalls.

Tree-SHA512: e84ba49e3872c29fed1e2aea237b0d6bdff0d1274fa3297e2e08317cb62004396ee97b1cd6addb7c8b582498f3fa857a6d84c8e8f5ca97791b93985b47ff7faa
@maflcko
Copy link
Member

maflcko commented Mar 2, 2023

@kristapsk
Copy link
Contributor

On my Gentoo system with GCC 11.3.1 and glibc 2.36 this now gives me these warnings for each .cpp file when building Bitcoin Core:

  CXX      bitcoind-bitcoind.o
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/11/include/g++-v11/x86_64-pc-linux-gnu/bits/os_defines.h:39,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/11/include/g++-v11/x86_64-pc-linux-gnu/bits/c++config.h:586,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/11/include/g++-v11/bits/stl_algobase.h:59,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/11/include/g++-v11/memory:63,
                 from ./chainparamsbase.h:8,
                 from ./chainparams.h:9,
                 from bitcoind.cpp:10:
/usr/include/features.h:424:5: warning: #warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform [-Wcpp]
  424 | #   warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform
      |     ^~~~~~~

@kristapsk
Copy link
Contributor

This triggered https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=56529 ?

What's there?

image

@fanquake
Copy link
Member Author

fanquake commented Mar 8, 2023

This triggered https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=56529 ?

It will have been #27118 that triggered it. I can't look at this in more detail right now, but will by next week. It's possible that this is already fixed, and there is a patch/similar we can drop into depends.

On my Gentoo system with GCC 11.3.1 and glibc 2.36 this now gives me these warnings for each .cpp file when building Bitcoin Core

Looks like that's because you're using GCC 11.x, which doesn't support >=3 (it is supported with Clang >= 9). Somewhat annoying that glibc is going to warn like that, but they are also harmless, and fortification (level 2) is still being applied.

@kristapsk
Copy link
Contributor

Looks like that's because you're using GCC 11.x, which doesn't support >=3 (it is supported with Clang >= 9). Somewhat annoying that glibc is going to warn like that, but they are also harmless, and fortification (level 2) is still being applied.

Could we somehow detect this at configure stage and apply fortification 3 only if it is supported?

@bitcoin bitcoin locked and limited conversation to collaborators Mar 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants