Esempio n. 1
0
    def test_error(self):
        soname_cache = elf.SonameCache()
        raised = self.assertRaises(
            EnvironmentError, soname_cache.__setitem__, self.key, "/soname.so"
        )

        self.assertThat(str(raised), StartsWith(self.partial_message))
Esempio n. 2
0
    def load_part(
        self,
        part_name,
        plugin_name=None,
        part_properties=None,
        project=None,
        stage_packages_repo=None,
        base="core18",
        build_base=None,
        confinement="strict",
        snap_type="app",
    ):
        if not plugin_name:
            plugin_name = "nil"
        properties = {"plugin": plugin_name}
        if part_properties:
            properties.update(part_properties)
        if not project:
            project = snapcraft.project.Project()

        project._snap_meta.type = snap_type
        project._snap_meta.confinement = confinement
        project._snap_meta.base = base
        if build_base is not None:
            project._snap_meta.build_base = build_base

        validator = _schema.Validator()
        schema = validator.part_schema
        definitions_schema = validator.definitions_schema
        plugin = snapcraft.internal.pluginhandler.load_plugin(
            part_name=part_name,
            plugin_name=plugin_name,
            properties=properties,
            project=project,
            part_schema=schema,
            definitions_schema=definitions_schema,
        )

        if not stage_packages_repo:
            stage_packages_repo = mock.Mock()
        grammar_processor = grammar_processing.PartGrammarProcessor(
            plugin=plugin,
            properties=properties,
            project=project,
            repo=stage_packages_repo,
        )

        return snapcraft.internal.pluginhandler.PluginHandler(
            plugin=plugin,
            part_properties=properties,
            project=project,
            part_schema=schema,
            definitions_schema=definitions_schema,
            grammar_processor=grammar_processor,
            stage_packages_repo=stage_packages_repo,
            snap_base_path="/snap/fake-name/current",
            soname_cache=elf.SonameCache(),
        )
Esempio n. 3
0
def handle_glibc_mismatch(*,
                          elf_files: FrozenSet[elf.ElfFile],
                          root_path: str,
                          core_base_path: str,
                          snap_base_path: str,
                          preferred_patchelf_path=None,
                          soname_cache: elf.SonameCache = None) -> None:
    """Copy over libc6 libraries from the host and patch necessary elf files.

    If no newer glibc version is detected in elf_files, this function returns.
    The dynamic linker and related libraries to libc6 are expected to be found
    in root_path.

    :param snapcraft.internal.elf.ElfFile elf_files:
        set of candidate elf files to patch if a newer libc6 is required.
    :param str root_path: the root path of a snap tree.
    :param str core_base_path: the path to the base snap.
    :param str snap_base_path: absolute path to the snap once installed to
                               setup proper rpaths.
    :param str preferred_patchelf_path: patch the necessary elf_files with
                                        this patchelf.
    """
    if soname_cache is None:
        soname_cache = elf.SonameCache()

    # We assume the current system will satisfy the GLIBC requirement,
    # get the current libc6 libraries (which includes the linker)
    libc6_libraries_list = repo.Repo.get_package_libraries('libc6')

    # For security reasons, we do not want to automatically pull in
    # libraries but expect them to be consciously brought in by stage-packages
    # instead.
    libc6_libraries_paths = [
        os.path.join(root_path, l[1:]) for l in libc6_libraries_list
    ]

    dynamic_linker = _get_dynamic_linker(libc6_libraries_paths)

    # Get the path to the "would be" dynamic linker when this snap is
    # installed. Strip the root_path from the retrieved dynamic_linker
    # variables + the leading `/` so that os.path.join can perform the
    # proper join with snap_base_path.
    dynamic_linker_path = os.path.join(snap_base_path,
                                       dynamic_linker[len(root_path) + 1:])

    elf_patcher = elf.Patcher(dynamic_linker=dynamic_linker_path,
                              root_path=root_path,
                              preferred_patchelf_path=preferred_patchelf_path)
    for elf_file in elf_files:
        # Search for dependencies again now that the new libc6 is
        # migrated.
        elf_file.load_dependencies(root_path=root_path,
                                   core_base_path=core_base_path,
                                   soname_cache=soname_cache)
        elf_patcher.patch(elf_file=elf_file)
