Esempio n. 1
0
    def run_elf_checks(self, pkg, pkgfile_path, path):
        self.readelf_parser = ReadelfParser(pkgfile_path, path)
        failed_reason = self.readelf_parser.parsing_failed_reason()
        if failed_reason:
            self.output.add_info('E', pkg, 'readelf-failed', path,
                                 failed_reason)
            return

        if not self.readelf_parser.is_archive:
            self.ldd_parser = LddParser(pkgfile_path, path)
            failed_reason = self.ldd_parser.parsing_failed_reason
            if failed_reason:
                self.output.add_info('E', pkg, 'ldd-failed', path,
                                     failed_reason)
                return

            self.objdump_parser = ObjdumpParser(pkgfile_path, path)
            failed_reason = self.objdump_parser.parsing_failed_reason
            if failed_reason:
                self.output.add_info('E', pkg, 'objdump-failed', path,
                                     failed_reason)
                return

        with concurrent.futures.ThreadPoolExecutor() as executor:
            futures = []
            for fn in self.check_functions:
                futures.append(executor.submit(fn, pkg, pkgfile_path, path))
            concurrent.futures.wait(futures)
Esempio n. 2
0
    def run_elf_checks(self, pkg, pkgfile_path, path):
        if self.is_archive and not self._is_standard_archive(
                pkg, pkgfile_path, path):
            return

        self.readelf_parser = ReadelfParser(pkgfile_path, path)
        failed_reason = self.readelf_parser.parsing_failed_reason()
        if failed_reason:
            self.output.add_info('E', pkg, 'readelf-failed', path,
                                 failed_reason)
            return

        if not self.is_archive:
            if self.is_dynamically_linked:
                is_installed_pkg = isinstance(pkg, InstalledPkg) or isinstance(
                    pkg, FakePkg)
                self.ldd_parser = LddParser(pkgfile_path, path,
                                            is_installed_pkg)
                failed_reason = self.ldd_parser.parsing_failed_reason
                if failed_reason:
                    self.output.add_info('E', pkg, 'ldd-failed', path,
                                         failed_reason)
                    return

            self.objdump_parser = ObjdumpParser(pkgfile_path, path)
            failed_reason = self.objdump_parser.parsing_failed_reason
            if failed_reason:
                self.output.add_info('E', pkg, 'objdump-failed', path,
                                     failed_reason)
                return

        with concurrent.futures.ThreadPoolExecutor() as executor:
            futures = []
            for fn in self.check_functions:
                futures.append(executor.submit(fn, pkg, pkgfile_path, path))
            concurrent.futures.wait(futures)
            for future in futures:
                err = future.exception()
                if err:
                    raise err
Esempio n. 3
0
    def run_elf_checks(self, pkg, pkgfile):
        if self.is_archive and not self._is_standard_archive(pkg, pkgfile):
            self.is_nonstandard_archive = True
            return

        self.readelf_parser = ReadelfParser(pkgfile.path, pkgfile.name)
        failed_reason = self.readelf_parser.parsing_failed_reason()
        if failed_reason:
            self.output.add_info('E', pkg, 'readelf-failed', pkgfile.name, failed_reason)
            return

        if not self.is_archive:
            if self.is_dynamically_linked:
                is_installed_pkg = isinstance(pkg, (InstalledPkg, FakePkg))
                self.ldd_parser = LddParser(pkgfile.path, pkgfile.name, is_installed_pkg)
                failed_reason = self.ldd_parser.parsing_failed_reason
                if failed_reason:
                    self.output.add_info('E', pkg, 'ldd-failed', pkgfile.name, failed_reason)
                    return

            if (self.config.configuration['MandatoryOptflags'] or
                    self.config.configuration['ForbiddenOptflags']):
                self.objdump_parser = ObjdumpParser(pkgfile.path, pkgfile.name)
                failed_reason = self.objdump_parser.parsing_failed_reason
                if failed_reason:
                    self.output.add_info('E', pkg, 'objdump-failed', pkgfile.name, failed_reason)
                    return

        # NOTE: the speed benefit of the ThreadPoolExecutor is limited due to
        # Global Interpreter Lock (GIL).
        with concurrent.futures.ThreadPoolExecutor() as executor:
            futures = []
            for fn in self.check_functions:
                futures.append(executor.submit(fn, pkg, pkgfile))
            concurrent.futures.wait(futures)
            for future in futures:
                err = future.exception()
                if err:
                    raise err
