diff options
author | laanwj <126646+laanwj@users.noreply.github.com> | 2022-01-25 15:53:32 +0100 |
---|---|---|
committer | laanwj <126646+laanwj@users.noreply.github.com> | 2022-01-25 16:01:21 +0100 |
commit | 792d0d8d512cf8ddca200317b74ce550c1a1a428 (patch) | |
tree | 3cd12489e88e543b417624b1620830bb53ae02df /contrib | |
parent | bd482b3ffebc68130f8a18dabf08ed1aff7ea159 (diff) | |
parent | 5a8f907c93f158c54e58706d6d8c6b0a1a3205ba (diff) |
Merge bitcoin/bitcoin#23839: Linux: build with and test for control flow instrumentation on x86_64
5a8f907c93f158c54e58706d6d8c6b0a1a3205ba scripts: add CONTROL_FLOW to ELF security checks (fanquake)
e13f8f775d9e8da04db0e072040d11237c5d1089 build: build x86_64 Linux Boost with -fcf-protection=full (fanquake)
6ca5efa8ed1ed9d5978bed0baf3c63dc2d406ec5 script rename control flow check to MACHO specific (fanquake)
Pull request description:
Closes #21888.
TODO:
* Duplication in security-check-tests
Guix build:
```bash
bash-5.1# find guix-build-$(git rev-parse --short=12 HEAD)/output/ -type f -print0 | env LC_ALL=C sort -z | xargs -r0 sha256sum
8025e2e6859247eaf865a4a5009d0a39570ec5e8ab51739fa4da0d8ee4ab2117 guix-build-5a8f907c93f1/output/aarch64-linux-gnu/SHA256SUMS.part
75576482994493262dbf7d3567b0450c0804bdc75c186d6b4c6a856bd0d8f0a3 guix-build-5a8f907c93f1/output/aarch64-linux-gnu/bitcoin-5a8f907c93f1-aarch64-linux-gnu-debug.tar.gz
7cb89c9327cc540859334b597c041a2250156e3e83ce2aa7d16177376056302f guix-build-5a8f907c93f1/output/aarch64-linux-gnu/bitcoin-5a8f907c93f1-aarch64-linux-gnu.tar.gz
e264053e4c7a5d65340dd7bbd2c664bcd596292ab80f00a0bf0026bfe0c480bc guix-build-5a8f907c93f1/output/arm-linux-gnueabihf/SHA256SUMS.part
6c3ee9b3c0c4583620301b183226678f1618605dd07dbed0bbdf7d06d3591314 guix-build-5a8f907c93f1/output/arm-linux-gnueabihf/bitcoin-5a8f907c93f1-arm-linux-gnueabihf-debug.tar.gz
f217cb8d8e233a8dbdbfde7dabf12c5d867d7de53e8c652b8ed1d4a55da82fd9 guix-build-5a8f907c93f1/output/arm-linux-gnueabihf/bitcoin-5a8f907c93f1-arm-linux-gnueabihf.tar.gz
48b4b2a1b52b3098f4e92c11cb60f1e5e9696a2a960560cd6adea72277eaa4a4 guix-build-5a8f907c93f1/output/dist-archive/bitcoin-5a8f907c93f1.tar.gz
40832db2446e129879caa9fbc9d682c53069876dbb2e0d4d76592e5dcb40bb12 guix-build-5a8f907c93f1/output/powerpc64-linux-gnu/SHA256SUMS.part
26fdfa9b7b77d5db415ef34054cf6f6d020a5dab73239db6dd05539f654bc5d5 guix-build-5a8f907c93f1/output/powerpc64-linux-gnu/bitcoin-5a8f907c93f1-powerpc64-linux-gnu-debug.tar.gz
3adbdb9d3eb1cb5f9adc38b29450054f286bd6d74cef8619adaee89494853605 guix-build-5a8f907c93f1/output/powerpc64-linux-gnu/bitcoin-5a8f907c93f1-powerpc64-linux-gnu.tar.gz
8ec2baf82483a698350bfdabf530cd9b5241690c916f597c746210e95ac451de guix-build-5a8f907c93f1/output/powerpc64le-linux-gnu/SHA256SUMS.part
1797e75e1f66ec9068fa4e57e0108960475e863f8f054fbe854358b1f995c4df guix-build-5a8f907c93f1/output/powerpc64le-linux-gnu/bitcoin-5a8f907c93f1-powerpc64le-linux-gnu-debug.tar.gz
448bd289ef26c777a1fc4498e7ba7fb17d0f6a932dcac91b2f89cbba63704bb8 guix-build-5a8f907c93f1/output/powerpc64le-linux-gnu/bitcoin-5a8f907c93f1-powerpc64le-linux-gnu.tar.gz
a23ee91eeae515c2a6a31eb25d659fab833839aaafa4676ccee364bdad2a468c guix-build-5a8f907c93f1/output/riscv64-linux-gnu/SHA256SUMS.part
82df1b6d5020d0af8268ecc8e823f752f20dec308277763b2dd675804dfa4bbd guix-build-5a8f907c93f1/output/riscv64-linux-gnu/bitcoin-5a8f907c93f1-riscv64-linux-gnu-debug.tar.gz
09a6098ce83896a6ee6d5c8aff12eaca51595bd724c8e0b2a6f90b6410dc168c guix-build-5a8f907c93f1/output/riscv64-linux-gnu/bitcoin-5a8f907c93f1-riscv64-linux-gnu.tar.gz
4fac2951f80eaa2bd1747a263be6be1b76282cac5062f7d86db631a2fb80f8db guix-build-5a8f907c93f1/output/x86_64-apple-darwin/SHA256SUMS.part
3392f417b09efca5916c384f0b2d0c177a72ec4921399c62e84484f0054cc8c4 guix-build-5a8f907c93f1/output/x86_64-apple-darwin/bitcoin-5a8f907c93f1-osx-unsigned.dmg
bfb4f8ade6107996ec4bc9efdb53959151b8fb19b6790c34472fe218dd02383d guix-build-5a8f907c93f1/output/x86_64-apple-darwin/bitcoin-5a8f907c93f1-osx-unsigned.tar.gz
4de92e149bad46fc863efb3b650753d194aad96be991d020e0b859452cf27457 guix-build-5a8f907c93f1/output/x86_64-apple-darwin/bitcoin-5a8f907c93f1-osx64.tar.gz
9329549a2f275a59e329afc8744ff8cbc297f3042e0ad03b47626805c7aae2e8 guix-build-5a8f907c93f1/output/x86_64-linux-gnu/SHA256SUMS.part
d87deb1eca8a1d3780f02edde78350d27f700e13c7ff444be0bfb34e7369904a guix-build-5a8f907c93f1/output/x86_64-linux-gnu/bitcoin-5a8f907c93f1-x86_64-linux-gnu-debug.tar.gz
76f3bc2fad010d9373e854d941e8205b68fa6c9a8ecaff34c4978ae3ae76c806 guix-build-5a8f907c93f1/output/x86_64-linux-gnu/bitcoin-5a8f907c93f1-x86_64-linux-gnu.tar.gz
2948631081c4bd475529da2b7bc2b32b5aa2e44de46dfdaa6cf9432b3c9fe869 guix-build-5a8f907c93f1/output/x86_64-w64-mingw32/SHA256SUMS.part
c5d56fac163b73c00e9745aa7b0f9a0bd9fcac7517e39b677869b6e76faf7218 guix-build-5a8f907c93f1/output/x86_64-w64-mingw32/bitcoin-5a8f907c93f1-win-unsigned.tar.gz
f12c7cd72511544c67f4934981c090cee0d9c17e931c059edbbbef6e843dd651 guix-build-5a8f907c93f1/output/x86_64-w64-mingw32/bitcoin-5a8f907c93f1-win64-debug.zip
eb952cc4554f92ba6787353f4305d7cbcb1c6dafc4a3867b3088106252a573b8 guix-build-5a8f907c93f1/output/x86_64-w64-mingw32/bitcoin-5a8f907c93f1-win64-setup-unsigned.exe
7bd2b071f1cdf9410535e6a10dd1da519f942bd2c1e47ed52c5b8c4f977e8f27 guix-build-5a8f907c93f1/output/x86_64-w64-mingw32/bitcoin-5a8f907c93f1-win64.zip
```
ACKs for top commit:
laanwj:
Code review ACK 5a8f907c93f158c54e58706d6d8c6b0a1a3205ba
hebasto:
ACK 5a8f907c93f158c54e58706d6d8c6b0a1a3205ba, I have reviewed the code and it looks OK, I agree it can be merged.
Tree-SHA512: 75702ac01175ccf08e73b5c3bce266cee9dd15ccf8fb38d46108cfada156de9a8c18e27d996f9343ae33f7a75a6904d335cbe25256d90af1f4ccbe72ce1788bb
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/devtools/security-check.py | 17 | ||||
-rwxr-xr-x | contrib/devtools/test-security-check.py | 49 |
2 files changed, 51 insertions, 15 deletions
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 137fe377da..9e7059685c 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -111,6 +111,17 @@ def check_ELF_separate_code(binary): return False return True +def check_ELF_control_flow(binary) -> bool: + ''' + Check for control flow instrumentation + ''' + main = binary.get_function_address('main') + content = binary.get_content_from_virtual_address(main, 4, lief.Binary.VA_TYPES.AUTO) + + if content == [243, 15, 30, 250]: # endbr64 + return True + return False + def check_PE_DYNAMIC_BASE(binary) -> bool: '''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)''' return lief.PE.DLL_CHARACTERISTICS.DYNAMIC_BASE in binary.optional_header.dll_characteristics_lists @@ -172,7 +183,7 @@ def check_NX(binary) -> bool: ''' return binary.has_nx -def check_control_flow(binary) -> bool: +def check_MACHO_control_flow(binary) -> bool: ''' Check for control flow instrumentation ''' @@ -205,12 +216,12 @@ BASE_MACHO = [ ('NX', check_NX), ('LAZY_BINDINGS', check_MACHO_LAZY_BINDINGS), ('Canary', check_MACHO_Canary), - ('CONTROL_FLOW', check_control_flow), + ('CONTROL_FLOW', check_MACHO_control_flow), ] CHECKS = { lief.EXE_FORMATS.ELF: { - lief.ARCHITECTURES.X86: BASE_ELF, + lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_control_flow)], lief.ARCHITECTURES.ARM: BASE_ELF, lief.ARCHITECTURES.ARM64: BASE_ELF, lief.ARCHITECTURES.PPC: BASE_ELF, diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 6b748e8743..a5b9eac302 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -5,6 +5,7 @@ ''' Test script for security-check.py ''' +import lief #type:ignore import os import subprocess from typing import List @@ -41,25 +42,49 @@ def call_security_check(cc, source, executable, options): p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True) return (p.returncode, p.stdout.rstrip()) +def get_arch(cc, source, executable): + subprocess.run([*cc, source, '-o', executable], check=True) + binary = lief.parse(executable) + arch = binary.abstract.header.architecture + os.remove(executable) + return arch + class TestSecurityChecks(unittest.TestCase): def test_ELF(self): source = 'test1.c' executable = 'test1' cc = determine_wellknown_cmd('CC', 'gcc') write_testcode(source) + arch = get_arch(cc, source, executable) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), - (1, executable+': failed PIE NX RELRO Canary')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), - (1, executable+': failed PIE RELRO Canary')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), - (1, executable+': failed PIE RELRO')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']), - (1, executable+': failed RELRO')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']), - (1, executable+': failed separate_code')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']), - (0, '')) + if arch == lief.ARCHITECTURES.X86: + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE NX RELRO Canary CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE RELRO Canary CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE RELRO CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']), + (1, executable+': failed RELRO CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']), + (1, executable+': failed separate_code CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']), + (1, executable+': failed CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code', '-fcf-protection=full']), + (0, '')) + else: + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE NX RELRO Canary')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE RELRO Canary')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']), + (1, executable+': failed PIE RELRO')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE', '-Wl,-z,separate-code']), + (1, executable+': failed RELRO')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,noseparate-code']), + (1, executable+': failed separate_code')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']), + (0, '')) clean_files(source, executable) |