Пример #1
0
    def execute_tcs(self, tc_dir, img_dir):
        tcs = [path.join(tc_dir, fn) for fn in os.listdir(tc_dir)]
        imgs = [path.join(img_dir, fn) for fn in os.listdir(img_dir)]

        iter = 0
        for tc in filter(nh.is_tc, tcs):
            # print(tc)
            # iter += 1
            # if iter > 5:
            #     return
            img = self.empty_img

            if nh.ancestor_cnt(path.basename(tc)) > 0:
                parent = nh.get_testcase_parent(path.basename(tc))
                img = nh.get_metadata_files(parent)['pm_cmpr_pool']
                img = path.join(path.dirname(img_dir), '@dedup', img)

                abort_if(
                    path.basename(img) not in os.listdir(img_dir),
                    'Img %s not found in %s' % (img, img_dir))

            printi('Running %s with image %s' % (tc, img))

            img_cmpr = img.endswith('.tar.gz')
            if img_cmpr:
                decompress(img, '/mnt/pmem0/', verbose=self.verbose)
                img = path.join(
                    '/mnt/pmem0/',
                    path.basename(nh.get_metadata_files(img)['pm_pool']))

            self.run_tgt(tc, img)

            if img_cmpr:
                os.remove(img)
    def _delete_tcs(self, testcases):
        """ @brief deletes a testcase and all metadata files with it, 
        including images and maps.

        @param testcases List of testcase name or complete path
        @return None"""

        delete_q = []

        # Find all the metadata files associated with all the testcases
        for testcase in testcases:
            metadata_files = nh.get_metadata_files(testcase)
            delete_q += metadata_files.values()

            # Write the placeholder file to indicate that this file is deleted
            placeholder_f \
                = nh.get_metadata_files(testcase, deleted=True)['deleted']
            with open(placeholder_f, 'w') as obj:
                obj.write('Deleted at epoch=%d' % int(time.time()))

        remove_files(delete_q, self.verbose, warn=True, force=True)
Пример #3
0
    def global_dedup_list_tc(self):
        """ @brief Get all testcase and corresponding images from global store.

        Does not include crash sites, to list that, see @ref 
        global_dedup_list_cs
        
        @return List of tuple with first entry the path to the testcase and 
                second entry a corresponding path to the image or None """

        result = []

        gbl_dedup_files = listdir(self.dedup_dir_gbl)

        # Complete the path
        gbl_dedup_files = [path.join(self.dedup_dir_gbl, fname) \
                                for fname in gbl_dedup_files]

        for filepath in gbl_dedup_files:

            # Only process testcases
            if nh.is_tc(filepath):
                entry = [filepath, None]

                # If this testcase has a corresponding pool image
                imgpath = nh.get_metadata_files(filepath)['pm_cmpr_pool']
                if imgpath in gbl_dedup_files:
                    # Add it to the tuple
                    entry[1] = imgpath
                else:
                    printw('No image found %s' % imgpath)

                # Add tuple to the results
                result.append(tuple(entry))

        if self.verbose:
            printv('Returning %d cases' % len(result))

        return result
