Skip to content

Conversation

fanquake
Copy link
Member

@fanquake fanquake commented May 9, 2020

Beginning with Ubuntu 19.10, it's packaged GCC now has some additional hardening options enabled by default (in addition to existing defaults like -fstack-protector-strong and reducing the minimum ssp buffer size). The new additions are-fcf-protection=full and -fstack-clash-protection.

-fcf-protection=[full|branch|return|none]
Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This prevents diverting the flow of control to an unexpected target. This is intended to protect against such threats as Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).

-fstack-clash-protection
Generate code to prevent stack clash style attacks. When this option is enabled, the compiler will only allocate one page of stack space at a time and each page is accessed immediately after allocation. Thus, it prevents allocations from jumping over any stack guard page provided by the operating system.

If your interested you can grab gcc-9_9.3.0-10ubuntu2.debian.tar.xz from https://packages.ubuntu.com/focal/g++-9. The relevant changes are part of the gcc-distro-specs patches, along with the relevant additions to the gcc manages:

NOTE: In Ubuntu 19.10 and later versions, -fcf-protection is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-cf-protection nor -fcf-protection=* are found.

NOTE: In Ubuntu 19.10 and later versions, -fstack-clash-protection is enabled by default for C, C++, ObjC, ObjC++, unless -fno-stack-clash-protection is found.

So, if you're C++ using GCC on Ubuntu 19.10 or later, these options will be active unless you explicitly opt out. This can be observed with a small test:

int main() { return 0; }
g++ --version 
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

g++ test.cpp

objdump -dC a.out
..
0000000000001129 <main>:
    1129:	f3 0f 1e fa          	endbr64 
    112d:	55                   	push   %rbp
    112e:	48 89 e5             	mov    %rsp,%rbp
    1131:	b8 00 00 00 00       	mov    $0x0,%eax
    1136:	5d                   	pop    %rbp
    1137:	c3                   	retq   
    1138:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
    113f:	00


# recompile opting out of control flow protection
g++ test.cpp -fcf-protection=none

objdump -dC a.out
...
0000000000001129 <main>:
    1129:	55                   	push   %rbp
    112a:	48 89 e5             	mov    %rsp,%rbp
    112d:	b8 00 00 00 00       	mov    $0x0,%eax
    1132:	5d                   	pop    %rbp
    1133:	c3                   	retq   
    1134:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
    113b:	00 00 00 
    113e:	66 90                	xchg   %ax,%ax

Note the insertion of an endbr64 instruction when compiling and not opting out. This instruction is part of the Intel Control-flow Enforcement Technology spec, which the GCC control flow implementation is based on.

If we're still doing gitian builds for the 0.21.0 and 0.22.0 releases, we'd likely update the gitian image to Ubuntu Focal, which would mean that the GCC used for gitian builds would also be using these options by default. So we should decide whether we want to explicitly turn these options on as part of our hardening options (although not just for this reason), or, we should be opting-out.

GCC has supported both options since 8.0.0. Clang has supported -fcf-protection from 7.0.0 and will support -fstack-clash-protection in it's upcoming 11.0.0 release.

configure.ac Outdated
@@ -768,6 +768,9 @@ if test x$use_hardening != xno; then
AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"])

AX_CHECK_COMPILE_FLAG([-fcf-protection],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fcf-protection=full"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the mismatch between -fcf-protection (left) and -fcf-protection=full (right) intentional? :)

@sipa
Copy link
Member

sipa commented May 9, 2020

The big question is what - if any - impact these options have on performance?

@practicalswift
Copy link
Contributor

Strongest possible concept ACK for additional hardening: thanks a lot for taking lead on this important work!

Performance impact would be nice to have quantified as @sipa requested to be able to reason about trade-offs :)

@fanquake
Copy link
Member Author

The big question is what - if any - impact these options have on performance?

I was hoping I could tag in @jamesob for a couple benchmarks if possible?

@DrahtBot
Copy link
Contributor

Gitian builds

