def test_test_for_reproducibility_greybox_succeed_after_multiple_tries(
            self):
        """Test test_for_reproducibility with with failure on first run and then
    succeed on remaining runs  (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.side_effect = [
            engine.ReproduceResult(['cmd'], 0, 0, 'output'),
            engine.ReproduceResult(['cmd'], 1, 1, 'crash'),
            engine.ReproduceResult(['cmd'], 1, 1, 'crash'),
        ]
        self.mock.get.return_value = mock_engine

        result = testcase_manager.test_for_reproducibility(
            'engine_target',
            '/fuzz-testcase',
            'state',
            expected_security_flag=False,
            test_timeout=10,
            http_flag=False,
            gestures=None)
        self.assertTrue(result)

        self.assertEqual(3, mock_engine.reproduce.call_count)
        self.mock.log.assert_has_calls([
            mock.call('No crash occurred (round 1).',
                      output=self.GREYBOX_FUZZER_NO_CRASH),
            mock.call('Crash occurred in 1 seconds (round 2). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash occurred in 1 seconds (round 3). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash is reproducible.'),
        ])
    def test_test_for_crash_with_retries_greybox_succeed_no_comparison(self):
        """Test test_for_crash_with_retries reproducing a crash with compare_crash
    set to False (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.side_effect = [
            engine.ReproduceResult(['cmd'], 0, 0, 'output'),
            engine.ReproduceResult(['cmd'], 1, 1, 'crash'),
        ]
        self.mock.get.return_value = mock_engine

        crash_result = testcase_manager.test_for_crash_with_retries(
            self.greybox_testcase, '/fuzz-testcase', 10, compare_crash=False)
        self.assertEqual(1, crash_result.return_code)
        self.assertEqual(1, crash_result.crash_time)
        self.assertEqual(self.GREYBOX_FUZZER_CRASH, crash_result.output)
        self.assertEqual(2, mock_engine.reproduce.call_count)
        mock_engine.reproduce.assert_has_calls([
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 120),
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 10),
        ])
        self.mock.log.assert_has_calls([
            mock.call('No crash occurred (round 1).',
                      output=self.GREYBOX_FUZZER_NO_CRASH),
            mock.call('Crash occurred in 1 seconds (round 2). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash stacktrace comparison skipped.')
        ])
Beispiel #3
0
    def reproduce(self, target_path, input_path, arguments, max_time):
        """Reproduce a crash given an input.
    Args:
      target_path: Path to the fuzzer script or binary.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.
    Returns:
      A ReproduceResult.
    """
        # For blackbox fuzzers, |target_path| supplies the path to the fuzzer script
        # rather than a target in the build archive.
        fuzzer_path = target_path
        os.chmod(fuzzer_path, 0o775)

        app_path = environment.get_value('APP_PATH')
        app_args = testcase_manager.get_command_line_for_application(
            get_arguments_only=True).strip()

        args = _get_arguments(app_path, app_args)
        args.append(f'--testcase_path={input_path}')

        result = _run_with_interpreter_if_needed(fuzzer_path, args, max_time)
        return engine.ReproduceResult(result.command, result.return_code,
                                      result.time_executed, result.output)