Пример #4
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)
Пример #5
0
    def update_local(self):
        """ @brief Copies testcases and images from global dedup store to local 
        dedup store 

        Local is updated in two steps:
        1. The testcases and corresponding images are copied
        2. Any crash site generated in the previous interation is copied
        
        @return None """

        printi('Updating local')

        loc_tc_files = listdir(self.dedup_dir_loc)
        loc_tc_files = [f.replace('.min', '') for f in loc_tc_files]

        # 1. Copy testcases
        for testcase, img in self.global_dedup_list_tc:

            # A testcase might not have an associated image
            if img == None:
                img = ''

            dest_name_tc = path.basename(testcase).replace('.min', '')
            dest_name_img = path.basename(img)

            #* Note: This piece of code assumes that dedup would only run
            #* update_local on stage 2
            abort_if(self.stage != 2, 'update_local() is only supported on ' \
                        + 'stage 2')
            is_min_tc = True  #re.search(nh.TC_MIN_REGEX, path.basename(testcase))

            # Make sure this testcase was generated from the immediate parent
            # of this stage and not earlier than that
            iter_id = nh.iter_cnt(path.basename(testcase))
            is_parent = iter_id == self.iter_id

            # Copy only if destination does not exists and the testcase is a
            # minimum testcase
            if dest_name_tc not in loc_tc_files and is_min_tc and is_parent:
                src = testcase
                dest = path.join(self.dedup_dir_loc, dest_name_tc)

                # Remove 'min' from testestcase name
                dest = dest.replace('.min', '')

                if self.verbose:
                    printv(f'Copying to local dedup: {src} -> {dest}')

                copypreserve(src, dest)

                if img != '':
                    # Copy image
                    src = img
                    dest = path.join(self.dedup_dir_loc, dest_name_img)

                    # Remove 'min' from testestcase name
                    dest = dest.replace('.min', '')

                    if self.verbose:
                        printv(f'Copying to local dedup: {src} -> {dest}')

                    copypreserve(src, dest)
                    abort_if(not os.path.isfile(dest), 'Cannot copy')

                else:
                    abort('Image not found for %s' % dest_name_tc)

                # Copy map
                testcasebasename = os.path.basename(testcase)
                metadata_files = nh.get_metadata_files(testcasebasename)
                src = os.path.join(self.dedup_dir_gbl, metadata_files['map'])
                dest = os.path.join(self.dedup_dir_loc, metadata_files['map'])

                if self.verbose:
                    printv(f'Copying map to local dedup {src} -> {dest}')
                copypreserve(src, dest)

                # Copy PM map
                testcasebasename = os.path.basename(testcase)
                metadata_files = nh.get_metadata_files(testcasebasename)
                src = os.path.join(self.dedup_dir_gbl,
                                   metadata_files['pm_map'])
                dest = os.path.join(self.dedup_dir_loc,
                                    metadata_files['pm_map'])

                copied = False
                if os.path.isfile(src):
                    copied = True
                    copypreserve(src, dest)

                if copied:
                    self.printv(f'Copying map to local dedup {src} -> {dest}')
                else:
                    self.printv(f'Did not find {src}')

        if len(self.global_dedup_list_cs) == 0:
            self.printv('Did not find any crash site in global dedup')
        else:
            self.printv('=> ' + str(self.global_dedup_list_cs))

        # 2. Copy crash images
        for cs in self.global_dedup_list_cs:
            if path.basename(cs) not in os.listdir(self.dedup_dir_loc):
                src = cs
                dest = path.join(self.dedup_dir_loc, path.basename(src))

                self.printv('Copying cs: %s -> %s' % (src, dest))

                copypreserve(src, dest)
Пример #6
0
    def update_global(self):
        """ @brief Copies testcases and images from local tc/img store to global 
        store

        Global is updated in two steps:
        1. The testcases and corresponding images are copied
        2. Any crash site generated is copied
        
        @return None """

        printi('Updating global')

        gbl_tc_files = listdir(self.dedup_dir_gbl)

        # 1. Copy testcases and corresponding images
        for testcase, img in self.local_testcases_list:
            dest_name_tc = path.basename(testcase)
            dest_name_img = path.basename(img)

            # for deleted cases
            dest_name_placeholder \
                = nh.get_metadata_files(dest_name_tc, deleted=True)['deleted']

            # Copy only if destination does not exists
            if (dest_name_tc not in gbl_tc_files) \
                    and (dest_name_placeholder not in gbl_tc_files):
                printi('Copying files related to ' \
                    + path.basename(dest_name_tc))

                # Copy testcase
                src = testcase
                dest = path.join(self.dedup_dir_gbl, dest_name_tc)

                copypreserve(src, dest)

                if self.verbose:
                    printv('Copying to global dedup: %s -> %s' % (src, dest))

                # Copy exec map
                src = testcase
                src = path.join(path.dirname(src), 'map_' + path.basename(src))
                dest = path.join(self.dedup_dir_gbl, 'map_' + dest_name_tc)

                if path.isfile(src):
                    copypreserve(src, dest)

                    if self.verbose:
                        printv('Copying to exec map: %s -> %s' % (src, dest))
                else:
                    if self.verbose:
                        printv('Unable to find exec map: ' + src)

                # Copy PM map
                src = testcase.replace(Dedup.TESTCASE_DIR, Dedup.TESTCASE_DIR)
                src = path.join(path.dirname(src),
                                'pm_map_' + path.basename(src))
                dest = path.join(self.dedup_dir_gbl, 'pm_map_' + dest_name_tc)

                if path.isfile(src):
                    copypreserve(src, dest)

                    if self.verbose:
                        printv('Copying to PM map: %s -> %s' % (src, dest))
                else:
                    if self.verbose:
                        printv('Unable to find PM map: ' + src)

                # Copy image
                src = img
                dest = path.join(self.dedup_dir_gbl, dest_name_img)

                copypreserve(src, dest)
                abort_if(not os.path.isfile(dest), 'Cannot copy')

                if self.verbose:
                    printv('Copying to global dedup: %s -> %s' % (src, dest))

        # 2. Copy crash sites
        for fname in os.listdir(self.img_dir):
            should_copy = fname not in os.listdir(self.dedup_dir_gbl)

            if nh.is_cmpr_crash_site(fname) and should_copy:
                src = path.join(self.img_dir, fname)
                dest = path.join(self.dedup_dir_gbl, fname)

                if self.verbose:
                    printv('Copying cs %s -> %s' % (src, dest))

                copypreserve(src, dest)