File commit 88d8b4e
(master)
commit 161c933
(master and this pull)
*-aarch64-linux-gnu-debug.tar.gz 369f45f49680bb03... b4d2135fc9b073e8...
*-aarch64-linux-gnu.tar.gz 8815fb42dbd6f035... 177fd9ced6bd602d...
*-arm-linux-gnueabihf-debug.tar.gz c18e08956f03cbfb... f6ebc519988abffd...
*-arm-linux-gnueabihf.tar.gz 45e33867d52277e1... a72ddd6e936d135b...
*-osx-unsigned.dmg c9eeee10330ee2b9... f73bbb9a17b854fe...
*-osx64.tar.gz 238b1b155bbde568... 88e464ddb830fbe8...
*-riscv64-linux-gnu-debug.tar.gz 190c87703632edd7... a77a0fea842a79e9...
*-riscv64-linux-gnu.tar.gz aac282c4af7d5944... 78d8a7dbc8f23f7b...
*-win64-debug.zip 0a8ac7d8454af240... 25ef4d700bd26bdd...
*-win64-setup-unsigned.exe 2500497846b0eebd... df5be8d409ce3282...
*-win64.zip 78402ce9625df621... cdf020765a1177de...
*-x86_64-linux-gnu-debug.tar.gz 5562d24f28e9ee15... ea88315bc0416c59...
*-x86_64-linux-gnu.tar.gz cd1c4bb3f22de2c1... c4d0b54fde1b53d0...
*.tar.gz c84b1941b1714f4f... 20b314b7da36b35b...
bitcoin-core-linux-0.21-res.yml 9b5de9f3ddb6316d... b5bdc135df557ec5...
bitcoin-core-osx-0.21-res.yml e431693014049dd8... b376622e0dd37546...
bitcoin-core-win-0.21-res.yml 75df8c423af3ce9d... 6e142cf994767195...
linux-build.log 0d674036963b8877... 5b103a54574bd5f2...
osx-build.log de659e88e298c8ab... 24abd0649ea30b7c...
win-build.log a01a9c1b8d076f53... f764bcfb00de2704...
bitcoin-core-linux-0.21-res.yml.diff 15a360a0fa828e73...
bitcoin-core-osx-0.21-res.yml.diff 693ba84c1a0c2f9f...
bitcoin-core-win-0.21-res.yml.diff fe51427716a8e54c...
linux-build.log.diff 9c63d277af01fdab...
osx-build.log.diff 184b4fafee467a9b...
win-build.log.diff 258002653b7bdbe6...

@maflcko
Copy link
Member

maflcko commented Jun 18, 2020

For reference, the guix build fails for win64
Making all in src
make[1]: Entering directory '/bitcoin/distsrc-x86_64-w64-mingw32/src'
make[2]: Entering directory '/bitcoin/distsrc-x86_64-w64-mingw32/src'
x86_64-w64-mingw32-g++ -std=c++11 -DHAVE_CONFIG_H -I. -I../src/config   -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -I.  -DBOOST_SP_USE_STD_ATOMIC -DBOOST_AC_USE_STD_ATOMIC -mthreads -I/bitcoin/depends/x86_64-w64-mingw32/share/../include -I./leveldb/include -I./leveldb/helpers/memenv -I./secp256k1/include -I./univalue/include -I/bitcoin/depends/x86_64-w64-mingw32/share/../include/  -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601 -D_FILE_OFFSET_BITS=64  -fstack-reuse=none -Wstack-protector -fstack-protector-all -fcf-protection=full -fstack-clash-protection      -fPIE -pipe -O2 -O2 -g -fno-ident -fno-extended-identifiers -fvisibility=hidden -c -o bitcoind-bitcoind.o `test -f 'bitcoind.cpp' || echo './'`bitcoind.cpp
during RTL pass: final
In file included from ./logging.h:10,
                 from ./util/system.h:21,
                 from ./init.h:11,
                 from bitcoind.cpp:13:
./tinyformat.h: In static member function 'static int tinyformat::detail::FormatArg::toIntImpl(const void*) [with T = std::__cxx11::basic_string<char>]':
./tinyformat.h:550:9: internal compiler error: in seh_emit_stackalloc, at config/i386/winnt.c:1043
  550 |         }
      |         ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
{standard input}: Assembler messages:
{standard input}: Error: open CFI at the end of file; missing .cfi_endproc directive
make[2]: *** [Makefile:14690: bitcoind-bitcoind.o] Error 1
make[2]: Leaving directory '/bitcoin/distsrc-x86_64-w64-mingw32/src'
make[1]: *** [Makefile:18181: all-recursive] Error 1
make[1]: Leaving directory '/bitcoin/distsrc-x86_64-w64-mingw32/src'
make: *** [Makefile:787: all-recursive] Error 1

fanquake added 2 commits June 19, 2020 17:20
Enables code instrumentation of control-flow transfers. Available in
GCC 8 and Clang 7.

This option is now on by default in Ubuntu GCC as of 19.10.
This option causes the compiler to insert probes whenever stack space
is allocated statically or dynamically to reliably detect stack overflows
and thus mitigate the attack vector that relies on jumping over a stack
guard page as provided by the operating system.

This option is now enabled by default in Ubuntu GCC as of 19.10.

Available in GCC 8 and Clang 11.
@fanquake fanquake force-pushed the add_cfi_to_hardening branch from 45a7f48 to b536813 Compare June 19, 2020 10:11
@fanquake fanquake marked this pull request as ready for review June 19, 2020 10:12
@fanquake
Copy link
Member Author

I've modified this to include the test case from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458, for -stack-clash-protection, rather than my test case from #19318.

@theuni
Copy link
Member

theuni commented Jun 19, 2020

Setting aside for a moment whether we should enable these, the code changes look good to me.

I agree with @fanquake's point here:

So we should decide whether we want to explicitly turn these options on as part of our hardening options (although not just for this reason), or, we should be opting-out.

Rather than letting distro's make the call, we should make a decision and explicitly opt-in or opt-out ourselves.

Agree with @sipa as well:

The big question is what - if any - impact these options have on performance?

With all of the stack safety options we're tweaking lately, I think it would be helpful to make sure we're not blowing up a bunch of our chained small+common hot-path functions with wasteful stack guarding operations. The most obvious that come to mind are the byteswapping and endian-changing functions in compat/. We generally assume (I always have, anyway) that those all end up inlined and thus having a negligible performance impact, but I think there's a slight chance that these options may change that assumption. That's not to say that we wouldn't want the additional stack protection safety in that case, only that we'd want to be more mindful of inlining annotations.

So in addition to running our existing benchmarks, how about adding one specifically to exercise a bunch of those small functions on either side of the fringe of inlining?

@laanwj
Copy link
Member

laanwj commented Aug 13, 2020

I think that we should ideally opt in to these options. If they're deemed suitable for general distribution use, I don't think the performance impact can be that substantial. It's still better to measure, of course.
Would be nice to get this in 0.21.0.

@laanwj laanwj added this to the 0.21.0 milestone Aug 13, 2020
@hebasto
Copy link
Member

hebasto commented Aug 27, 2020

Concept ACK on more code hardening and explicit compiler flag settings.

@jamesob
Copy link
Contributor

jamesob commented Aug 27, 2020

I was hoping I could tag in @jamesob for a couple benchmarks if possible?

Sorry for the delay here, missed the notification. Will run a few benchmarks.

@jamesob
Copy link
Contributor

jamesob commented Aug 28, 2020

Changes look good to me.

ibd local range 500000 505000

