Skip to content

Commit c90a9e6

Browse files
committed
Merge #18713: scripts: Add MACHO stack canary check to security-check.py
8334ee3 scripts: add MACHO LAZY_BINDINGS test to test-security-check.py (fanquake) 7b99c74 scripts: add MACHO Canary check to security-check.py (fanquake) Pull request description: 7b99c74 uses `otool -Iv` to check for `___stack_chk_fail` in the macOS binaries. Similar to the [ELF check](https://github.com/bitcoin/bitcoin/blob/master/contrib/devtools/security-check.py#L105). Note that looking for a triple underscore prefixed function (as opposed to two for ELF) is correct for the macOS binaries. i.e: ```bash otool -Iv bitcoind | grep chk 0x00000001006715b8 509 ___memcpy_chk 0x00000001006715be 510 ___snprintf_chk 0x00000001006715c4 511 ___sprintf_chk 0x00000001006715ca 512 ___stack_chk_fail 0x00000001006715d6 517 ___vsnprintf_chk 0x0000000100787898 513 ___stack_chk_guard ``` 8334ee3 is a follow up to #18295 and adds test cases to `test-security-check.py` that for some reason I didn't add at the time. I'll sort out #18434 so that we can run these tests in the CI. ACKs for top commit: practicalswift: ACK 8334ee3: Mitigations are important. Important things are worth asserting :) jonasschnelli: utACK 8334ee3. Tree-SHA512: 1aa5ded34bbd187eddb112b27278deb328bfc21ac82316b20fab6ad894f223b239a76b53dab0ac1770d194c1760fcc40d4da91ec09959ba4fc8eadedb173936a
2 parents 7d1a3bd + 8334ee3 commit c90a9e6

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

contrib/devtools/security-check.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,20 @@ def check_MACHO_LAZY_BINDINGS(executable) -> bool:
223223
return False
224224
return True
225225

226+
def check_MACHO_Canary(executable) -> bool:
227+
'''
228+
Check for use of stack canary
229+
'''
230+
p = subprocess.Popen([OTOOL_CMD, '-Iv', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
231+
(stdout, stderr) = p.communicate()
232+
if p.returncode:
233+
raise IOError('Error opening file')
234+
ok = False
235+
for line in stdout.splitlines():
236+
if '___stack_chk_fail' in line:
237+
ok = True
238+
return ok
239+
226240
CHECKS = {
227241
'ELF': [
228242
('PIE', check_ELF_PIE),
@@ -239,7 +253,8 @@ def check_MACHO_LAZY_BINDINGS(executable) -> bool:
239253
('PIE', check_MACHO_PIE),
240254
('NOUNDEFS', check_MACHO_NOUNDEFS),
241255
('NX', check_MACHO_NX),
242-
('LAZY_BINDINGS', check_MACHO_LAZY_BINDINGS)
256+
('LAZY_BINDINGS', check_MACHO_LAZY_BINDINGS),
257+
('Canary', check_MACHO_Canary)
243258
]
244259
}
245260

contrib/devtools/test-security-check.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,17 @@ def test_MACHO(self):
6464
cc = 'clang'
6565
write_testcode(source)
6666

67-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace', '-Wl,-allow_stack_execute']),
68-
(1, executable+': failed PIE NOUNDEFS NX'))
69-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace']),
70-
(1, executable+': failed PIE NOUNDEFS'))
71-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie']),
67+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector']),
68+
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS Canary'))
69+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fstack-protector-all']),
70+
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS'))
71+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-fstack-protector-all']),
72+
(1, executable+': failed PIE NOUNDEFS LAZY_BINDINGS'))
73+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all']),
74+
(1, executable+': failed PIE LAZY_BINDINGS'))
75+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-bind_at_load','-fstack-protector-all']),
7276
(1, executable+': failed PIE'))
73-
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie']),
77+
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all']),
7478
(0, ''))
7579

7680
if __name__ == '__main__':

0 commit comments

Comments
 (0)