Пример #7
0
    def minimize_corpus_lcl(self):
        """ @brief Minimizes the local testcase directory by combining it with 
        the global testcases.
        
        This method uses modified afl-cmin that supports providing before and 
        after shell scripts that provide the corresponding tgtcmd for each
        testcase. Before and after shell scripts are passed to afl-cmin using
        a config directory (tmp_cfgdir).
        
        @returns None """

        # Create temporary directories for managing corpus
        tmp_indir = tempfile.mkdtemp(prefix='cmin-in-', dir=self.tempdir)
        tmp_mapdir = tempfile.mkdtemp(prefix='cmin-map-dir-', dir=self.tempdir)

        # Copy all testcases from global dedup to tmp_indir to allow
        # minimization on global corpus along with local
        for f in os.listdir(self.dedup_dir_loc):
            if nh.is_tc(f):
                src = path.join(self.dedup_dir_loc, f)
                dest = path.join(tmp_indir, f)

                if self.verbose:
                    printv(f'Copying to testcase: {src} -> {dest}')

                copypreserve(src, dest)
            elif nh.is_map(f) or nh.is_pm_map(f):
                src = path.join(self.dedup_dir_loc, f)
                dest = path.join(tmp_mapdir, f)

                if path.isfile(src):
                    copypreserve(src, dest)

                    if self.verbose:
                        printv(f'Copying to map: {src} -> {dest}')
                elif self.verbose:
                    printv(f'Did not find {src}')

        # Copy all the test cases from self.tc_dir to temp directory for corpus
        # minimization
        lcl_tcs = [path.join(self.tc_dir, f) for f in os.listdir(self.tc_dir)]
        for f in lcl_tcs:
            if nh.is_tc(f):
                src = f
                dest = path.join(tmp_indir, path.basename(f))
                copypreserve(src, dest)

                if self.verbose:
                    printv(f'Copying to testcase: {src} -> {dest}')
            elif nh.is_map(f) or nh.is_pm_map(f):
                src = f
                dest = path.join(tmp_mapdir, path.basename(f))

                if path.isfile(src):
                    copypreserve(src, dest)

                    if self.verbose:
                        printv(f'Copying to map: {src} -> {dest}')
                elif self.verbose:
                    printv(f'Did not find {src}')

        total_tcs = len(os.listdir(tmp_indir))

        # Create a temp image for cases that don't have any parent
        _, temp_img = tempfile.mkstemp(prefix='pmfuzz-tmp-img-',
                                       dir=self.tempdir)
        _, tgtcmd_loc \
            = nh.set_img_path(list(self.cfg.tgtcmd), temp_img, self.cfg)
        gen_tgt_img(tgtcmd_loc, self.cfg, verbose=self.verbose)

        # Run the actual thing
        outdir = run_afl_cmin(
            indir=tmp_indir,
            pmfuzzdir=self.outdir,
            tgtcmd=self.cfg.tgtcmd,
            cfg=self.cfg,
            # cfgdir=tmp_cfgdir,
            verbose=self.verbose,
            mapdir=tmp_mapdir,
            dry_run=False,
        )

        dropped_files = []
        for f in os.listdir(tmp_indir):
            if f not in os.listdir(outdir):
                dropped_files.append(f)

        if self.verbose:
            printv('Dropping %d of %d testcases after cmin' \
                % (len(dropped_files), total_tcs))

        # Remove the dropped testcases and associated metadata files from the
        # local testcase directory
        for f in dropped_files:
            metadata_files = nh.get_metadata_files(f)
            for metadata_file_type in metadata_files:
                file_to_delete = path.join(self.tc_dir,
                                           metadata_files[metadata_file_type])

                try:
                    os.remove(file_to_delete)
                    if self.verbose:
                        printv('Removed ' + file_to_delete)
                except FileNotFoundError:
                    pass

        # Remove the dropped testcases and associated metadata files from the
        # global dedup directory
        for f in dropped_files:
            metadata_files = nh.get_metadata_files(f)
            types_to_delete \
                = ['testcase', 'min_testcase', 'pm_map', 'map']
            for metadata_file_type in types_to_delete:
                file_to_delete = path.join(self.dedup_dir_gbl,
                                           metadata_files[metadata_file_type])

                try:
                    os.remove(file_to_delete)
                    placeholder_f = path.join(
                        self.dedup_dir_gbl,
                        nh.get_metadata_files(f, True)['deleted'])
                    with open(placeholder_f, 'w') as obj:
                        obj.write('Deleted at epoch = ' +
                                  str(int(time.time())))
                    if self.verbose:
                        printv('Writing to ' + placeholder_f)
                        printv('Removed ' + file_to_delete)
                except FileNotFoundError:
                    pass

        # TODO: Clean up file descriptors

        if self.verbose:
            printv('Removing dir %s' % tmp_indir)
            printv('Removing dir %s' % tmp_mapdir)
            printv('Removing %s' % temp_img)

        rmtree(tmp_indir)
        rmtree(tmp_mapdir)
        os.remove(temp_img)

        return
