mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-21 13:51:19 +00:00
Capture crash dumps from libfuzzer, when provided (#2793)
Enables capturing crashdumps generated by ASAN at point of failure. This helps in several ways: - provides a crash dump in the case that we cannot repro a failure later - some people have stated that crash dumps would be more useful to their team than the repro VM - we should be able to use these for automated submission to Watson or similar --- Crash dumps are automatically collected (for libfuzzer) jobs, if we find any. They should be activated by enabling crash dumps in ASAN, via: - On Linux: `ASAN_OPTIONS=disable_coredump=0:abort_on_error=1:unmap_shadow_on_exit=1` - OneFuzz will override the (Ubuntu) crash dump options to generate core dumps instead and then upload them. - On Windows: `ASAN_SAVE_DUMPS=my_dump.dmp` - OneFuzz will look for any `*.dmp` files in the working directory and then upload them. In both cases, the crash dump will be renamed to match the crashing input, if possible, and uploaded to a new `crashdumps` container. --- Also updated: the “simple” LibFuzzer test has been updated to be compiled with `cl.exe` instead of `clang` on Windows, so that we are exercising the MSVC implementation of ASAN/LibFuzzer, and the CI image has been updated to `windows-2022`. The restriction to an old version of the Windows SDK has been removed.
This commit is contained in:
@ -87,6 +87,7 @@ class Integration(BaseModel):
|
||||
target_class: Optional[str]
|
||||
target_method: Optional[str]
|
||||
setup_dir: Optional[str]
|
||||
target_env: Optional[Dict[str, str]]
|
||||
|
||||
|
||||
TARGETS: Dict[str, Integration] = {
|
||||
@ -106,12 +107,21 @@ TARGETS: Dict[str, Integration] = {
|
||||
ContainerType.unique_reports: 1,
|
||||
ContainerType.coverage: 1,
|
||||
ContainerType.inputs: 2,
|
||||
# TODO: crashdumps are intermittently not captured
|
||||
# during integration tests on Linux. This requires more
|
||||
# investigation before we can fully enable this test.
|
||||
# ContainerType.crashdumps: 1,
|
||||
ContainerType.extra_output: 1,
|
||||
},
|
||||
reboot_after_setup=True,
|
||||
inject_fake_regression=True,
|
||||
target_env={
|
||||
# same TODO
|
||||
# "ASAN_OPTIONS": "disable_coredump=0:abort_on_error=1:unmap_shadow_on_exit=1"
|
||||
},
|
||||
fuzzing_target_options=[
|
||||
"--test:{extra_setup_dir}",
|
||||
"--only_asan_failures",
|
||||
"--write_test_file={extra_output_dir}/test.txt",
|
||||
],
|
||||
),
|
||||
@ -213,11 +223,15 @@ TARGETS: Dict[str, Integration] = {
|
||||
ContainerType.inputs: 2,
|
||||
ContainerType.unique_reports: 1,
|
||||
ContainerType.coverage: 1,
|
||||
ContainerType.crashdumps: 1,
|
||||
ContainerType.extra_output: 1,
|
||||
},
|
||||
inject_fake_regression=True,
|
||||
target_env={"ASAN_SAVE_DUMPS": "my_dump.dmp"},
|
||||
# we should set unmap_shadow_on_exit=1 but it fails on Windows at the moment
|
||||
fuzzing_target_options=[
|
||||
"--test:{extra_setup_dir}",
|
||||
"--only_asan_failures",
|
||||
"--write_test_file={extra_output_dir}/test.txt",
|
||||
],
|
||||
),
|
||||
@ -631,6 +645,7 @@ class TestOnefuzz:
|
||||
fuzzing_target_options=config.fuzzing_target_options,
|
||||
extra_setup_container=Container(extra_setup_container.name),
|
||||
extra_output_container=Container(extra_output_container.name),
|
||||
target_env=config.target_env,
|
||||
)
|
||||
elif config.template == TemplateType.libfuzzer_dotnet:
|
||||
if setup is None:
|
||||
@ -653,6 +668,7 @@ class TestOnefuzz:
|
||||
fuzzing_target_options=config.target_options,
|
||||
target_class=config.target_class,
|
||||
target_method=config.target_method,
|
||||
target_env=config.target_env,
|
||||
)
|
||||
elif config.template == TemplateType.libfuzzer_qemu_user:
|
||||
return self.of.template.libfuzzer.qemu_user(
|
||||
@ -665,6 +681,7 @@ class TestOnefuzz:
|
||||
duration=duration,
|
||||
vm_count=1,
|
||||
target_options=config.target_options,
|
||||
target_env=config.target_env,
|
||||
)
|
||||
elif config.template == TemplateType.radamsa:
|
||||
return self.of.template.radamsa.basic(
|
||||
@ -679,6 +696,7 @@ class TestOnefuzz:
|
||||
disable_check_debugger=config.disable_check_debugger or False,
|
||||
duration=duration,
|
||||
vm_count=1,
|
||||
target_env=config.target_env,
|
||||
)
|
||||
elif config.template == TemplateType.afl:
|
||||
return self.of.template.afl.basic(
|
||||
@ -692,6 +710,7 @@ class TestOnefuzz:
|
||||
duration=duration,
|
||||
vm_count=1,
|
||||
target_options=config.target_options,
|
||||
target_env=config.target_env,
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
@ -798,14 +817,18 @@ class TestOnefuzz:
|
||||
return (True, "timed out while checking jobs", False)
|
||||
|
||||
for job_id in check_containers:
|
||||
job_name = jobs[job_id].config.name
|
||||
finished_containers: Set[Container] = set()
|
||||
for container_name, container_impl in check_containers[job_id].items():
|
||||
container_client, count = container_impl
|
||||
if len(container_client.list_blobs()) >= count:
|
||||
container_client, required_count = container_impl
|
||||
found_count = len(container_client.list_blobs())
|
||||
if found_count >= required_count:
|
||||
clear()
|
||||
self.logger.info(
|
||||
"found files for %s - %s",
|
||||
jobs[job_id].config.name,
|
||||
"found %d files (needed %d) for %s - %s",
|
||||
found_count,
|
||||
required_count,
|
||||
job_name,
|
||||
container_name,
|
||||
)
|
||||
finished_containers.add(container_name)
|
||||
@ -813,6 +836,12 @@ class TestOnefuzz:
|
||||
for container_name in finished_containers:
|
||||
del check_containers[job_id][container_name]
|
||||
|
||||
to_check = check_containers[job_id].keys()
|
||||
if len(to_check) > 0:
|
||||
self.logger.info(
|
||||
"%s - still waiting for %s", job_name, ", ".join(to_check)
|
||||
)
|
||||
|
||||
scalesets = self.of.scalesets.list()
|
||||
for job_id in job_tasks:
|
||||
finished_tasks: Set[UUID] = set()
|
||||
|
Reference in New Issue
Block a user