From 17c041fb339d080509507a5e58f705685270aa95 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Sat, 26 Dec 2015 21:00:26 +0100 Subject: [PATCH] check SELinux status before build libear --- libscanbuild/intercept.py | 26 +++++++++++++------ tests/unit/test_intercept.py | 50 +++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/libscanbuild/intercept.py b/libscanbuild/intercept.py index ecef1c7..6062e2e 100644 --- a/libscanbuild/intercept.py +++ b/libscanbuild/intercept.py @@ -88,8 +88,7 @@ def post_processing(commands): previous = iter([]) # filter out duplicate entries from both duplicate = duplicate_check(entry_hash) - return (entry - for entry in itertools.chain(previous, current) + return (entry for entry in itertools.chain(previous, current) if os.path.exists(entry['file']) and not duplicate(entry)) with TemporaryDirectory(prefix='intercept-', dir=tempdir()) as tmp_dir: @@ -123,8 +122,8 @@ def setup_environment(args, destination, bin_dir): c_compiler = args.cc if 'cc' in args else 'cc' cxx_compiler = args.cxx if 'cxx' in args else 'c++' - libear_path = None if args.override_compiler or is_sip_enabled() else \ - build_libear(c_compiler, destination) + libear_path = None if args.override_compiler or is_preload_disabled( + sys.platform) else build_libear(c_compiler, destination) environment = dict(os.environ) environment.update({'INTERCEPT_BUILD_TARGET_DIR': destination}) @@ -252,16 +251,27 @@ def is_compiler_call(entry): return any((pattern.match(executable) for pattern in patterns)) -def is_sip_enabled(): +def is_preload_disabled(platform): """ Library-based interposition will fail silently if SIP is enabled, so this should be detected. You can detect whether SIP is enabled on Darwin by checking whether (1) there is a binary called 'csrutil' in the path and, if so, (2) whether the output of executing 'csrutil status' - contains 'System Integrity Protection status: enabled'. """ + contains 'System Integrity Protection status: enabled'. + + Same problem on linux when SELinux is enabled. The status query program + 'sestatus' and the output when it's enabled 'SELinux status: enabled'. """ + + if platform == 'darwin': + pattern = re.compile(r'System Integrity Protection status:\s+enabled') + command = ['csrutil', 'status'] + elif platform in {'linux', 'linux2'}: + pattern = re.compile(r'SELinux status:\s+enabled') + command = ['sestatus'] + else: + return False - pattern = re.compile(r'System Integrity Protection status: enabled') try: - lines = subprocess.check_output(['csrutil', 'status']).decode('utf-8') + lines = subprocess.check_output(command).decode('utf-8') return any((pattern.match(line) for line in lines.splitlines())) except: return False diff --git a/tests/unit/test_intercept.py b/tests/unit/test_intercept.py index 1a0bf2c..b6f01f3 100644 --- a/tests/unit/test_intercept.py +++ b/tests/unit/test_intercept.py @@ -62,29 +62,52 @@ def test(command): '/opt/file.c') def test_sip(self): - def create_csrutil(dest_dir, enabled): - filename = os.path.join(dest_dir, 'csrutil') + def create_status_report(filename, message): content = """#!/usr/bin/env sh - echo 'bla-bla-bla' - echo 'System Integrity Protection status: {0}' echo 'sa-la-la-la' - """.format('enabled' if enabled else 'disabled') + echo 'la-la-la' + echo '{0}' + echo 'sa-la-la-la' + echo 'la-la-la' + """.format(message) lines = [line.strip() for line in content.split('\n')] with open(filename, 'w') as handle: handle.write('\n'.join(lines)) handle.close() os.chmod(filename, 0x1ff) + def create_csrutil(dest_dir, status): + filename = os.path.join(dest_dir, 'csrutil') + message = 'System Integrity Protection status: {0}'.format(status) + return create_status_report(filename, message) + + def create_sestatus(dest_dir, status): + filename = os.path.join(dest_dir, 'sestatus') + message = 'SELinux status:\t{0}'.format(status) + return create_status_report(filename, message) + + ENABLED = 'enabled' + DISABLED = 'disabled' + + OSX = 'darwin' + LINUX = 'linux' + with fixtures.TempDir() as tmpdir: try: saved = os.environ['PATH'] os.environ['PATH'] = tmpdir + ':' + saved - # shall be true when enabled - create_csrutil(tmpdir, True) - self.assertTrue(sut.is_sip_enabled()) - # shall be false when disabled - create_csrutil(tmpdir, False) - self.assertFalse(sut.is_sip_enabled()) + + create_csrutil(tmpdir, ENABLED) + self.assertTrue(sut.is_preload_disabled(OSX)) + + create_csrutil(tmpdir, DISABLED) + self.assertFalse(sut.is_preload_disabled(OSX)) + + create_sestatus(tmpdir, ENABLED) + self.assertTrue(sut.is_preload_disabled(LINUX)) + + create_sestatus(tmpdir, DISABLED) + self.assertFalse(sut.is_preload_disabled(LINUX)) finally: os.environ['PATH'] = saved @@ -92,6 +115,9 @@ def create_csrutil(dest_dir, enabled): saved = os.environ['PATH'] os.environ['PATH'] = '' # shall be false when it's not in the path - self.assertFalse(sut.is_sip_enabled()) + self.assertFalse(sut.is_preload_disabled(OSX)) + self.assertFalse(sut.is_preload_disabled(LINUX)) + + self.assertFalse(sut.is_preload_disabled('unix')) finally: os.environ['PATH'] = saved