Пример #8
0
    def minimize_corpus_gbl(self):
        """ @brief Minimizes the global dedup directory.
        
        This method uses modified afl-cmin that supports providing before and 
        after shell scripts that provide the corresponding tgtcmd for each
        testcase. Before and after shell scripts are passed to afl-cmin using
        a config directory (tmp_cfgdir).

        @todo Replace call to copypreserve with a softlink
        @todo Cleanup indir and cfgdir after completion
        @returns None """

        write_state(self.outdir, 'Minimizing global corpus')

        # Create temporary directories for managing corpus
        tmp_indir = tempfile.mkdtemp(prefix='cmin-in-', dir=self.tempdir)
        tmp_mapdir = tempfile.mkdtemp(prefix='cmin-map-dir-', dir=self.tempdir)

        # Copy all the test cases from self.tc_dir to temp directory for corpus
        # minimization
        total_global_count = 0
        for tc, _ in self.global_dedup_list_tc:
            if nh.is_tc(tc):
                total_global_count += 1
                src = tc
                dest = path.join(tmp_indir, path.basename(tc))
                copypreserve(src, dest)

                if self.verbose:
                    printv(f'Copying testcase {src} -> {dest}')

                # Copy the map
                src = path.join(path.dirname(tc), 'map_' + path.basename(tc))
                dest = path.join(tmp_mapdir, 'map_' + path.basename(tc))
                copypreserve(src, dest)

                if self.verbose:
                    printv(f'Copying map {src} -> {dest}')

                # Copy the pm map
                src = path.join(path.dirname(tc),
                                'pm_map_' + path.basename(tc))
                dest = path.join(tmp_mapdir, 'pm_map_' + path.basename(tc))

                if path.isfile(src):
                    copypreserve(src, dest)
                    self.printv(f'Copying map {src} -> {dest}')

        # Create a temp image for cases that don't have any parent
        fd, temp_img = tempfile.mkstemp(prefix='pmfuzz-tmp-img-',
                                        dir=self.tempdir)

        # We don't actually need this file, todo: do better
        os.close(fd)
        os.remove(temp_img)

        _, tgtcmd_loc = \
            nh.set_img_path(list(self.cfg.tgtcmd), temp_img, self.cfg)
        gen_tgt_img(tgtcmd_loc, self.cfg, verbose=self.verbose)

        # Run the actual thing
        outdir = run_afl_cmin(
            indir=tmp_indir,
            pmfuzzdir=self.outdir,
            tgtcmd=tgtcmd_loc,
            cfg=self.cfg,
            # cfgdir=tmp_cfgdir,
            verbose=self.verbose,
            dry_run=False,
            mapdir=tmp_mapdir,
        )

        dropped_files = []
        for f in os.listdir(tmp_indir):
            if f not in os.listdir(outdir):
                dropped_files.append(f)

        if self.verbose:
            printv('Dropping %d of %d testcases after cmin' \
                % (len(dropped_files), total_global_count))

        # Remove the dropped testcases and associated metadata files
        for f in dropped_files:
            metadata_files = nh.get_metadata_files(f, deleted=False)
            for metadata_file_type in metadata_files:
                if not metadata_files[metadata_file_type].endswith('.tar.gz'):
                    file_to_delete = path.join(
                        self.dedup_dir_gbl, metadata_files[metadata_file_type])

                    try:
                        os.remove(file_to_delete)
                        if self.verbose:
                            printv('Removing ' + file_to_delete)
                    except FileNotFoundError:
                        pass

            # Create a placeholder .deleted file to avoid stage1 from
            # repopulating that testcase
            placeholder_f = path.join(
                self.dedup_dir_gbl,
                nh.get_metadata_files(f, deleted=True)['deleted'])

            with open(placeholder_f, 'w') as obj:
                obj.write('deleted at epoch=%d' % int(time.time()))

        if self.verbose:
            printv('Removing dir %s' % tmp_indir)
            printv('Removing dir %s' % tmp_mapdir)
            printv('Removing %s' % temp_img)

        rmtree(tmp_indir)
        rmtree(tmp_mapdir)
        os.remove(temp_img)

        return
