예제 #1
0
def record_progress(args, total_tc, total_pm_tc, total_paths, total_pm_paths,
                    exec_rate, mq_pop):
    if args.progress_file != None:
        # Create the file
        if not os.path.isfile(args.progress_file):
            with open(args.progress_file, 'w') as obj:
                obj.write('')

        interval = args.progress_interval

        tail_cmd = ['tail', '-1', args.progress_file]
        last_line = subprocess.check_output(tail_cmd).decode("utf-8")

        last_write = last_line.split(',')[0]

        if last_write.strip() == '':
            last_write = 0
        else:
            last_write = int(last_write)

        cur_time = int(time.time())

        if (cur_time - last_write) < 0:
            common.abort('Corrupted progress file: ' + args.progress_file)

        if (cur_time - last_write) > interval:
            with open(args.progress_file, 'a') as obj:
                obj.write(str(cur_time) + ',' + str(total_tc) + ',' \
                    + str(total_pm_tc) + ',' + str(total_paths) + ','\
                    + str(total_pm_paths) + ',' + str(exec_rate) + ','\
                    + str(mq_pop) + '\n')
예제 #2
0
    def iter_id(self):
        """ Returns the highest iter_id for the highest stage in the outdir, 
        requires a call to sync() before the first use. Each subsequent calls 
        would require sync() calls to retrieve latest `outdir` state. """

        if not hasattr(self, '_iter_id'):
            common.abort('No state found, was sync() called?')
        return self._iter_id
예제 #3
0
    def dedup_exists(self):
        """ Returns boolean value denoting the existence of deduplication 
        directory in the outdir, requires a call to sync() before the first
        use. Each subsequent calls would require sync() calls to retrieve
        lates `outdir` state. """

        if not hasattr(self, '_dedup_exists'):
            common.abort('No state found, was sync() called?')
        return self._dedup_exists
예제 #4
0
def except_hook(exctype, value, tb):
    tb_fmt = traceback.format_exception(exctype, value, tb)[1:-1]

    # Too many open files
    if '[Errno 24]' in str(value):
        print('Open files:')
        list_open_fd()

    common.abort('Exception raised: ' + exctype.__name__ + ': ' + str(value),
                 tb_fmt=tb_fmt)
예제 #5
0
def run_failure_inj(cfg,
                    tgtcmd,
                    imgpath,
                    testcase_f,
                    clean_name,
                    create,
                    verbose=False):
    """ @brief Run failure injection on an image 
    @param create If true, inject the failure to the process of creating the
                  image
    @return None"""

    if not create and not os.path.isfile(imgpath):
        abort('Image path %s does not exist' % imgpath)

    env, cmd = gen_failure_inj_cmd(cfg, cfg.tgtcmd, imgpath, create, verbose)
    env.update({"FI_IMG_SUFFIX": clean_name.replace('.testcase', '')})

    if verbose:
        printv('Failure Injection:')
        printv('%20s : %s' % ('env', str(env)))
        printv('%20s : %s' % ('cmd', ' '.join(cmd)))
        printv('%20s : %s' % ('stdin', testcase_f))

    fd, out_file = tempfile.mkstemp(prefix='pmfuzz-img-gen-out-')
    printv('Redirecting output to ' + out_file)

    exit_code = None
    with open(out_file, 'w') as stdout, open(testcase_f, 'r') as stdin:
        exit_code = exec_shell(
            cmd=cmd,
            stdin=stdin,
            stdout=stdout,
            stderr=subprocess.STDOUT,
            env=env,
            wait=True,
            timeout=
            30  # Set a generous timeout of 30 seconds so things don't crash
        )

    os.close(fd)

    descr_str, success = translate_exit_code(exit_code)
    if not success:
        abort('Failure injection for pid %d failed: %s' \
            % (os.getpid(), descr_str))
예제 #6
0
    def test_img_gen(self, imgpath):
        """ @brief Tests the process of creating a new image with the testcase 
        by checking return code of the target

        @param imgpath str representing the complete path of the image to test,
               the path should not exist
        @return bool value indicating success """

        # Create a tempfile for writing run output
        fd, tmp = tempfile.mkstemp(prefix='pmfuzz-test-img-output-')
        os.close(fd)

        tgtcmd_loc = list(self.cfg.tgtcmd)
        imgpath, tgtcmd_loc = nh.set_img_path(tgtcmd_loc, imgpath, self.cfg)

        env = self.cfg.get_env(persist=False)

        if self.verbose:
            printv('Writing run output to ' + tmp)

        success, exit_code = None, None
        with open(tmp, 'w') as out:
            with open(self.testcase_f, 'r') as testcase_obj:
                exit_code = exec_shell(
                    cmd     = tgtcmd_loc,
                    stdin   = testcase_obj,
                    stdout  = out,
                    stderr  = subprocess.STDOUT,
                    env     = env,
                    wait    = True
                )

                code_desc, success = translate_exit_code(exit_code)

                if not success and self.verbose:
                    printv('Image failed.')

        if success == None:
            abort('Test run failed, unable to check image.')

        return success, exit_code, tgtcmd_loc, env
