Example #1
0
    def test_windows(self):
        """Tests that it behaves as intended on Windows."""
        self.mock.platform.return_value = 'WINDOWS'
        executable_with_extension = self.EXECUTABLE + '.exe'
        # Test that it adds an extension if needed.
        self.assertEqual(executable_with_extension,
                         environment.get_executable_filename(self.EXECUTABLE))

        # Now test that it doesn't add an extension when not needed.
        self.assertEqual(
            executable_with_extension,
            environment.get_executable_filename(executable_with_extension))
Example #2
0
def find_fuzzer_path(build_directory, fuzzer_name):
    """Find the fuzzer path with the given name."""
    if not build_directory:
        # Grey-box fuzzers might not have the build directory for a particular job
        # configuration when doing variant task testing (e.g. Android on-device
        # fuzz target might not exist on host). In this case, treat it similar to
        # target not found by returning None.
        logs.log_warn('No build directory found for fuzzer: %s' % fuzzer_name)
        return None

    if environment.platform() == 'FUCHSIA':
        # Fuchsia targets are not on disk.
        return fuzzer_name

    # TODO(ochang): This is necessary for legacy testcases, which include the
    # project prefix in arguments. Remove this in the near future.
    project_name = environment.get_value('PROJECT_NAME')
    legacy_name_prefix = u''
    if project_name:
        legacy_name_prefix = project_name + u'_'

    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for root, _, files in shell.walk(build_directory):
        for filename in files:
            if (legacy_name_prefix.encode() + filename == fuzzer_name
                    or filename == fuzzer_filename):
                return os.path.join(root, filename)

    # This is an expected case when doing regression testing with old builds
    # that do not have that fuzz target. It can also happen when a host sends a
    # message to an untrusted worker that just restarted and lost information on
    # build directory.
    logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                  (fuzzer_name, build_directory))
    return None
def find_fuzzer_path(build_directory, fuzzer_name):
  """Find the fuzzer path with the given name."""
  if environment.platform() == 'FUCHSIA':
    # Fuchsia targets are not on disk.
    return fuzzer_name

  # TODO(ochang): This is necessary for legacy testcases, which include the
  # project prefix in arguments. Remove this in the near future.
  project_name = environment.get_value('PROJECT_NAME')
  legacy_name_prefix = ''
  if project_name:
    legacy_name_prefix = project_name + '_'

  fuzzer_filename = environment.get_executable_filename(fuzzer_name)
  for root, _, files in os.walk(build_directory):
    for filename in files:
      if (legacy_name_prefix + filename == fuzzer_name or
          filename == fuzzer_filename):
        return os.path.join(root, filename)

  # This is an expected case when doing regression testing with old builds
  # that do not have that fuzz target. It can also happen when a host sends a
  # message to an untrusted worker that just restarted and lost information on
  # build directory.
  logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                (fuzzer_name, build_directory))
  return None
Example #4
0
def _get_fuzzer_path(target_list, fuzzer_name):
    """Return the full fuzzer path and actual binary name of |fuzzer_name|."""
    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for path in target_list:
        if os.path.basename(path) == fuzzer_filename:
            return path

    raise BuiltinFuzzerException('Failed to find chosen target ' + fuzzer_name)
Example #5
0
def set_environment_vars(search_directories, app_path='APP_PATH'):
  """Set build-related environment variables (APP_PATH, APP_DIR etc) by walking
  through the build directory."""
  app_name = environment.get_value('APP_NAME')
  llvm_symbolizer_filename = environment.get_executable_filename(
      'llvm-symbolizer')
  llvm_symbolizer_path = None
  gn_args_filename = 'args.gn'
  gn_args_path = None
  platform = environment.platform()
  absolute_file_path = None
  app_directory = None

  # Chromium specific folder to ignore.
  initialexe_folder_path = '%sinitialexe' % os.path.sep

  for search_directory in search_directories:
    for root, _, files in os.walk(search_directory):
      # .dSYM folder contain symbol files on Mac and should
      # not be searched for application binary.
      if platform == 'MAC' and '.dSYM' in root:
        continue

      # Ignore some folders on Windows.
      if (platform == 'WINDOWS' and (initialexe_folder_path in root)):
        continue

      for filename in files:
        if not absolute_file_path and filename == app_name:
          absolute_file_path = os.path.join(root, filename)
          app_directory = os.path.dirname(absolute_file_path)

          # We don't want to change the state of system binaries.
          if not environment.get_value('SYSTEM_BINARY_DIR'):
            os.chmod(absolute_file_path, 0750)

          environment.set_value(app_path, absolute_file_path)
          environment.set_value('APP_DIR', app_directory)

        if not gn_args_path and filename == gn_args_filename:
          gn_args_path = os.path.join(root, gn_args_filename)
          environment.set_value('GN_ARGS_PATH', gn_args_path)

        if (not llvm_symbolizer_path and
            filename == llvm_symbolizer_filename and
            not environment.get_value('USE_DEFAULT_LLVM_SYMBOLIZER')):
          llvm_symbolizer_path = os.path.join(root, llvm_symbolizer_filename)
          environment.set_value('LLVM_SYMBOLIZER_PATH', llvm_symbolizer_path)