Пример #9
0
    def construct_cmin_sh_files(self, srcdir, scriptsdir, imgdirs, tmp_img):
        """ @brief Constructs the .before.sh and .after.sh for testcases

        @param srcdir Path to directory containing the testcases
        @param scriptsdir Path to directory to write the scripts in
        @param imgdirs List of path to the directory that contains all the 
               compressed img
        @param Path to an empty image for testcases with no parents

        @return None
        """

        # Create config directory containing the command for each testcase
        for f in os.listdir(srcdir):
            tc_name = path.basename(f)
            parent = nh.get_testcase_parent(tc_name)

            # Results of the first stage don't have any parents and have to be
            # run with empty images
            has_parent = nh.iter_cnt(tc_name) > 1

            with open(path.join(scriptsdir, tc_name + '.before.sh'),
                      'w') as obj:
                # Generate a decompress commmand to decompress the images only
                # if the testcase is not from the first stage

                if has_parent:
                    # Src
                    img_src_fname = nh.get_metadata_files(
                        parent)['pm_cmpr_pool']
                    img_src = None

                    for imgdir in imgdirs:
                        img_src = path.join(imgdir, img_src_fname)
                        if os.path.isfile(img_src):
                            break
                    else:
                        abort('No candidate for parent image found in %d dirs'\
                                % len(imgdirs))

                    # Dest
                    img_dest_fname = nh.get_metadata_files(parent)['pm_pool']
                    img_dest = path.join(scriptsdir, img_dest_fname)

                    decompress_cmd = \
                        get_decompress_cmd(img_src, img_dest, self.verbose)

                    # Generate an echo command with the target command
                    tgtcmd_loc = list(self.cfg.tgtcmd)
                    _, tgtcmd_loc \
                        = nh.set_img_path(tgtcmd_loc, img_dest, self.cfg)
                    echo_cmd = 'echo "%s"' % (' '.join(tgtcmd_loc))

                    obj.write('%s;\n%s;\n' %
                              (' '.join(decompress_cmd), echo_cmd))
                else:
                    # 1. Set the temp image in tgt command
                    tgtcmd_loc = list(self.cfg.tgtcmd)
                    _, tgtcmd_loc \
                        = nh.set_img_path(tgtcmd_loc, tmp_img, self.cfg)

                    # 2. Generate an echo command with the target command
                    echo_cmd = 'echo "%s"' % (' '.join(tgtcmd_loc))

                    # 3. Construct the shell script and write it
                    obj.write('%s;\n' % (echo_cmd))

            with open(path.join(scriptsdir, tc_name + '.after.sh'),
                      'w') as obj:
                if has_parent:
                    # Generate command to remove the image
                    rm_img_cmd = 'rm %s' % (img_dest)

                    obj.write('%s;\n' % (rm_img_cmd))
                else:
                    # Don't do anything, ':' character is NOP for shell
                    obj.write(':;\n')