예제 #7
0
def perform_checks():
    """ @brief Performs a series of checks to make sure basic AFL requirements
    are met 
    @return None
    """

    # Check for core dump notification
    printi('Checking for core dump notification')
    with open('/proc/sys/kernel/core_pattern', 'r') as obj:
        content = obj.read().strip()
        if content != 'core':
            print()
            printi(
                'Run "sudo bash -c \'echo core >/proc/sys/kernel/core_pattern\'"',
                format_path=False)
            common.abort('Incorrectly configured core dump notifications')

    # Check if ASLR is enabled
    printi('Checking for ASLR')
    with open('/proc/sys/kernel/randomize_va_space', 'r') as obj:
        content = obj.read().strip()
        if content != '0':
            print()
            printi(
                'Run "sudo bash -c \'echo 0 >/proc/sys/kernel/randomize_va_space\'"',
                format_path=False)
            common.abort(
                'ASLR should be disabled for image deduplication to work.')

    printi('Checking for Python version')
    PY_MAJOR = sys.version_info[0]
    PY_MINOR = sys.version_info[1]

    if (PY_MAJOR != 3 or PY_MINOR < 6):
        common.abort("Python 3.6+ required.")
예제 #8
0
    def gen_img(self, dest_dir, compress_img=True, img_path=None):
        """ @brief Generate image for a testcase file 
        
        @param testcase_f str that points to the testcase to use for generation
        @param dest_dir str Directory to store the resulting image
        @param tgtcmd List of str for the command for running the target prog
        @param cfg Config for setting up the target process' environment

        @return None """

        testcase_f = self.testcase_f
        cfg        = self.cfg
        verbose    = self.verbose

        tgtcmd = cfg.tgtcmd

        tgtcmd_loc = None
        if img_path == None:
            img_name = path.basename(nh.get_metadata_files(testcase_f)['pm_pool'])

            # Get the command for generating the image
            img_path, tgtcmd_loc = nh.set_img_name(tgtcmd, img_name, cfg)

            abort_if(img_path=='', 'Unable to parse image path, tgtcmd=' + \
                                    str(tgtcmd) + ', img_name=' + img_name)
        else:
            img_name = path.basename(img_path)

            # Get the command for generating the image
            img_path, tgtcmd_loc = nh.set_img_path(tgtcmd, img_path, cfg)

            abort_if(img_path=='', 'Unable to parse image path, tgtcmd=' + \
                                    str(tgtcmd) + ', img_name=' + img_name)


        # Enable persistence for image in the environment
        env = cfg.get_env(persist=True)

        if verbose:
            printv('cmd: %s' % (' '.join(tgtcmd_loc)))
            printv('env: %s' % (str(env)))
            printv('stdin: %s' % testcase_f)

        # Create a tempfile for writing run output
        fd, tmp = tempfile.mkstemp(prefix='pmfuzz-img-gen-output-')
        os.close(fd)

        if verbose:
            printv('Writing image generation output to ' + tmp)

        with open(tmp, 'w') as out:
            with open(testcase_f, 'r') as testcase_obj:
                exit_code = exec_shell(
                    cmd=tgtcmd_loc,
                    stdin=testcase_obj,
                    stdout=out,
                    stderr=subprocess.STDOUT,
                    env=env,
                    wait=True,
                    timeout = 30 # Set a generous timeout of 30 seconds so things don't crash
                )

                code_desc, success = translate_exit_code(exit_code)
                if not success:
                    abort('Image generation failed: ' + code_desc)
                    
        if not path.isfile(img_path):
            abort('Image generation failed (%s).' % img_path)
        
        # Copy the file back to the pmfuzz result directory
        if compress_img:
            src = img_path
            dest = path.join(dest_dir, path.basename(img_path))
            dest = nh.get_metadata_files(dest)['pm_cmpr_pool']

            compress(src, dest, verbose)
            remove(src)
            
            if verbose:
                printw('Deleting: ' + src)