def use_mutator_plugin(target_name, extra_env, chroot): """Decide whether to use a mutator plugin. If yes and there is a usable plugin available for |target_name|, then add it to LD_PRELOAD in |extra_env|, add chroot bindings if |chroot| is not None, and return True.""" # TODO(metzman): Support Windows. if environment.platform() == 'WINDOWS': return False mutator_plugin_path = mutator_plugin.get_mutator_plugin(target_name) if not mutator_plugin_path: return False logs.log('Using mutator plugin: %s' % mutator_plugin_path) # TODO(metzman): Change the strategy to record which plugin was used, and # not simply that a plugin was used. extra_env['LD_PRELOAD'] = mutator_plugin_path if chroot: mutator_plugin_dir = os.path.dirname(mutator_plugin_path) chroot.add_binding( minijail.ChrootBinding(mutator_plugin_dir, mutator_plugin_dir, False)) return True
def test_minijail_bindings(self): """Test minijail process command with additional bind dirs.""" with minijail.MinijailChroot(bindings=[ minijail.ChrootBinding('/foo/bar', '/bar', True), minijail.ChrootBinding('/foo/barr', '/barr', False), ]) as chroot: runner = minijail.MinijailProcessRunner(chroot, '/bin/ls') self.assertListEqual(runner.get_command(), [ '/sbin/minijail', '-U', '-m', '0 1000 1', '-T', 'static', '-c', '0', '-n', '-v', '-p', '-l', '-I', '-k', 'proc,/proc,proc,1', '-P', chroot.directory, '-b', '%s,/tmp,1' % chroot.tmp_directory, '-b', '/lib,/lib,0', '-b', '/lib32,/lib32,0', '-b', '/lib64,/lib64,0', '-b', '/usr/lib,/usr/lib,0', '-b', '/foo/bar,/bar,1', '-b', '/foo/barr,/barr,0', '/bin/ls' ])
def get_runner(fuzzer_path, temp_dir=None): """Get a libfuzzer runner.""" use_minijail = environment.get_value('USE_MINIJAIL') build_dir = environment.get_value('BUILD_DIR') if use_minijail: # Set up chroot and runner. if environment.is_chromeos_system_job(): minijail_chroot = minijail.ChromeOSChroot(build_dir) else: minijail_chroot = minijail.MinijailChroot(base_dir=temp_dir) # While it's possible for dynamic binaries to run without this, they need # to be accessible for symbolization etc. For simplicity we bind BUILD_DIR # to the same location within the chroot, which leaks the directory # structure of CF but this shouldn't be a big deal. minijail_chroot.add_binding( minijail.ChrootBinding(build_dir, build_dir, False)) # Also bind the build dir to /out to make it easier to hardcode references # to data files. minijail_chroot.add_binding( minijail.ChrootBinding(build_dir, '/out', False)) minijail_bin = os.path.join(minijail_chroot.directory, 'bin') shell.create_directory(minijail_bin) # Set up /bin with llvm-symbolizer to allow symbolized stacktraces. # Don't copy if it already exists (e.g. ChromeOS chroot jail). llvm_symbolizer_source_path = environment.get_llvm_symbolizer_path() llvm_symbolizer_destination_path = os.path.join(minijail_bin, 'llvm-symbolizer') if not os.path.exists(llvm_symbolizer_destination_path): shutil.copy(llvm_symbolizer_source_path, llvm_symbolizer_destination_path) # copy /bin/sh, necessary for system(). if not environment.is_chromeos_system_job(): # The chroot has its own shell we don't need to copy (and probably # shouldn't because of library differences). shutil.copy(os.path.realpath('/bin/sh'), os.path.join(minijail_bin, 'sh')) runner = MinijailLibFuzzerRunner(fuzzer_path, minijail_chroot) elif environment.platform() == 'FUCHSIA': runner = FuchsiaQemuLibFuzzerRunner(fuzzer_path) else: runner = LibFuzzerRunner(fuzzer_path) return runner
def unbind_corpus_dirs(chroot, corpus_directories): """Unbind corpus directories from the minijail chroot. Args: chroot: The MinijailChroot. corpus_directories: A list of corpus paths. """ for corpus_directory in corpus_directories: target_dir = '/' + os.path.basename(corpus_directory) chroot.remove_binding( minijail.ChrootBinding(corpus_directory, target_dir, True))
def test_chroot(self): """Tests basic chroot setup.""" chroot_directory = None with minijail.MinijailChroot() as chroot: chroot_directory = chroot.directory self.assertListEqual( sorted(os.listdir(chroot_directory)), ['dev', 'lib', 'lib32', 'lib64', 'proc', 'tmp', 'usr']) self.assertEqual( chroot.get_binding(chroot.tmp_directory), minijail.ChrootBinding(chroot.tmp_directory, '/tmp', True)) for directory in ['/lib', '/lib32', '/lib64', '/usr/lib']: self.assertEqual( chroot.get_binding(directory), minijail.ChrootBinding(directory, directory, False)) self.assertIsNone(chroot.get_binding('/usr')) self.assertFalse(os.path.exists(chroot_directory))
def _bind_corpus_dirs(self, corpus_directories): """Bind corpus directories to the minijail chroot. Also makes sure that the directories are world writeable. Args: corpus_directories: A list of corpus paths. """ for corpus_directory in corpus_directories: target_dir = '/' + os.path.basename(corpus_directory) self.chroot.add_binding( minijail.ChrootBinding(corpus_directory, target_dir, writeable=True))