From ad70d3b1d542a96af3e05c12c8d701d621f46ed0 Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Wed, 26 Feb 2025 17:50:18 +0200 Subject: [PATCH] Fix a Podman regression regarding Buildkit images Loading an image built with Buildkit in Podman 3.4 messes up its name. The tag somehow becomes the name of the loaded image. We know that older Podman versions are not generally affected, since Podman v3.0.1 on Debian Bullseye works properly. Also, Podman v4.0 is not affected, so it makes sense to target only Podman v3.4 for a fix. The fix is simple, tag the image properly based on the expected tag from `share/image-id.txt` and delete the incorrect tag. Refs containers/podman/#16490 --- dangerzone/container_utils.py | 41 +++++++++++++++++++--- dangerzone/isolation_provider/container.py | 1 + tests/isolation_provider/test_container.py | 4 +++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/dangerzone/container_utils.py b/dangerzone/container_utils.py index 0b43c96..ee528d0 100644 --- a/dangerzone/container_utils.py +++ b/dangerzone/container_utils.py @@ -95,18 +95,26 @@ def list_image_tags() -> List[str]: ) +def add_image_tag(image_id: str, new_tag: str) -> None: + """Add a tag to the Dangerzone image.""" + log.debug(f"Adding tag '{new_tag}' to image '{image_id}'") + subprocess.check_output( + [get_runtime(), "tag", image_id, new_tag], + startupinfo=get_subprocess_startupinfo(), + ) + + def delete_image_tag(tag: str) -> None: """Delete a Dangerzone image tag.""" - name = CONTAINER_NAME + ":" + tag - log.warning(f"Deleting old container image: {name}") + log.warning(f"Deleting old container image: {tag}") try: subprocess.check_output( - [get_runtime(), "rmi", "--force", name], + [get_runtime(), "rmi", "--force", tag], startupinfo=get_subprocess_startupinfo(), ) except Exception as e: log.warning( - f"Couldn't delete old container image '{name}', so leaving it there." + f"Couldn't delete old container image '{tag}', so leaving it there." f" Original error: {e}" ) @@ -122,7 +130,7 @@ def load_image_tarball() -> None: tarball_path = get_resource_path("container.tar") with open(tarball_path) as f: try: - subprocess.run( + res = subprocess.run( [get_runtime(), "load"], stdin=f, startupinfo=get_subprocess_startupinfo(), @@ -138,4 +146,27 @@ def load_image_tarball() -> None: f"Could not install container image: {error}" ) + # Loading an image built with Buildkit in Podman 3.4 messes up its name. The tag + # somehow becomes the name of the loaded image [1]. + # + # We know that older Podman versions are not generally affected, since Podman v3.0.1 + # on Debian Bullseye works properly. Also, Podman v4.0 is not affected, so it makes + # sense to target only Podman v3.4 for a fix. + # + # The fix is simple, tag the image properly based on the expected tag from + # `share/image-id.txt` and delete the incorrect tag. + # + # [1] https://github.com/containers/podman/issues/16490 + if get_runtime_name() == "podman" and get_runtime_version() == (3, 4): + expected_tag = get_expected_tag() + bad_tag = f"localhost/{expected_tag}:latest" + good_tag = f"{CONTAINER_NAME}:{expected_tag}" + + log.debug( + f"Dangerzone images loaded in Podman v3.4 usually have an invalid tag." + " Fixing it..." + ) + add_image_tag(bad_tag, good_tag) + delete_image_tag(bad_tag) + log.info("Successfully installed container image") diff --git a/dangerzone/isolation_provider/container.py b/dangerzone/isolation_provider/container.py index 0213cde..1cd80cc 100644 --- a/dangerzone/isolation_provider/container.py +++ b/dangerzone/isolation_provider/container.py @@ -97,6 +97,7 @@ class Container(IsolationProvider): f"Could not find a Dangerzone container image with tag '{expected_tag}'" ) for tag in old_tags: + tag = container_utils.CONTAINER_NAME + ":" + tag container_utils.delete_image_tag(tag) else: return True diff --git a/tests/isolation_provider/test_container.py b/tests/isolation_provider/test_container.py index 5464b52..dd2565d 100644 --- a/tests/isolation_provider/test_container.py +++ b/tests/isolation_provider/test_container.py @@ -83,6 +83,10 @@ class TestContainer(IsolationProviderTest): self, mocker: MockerFixture, provider: Container, fp: FakeProcess ) -> None: """When an image keep being not installed, it should return False""" + fp.register_subprocess( + ["podman", "version", "-f", "{{.Client.Version}}"], + stdout="4.0.0", + ) fp.register_subprocess( [container_utils.get_runtime(), "image", "ls"],