Example #6
0
def find_fuzzer_path(build_directory, fuzzer_name, is_blackbox=False):
    """Find the fuzzer path with the given name."""
    # Blackbox fuzzers are special cases. They run from the fuzzers directory
    # rather than using a target from the build archive.
    if is_blackbox:
        fuzzer_directory = environment.get_value('FUZZERS_DIR')
        fuzzer_directory = os.path.join(fuzzer_directory, fuzzer_name)
        fuzzer = data_types.Fuzzer.query(
            data_types.Fuzzer.name == fuzzer_name).get()
        return os.path.join(fuzzer_directory, fuzzer.executable_path)

    if not build_directory:
        # Grey-box fuzzers might not have the build directory for a particular job
        # configuration when doing variant task testing (e.g. Android on-device
        # fuzz target might not exist on host). In this case, treat it similar to
        # target not found by returning None.
        logs.log_warn('No build directory found for fuzzer: %s' % fuzzer_name)
        return None

    if environment.platform() == 'FUCHSIA':
        # Fuchsia targets are not on disk.
        return fuzzer_name

    if environment.platform() == 'ANDROID_KERNEL':
        return os.path.join(build_directory, 'syzkaller', 'bin', 'syz-manager')

    # TODO(ochang): This is necessary for legacy testcases, which include the
    # project prefix in arguments. Remove this in the near future.
    project_name = environment.get_value('PROJECT_NAME')
    legacy_name_prefix = u''
    if project_name:
        legacy_name_prefix = project_name + u'_'

    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for root, _, files in shell.walk(build_directory):
        for filename in files:
            if (legacy_name_prefix + filename == fuzzer_name
                    or filename == fuzzer_filename):
                return os.path.join(root, filename)

    # This is an expected case when doing regression testing with old builds
    # that do not have that fuzz target. It can also happen when a host sends a
    # message to an untrusted worker that just restarted and lost information on
    # build directory.
    logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                  (fuzzer_name, build_directory))
    return None
Example #7
0
def find_fuzzer_path(build_directory, fuzzer_name):
    """Find the fuzzer path with the given name."""
    # TODO(ochang): This is necessary for legacy testcases, which include the
    # project prefix in arguments. Remove this in the near future.
    project_name = environment.get_value('PROJECT_NAME')
    legacy_name_prefix = ''
    if project_name:
        legacy_name_prefix = project_name + '_'

    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for root, _, files in os.walk(build_directory):
        for filename in files:
            if (legacy_name_prefix + filename == fuzzer_name
                    or filename == fuzzer_filename):
                return os.path.join(root, filename)

    logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                  (fuzzer_name, build_directory))
    return None
Example #8
0
def terminate_stale_application_instances():
    """Kill stale instances of the application running for this command."""
    if environment.is_trusted_host():
        from bot.untrusted_runner import remote_process_host
        remote_process_host.terminate_stale_application_instances()
        return

    # Stale instance cleanup is sometimes disabled for local testing.
    if not environment.get_value('KILL_STALE_INSTANCES', True):
        return

    additional_process_to_kill = environment.get_value(
        'ADDITIONAL_PROCESSES_TO_KILL')
    builds_directory = environment.get_value('BUILDS_DIR')
    llvm_symbolizer_filename = environment.get_executable_filename(
        'llvm-symbolizer')
    platform = environment.platform()
    start_time = time.time()

    processes_to_kill = []
    # Avoid killing the test binary when running the reproduce tool. It is
    # commonly in-use on the side on developer workstations.
    if not environment.get_value('REPRODUCE_TOOL'):
        app_name = environment.get_value('APP_NAME')
        processes_to_kill += [app_name]

    if additional_process_to_kill:
        processes_to_kill += additional_process_to_kill.split(' ')
    processes_to_kill = [x for x in processes_to_kill if x]

    if platform == 'ANDROID':
        # Cleanup any stale adb connections.
        device_serial = environment.get_value('ANDROID_SERIAL')
        adb_search_string = 'adb -s %s' % device_serial

        # Terminate llvm symbolizer processes matching exact path. This is important
        # for Android where multiple device instances run on same host.
        llvm_symbolizer_path = environment.get_llvm_symbolizer_path()

        terminate_processes_matching_cmd_line(
            [adb_search_string, llvm_symbolizer_path], kill=True)

        # Make sure device is online and rooted.
        android.adb.run_as_root()

        # Make sure to reset SE Linux Permissive Mode (might be lost in reboot).
        android.settings.change_se_linux_to_permissive_mode()

        # Make sure that device forwarder is running (might be lost in reboot or
        # process crash).
        android.device.setup_host_and_device_forwarder_if_needed()

        # Make sure that package optimization is complete (might be triggered due to
        # unexpected circumstances).
        android.app.wait_until_optimization_complete()

        # Reset application state, which kills its pending instances and re-grants
        # the storage permissions.
        android.app.reset()

    elif platform == 'WINDOWS':
        processes_to_kill += [
            'cdb.exe',
            'handle.exe',
            'msdt.exe',
            'openwith.exe',
            'WerFault.exe',
            llvm_symbolizer_filename,
        ]
        terminate_processes_matching_names(processes_to_kill, kill=True)
        terminate_processes_matching_cmd_line(builds_directory, kill=True)

        # Artifical sleep to let the processes get terminated.
        time.sleep(1)

    else:
        # Handle Linux and Mac platforms.
        processes_to_kill += [
            'addr2line',
            'atos',
            'chrome-devel-sandbox',
            'gdb',
            'nacl_helper',
            'xdotool',
            llvm_symbolizer_filename,
        ]
        terminate_processes_matching_names(processes_to_kill, kill=True)
        terminate_processes_matching_cmd_line(builds_directory, kill=True)

    duration = int(time.time() - start_time)
    if duration >= 5:
        logs.log('Process kill took longer than usual - %s.' %
                 str(datetime.timedelta(seconds=duration)))
Example #9
0
 def test_non_windows(self, platform):
     """Tests that it behaves as intended on platforms that aren't Windows."""
     self.mock.platform.return_value = platform
     self.assertEqual(self.EXECUTABLE,
                      environment.get_executable_filename(self.EXECUTABLE))