Esempio n. 4
0
    def __init__(self, *, parts, project, validator):
        self._soname_cache = elf.SonameCache()
        self._parts_data = parts.get("parts", {})
        self._snap_type = parts.get("type", "app")
        self._project = project
        self._validator = validator

        self.all_parts = []
        self._part_names = []
        self.after_requests = {}

        self._process_parts()
Esempio n. 5
0
    def load_part(self,
                  part_name,
                  plugin_name=None,
                  part_properties=None,
                  project_options=None,
                  stage_packages_repo=None,
                  base='core',
                  confinement='strict',
                  snap_type='app'):
        if not plugin_name:
            plugin_name = 'nil'
        properties = {'plugin': plugin_name}
        if part_properties:
            properties.update(part_properties)
        if not project_options:
            project_options = snapcraft.ProjectOptions()

        validator = snapcraft.internal.project_loader.Validator()
        schema = validator.part_schema
        definitions_schema = validator.definitions_schema
        plugin = snapcraft.internal.pluginhandler.load_plugin(
            part_name=part_name,
            plugin_name=plugin_name,
            properties=properties,
            project_options=project_options,
            part_schema=schema,
            definitions_schema=definitions_schema)

        if not stage_packages_repo:
            stage_packages_repo = mock.Mock()
        grammar_processor = grammar_processing.PartGrammarProcessor(
            plugin=plugin,
            properties=properties,
            project=project_options,
            repo=stage_packages_repo)

        return snapcraft.internal.pluginhandler.PluginHandler(
            plugin=plugin,
            part_properties=properties,
            project_options=project_options,
            part_schema=schema,
            definitions_schema=definitions_schema,
            grammar_processor=grammar_processor,
            stage_packages_repo=stage_packages_repo,
            snap_base_path='/snap/fake-name/current',
            base=base,
            confinement=confinement,
            snap_type=snap_type,
            soname_cache=elf.SonameCache())
Esempio n. 6
0
    def test_get_libraries_with_soname_cache(self):
        elf_file = self.fake_elf['fake_elf-2.23']

        soname_cache = elf.SonameCache()
        soname_cache['bar.so.2'] = '/lib/bar.so.2'

        libs = elf_file.load_dependencies(
            root_path=self.fake_elf.root_path,
            core_base_path=self.fake_elf.core_base_path,
            soname_cache=soname_cache)

        # With no cache this would have returned '/usr/lib/bar.so.2'
        self.assertThat(libs, Equals(set(
            [self.fake_elf.root_libraries['foo.so.1'],
             '/lib/bar.so.2'])))
Esempio n. 7
0
    def __init__(self, *, parts, project, validator, build_snaps, build_tools):
        self._snap_name = parts["name"]
        self._base = parts.get("base", "core")
        self._confinement = parts.get("confinement")
        self._soname_cache = elf.SonameCache()
        self._parts_data = parts.get("parts", {})
        self._snap_type = parts.get("type", "app")
        self._project = project
        self._validator = validator
        self.build_snaps = build_snaps
        self.build_tools = build_tools

        self.all_parts = []
        self._part_names = []
        self.after_requests = {}

        self._process_parts()
Esempio n. 8
0
    def __init__(self, *, parts, project_options, validator, build_snaps,
                 build_tools, snapcraft_yaml):
        self._snap_name = parts['name']
        self._confinement = parts['confinement']
        self._soname_cache = elf.SonameCache()
        self._parts_data = parts.get('parts', {})
        self._project_options = project_options
        self._validator = validator
        self.build_snaps = build_snaps
        self.build_tools = build_tools
        self._snapcraft_yaml = snapcraft_yaml

        self.all_parts = []
        self._part_names = []
        self.after_requests = {}

        self._process_parts()