Пример #10
0
    def tc_gen_crash_sites(self, raw_tcname):
        """ Generates crash sites for a testcase

        Testcases is read and crash sites are generated for each of the 
        failure point using the testcase's parent's image. These generated
        results are then sent to the crashsite directory: 
        (e.g., <outdir>/stage=2,iter=1/crashsites/)

        @param raw_tcname Path to a testcase to generate crash sites for
        """

        printi('Generating crash images for testcase: ' + raw_tcname)
        clean_name = nh.clean_tc_name(path.basename(raw_tcname))
        tc_components = os.path.normpath(raw_tcname).split(os.sep)
        parent_name = tc_components[-4] + '.testcase'

        printi('Clean name: ' + clean_name)
        printi('Parent name: ' + parent_name)

        # NOTE:
        # Create image names, *_uniq files are to provide each instance of
        # tc_gen_crash_sites() with a unique image to work with

        pm_dir = tempfile.mkdtemp(prefix='pmfuzz-cs-gen-st2-',
                                  dir=self.cfg('pmfuzz.img_loc'))
        parent_cmpr_img = nh.get_parent_img(parent_name,
                                            self.dedup.dedup_dir_gbl,
                                            'exists',
                                            isparent=True,
                                            verbose=self.verbose)

        # Create image path
        parent_img_name = ''
        if parent_cmpr_img.endswith(nh.CMPR_PM_IMG_EXT):
            parent_img_name = nh.get_metadata_files(parent_name)['pm_pool']
        elif parent_cmpr_img.endswith(nh.CMPR_CRASH_SITE_EXT):
            parent_img_name = nh.get_metadata_files(parent_name)['crash_site']

        parent_img_name_uniq = nh.get_metadata_files(parent_name)\
                                ['clean'] + '<pid=' + str(os.getpid()) + '>'\
                                + '.' + nh.CRASH_SITE_EXT

        parent_img = path.join(pm_dir, parent_img_name)
        parent_img_uniq = path.join(pm_dir, parent_img_name_uniq)

        # Decompres+Copy the image
        if not os.path.isfile(parent_img):
            decompress(parent_cmpr_img, parent_img, self.verbose)
        printv('tempimg: %s -> %s' % (parent_cmpr_img, parent_img))

        copypreserve(parent_img, parent_img_uniq)
        printv('unique image: %s -> %s' % (parent_img, parent_img))

        finj.run_failure_inj(self.cfg, self.cfg.tgtcmd, parent_img_uniq,
                             raw_tcname, clean_name, self.verbose)

        crash_imgs_pattern = parent_img.replace('.pm_pool', '') + '.' \
                                + clean_name.replace('.testcase', '') + '.*'
        crash_imgs = glob(crash_imgs_pattern)

        if self.verbose:
            printi('Total %d crash images generated.' % len(crash_imgs))
            printw('Deleting %s' % (parent_img))

        os.remove(parent_img_uniq)

        if self.verbose:
            printv('Compressing all the crash sites')

        self.process_new_crash_sites(parent_img_uniq, clean_name)

        if self.verbose:
            printv('Crash sites compressed')