Merge bitcoin/bitcoin#23839: Linux: build with and test for control flow instrumentation on x86_64

5a8f907c93 scripts: add CONTROL_FLOW to ELF security checks (fanquake)
e13f8f775d build: build x86_64 Linux Boost with -fcf-protection=full (fanquake)
6ca5efa8ed 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 5a8f907c93
  hebasto:
    ACK 5a8f907c93, I have reviewed the code and it looks OK, I agree it can be merged.

Tree-SHA512: 75702ac01175ccf08e73b5c3bce266cee9dd15ccf8fb38d46108cfada156de9a8c18e27d996f9343ae33f7a75a6904d335cbe25256d90af1f4ccbe72ce1788bb
pull/24154/head
laanwj 3 years ago
commit 792d0d8d51
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D

@ -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,

@ -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)

@ -26,8 +26,7 @@ $(package)_config_libraries=filesystem,system,test
$(package)_cxxflags+=-std=c++17
$(package)_cxxflags_linux=-fPIC
$(package)_cxxflags_android=-fPIC
$(package)_cxxflags_x86_64_darwin=-fcf-protection=full
$(package)_cxxflags_mingw32=-fcf-protection=full
$(package)_cxxflags_x86_64=-fcf-protection=full
endef
define $(package)_preprocess_cmds

Loading…
Cancel
Save