Skip to content

mz978: key hardlink tracking by device and inode - #979

Open
mzihlmann wants to merge 2 commits into
2595-hardlinksfrom
mz978-hardlink-dev-inode
Open

mz978: key hardlink tracking by device and inode#979
mzihlmann wants to merge 2 commits into
2595-hardlinksfrom
mz978-hardlink-dev-inode

Conversation

@mzihlmann

@mzihlmann mzihlmann commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Fixes #978

Hardlink tracking keyed its seen-map by inode number alone, in checkCopyHardlink for the copy path and in Tar.checkHardlink for the snapshot path. An inode number is only unique within one filesystem, so a COPY of a tree that spans a mount point could match two unrelated files and hardlink them together, leaving one with the other's content. Nothing failed loudly, because the link target is a destination path already written and both ends sit on the destination filesystem, so there is no EXDEV to catch. Both maps now key on {dev, ino}, fixed together so the two implementations do not drift apart again.

No feature flag. Per docs/releases.md a fix for behaviour that produced corrupt images has no stable behaviour to protect, and gating it would mean shipping known content corruption behind an opt-in.

The bug predates this stack and reproduces on main through COPY from the build context, but FF_KANIKO_NATIVE_COPY widens it considerably: it routes the multistage save path through copyDirInner, and that one walks the source stage's live rootfs, which always spans several filesystems. That is why this is stacked ahead of the flag graduating to default in v1.29.0, and why the test uses COPY --from.

Getting a deterministic collision turned out not to need privileges. Two tmpfs mounts do it, since a tmpfs numbers its inodes per superblock, so each mount hands its first file inode 2. extraDockerRunFlags already existed for per-test docker run flags, so no harness change was needed. Only the executor gets the mounts, so the docker half of the comparison keeps one filesystem and stays correct, and diffoci names the defect directly rather than a shell assertion returning a bare exit code:

TYPE    NAME       INPUT-0             INPUT-1
File    out/b/1    Linkname            Linkname out/a/1
File    out/b/2    Linkname out/b/1    Linkname out/a/1

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a36d1f7-8338-45cf-802a-88ecf920ace5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mzihlmann mzihlmann added the bug Something isn't working label Aug 4, 2026
@mzihlmann
mzihlmann force-pushed the mz978-hardlink-dev-inode branch from de943e8 to cab920a Compare August 12, 2026 07:10
@mzihlmann
mzihlmann requested review from 0hlov3, BobDu, babs and nejch August 12, 2026 09:23
@mzihlmann
mzihlmann force-pushed the mz978-hardlink-dev-inode branch from cab920a to 2e0a3e7 Compare August 12, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant