libfuzzer-dotnet integration (#535)

This commit is contained in:
bmc-msft
2021-02-11 17:30:24 -05:00
committed by GitHub
parent 360693e8a4
commit 933fe6850c
10 changed files with 451 additions and 7 deletions

View File

@ -31,7 +31,7 @@ from onefuzz.backend import ContainerWrapper, wait
from onefuzz.cli import execute_api
from onefuzztypes.enums import OS, ContainerType, TaskState, VmState
from onefuzztypes.models import Job, Pool, Repro, Scaleset
from onefuzztypes.primitives import Directory, File
from onefuzztypes.primitives import Container, Directory, File, PoolName, Region
from pydantic import BaseModel, Field
LINUX_POOL = "linux-test"
@ -41,6 +41,7 @@ BUILD = "0"
class TemplateType(Enum):
libfuzzer = "libfuzzer"
libfuzzer_dotnet = "libfuzzer_dotnet"
afl = "afl"
radamsa = "radamsa"
@ -51,6 +52,7 @@ class Integration(BaseModel):
target_exe: str
inputs: Optional[str]
use_setup: bool = Field(default=False)
nested_setup_dir: Optional[str]
wait_for_files: List[ContainerType]
check_asan_log: Optional[bool] = Field(default=False)
disable_check_debugger: Optional[bool] = Field(default=False)
@ -73,6 +75,15 @@ TARGETS: Dict[str, Integration] = {
wait_for_files=[ContainerType.unique_reports, ContainerType.coverage],
reboot_after_setup=True,
),
"linux-libfuzzer-dotnet": Integration(
template=TemplateType.libfuzzer_dotnet,
os=OS.linux,
target_exe="wrapper",
nested_setup_dir="my-fuzzer",
inputs="inputs",
use_setup=True,
wait_for_files=[ContainerType.inputs, ContainerType.crashes],
),
"linux-libfuzzer-rust": Integration(
template=TemplateType.libfuzzer,
os=OS.linux,
@ -159,7 +170,7 @@ class TestOnefuzz:
def setup(
self,
*,
region: Optional[str] = None,
region: Optional[Region] = None,
user_pools: Optional[Dict[str, str]] = None,
) -> None:
for entry in self.os:
@ -169,7 +180,7 @@ class TestOnefuzz:
)
self.pools[entry] = self.of.pools.get(user_pools[entry.name])
else:
name = "pool-%s-%s" % (self.project, entry.name)
name = PoolName("pool-%s-%s" % (self.project, entry.name))
self.logger.info("creating pool: %s:%s", entry.name, name)
self.pools[entry] = self.of.pools.create(name, entry)
self.logger.info("creating scaleset for pool: %s", name)
@ -195,6 +206,9 @@ class TestOnefuzz:
else None
)
if setup and config.nested_setup_dir:
setup = Directory(os.path.join(setup, config.nested_setup_dir))
job: Optional[Job] = None
if config.template == TemplateType.libfuzzer:
job = self.of.template.libfuzzer.basic(
@ -207,7 +221,21 @@ class TestOnefuzz:
setup_dir=setup,
duration=1,
vm_count=1,
reboot_after_setup=config.reboot_after_setup,
reboot_after_setup=config.reboot_after_setup or False,
)
elif config.template == TemplateType.libfuzzer_dotnet:
if setup is None:
raise Exception("setup required for libfuzzer_dotnet")
job = self.of.template.libfuzzer.dotnet(
self.project,
target,
BUILD,
self.pools[config.os].name,
target_harness=config.target_exe,
inputs=inputs,
setup_dir=setup,
duration=1,
vm_count=1,
)
elif config.template == TemplateType.radamsa:
job = self.of.template.radamsa.basic(
@ -362,7 +390,7 @@ class TestOnefuzz:
self.logger.info("checking jobs")
return wait(self.check_jobs_impl)
def get_job_crash(self, job_id: UUID) -> Optional[Tuple[str, str]]:
def get_job_crash(self, job_id: UUID) -> Optional[Tuple[Container, str]]:
# get the crash container for a given job
for task in self.of.tasks.list(job_id=job_id, state=None):
@ -396,6 +424,7 @@ class TestOnefuzz:
self.logger.info("launching repro: %s", self.target_jobs[job_id])
report = self.get_job_crash(job_id)
if report is None:
self.logger.warning("target does not include crash reports: %s", self.target_jobs[job_id])
return
(container, path) = report
self.repros[job_id] = self.of.repro.create(container, path, duration=1)
@ -555,7 +584,7 @@ class Run(Command):
endpoint: Optional[str] = None,
user_pools: Optional[Dict[str, str]] = None,
pool_size: int = 10,
region: Optional[str] = None,
region: Optional[Region] = None,
os_list: List[OS] = [OS.linux, OS.windows],
targets: List[str] = list(TARGETS.keys()),
skip_repro: bool = False,
@ -580,6 +609,7 @@ class Run(Command):
if skip_repro:
self.logger.warning("not testing crash repro")
else:
self.logger.info("launching crash repro tests")
tester.launch_repro()
tester.check_repro()
except Exception as e: