aboutsummaryrefslogtreecommitdiff
path: root/contrib/devtools
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-09-26 13:03:44 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2016-09-26 13:34:38 +0200
commit4e1567acff4b2d0116594b71af111b125517a87d (patch)
tree281d2cec5f33ea21d17a85624b9cc124da3836b0 /contrib/devtools
parent37871f216e0d9463f456b8b014b80cc064011351 (diff)
parent62c291596bccca43609e61a01a027e86a81f69b2 (diff)
Merge #8249: Enable (and check for) 64-bit ASLR on Windows
62c2915 build: supply `-Wl,--high-entropy-va` (Wladimir J. van der Laan) 9a75d29 devtools: Check for high-entropy ASLR in 64-bit PE executables (Wladimir J. van der Laan)
Diffstat (limited to 'contrib/devtools')
-rwxr-xr-xcontrib/devtools/security-check.py48
1 files changed, 40 insertions, 8 deletions
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index b4b4b4603d..c90541e271 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -15,6 +15,7 @@ import os
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
+NONFATAL = {'HIGH_ENTROPY_VA'} # checks which are non-fatal for now but only generate a warning
def check_ELF_PIE(executable):
'''
@@ -117,26 +118,50 @@ def check_ELF_Canary(executable):
def get_PE_dll_characteristics(executable):
'''
- Get PE DllCharacteristics bits
+ Get PE DllCharacteristics bits.
+ Returns a tuple (arch,bits) where arch is 'i386:x86-64' or 'i386'
+ and bits is the DllCharacteristics value.
'''
p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
+ arch = ''
+ bits = 0
for line in stdout.split('\n'):
tokens = line.split()
+ if len(tokens)>=2 and tokens[0] == 'architecture:':
+ arch = tokens[1].rstrip(',')
if len(tokens)>=2 and tokens[0] == 'DllCharacteristics':
- return int(tokens[1],16)
- return 0
+ bits = int(tokens[1],16)
+ return (arch,bits)
+IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
+IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
+IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
-def check_PE_PIE(executable):
+def check_PE_DYNAMIC_BASE(executable):
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
- return bool(get_PE_dll_characteristics(executable) & 0x40)
+ (arch,bits) = get_PE_dll_characteristics(executable)
+ reqbits = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
+ return (bits & reqbits) == reqbits
+
+# On 64 bit, must support high-entropy 64-bit address space layout randomization in addition to DYNAMIC_BASE
+# to have secure ASLR.
+def check_PE_HIGH_ENTROPY_VA(executable):
+ '''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR'''
+ (arch,bits) = get_PE_dll_characteristics(executable)
+ if arch == 'i386:x86-64':
+ reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
+ else: # Unnecessary on 32-bit
+ assert(arch == 'i386')
+ reqbits = 0
+ return (bits & reqbits) == reqbits
def check_PE_NX(executable):
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
- return bool(get_PE_dll_characteristics(executable) & 0x100)
+ (arch,bits) = get_PE_dll_characteristics(executable)
+ return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
CHECKS = {
'ELF': [
@@ -146,7 +171,8 @@ CHECKS = {
('Canary', check_ELF_Canary)
],
'PE': [
- ('PIE', check_PE_PIE),
+ ('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
+ ('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
('NX', check_PE_NX)
]
}
@@ -171,12 +197,18 @@ if __name__ == '__main__':
continue
failed = []
+ warning = []
for (name, func) in CHECKS[etype]:
if not func(filename):
- failed.append(name)
+ if name in NONFATAL:
+ warning.append(name)
+ else:
+ failed.append(name)
if failed:
print('%s: failed %s' % (filename, ' '.join(failed)))
retval = 1
+ if warning:
+ print('%s: warning %s' % (filename, ' '.join(warning)))
except IOError:
print('%s: cannot open' % filename)
retval = 1