def __init__(self, stage, iter_id, srcdir, outdir, cfg, cores, verbose, force_resp, dry_run): super().__init__('', srcdir, outdir, cfg, cores, verbose, force_resp, dry_run) stageoutdir = path.join(outdir, nh.get_outdir_name(stage, iter_id)) self.stage = stage self.iter_id = iter_id self.img_dir = path.join(stageoutdir, Dedup.PM_IMG_DIR) self.tc_dir = path.join(stageoutdir, Dedup.TESTCASE_DIR) if verbose: printv('Creating stage %d with iter_id %d' % (stage, iter_id)) # Initialize an instance of Dedup class to manage the global and local # dedup directories self.dedup = Dedup(stage, iter_id, srcdir, outdir, cfg, cores, verbose, force_resp, dry_run) # Create the directories outdir = path.join(self.outdir, nh.get_outdir_name(self.stage, self.iter_id), nh.AFL_DIR_NM) self.afl_dir = outdir try: makedirs(outdir) except OSError as e: if path.isfile(outdir): abort('%s is not a directory.' % outdir) self.tc_timeout = cfg['pmfuzz']['stage']['2']['tc_timeout']
def __init__(self, name, srcdir, outdir, cfg, cores, verbose, force_resp, dry_run): # Create an outdir afloutdir = path.join(outdir, nh.get_outdir_name(1, 1), nh.AFL_DIR_NM) stageoutdir = path.join(outdir, nh.get_outdir_name(1, 1)) self.afloutdir = afloutdir try: makedirs(afloutdir) except OSError: if path.isfile(afloutdir): abort('%s is not a directory.' % afloutdir) # Call the parent constructor super().__init__(name, srcdir, outdir, cfg, cores, verbose, force_resp, dry_run) # TODO: Share these values between dedup and Stage1 # self.resultdir = path.join(self.afloutdir, nh.get_outdir_name(1, 1)) self.o_tc_dir = path.join(self.afloutdir, 'master_fuzzer/queue') self.img_dir = path.join(stageoutdir, Dedup.PM_IMG_DIR) self.tc_dir = path.join(stageoutdir, Dedup.TESTCASE_DIR) self.map_dir = path.join(stageoutdir, Dedup.MAP_DIR) try: makedirs(self.tc_dir) except OSError as e: if path.isfile(self.tc_dir): abort('%s is not a directory.' % self.tc_dir) try: makedirs(self.img_dir) except OSError as e: if path.isfile(self.img_dir): abort('%s is not a directory.' % self.img_dir) try: makedirs(self.o_tc_dir) except OSError as e: if path.isfile(self.o_tc_dir): abort('%s is not a directory.' % self.o_tc_dir) try: makedirs(self.map_dir) except OSError as e: if path.isfile(self.map_dir): abort('%s is not a directory.' % self.map_dir)
def __init__(self, stage, iter_id, srcdir, outdir, cfg, cores, verbose, force_resp, dry_run): super().__init__('', srcdir, outdir, cfg, cores, verbose, force_resp, dry_run) self.stage = stage self.iter_id = iter_id self.resultdir = path.join(self.outdir, \ nh.get_outdir_name(stage, iter_id)) self.total_min_dir = path.join(self.resultdir, nh.ST2_MIN_DIR) self.tc_dir = path.join(self.resultdir, Dedup.TESTCASE_DIR) self.img_dir = path.join(self.resultdir, Dedup.PM_IMG_DIR) self.dedup_dir_gbl = path.join(self.outdir, Dedup.DEDUP_DIR_GBL) self.dedup_dir_loc = path.join(self.resultdir, Dedup.DEDUP_DIR_LOC) self.o_tc_dir = path.join(self.resultdir, Dedup.OUTPUT_TC_DIR) # Create all the directories at startup self._gen_dirs() self.crash_site_db_f = path.join(self.outdir, '@crashsitehashes.db') if verbose: printv('Creating dedup for stage %d with iter_id %d' % (stage, iter_id))
def run_lcov(indir, outdir, cfg, verbose): gbl_dedup = os.path.join(indir, '@dedup') tc_dirs = [gbl_dedup] img_dirs = [gbl_dedup] state = State('State', '/dev/null', indir, cfg, 0, verbose, force_resp=None, dry_run=False) state.sync() stage = int(state.stage) iterid = int(state.iter_id) if stage == 2: stage_d = nh.get_outdir_name(stage, iterid) tc_dirs.append(os.path.join(indir, stage_d, 'testcases')) img_dirs.append(gbl_dedup) print(tc_dirs) lcov = Lcov( tc_dirs=tc_dirs, img_dirs=img_dirs, cfg=cfg, empty_img='/mnt/pmem0/__empty_img__', verbose=verbose, ) lcov.run()
def get_result_dir(self, name): """ Returns the path to the queue directory for a run @param name str representing the name of the run @return str representing complete path to the queue dir""" stage_dir = nh.get_outdir_name(self.stage, self.iter_id) tc_dir = path.join(self.outdir, stage_dir, nh.AFL_DIR_NM, \ name) outdir = path.join(tc_dir, 'master_fuzzer') return outdir
def get_inclusive_map(pmfuzz_d, cur_stage, cur_iterid, filt, rename): """ @brief Returns the cumulative map for the currently running stage, returns 0 if the currently running stage is stage 1""" cumulative = None if cur_stage != 1: stage_d = nh.get_outdir_name(cur_stage, cur_iterid) testcase_d = os.path.join(pmfuzz_d, stage_d, 'testcases') cumulative = get_cumulative_map(testcase_d, filt, rename) return cumulative
def clear(self): """ @brief Deletes all local files associated with this stage. @return None """ # Generate the name of the directory to delete odir_name = nh.get_outdir_name(self.stage, self.iter_id) outdir = path.join(self.outdir, odir_name) printw('Removing tree: ' + outdir) # Delete it rmtree(outdir)
def _run_cs(self, csname: str): """ @brief Runs a testcase @param csname Name of the crash site to run, name conforms to nh.is_crash_site @return None """ cspath = path.join(self.dedup.dedup_dir_loc, csname + '.' + nh.CMPR_CRASH_SITE_EXT) pmdir = self.cfg['pmfuzz']['img_loc'] imgdir = tempfile.mkdtemp(prefix=('pmfuzz-cs-run-' + csname), dir=pmdir) #TODO: Figure out a way to clean this up on completion decompress(cspath, imgdir + '/', self.verbose) imgpm = path.join(imgdir, csname + '.' + nh.CRASH_SITE_EXT) indir = self.srcdir outdir = path.join(self.outdir, nh.get_outdir_name(self.stage, self.iter_id), nh.AFL_DIR_NM, csname) img_path, tgtcmd_loc = nh.set_img_path(self.cfg.tgtcmd, imgpm, self.cfg) abort_if(img_path == "", 'Unable to set img path for %s.' % img_path) pids = run_afl( indir=indir, outdir=outdir, tgtcmd=tgtcmd_loc, cfg=self.cfg, cores=1, # WARN: Use one core per testcase verbose=self.verbose, persist_tgt=False, dry_run=self.dry_run, gen_img=False, ) # Wait for AFL to start and see if it works if self.verbose: printv('Checking for PID: ' + str(pids)) time.sleep(5) for pid in pids: abort_if(not psutil.pid_exists(pid), f'AFL crashed for pid {pid}')
def get_inclusive_tc_cnt(pmfuzz_d, cur_stage, cur_iterid, filt): """ @brief Returns the total count of testcases for the currently running stage, returns 0 if the currently running stage is stage 1 @param pmfuzz_d @param cur_stage @param cur_iterid @param filt""" count = 0 if cur_stage != 1: stage_d = nh.get_outdir_name(cur_stage, cur_iterid) testcase_d = os.path.join(pmfuzz_d, stage_d, 'testcases') for fname in filter(filt, os.listdir(testcase_d)): count += 1 return count
def _run_testcase(self, testcasename: str): """ @brief Runs a testcase @param testcasename Name of the testcase to run, format: id=<id> @return None """ imgdestdir = self.get_img_dir(testcasename) if path.exists(imgdestdir): rmtree(imgdestdir) os.makedirs(imgdestdir) indir = self.srcdir outdir = path.join(self.outdir, nh.get_outdir_name(self.stage, self.iter_id), nh.AFL_DIR_NM, testcasename) img_path = path.join(imgdestdir, testcasename + self.dedup.EXT_PM_POOL) img_path, tgtcmd_loc = nh.set_img_path(self.cfg.tgtcmd, img_path, self.cfg) img_name = path.basename(img_path) img_src_path = path.join(self.dedup.dedup_dir_gbl, img_name) abort_if(img_path == "", 'Unable to set img path for %s.' % img_path) decompress(img_src_path + '.tar.gz', imgdestdir, self.verbose) pids = run_afl( indir=indir, outdir=outdir, tgtcmd=tgtcmd_loc, cfg=self.cfg, cores=1, # WARN: Use one core per testcase verbose=self.verbose, persist_tgt=False, dry_run=self.dry_run, gen_img=False, )
def run_pmfuzz(indir, outdir, cfg, cores1=1, cores2=1, verbose: bool = False, force_yes=False, dry_run=False, disable_stage2=False): """ PMFuzz entry point """ update_info(outdir) state = State('State', indir, outdir, cfg, cores1, verbose, force_yes, dry_run) state.sync() stage_id = int(state.stage) iter_id = int(state.iter_id) # Deduplication output should always exist on completing stage 1 if stage_id > 1 and not state.dedup_exists: abort('Result directory corrupted, deduplication is absent with' ' stage(%d) > 1' % stage_id) # Give an option to resume from the saved state if stage_id != 1 and stage_id != 0: resp = ask_yn('Running PMFuzz found: stage %d, iter %d, ' \ %(stage_id, iter_id) + 'resume', force_yes) if not resp: abort('Resume cancelled.') # Run the state machine while True: # Update state state.sync() stage_id = int(state.stage) iter_id = int(state.iter_id) if stage_id != 0: # Always run deduplication on stage 1 first collect_stage1(indir, outdir, cfg, cores1, cores2, disable_stage2, verbose, force_yes, dry_run) # No stage is running if stage_id == 0: run_stage1(indir, outdir, cfg, cores1, verbose, force_yes, dry_run) # Create a timer for future ptimer = PTimer(path.join(outdir, nh.get_outdir_name(1, 1))) ptimer.start_new(STAGE1_WAITTIME) # Stage 1 is already is running elif stage_id == 1 and not disable_stage2: # Continue to stage 2 if stage 1 timer has expired timer = PTimer(path.join(outdir, nh.get_outdir_name(1, 1))) if timer.expired(): printi('Starting to stage 2 (elapsed: %s)' % timer.elapsed_hr()) run_stage2(indir, outdir, cfg, cores2, verbose, force_yes, dry_run) elif stage_id == 2 and not disable_stage2: # Run/resume stage 2 run_stage2(indir, outdir, cfg, cores2, verbose, force_yes, dry_run) elif not disable_stage2: abort('Unimplemented') time.sleep(2)