Skip to content

Layered extraction fails when layer replaces symlink with real file #38

@JAORMX

Description

@JAORMX

Summary

Layered OCI image extraction fails with refusing to write through symlink when a higher layer legitimately replaces a symlink (created by a lower layer) with a real file. Extraction falls back to flat mode, losing the layer caching benefit.

Reproduction

Build a layered Alpine image where the base layer has busybox (which creates /usr/bin/env as a symlink) and a subsequent layer installs coreutils (which replaces /usr/bin/env with a real binary):

# base image
FROM alpine:3.21
RUN apk add --no-cache coreutils findutils

When propolis extracts this image with layered extraction enabled, layer 1 (the apk add layer) tries to write the real coreutils /usr/bin/env over the busybox symlink from layer 0 and hits the symlink traversal guard:

level=WARN msg="layered extraction failed, falling back to flat extraction"
  err="apply layer 1 (sha256:6a4114a...): copy file usr/bin/env: refusing to write through symlink: /path/to/cache/tmp-rootfs-.../usr/bin/env"

Expected behavior

Layered extraction should handle the case where a layer replaces an existing symlink with a real file. The symlink traversal protection should detect that the target path is the symlink itself (not traversing through one to reach a different location) and allow the replacement.

Context

This was discovered in waggle after upgrading to propolis v0.0.15 and introducing a shared base image with coreutils. The flat extraction fallback works correctly — VMs boot and run fine — but layer-level caching is not effective since every extraction falls back to flat mode.

Environment

  • propolis v0.0.15
  • Alpine 3.21 base images
  • coreutils package triggers the symlink replacement

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions