diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -228,7 +228,7 @@ def identify_executable(executable) -> Optional[str]: - with open(filename, "rb") as f: + with open(executable, "rb") as f: magic = f.read(4) if magic.startswith(b"MZ"): return "PE" diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -30,16 +30,13 @@ def call_security_check(cc, source, executable, options): - subprocess.check_call([*cc, source, "-o", executable] + options) - p = subprocess.Popen( - ["./security-check.py", executable], + subprocess.run([*cc, source, "-o", executable] + options, check=True) + p = subprocess.run( + ["./contrib/devtools/security-check.py", executable], stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE, universal_newlines=True, ) - (stdout, stderr) = p.communicate() - return (p.returncode, stdout.rstrip()) + return p.returncode, p.stdout.rstrip() class TestSecurityChecks(unittest.TestCase): @@ -163,13 +160,18 @@ executable, [ "-Wl,--no-nxcompat", + "-Wl,--disable-reloc-section", "-Wl,--no-dynamicbase", "-Wl,--no-high-entropy-va", "-no-pie", "-fno-PIE", ], ), - (1, executable + ": failed DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION"), + ( + 1, + executable + + ": failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION", + ), ) self.assertEqual( call_security_check( @@ -178,13 +180,14 @@ executable, [ "-Wl,--nxcompat", + "-Wl,--disable-reloc-section", "-Wl,--no-dynamicbase", "-Wl,--no-high-entropy-va", "-no-pie", "-fno-PIE", ], ), - (1, executable + ": failed DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION"), + (1, executable + ": failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION"), ) self.assertEqual( call_security_check( @@ -193,13 +196,31 @@ executable, [ "-Wl,--nxcompat", - "-Wl,--dynamicbase", + "-Wl,--enable-reloc-section", + "-Wl,--no-dynamicbase", "-Wl,--no-high-entropy-va", "-no-pie", "-fno-PIE", ], ), - (1, executable + ": failed HIGH_ENTROPY_VA RELOC_SECTION"), + (1, executable + ": failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA"), + ) + self.assertEqual( + call_security_check( + cc, + source, + executable, + [ + "-Wl,--nxcompat", + "-Wl,--enable-reloc-section", + "-Wl,--no-dynamicbase", + "-Wl,--no-high-entropy-va", + # -pie -fPIE does nothing unless --dynamicbase is also supplied + "-pie", + "-fPIE", + ], + ), + (1, executable + ": failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA"), ) self.assertEqual( call_security_check( @@ -208,13 +229,14 @@ executable, [ "-Wl,--nxcompat", + "-Wl,--enable-reloc-section", "-Wl,--dynamicbase", - "-Wl,--high-entropy-va", - "-no-pie", - "-fno-PIE", + "-Wl,--no-high-entropy-va", + "-pie", + "-fPIE", ], ), - (1, executable + ": failed RELOC_SECTION"), + (1, executable + ": failed HIGH_ENTROPY_VA"), ) self.assertEqual( call_security_check( @@ -223,6 +245,7 @@ executable, [ "-Wl,--nxcompat", + "-Wl,--enable-reloc-section", "-Wl,--dynamicbase", "-Wl,--high-entropy-va", "-pie", @@ -285,7 +308,10 @@ ) self.assertEqual( call_security_check( - cc, source, executable, ["-Wl,-pie", "-fstack-protector-all"] + cc, + source, + executable, + ["-Wl,-pie", "-fstack-protector-all"], ), (0, ""), ) 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 @@ -87,20 +87,22 @@ ), ) - # finally, check a conforming file that simply uses a math function + # finally, check a simple conforming binary source = "test3.c" executable = "test3" + with open(source, "w", encoding="utf8") as f: f.write(""" - #include + #include int main() { - return (int)pow(2.0, 4.0); + printf("42"); + return 0; } """) - self.assertEqual(call_symbol_check(cc, source, executable, ["-lm"]), (0, "")) + self.assertEqual(call_symbol_check(cc, source, executable, []), (0, "")) def test_MACHO(self): source = "test1.c"