Beispiel #4
0
def process_testcase(engine_name, tool_name, target_name, arguments,
                     testcase_path, output_path, timeout):
    """Process testcase on untrusted worker."""
    if tool_name == 'minimize':
        operation = untrusted_runner_pb2.ProcessTestcaseRequest.MINIMIZE
    else:
        operation = untrusted_runner_pb2.ProcessTestcaseRequest.CLEANSE

    rebased_testcase_path = file_host.rebase_to_worker_root(testcase_path)
    file_host.copy_file_to_worker(testcase_path, rebased_testcase_path)

    request = untrusted_runner_pb2.ProcessTestcaseRequest(
        engine=engine_name,
        operation=operation,
        target_name=target_name,
        arguments=arguments,
        testcase_path=file_host.rebase_to_worker_root(testcase_path),
        output_path=file_host.rebase_to_worker_root(output_path),
        timeout=timeout)

    response = host.stub().ProcessTestcase(request)

    rebased_output_path = file_host.rebase_to_worker_root(output_path)
    file_host.copy_file_from_worker(rebased_output_path, output_path)

    return engine.ReproduceResult(list(response.command), response.return_code,
                                  response.time_executed, response.output)
    def test_test_for_crash_with_retries_greybox_fail(self):
        """Test test_for_crash_with_retries failing to reproduce a crash
    (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.return_value = engine.ReproduceResult(['cmd'], 0,
                                                                    0,
                                                                    'output')
        self.mock.get.return_value = mock_engine

        crash_result = testcase_manager.test_for_crash_with_retries(
            self.greybox_testcase, '/fuzz-testcase', 10)
        self.assertEqual(0, crash_result.return_code)
        self.assertEqual(0, crash_result.crash_time)
        self.assertEqual(self.GREYBOX_FUZZER_NO_CRASH, crash_result.output)
        self.assertEqual(3, mock_engine.reproduce.call_count)
        mock_engine.reproduce.assert_has_calls([
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 120),
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 10),
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 10),
        ])
        self.mock.log.assert_has_calls([
            mock.call('No crash occurred (round 1).',
                      output=self.GREYBOX_FUZZER_NO_CRASH),
            mock.call('No crash occurred (round 2).',
                      output=self.GREYBOX_FUZZER_NO_CRASH),
            mock.call('No crash occurred (round 3).',
                      output=self.GREYBOX_FUZZER_NO_CRASH),
            mock.call("Didn't crash at all.")
        ])
Beispiel #6
0
  def cleanse(self, target_path, arguments, input_path, output_path, max_time):
    """Optional (but recommended): Cleanse a testcase.

    Args:
      target_path: Path to the target.
      arguments: Additional arguments needed for testcase cleanse.
      input_path: Path to the reproducer input.
      output_path: Path to the cleansed output.
      max_time: Maximum allowed time for the cleanse.

    Returns:
      A ReproduceResult.
    """
    runner = libfuzzer.get_runner(target_path)
    launcher.set_sanitizer_options(target_path)

    cleanse_tmp_dir = self._create_temp_corpus_dir('cleanse-workdir')
    result = runner.cleanse_crash(
        input_path,
        output_path,
        max_time,
        artifact_prefix=cleanse_tmp_dir,
        additional_args=arguments)

    return engine.ReproduceResult(result.command, result.return_code,
                                  result.time_executed, result.output)
Beispiel #7
0
  def reproduce(self, target_path, input_path, arguments, max_time):
    """Reproduce a crash given an input.

    Args:
      target_path: Path to the target.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.

    Returns:
      A ReproduceResult.
    """
    runner = libfuzzer.get_runner(target_path)
    launcher.set_sanitizer_options(target_path)

    # Remove fuzzing specific arguments. This is only really needed for legacy
    # testcases, and can be removed in the distant future.
    arguments = arguments[:]
    launcher.remove_fuzzing_arguments(arguments)

    runs_argument = constants.RUNS_FLAG + str(constants.RUNS_TO_REPRODUCE)
    arguments.append(runs_argument)

    result = runner.run_single_testcase(
        input_path, timeout=max_time, additional_args=arguments)
    return engine.ReproduceResult(result.command, result.return_code,
                                  result.time_executed, result.output)
Beispiel #8
0
    def minimize_testcase(self, target_path, arguments, input_path,
                          output_path, max_time):
        """Optional (but recommended): Minimize a testcase.

    Args:
      target_path: Path to the target.
      arguments: Additional arguments needed for testcase minimization.
      input_path: Path to the reproducer input.
      output_path: Path to the minimized output.
      max_time: Maximum allowed time for the minimization.

    Returns:
      A ReproduceResult.

    Raises:
      TimeoutError: If the testcase minimization exceeds max_time.
    """
        runner = libfuzzer.get_runner(target_path)
        libfuzzer.set_sanitizer_options(target_path)

        minimize_tmp_dir = self._create_temp_corpus_dir('minimize-workdir')
        result = runner.minimize_crash(input_path,
                                       output_path,
                                       max_time,
                                       artifact_prefix=minimize_tmp_dir,
                                       additional_args=arguments)

        if result.timed_out:
            raise TimeoutError('Minimization timed out\n' + result.output)

        return engine.ReproduceResult(result.command, result.return_code,
                                      result.time_executed, result.output)
Beispiel #9
0
    def reproduce(self, target_path, input_path, arguments, max_time):  # pylint: disable=unused-argument
        """Reproduce a crash given an input.
       Example: ./syz-crush -config my.cfg -infinite=false -restart_time=20s
        crash-qemu-1-1455745459265726910

    Args:
      target_path: Path to the target.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.

    Returns:
      A ReproduceResult.
    """
        binary_dir = self.prepare_binary_path()
        syzkaller_runner = runner.get_runner(
            os.path.join(binary_dir, constants.SYZ_REPRO))
        repro_args = runner.get_config()
        repro_args.extend([
            '-infinite=false', '-restart_time={}s'.format(REPRO_TIME),
            input_path
        ])
        result = syzkaller_runner.repro(max_time, repro_args=repro_args)

        return engine.ReproduceResult(result.command, result.return_code,
                                      result.time_executed, result.output)
Beispiel #10
0
def engine_reproduce(engine_impl, target_name, testcase_path, arguments,
                     timeout):
    """Run engine reproduce on untrusted worker."""
    rebased_testcase_path = file_host.rebase_to_worker_root(testcase_path)
    file_host.copy_file_to_worker(testcase_path, rebased_testcase_path)

    request = untrusted_runner_pb2.EngineReproduceRequest(
        engine=engine_impl.name,
        target_name=target_name,
        testcase_path=rebased_testcase_path,
        arguments=arguments,
        timeout=timeout)

    try:
        response = host.stub().EngineReproduce(request)
    except grpc.RpcError as e:
        if 'TargetNotFoundError' in str(e, encoding='utf-8', errors='ignore'):
            # Resurface the right exception.
            raise testcase_manager.TargetNotFoundError(
                'Failed to find target ' + target_name)
        else:
            raise

    return engine.ReproduceResult(list(response.command), response.return_code,
                                  response.time_executed, response.output)
    def test_test_for_reproducibility_greybox_succeed(self):
        """Test test_for_reproducibility with success on all runs (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.return_value = engine.ReproduceResult(['cmd'], 1,
                                                                    1, 'crash')
        self.mock.get.return_value = mock_engine

        result = testcase_manager.test_for_reproducibility(
            'engine_target',
            '/fuzz-testcase',
            'state',
            expected_security_flag=False,
            test_timeout=10,
            http_flag=False,
            gestures=None)
        self.assertTrue(result)

        # Only 2/3 runs needed to verify reproducibility.
        self.assertEqual(2, mock_engine.reproduce.call_count)
        self.mock.log.assert_has_calls([
            mock.call('Crash occurred in 1 seconds (round 1). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash occurred in 1 seconds (round 2). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash is reproducible.'),
        ])
Beispiel #12
0
  def test_test_for_crash_with_retries_greybox_succeed(self):
    """Test test_for_crash_with_retries reproducing a crash (greybox)."""
    mock_engine = mock.Mock()
    mock_engine.reproduce.side_effect = [
        engine.ReproduceResult(['cmd'], 0, 0, 'output'),
        engine.ReproduceResult(['cmd'], 1, 0, 'crash'),
    ]
    self.mock.get.return_value = mock_engine

    crash_result = testcase_manager.test_for_crash_with_retries(
        self.greybox_testcase, '/fuzz-testcase', 10)
    self.assertEqual(1, crash_result.return_code)
    self.assertEqual(0, crash_result.crash_time)
    self.assertEqual(self.EXPECTED_HEADER + 'crash', crash_result.output)
    self.assertEqual(2, mock_engine.reproduce.call_count)
    mock_engine.reproduce.assert_has_calls([
        mock.call('/build_dir/target', '/fuzz-testcase', ['-arg1', '-arg2'],
                  120),
        mock.call('/build_dir/target', '/fuzz-testcase', ['-arg1', '-arg2'],
                  10),
    ])
Beispiel #13
0
 def repro(self, repro_timeout, repro_args):
     """This is where crash repro'ing is done.
 Args:
   repro_timeout: The maximum time in seconds that repro job is allowed
       to run for.
   repro_args: A sequence of arguments to be passed to the executable.
 """
     logs.log('Running Syzkaller testcase.')
     additional_args = copy.copy(repro_args)
     result = self.run_and_wait(additional_args, timeout=repro_timeout)
     logs.log('Syzkaller testcase stopped.')
     return engine.ReproduceResult(result.command, result.return_code,
                                   result.time_executed, result.output)
Beispiel #14
0
  def test_test_for_crash_with_retries_greybox_legacy(self):
    """Test test_for_crash_with_retries reproducing a legacy crash (greybox)."""
    mock_engine = mock.Mock()
    mock_engine.reproduce.side_effect = [
        engine.ReproduceResult(['cmd'], 1, 1, 'crash'),
    ]
    self.mock.get.return_value = mock_engine

    with open('/flags-testcase', 'w') as f:
      f.write('%TESTCASE% target -arg1 -arg2')

    testcase_manager.test_for_crash_with_retries(self.greybox_testcase,
                                                 '/fuzz-testcase', 10)
    mock_engine.reproduce.assert_has_calls([
        mock.call('/build_dir/target', '/fuzz-testcase', ['-arg1', '-arg2'],
                  120),
    ])
Beispiel #15
0
    def reproduce(self, target_path, input_path, arguments, max_time):
        """Reproduce a crash given an input.

    Args:
      target_path: Path to the target.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.

    Returns:
      A ReproduceResult.
    """
        runner = new_process.ProcessRunner(target_path)
        with open(input_path) as f:
            result = runner.run_and_wait(timeout=max_time, stdin=f)

        return engine.ReproduceResult(result.command, result.return_code,
                                      result.time_executed, result.output)
Beispiel #16
0
  def test_test_for_reproducibility_greybox(self):
    """Test test_for_reproducibility (greybox)."""
    mock_engine = mock.Mock()
    mock_engine.reproduce.return_value = engine.ReproduceResult(['cmd'], 1, 1,
                                                                'crash')
    self.mock.get.return_value = mock_engine

    result = testcase_manager.test_for_reproducibility(
        'engine_target',
        '/fuzz-testcase',
        'state',
        expected_security_flag=False,
        test_timeout=10,
        http_flag=False,
        gestures=None)
    self.assertTrue(result)

    # Only 2/3 runs needed to verify reproducibility.
    self.assertEqual(2, mock_engine.reproduce.call_count)
Beispiel #17
0
    def reproduce(self, target_path, input_path, arguments, max_time):
        """Reproduce a crash given an input.

    Args:
      target_path: Path to the target.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.

    Returns:
      A ReproduceResult.
    """
        runner = libfuzzer.get_runner(target_path)
        launcher.set_sanitizer_options(target_path)

        result = runner.run_single_testcase(input_path,
                                            timeout=max_time,
                                            additional_args=arguments)
        return engine.ReproduceResult(result.return_code, result.time_executed,
                                      result.output)
    def test_test_for_crash_with_retries_greybox_fail(self):
        """Test test_for_crash_with_retries failing to reproduce a crash
    (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.return_value = engine.ReproduceResult(
            0, 0, 'output')
        self.mock.get.return_value = mock_engine

        crash_result = testcase_manager.test_for_crash_with_retries(
            self.testcase, '/fuzz-testcase', 10)
        self.assertEqual(0, crash_result.return_code)
        self.assertEqual(0, crash_result.crash_time)
        self.assertEqual('output', crash_result.output)
        self.assertEqual(3, mock_engine.reproduce.call_count)
        mock_engine.reproduce.assert_has_calls([
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 120),
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 10),
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 10),
        ])
Beispiel #19
0
  def reproduce(self, target_path, input_path, arguments, max_time):
    """Reproduce a crash given an input.
       Example: ./syz-repro -config my.cfg crash-qemu-1-1455745459265726910

    Args:
      target_path: Path to the target.
      input_path: Path to the reproducer input.
      arguments: Additional arguments needed for reproduction.
      max_time: Maximum allowed time for the reproduction.

    Returns:
      A ReproduceResult.
    """
    binary_dir = self.prepare_binary_path()
    syzkaller_runner = runner.get_runner(
        os.path.join(binary_dir, constants.SYZ_REPRO))
    repro_args = runner.get_config()
    repro_args.extend(input_path)
    result = syzkaller_runner.repro(max_time, repro_args=repro_args)

    return engine.ReproduceResult(result.command, result.return_code,
                                  result.time_executed, result.output)
    def test_test_for_crash_with_retries_greybox_legacy(self):
        """Test test_for_crash_with_retries reproducing a legacy crash (greybox)."""
        mock_engine = mock.Mock()
        mock_engine.reproduce.side_effect = [
            engine.ReproduceResult(['cmd'], 1, 1, 'crash'),
        ]
        self.mock.get.return_value = mock_engine

        with open('/flags-testcase', 'w') as f:
            f.write('%TESTCASE% target -arg1 -arg2')

        testcase_manager.test_for_crash_with_retries(self.greybox_testcase,
                                                     '/fuzz-testcase', 10)
        mock_engine.reproduce.assert_has_calls([
            mock.call('/build_dir/target', '/fuzz-testcase',
                      ['-arg1', '-arg2'], 120),
        ])
        self.mock.log.assert_has_calls([
            mock.call('Crash occurred in 1 seconds (round 1). State:\nstate',
                      output=self.GREYBOX_FUZZER_CRASH),
            mock.call('Crash stacktrace is similar to original stacktrace.')
        ])