diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -216,6 +216,16 @@ return ok +def check_MACHO_min_os(filename) -> bool: + binary = lief.parse(filename) + return binary.build_version.minos == [10, 14, 0] + + +def check_MACHO_sdk(filename) -> bool: + binary = lief.parse(filename) + return binary.build_version.sdk == [10, 15, 6] + + def check_PE_libraries(filename) -> bool: ok: bool = True binary = lief.parse(filename) @@ -226,6 +236,13 @@ return ok +def check_PE_subsystem_version(filename) -> bool: + binary = lief.parse(filename) + major: int = binary.optional_header.major_subsystem_version + minor: int = binary.optional_header.minor_subsystem_version + return major == 6 and minor == 1 + + CHECKS = { 'ELF': [ ('IMPORTED_SYMBOLS', check_imported_symbols), @@ -233,10 +250,13 @@ ('LIBRARY_DEPENDENCIES', check_ELF_libraries) ], 'MACHO': [ - ('DYNAMIC_LIBRARIES', check_MACHO_libraries) + ('DYNAMIC_LIBRARIES', check_MACHO_libraries), + ('MIN_OS', check_MACHO_min_os), + ('SDK', check_MACHO_sdk), ], 'PE': [ - ('DYNAMIC_LIBRARIES', check_PE_libraries) + ('DYNAMIC_LIBRARIES', check_PE_libraries), + ('SUBSYSTEM_VERSION', check_PE_subsystem_version), ] } diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py --- a/contrib/devtools/test-symbol-check.py +++ b/contrib/devtools/test-symbol-check.py @@ -103,9 +103,12 @@ ''') - self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat']), - (1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' + - executable + ': failed DYNAMIC_LIBRARIES')) + self.assertEqual( + call_symbol_check(cc, source, executable, + ['-lexpat', '-Wl,-platform_version', '-Wl,macos', + '-Wl,11.4', '-Wl,11.4']), + (1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' + + f'{executable}: failed DYNAMIC_LIBRARIES MIN_OS SDK')) source = 'test2.c' executable = 'test2' @@ -120,8 +123,26 @@ } ''') - self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics']), - (0, '')) + self.assertEqual( + call_symbol_check(cc, source, executable, + ['-framework', 'CoreGraphics', '-Wl,-platform_version', + '-Wl,macos', '-Wl,11.4', '-Wl,11.4']), + (1, f'{executable}: failed MIN_OS SDK')) + + source = 'test3.c' + executable = 'test3' + with open(source, 'w', encoding="utf8") as f: + f.write(''' + int main() + { + return 0; + } + ''') + + self.assertEqual(call_symbol_check(cc, source, executable, + ['-Wl,-platform_version', '-Wl,macos', + '-Wl,10.14', '-Wl,11.4']), + (1, f'{executable}: failed SDK')) def test_PE(self): source = 'test1.c' @@ -139,12 +160,30 @@ } ''') - self.assertEqual(call_symbol_check(cc, source, executable, ['-lpdh']), - (1, 'pdh.dll is not in ALLOWED_LIBRARIES!\n' + - executable + ': failed DYNAMIC_LIBRARIES')) + self.assertEqual( + call_symbol_check( + cc, source, executable, + ['-lpdh', '-Wl,--major-subsystem-version', '-Wl,6', + '-Wl,--minor-subsystem-version', '-Wl,1']), + (1, 'pdh.dll is not in ALLOWED_LIBRARIES!\n' + + executable + ': failed DYNAMIC_LIBRARIES')) source = 'test2.c' executable = 'test2.exe' + + with open(source, 'w', encoding="utf8") as f: + f.write(''' + int main() + { + return 0; + } + ''') + + self.assertEqual(call_symbol_check(cc, source, executable, ['-Wl,--major-subsystem-version', '-Wl,9', '-Wl,--minor-subsystem-version', '-Wl,9']), + (1, executable + ': failed SUBSYSTEM_VERSION')) + + source = 'test3.c' + executable = 'test3.exe' with open(source, 'w', encoding="utf8") as f: f.write(''' #include @@ -156,8 +195,11 @@ } ''') - self.assertEqual(call_symbol_check(cc, source, executable, ['-lole32']), - (0, '')) + self.assertEqual( + call_symbol_check(cc, source, executable, + ['-lole32', '-Wl,--major-subsystem-version', '-Wl,6', + '-Wl,--minor-subsystem-version', '-Wl,1']), + (0, '')) if __name__ == '__main__': diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -118,7 +118,7 @@ done } - pip3 install lief==0.11.4 + pip3 install lief==0.11.5 # Faketime for depends so intermediate results are comparable export PATH_orig=${PATH} diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -87,7 +87,7 @@ done } - pip3 install lief==0.11.4 + pip3 install lief==0.11.5 # Faketime for depends so intermediate results are comparable export PATH_orig=${PATH} diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -95,7 +95,7 @@ done } - pip3 install lief==0.11.4 + pip3 install lief==0.11.5 # Faketime for depends so intermediate results are comparable export PATH_orig=${PATH} diff --git a/contrib/utils/install-dependencies-bullseye.sh b/contrib/utils/install-dependencies-bullseye.sh --- a/contrib/utils/install-dependencies-bullseye.sh +++ b/contrib/utils/install-dependencies-bullseye.sh @@ -141,7 +141,7 @@ # This version is compatible with Debian's "protobuf-compiler" package pip3 install "protobuf<=3.20" # For security-check.py and symbol-check.py -pip3 install "lief>=0.11.4" +pip3 install "lief>=0.11.5" # For Chronik WebSocket endpoint pip3 install websocket-client diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,9 @@ # RPC, Shell, and Windows Sockets. WIN32_LEAN_AND_MEAN ) + + # We require Windows 7 (NT 6.1) or later + add_linker_flags(-Wl,--major-subsystem-version,6 -Wl,--minor-subsystem-version,1) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")