def readelfparser(path, system_path=None):
    if system_path is None:
        system_path = path
    return ReadelfParser(get_full_path(path), system_path)
Esempio n. 5
0
    def check(self, pkg):
        if pkg.is_source:
            return

        # Consider only non-development, non-language library packages
        if (not pkg.name.startswith('lib') or pkg.name.endswith('-devel')
                or pkg.name.endswith('-lang')):
            return

        self._check_missing_policy_lib(pkg)

        # the soname validation matching the name is done
        # already in BinaryCheck._check_shared_library
        # Search for shared libraries in this package
        libs = set()
        libs_needed = set()
        libs_to_dir = {}
        reqlibs = set()
        pkg_requires = {x.name.split('(')[0] for x in pkg.requires}

        for filename, pkgfile in pkg.files.items():
            path = Path(filename)
            if '.so.' in filename or filename.endswith('.so'):
                if stat.S_ISREG(pkg.files[filename].mode
                                ) and pkgfile.magic.startswith('ELF '):
                    readelf_parser = ReadelfParser(pkgfile.path, filename)
                    failed_reason = readelf_parser.parsing_failed_reason()
                    if failed_reason:
                        self.output.add_info('E', pkg, 'readelf-failed',
                                             filename, failed_reason)
                        return
                    dyn_section = readelf_parser.dynamic_section_info
                    libs_needed = libs_needed.union(dyn_section.needed)
                    if dyn_section.soname:
                        lib_dir = str(path.parent)
                        libs.add(dyn_section.soname)
                        libs_to_dir[dyn_section.soname] = lib_dir
                    if dyn_section.soname in pkg_requires:
                        # But not if the library is used by the pkg itself
                        # This avoids program packages with their own
                        # private lib
                        # FIXME: we'd need to check if somebody else links
                        # to this lib
                        reqlibs.add(dyn_section.soname)

        if not libs.difference(reqlibs):
            return

        if pkg.name[-1].isdigit():
            # ignore libs in a versioned non_std_dir
            for lib in libs.copy():
                lib_dir = libs_to_dir[lib]
                for lib_part in lib_dir.split('/'):
                    if not lib_part:
                        continue
                    if lib_part[-1].isdigit(
                    ) and not lib_part.endswith('lib64'):
                        libs.remove(lib)
                        break

            # Check for non-versioned libs in a std lib package
            for lib in libs.copy():
                if (not (lib[-1].isdigit()
                         or self.re_soname_strongly_versioned.search(lib))):
                    self.output.add_info('W', pkg, 'shlib-unversioned-lib',
                                         lib)

            # Verify shared lib policy package doesn't have hard dependency on non-lib packages
            for dep in pkg.requires:
                if dep[0].startswith('rpmlib(') or dep[0].startswith(
                        'config('):
                    continue
                if (dep[1] & (rpm.RPMSENSE_GREATER
                              | rpm.RPMSENSE_EQUAL)) == rpm.RPMSENSE_EQUAL:
                    self.output.add_info('W', pkg, 'shlib-fixed-dependency',
                                         formatRequire(dep[0], dep[1], dep[2]))

        # Verify non-lib stuff does not add dependencies
        if libs:
            for dep in pkg_requires:
                if '.so.' in dep and dep not in libs and dep not in libs_needed:
                    self.output.add_info('E', pkg,
                                         'shlib-policy-excessive-dependency',
                                         dep)