Esempio n. 9
0
    def test_get_libraries_with_soname_cache(self):
        elf_file = self.fake_elf["fake_elf-2.23"]

        arch = ("ELFCLASS64", "ELFDATA2LSB", "EM_X86_64")
        soname_cache = elf.SonameCache()
        soname_cache[arch, "bar.so.2"] = "/lib/bar.so.2"

        libs = elf_file.load_dependencies(
            root_path=self.fake_elf.root_path,
            core_base_path=self.fake_elf.core_base_path,
            soname_cache=soname_cache,
        )

        # With no cache this would have returned '/usr/lib/bar.so.2'
        self.assertThat(
            libs,
            Equals(set([self.fake_elf.root_libraries["foo.so.1"], "/lib/bar.so.2"])),
        )
Esempio n. 10
0
    def test_is_valid_elf_ignores_corrupt_files(self):
        soname = "libssl.so.1.0.0"
        soname_path = os.path.join(self.path, soname)
        library = elf.Library(
            soname=soname,
            soname_path=soname_path,
            search_paths=[self.path],
            core_base_path="/snap/core/current",
            arch=("ELFCLASS64", "ELFDATA2LSB", "EM_X86_64"),
            soname_cache=elf.SonameCache(),
        )

        self.assertThat(library._is_valid_elf(soname_path), Equals(True))

        self.useFixture(
            fixtures.MockPatch(
                "snapcraft.internal.elf.ElfFile",
                side_effect=errors.CorruptedElfFileError(path=soname_path,
                                                         error=RuntimeError()),
            ))

        self.assertThat(library._is_valid_elf(soname_path), Equals(False))
Esempio n. 11
0
 def setUp(self):
     super().setUp()
     self.arch = ('ELFCLASS64', 'ELFDATA2LSB', 'EM_X86_64')
     self.soname_cache = elf.SonameCache()
Esempio n. 12
0
 def setUp(self):
     super().setUp()
     self.arch = ("ELFCLASS64", "ELFDATA2LSB", "EM_X86_64")
     self.soname_cache = elf.SonameCache()
Esempio n. 13
0
def load_part(
    part_name,
    plugin_name=None,
    part_properties=None,
    project=None,
    stage_packages_repo=None,
    snap_name="test-snap",
    base="core18",
    build_base=None,
    confinement="strict",
    snap_type="app",
):
    if not plugin_name:
        plugin_name = "nil"
    properties = {"plugin": plugin_name}
    if part_properties:
        properties.update(part_properties)
    if "build-environment" not in properties:
        properties["build-environment"] = list()
    if not project:
        project = Project()

    project._snap_meta.name = snap_name
    project._snap_meta.version = "1.0"
    project._snap_meta.grade = "devel"
    project._snap_meta.type = snap_type
    project._snap_meta.confinement = confinement
    project._snap_meta.base = base
    if build_base is not None:
        project._snap_meta.build_base = build_base

    validator = _schema.Validator()
    schema = validator.part_schema
    definitions_schema = validator.definitions_schema
    plugin = pluginhandler.load_plugin(
        part_name=part_name,
        plugin_name=plugin_name,
        properties=properties,
        project=project,
        part_schema=schema,
        definitions_schema=definitions_schema,
    )

    if not stage_packages_repo:
        stage_packages_repo = mock.Mock()
    grammar_processor = grammar_processing.PartGrammarProcessor(
        plugin=plugin,
        properties=properties,
        project=project,
        repo=stage_packages_repo)

    return pluginhandler.PluginHandler(
        plugin=plugin,
        part_properties=properties,
        project=project,
        part_schema=schema,
        definitions_schema=definitions_schema,
        grammar_processor=grammar_processor,
        stage_packages_repo=stage_packages_repo,
        snap_base_path="/snap/fake-name/current",
        soname_cache=elf.SonameCache(),
    )
Esempio n. 14
0
 def test_error(self, key, partial_message):
     soname_cache = elf.SonameCache()
     with pytest.raises(EnvironmentError) as error:
         soname_cache.__setitem__(key, "/soname.so")
         assert str(error).startswith(partial_message)
Esempio n. 15
0
 def setUp(self):
     super().setUp()
     self.soname_cache = elf.SonameCache()