示例#1
0
def Libraries(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename,
              pkg_by_path):
    """Checks shared libraries.

  Returns:
    [
      (u"CSWfoo", "why is this needed"),
    ]

  New idea, a list of reasons:
    [
      [(u"CSWfoo", "why is it needed"),
       (u"CSWfooalt", "there must be a reason"),
       (u"CSWfooyetanother", "here's another one")],
      [(u"CSWbar", "this serves another purpose")],
    ]
  """
    pkgname = pkg_data["basic_stats"]["pkgname"]
    logger.debug("Libraries(): pkgname = %s", repr(pkgname))
    isalist = pkg_data["isalist"]
    ldd_emulator = ldd_emul.LddEmulator()
    orphan_sonames = []
    for binary_info in pkg_data["binaries_dump_info"]:
        binary_path, binary_basename = os.path.split(binary_info["path"])
        for soname in binary_info["needed sonames"]:
            orphan_sonames_tmp = ProcessSoname(ldd_emulator, soname,
                                               path_and_pkg_by_basename,
                                               binary_info, isalist,
                                               binary_path, logger, error_mgr,
                                               pkgname, messenger)
            orphan_sonames.extend(orphan_sonames_tmp)
    orphan_sonames = set(orphan_sonames)
    for soname, binary_path in orphan_sonames:
        if soname not in ALLOWED_ORPHAN_SONAMES:
            error_mgr.ReportError(pkgname, "soname-not-found",
                                  "%s is needed by %s" % (soname, binary_path))
示例#2
0
 def setUp(self):
   self.pkgmap_mocker = mox.Mox()
   self.e = ldd_emul.LddEmulator()
示例#3
0
def Libraries(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename,
              pkg_by_path):
    """Checks shared libraries.

  Returns:
    [
      (u"CSWfoo", "why is this needed"),
    ]

  New idea, a list of reasons:
    [
      [(u"CSWfoo", "why is it needed"),
       (u"CSWfooalt", "there must be a reason"),
       (u"CSWfooyetanother", "here's another one")],
      [(u"CSWbar", "this serves another purpose")],
    ]
  """
    pkgname = pkg_data["basic_stats"]["pkgname"]
    logger.debug("Libraries(): pkgname = %s", repr(pkgname))
    isalist = pkg_data["isalist"]
    ldd_emulator = ldd_emul.LddEmulator()
    orphan_sonames = []
    for binary_info in pkg_data["binaries_dump_info"]:
        binary_path, binary_basename = os.path.split(binary_info["path"])
        for soname in binary_info["needed sonames"]:
            orphan_sonames_tmp = ProcessSoname(ldd_emulator, soname,
                                               path_and_pkg_by_basename,
                                               binary_info, isalist,
                                               binary_path, logger, error_mgr,
                                               pkgname, messenger)
            orphan_sonames.extend(orphan_sonames_tmp)

        sonames_unused = set()
        ldd_info = pkg_data['ldd_info'][binary_info["path"]]
        for ldd_response in ldd_info:
            if (ldd_response['state'] == 'soname-unused'
                    and ldd_response['soname'] not in BASE_SOLARIS_LIBRARIES):
                sonames_unused.add(ldd_response['soname'])
                messenger.Message(
                    "Binary %s links to library %s but doesn't seem to use any"
                    " of its symbols. It usually happens because superfluous"
                    " libraries were added to the linker options, either because"
                    " of the configure script itself or because of the"
                    " \"pkg-config --libs\" output of one the dependency." %
                    ("/" + binary_info["path"], ldd_response['soname']))
                error_mgr.ReportError(
                    pkgname, "soname-unused",
                    "%s is needed by %s but never used" %
                    (ldd_response['soname'], "/" + binary_info["path"]))

        # Even when direct binding is enabled, some symbols might not be
        # directly bound because the library explicitely requested the symbol
        # not to be drectly bound to.
        # For example, libc.so.1 does it for symbol sigaction, free, malloc...
        # So we consider that direct binding is enabled if at least one
        # symbol is directly bound to because that definitely means that
        # -B direct or -z direct was used.
        binary_elf_info = pkg_data["binaries_elf_info"][binary_info["path"]]
        libs = set(binary_info["needed sonames"])

        # we skip the standard Solaris libraries: a lot of plugins only
        # link to non directly bindable symbols of libc.so.1, librt.so.1
        # which trigger false positives.
        # Direct binding really matters for opencsw libraries so it's
        # easier and riskless to just skip theses libraries
        libs.difference_update(BASE_SOLARIS_LIBRARIES)

        db_libs = set()
        for syminfo in binary_elf_info['symbol table']:
            if (syminfo['shndx'] == 'UNDEF' and syminfo['flags']
                    and 'D' in syminfo['flags'] and 'B' in syminfo['flags']):
                db_libs.add(syminfo['soname'])
        no_db_libs = libs.difference(db_libs)

        # no symbol used means no way to detect if direct binding was
        # enabled so we must ignore the libraries which were linked
        # without being used
        no_db_libs.difference_update(sonames_unused)

        if no_db_libs:
            messenger.Message(
                "No symbol of binary %s is directly bound against the following"
                " libraries: %s. Please make sure the binaries are compiled using"
                " the \"-Bdirect\" linker option." %
                ("/" + binary_info["path"], ", ".join(no_db_libs)))
            for soname in no_db_libs:
                error_mgr.ReportError(
                    pkgname, "no-direct-binding",
                    "%s is not directly bound to soname %s" %
                    ("/" + binary_info["path"], soname))

        for version_dep in binary_elf_info['version needed']:
            if (version_dep['soname'] in ALLOWED_VERSION_DEPENDENCIES
                    and not version_dep['version']
                    in ALLOWED_VERSION_DEPENDENCIES[version_dep['soname']]):
                messenger.Message(
                    "Binary %s requires interface version %s in library %s which is"
                    " only available in recent Solaris releases." %
                    ("/" + binary_info["path"], version_dep['version'],
                     version_dep['soname']))
                error_mgr.ReportError(
                    pkgname, "forbidden-version-interface-dependencies",
                    "%s requires forbidden interface version %s in library %s"
                    % ("/" + binary_info["path"], version_dep['version'],
                       version_dep['soname']))

    orphan_sonames = set(orphan_sonames)
    for soname, binary_path in orphan_sonames:
        if soname not in ALLOWED_ORPHAN_SONAMES:
            error_mgr.ReportError(pkgname, "soname-not-found",
                                  "%s is needed by %s" % (soname, binary_path))