dockerfile: reject --chown by name with --link at parse time - #7134
Open
KR-Ravindra wants to merge 1 commit into
Open
dockerfile: reject --chown by name with --link at parse time#7134KR-Ravindra wants to merge 1 commit into
KR-Ravindra wants to merge 1 commit into
Conversation
When --link is used and the worker supports MergeOp, the COPY/ADD FileOp runs against llb.Scratch() and the result is merged on top of the stage. llb.WithUser() marshals a non-numeric --chown value as a by-name lookup against the FileOp base, which for scratch is input -1, so the solver later fails with "invalid user index: -1" and nothing points back to the offending --chown. Validate this in dispatchCopy when the link path is taken and return an error naming the flag and asking for numeric uid[:gid]. Numeric IDs and "root" keep working, and workers without MergeOp are unchanged because they fall back to a regular copy where names resolve against the stage filesystem. Document the restriction in the --chown section. Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
Author
|
Round 1 self-review. Checked before marking ready:
CI workflows are waiting for first-contributor approval. |
KR-Ravindra
marked this pull request as ready for review
September 8, 2026 21:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
COPY --link --chown=<user>[:<group>]with a non-numeric user or group is accepted by the Dockerfile frontend, but on any worker that supports MergeOp the build fails late in the solver withNothing in that message points at
--chown, so people end up either dropping--linkor hard-coding UIDs after a lot of trial and error (see the issue thread and the linked buildx issues). Only numeric--chown=UID[:GID](androot) work with--link.Root cause
frontend/dockerfile/dockerfile2llb/convert_copy.go:54-56:llb.WithUser(cfg.chown)is added unconditionally.WithUser(client/llb/fileop.go:231) turns anything that is not an integer orrootinto aUserOpt{Name: ...}, which marshals as apb.UserOpt_ByNamewhoseInputis the FileOp base index.frontend/dockerfile/dockerfile2llb/convert_copy.go:334-349: when--linkis set,--chmodis empty and the worker supportsCapMergeOp, the FileOp is executed onllb.Scratch()and the result is merged on top of the stage. The base of that FileOp ispb.Empty(-1), so the marshalled owner isbyName:{name:"foo" input:-1}(verified by marshalling the frontend output in a unit test).solver/llbsolver/ops/file.go:289and:534rejectByName.Input < 0withinvalid user index.Workers without MergeOp never take this path: they fall back to a regular
d.state.File(...)copy where names resolve against the stage's/etc/passwd, which is why the classic graphdriver backend of thedockerdriver is unaffected.docker buildwith the containerd image store enables MergeOp and takes the same path.Fix
In
dispatchCopy, compute the "linked layer" condition once and, when it holds, reject a--chownthat refers to a user or group by name with an error that names the flag and the remedy:The check reuses
llb.WithUserto decide what counts as "by name", so it can never disagree with how the value is actually marshalled (rootand numeric IDs still pass). Behaviour is unchanged for numeric IDs, for--linkcombined with--chmod, and for workers without MergeOp. The--chownsection offrontend/dockerfile/docs/reference.mdnow states the restriction.No new linter rule: the build would fail anyway on this path, so a hard error at frontend time is strictly more informative than a warning followed by the solver error.
How tested
New unit test
TestCopyLinkChownByNameinfrontend/dockerfile/dockerfile2llb/convert_test.go(no daemon needed; it enablesCapMergeOpviapb.Caps.CapSet(pb.Caps.All())).Before the fix:
Marshalling the frontend output for
FROM scratch/COPY --link --chown=foo:bar a /bbefore the fix showed the FileOp copy owner asuser=byName:{name:"foo" input:-1} group=byName:{name:"bar" input:-1}, i.e. exactly what the solver rejects.After the fix:
Also:
go test ./frontend/dockerfile/dockerfile2llb/ ./frontend/dockerfile/instructions/pass,gofmt -lclean,go vetclean,golangci-lint run ./frontend/dockerfile/dockerfile2llb/reports 0 issues,go build ./frontend/dockerfile/... ./cmd/...succeeds.Links
COPY --linknot compatible withchown#2987 (this PR makes the failure explicit and documents it; it does not implement resolving names against the base image, so it does not close the issue)COPY --link --chown=user(Fails with "failed to solve: invalid user index: -1") docker/buildx#1526, docs: proposal to raise awareness about an unexpected behavior of COPY --link #4964This change was prepared with an AI agent operated by KR-Ravindra, who reviewed and tested it.