11:27:57 james@slug /home/james % g++-8 --version
g++-8 (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 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.

11:28:03 james@slug /home/james % g++-9 --version
g++-9 (Debian 9.3.0-17) 9.3.0
Copyright (C) 2019 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.

11:28:10 james@slug /home/james % grep HARDEN ~/.bitcoinperf/runs/latest/artifacts-build.make.4.gcc-add_cfi_to_hardening.0/config.log
HARDENED_CPPFLAGS=' -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2'
HARDENED_CXXFLAGS=' -fstack-reuse=none -Wstack-protector -fstack-protector-all -fcf-protection=full -fstack-clash-protection'
HARDENED_LDFLAGS=' -Wl,-z,relro -Wl,-z,now -Wl,-z,separate-code -pie'
HARDEN_FALSE='#'
HARDEN_TRUE=''

11:29:23 james@slug /home/james % grep HARDEN ~/.bitcoinperf/runs/latest/artifacts-build.make.4.gcc-master.0/config.log
HARDENED_CPPFLAGS=' -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2'
HARDENED_CXXFLAGS=' -fstack-reuse=none -Wstack-protector -fstack-protector-all'
HARDENED_LDFLAGS=' -Wl,-z,relro -Wl,-z,now -Wl,-z,separate-code -pie'
HARDEN_FALSE='#'
HARDEN_TRUE=''

Note that the peer servicing this IBD test was on my local network, not co-located on the same host (I don't have enough disk space for that on a single host) but I think that should be fine given that it sort of resembles realistic use and we're just looking for red flags here.

@jamesob
Copy link
Contributor

jamesob commented Aug 28, 2020

ACK b536813 (jamesob/ackr/18921.1.fanquake.build_add_stack_clash_an)

Tested locally via bench results above.

@laanwj
Copy link
Member

laanwj commented Aug 29, 2020

Thanks for doing benchmarks @jamesob !
Code review ACK b536813

@laanwj laanwj merged commit 4631dc5 into bitcoin:master Aug 29, 2020
@fanquake fanquake deleted the add_cfi_to_hardening branch August 30, 2020 03:26
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Aug 30, 2020
…on options to hardening flags

b536813 build: add -fstack-clash-protection to hardening flags (fanquake)
076183b build: add -fcf-protection=full to hardening options (fanquake)

Pull request description:

  Beginning with Ubuntu `19.10`, it's packaged GCC now has some additional hardening options enabled by default (in addition to existing defaults like `-fstack-protector-strong` and reducing the minimum ssp buffer size). The new additions are`-fcf-protection=full` and `-fstack-clash-protection`.

  > -fcf-protection=[full|branch|return|none]
  > Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This prevents diverting the flow of control to an unexpected target. This is intended to protect against such threats as Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).

  > -fstack-clash-protection
  > Generate code to prevent stack clash style attacks. When this option is enabled, the compiler will only allocate one page of stack space at a time and each page is accessed immediately after allocation. Thus, it prevents allocations from jumping over any stack guard page provided by the operating system.

  If your interested you can grab `gcc-9_9.3.0-10ubuntu2.debian.tar.xz` from https://packages.ubuntu.com/focal/g++-9. The relevant changes are part of the `gcc-distro-specs` patches, along with the relevant additions to the gcc manages:

  > NOTE: In Ubuntu 19.10 and later versions, -fcf-protection is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-cf-protection nor -fcf-protection=* are found.

  > NOTE: In Ubuntu 19.10 and later versions, -fstack-clash-protection is enabled by default for C, C++, ObjC, ObjC++, unless -fno-stack-clash-protection is found.

  So, if you're C++ using GCC on Ubuntu 19.10 or later, these options will be active unless you explicitly opt out. This can be observed with a small test:

  ```c++
  int main() { return 0; }
  ```

  ```bash
  g++ --version
  g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

  g++ test.cpp

  objdump -dC a.out
  ..
  0000000000001129 <main>:
      1129:	f3 0f 1e fa          	endbr64
      112d:	55                   	push   %rbp
      112e:	48 89 e5             	mov    %rsp,%rbp
      1131:	b8 00 00 00 00       	mov    $0x0,%eax
      1136:	5d                   	pop    %rbp
      1137:	c3                   	retq
      1138:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
      113f:	00

  # recompile opting out of control flow protection
  g++ test.cpp -fcf-protection=none

  objdump -dC a.out
  ...
  0000000000001129 <main>:
      1129:	55                   	push   %rbp
      112a:	48 89 e5             	mov    %rsp,%rbp
      112d:	b8 00 00 00 00       	mov    $0x0,%eax
      1132:	5d                   	pop    %rbp
      1133:	c3                   	retq
      1134:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
      113b:	00 00 00
      113e:	66 90                	xchg   %ax,%ax
  ```

  Note the insertion of an `endbr64` instruction when compiling and _not_ opting out. This instruction is part of the Intel Control-flow Enforcement Technology [spec](https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf), which the GCC control flow implementation is based on.

  If we're still doing gitian builds for the `0.21.0` and `0.22.0` releases, we'd likely update the gitian image to Ubuntu Focal, which would mean that the GCC used for gitian builds would also be using these options by default. So we should decide whether we want to explicitly turn these options on as part of our hardening options (although not just for this reason), or, we should be opting-out.

  GCC has supported both options since 8.0.0. Clang has supported `-fcf-protection` from 7.0.0 and will support `-fstack-clash-protection` in it's upcoming [11.0.0 release](https://clang.llvm.org/docs/ReleaseNotes.html#id6).

ACKs for top commit:
  jamesob:
    ACK b536813 ([`jamesob/ackr/18921.1.fanquake.build_add_stack_clash_an`](https://github.com/jamesob/bitcoin/tree/ackr/18921.1.fanquake.build_add_stack_clash_an))
  laanwj:
    Code review ACK b536813

Tree-SHA512: abc9adf23cdf1be384f5fb9aa5bfffdda86b9ecd671064298d4cda0440828b509f070f9b19c88c7ce50ead9ff32afff9f14c5e78d75f01241568fbfa077be0b7
@fanquake fanquake mentioned this pull request Aug 31, 2020
@vasild
Copy link
Contributor

vasild commented Aug 31, 2020

This seems to be causing

clang++: warning: argument unused during compilation: '-fstack-clash-protection' [-Wunused-command-line-argument]

@fanquake
Copy link
Member Author

This seems to be causing

You need to provide more information. Which version of Clang? What is the output of the test in config.log? If your Clang is claiming to support an argument that it doesn't actually understand, something is wrong. As mentioned in the OP:

GCC has supported both options since 8.0.0. Clang has supported -fcf-protection from 7.0.0 and will support -fstack-clash-protection in it's upcoming 11.0.0 release.

I've just re-tested using Clang 10 and as expected, it does not recognize -fstack-clash-protection, and it does not get added to the hardening options:

configure:21072: checking whether C++ compiler accepts -fcf-protection=full
configure:21091: clang++-10 -std=c++11 -c -g -O2  -fcf-protection=full  -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS conftest.cpp >&5
configure:21091: $? = 0
configure:21099: result: yes
configure:21109: checking whether C++ compiler accepts -fstack-clash-protection
configure:21121: clang++-10 -std=c++11 -c -g -O2 -O0 -fstack-clash-protection  -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS conftest.cpp >&5
clang: error: unknown argument: '-fstack-clash-protection'
configure:21121: $? = 1
configure: failed program was:
...
HARDENED_CXXFLAGS=' -Wstack-protector -fstack-protector-all -fcf-protection=full'

@vasild
Copy link
Contributor

vasild commented Aug 31, 2020

Clang 12 (or I guess would also happen with any version of clang which supports -fstack-clash-protection, ie clang >= 11).

Relevant snippet from config.log:

configure:25508: checking whether C++ compiler accepts -fstack-clash-protection
configure:25520: clang++-devel -std=c++11 -c  -O0 -fstack-clash-protection ... conftest.cpp >&5
clang++: warning: argument unused during compilation: '-fstack-clash-protection' [-Wunused-command-line-argument]
configure:25520: $? = 0
configure:25529: result: yes

This should explain:

$ clang++-devel -c -Wall -fstack-clash-protection t.cc -o t.o # warning
clang++: warning: argument unused during compilation: '-fstack-clash-protection' [-Wunused-command-line-argument]
$ clang++-devel -Wall -fstack-clash-protection t.o -o t # no warning
$ clang++-devel --version
clang version 12.0.0 (git@github.com:freebsd/freebsd-ports.git 708bdc5c29e539ae9797f1c67aaef9aad7b68200)

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 19, 2022
…on options to hardening flags

b536813 build: add -fstack-clash-protection to hardening flags (fanquake)
076183b build: add -fcf-protection=full to hardening options (fanquake)

Pull request description:

  Beginning with Ubuntu `19.10`, it's packaged GCC now has some additional hardening options enabled by default (in addition to existing defaults like `-fstack-protector-strong` and reducing the minimum ssp buffer size). The new additions are`-fcf-protection=full` and `-fstack-clash-protection`.

  > -fcf-protection=[full|branch|return|none]
  > Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This prevents diverting the flow of control to an unexpected target. This is intended to protect against such threats as Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).

  > -fstack-clash-protection
  > Generate code to prevent stack clash style attacks. When this option is enabled, the compiler will only allocate one page of stack space at a time and each page is accessed immediately after allocation. Thus, it prevents allocations from jumping over any stack guard page provided by the operating system.

  If your interested you can grab `gcc-9_9.3.0-10ubuntu2.debian.tar.xz` from https://packages.ubuntu.com/focal/g++-9. The relevant changes are part of the `gcc-distro-specs` patches, along with the relevant additions to the gcc manages:

  > NOTE: In Ubuntu 19.10 and later versions, -fcf-protection is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-cf-protection nor -fcf-protection=* are found.

  > NOTE: In Ubuntu 19.10 and later versions, -fstack-clash-protection is enabled by default for C, C++, ObjC, ObjC++, unless -fno-stack-clash-protection is found.

  So, if you're C++ using GCC on Ubuntu 19.10 or later, these options will be active unless you explicitly opt out. This can be observed with a small test:

  ```c++
  int main() { return 0; }
  ```

  ```bash
  g++ --version
  g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

  g++ test.cpp

  objdump -dC a.out
  ..
  0000000000001129 <main>:
      1129:	f3 0f 1e fa          	endbr64
      112d:	55                   	push   %rbp
      112e:	48 89 e5             	mov    %rsp,%rbp
      1131:	b8 00 00 00 00       	mov    $0x0,%eax
      1136:	5d                   	pop    %rbp
      1137:	c3                   	retq
      1138:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
      113f:	00

  # recompile opting out of control flow protection
  g++ test.cpp -fcf-protection=none

  objdump -dC a.out
  ...
  0000000000001129 <main>:
      1129:	55                   	push   %rbp
      112a:	48 89 e5             	mov    %rsp,%rbp
      112d:	b8 00 00 00 00       	mov    $0x0,%eax
      1132:	5d                   	pop    %rbp
      1133:	c3                   	retq
      1134:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
      113b:	00 00 00
      113e:	66 90                	xchg   %ax,%ax
  ```

  Note the insertion of an `endbr64` instruction when compiling and _not_ opting out. This instruction is part of the Intel Control-flow Enforcement Technology [spec](https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf), which the GCC control flow implementation is based on.

  If we're still doing gitian builds for the `0.21.0` and `0.22.0` releases, we'd likely update the gitian image to Ubuntu Focal, which would mean that the GCC used for gitian builds would also be using these options by default. So we should decide whether we want to explicitly turn these options on as part of our hardening options (although not just for this reason), or, we should be opting-out.

  GCC has supported both options since 8.0.0. Clang has supported `-fcf-protection` from 7.0.0 and will support `-fstack-clash-protection` in it's upcoming [11.0.0 release](https://clang.llvm.org/docs/ReleaseNotes.html#id6).

ACKs for top commit:
  jamesob:
    ACK b536813 ([`jamesob/ackr/18921.1.fanquake.build_add_stack_clash_an`](https://github.com/jamesob/bitcoin/tree/ackr/18921.1.fanquake.build_add_stack_clash_an))
  laanwj:
    Code review ACK b536813

Tree-SHA512: abc9adf23cdf1be384f5fb9aa5bfffdda86b9ecd671064298d4cda0440828b509f070f9b19c88c7ce50ead9ff32afff9f14c5e78d75f01241568fbfa077be0b7
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 19, 2022
…on options to hardening flags

b536813 build: add -fstack-clash-protection to hardening flags (fanquake)
076183b build: add -fcf-protection=full to hardening options (fanquake)

Pull request description:

  Beginning with Ubuntu `19.10`, it's packaged GCC now has some additional hardening options enabled by default (in addition to existing defaults like `-fstack-protector-strong` and reducing the minimum ssp buffer size). The new additions are`-fcf-protection=full` and `-fstack-clash-protection`.

  > -fcf-protection=[full|branch|return|none]
  > Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This prevents diverting the flow of control to an unexpected target. This is intended to protect against such threats as Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).

  > -fstack-clash-protection
  > Generate code to prevent stack clash style attacks. When this option is enabled, the compiler will only allocate one page of stack space at a time and each page is accessed immediately after allocation. Thus, it prevents allocations from jumping over any stack guard page provided by the operating system.

  If your interested you can grab `gcc-9_9.3.0-10ubuntu2.debian.tar.xz` from https://packages.ubuntu.com/focal/g++-9. The relevant changes are part of the `gcc-distro-specs` patches, along with the relevant additions to the gcc manages:

  > NOTE: In Ubuntu 19.10 and later versions, -fcf-protection is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-cf-protection nor -fcf-protection=* are found.

  > NOTE: In Ubuntu 19.10 and later versions, -fstack-clash-protection is enabled by default for C, C++, ObjC, ObjC++, unless -fno-stack-clash-protection is found.

  So, if you're C++ using GCC on Ubuntu 19.10 or later, these options will be active unless you explicitly opt out. This can be observed with a small test:

  ```c++
  int main() { return 0; }
  ```

  ```bash
  g++ --version
  g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

  g++ test.cpp

  objdump -dC a.out
  ..
  0000000000001129 <main>:
      1129:	f3 0f 1e fa          	endbr64
      112d:	55                   	push   %rbp
      112e:	48 89 e5             	mov    %rsp,%rbp
      1131:	b8 00 00 00 00       	mov    $0x0,%eax
      1136:	5d                   	pop    %rbp
      1137:	c3                   	retq
      1138:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
      113f:	00

  # recompile opting out of control flow protection
  g++ test.cpp -fcf-protection=none

  objdump -dC a.out
  ...
  0000000000001129 <main>:
      1129:	55                   	push   %rbp
      112a:	48 89 e5             	mov    %rsp,%rbp
      112d:	b8 00 00 00 00       	mov    $0x0,%eax
      1132:	5d                   	pop    %rbp
      1133:	c3                   	retq
      1134:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
      113b:	00 00 00
      113e:	66 90                	xchg   %ax,%ax
  ```

  Note the insertion of an `endbr64` instruction when compiling and _not_ opting out. This instruction is part of the Intel Control-flow Enforcement Technology [spec](https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf), which the GCC control flow implementation is based on.

  If we're still doing gitian builds for the `0.21.0` and `0.22.0` releases, we'd likely update the gitian image to Ubuntu Focal, which would mean that the GCC used for gitian builds would also be using these options by default. So we should decide whether we want to explicitly turn these options on as part of our hardening options (although not just for this reason), or, we should be opting-out.

  GCC has supported both options since 8.0.0. Clang has supported `-fcf-protection` from 7.0.0 and will support `-fstack-clash-protection` in it's upcoming [11.0.0 release](https://clang.llvm.org/docs/ReleaseNotes.html#id6).

ACKs for top commit:
  jamesob:
    ACK b536813 ([`jamesob/ackr/18921.1.fanquake.build_add_stack_clash_an`](https://github.com/jamesob/bitcoin/tree/ackr/18921.1.fanquake.build_add_stack_clash_an))
  laanwj:
    Code review ACK b536813

Tree-SHA512: abc9adf23cdf1be384f5fb9aa5bfffdda86b9ecd671064298d4cda0440828b509f070f9b19c88c7ce50ead9ff32afff9f14c5e78d75f01241568fbfa077be0b7
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
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.

10 participants