Repository navigation
dockerfile: reject --chown by name with --link at parse time - #7134
Merged
Merged
Conversation
Contributor
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
tonistiigi
reviewed
Sep 10, 2026
| } | ||
|
|
||
| // cfg.opt.llbCaps can be nil in unit tests | ||
| useLink := cfg.opt.llbCaps != nil && cfg.opt.llbCaps.Supports(pb.CapMergeOp) == nil && cfg.link && cfg.chmod == "" |
Member
There was a problem hiding this comment.
This should not depend on what capabilities the current daemon happens to support (opt.llbCaps), but Dockerfile behavior should be consistent.
When --link is used 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 whenever --link is set and return an error naming the flag and asking for numeric uid[:gid]. The check does not depend on the worker's capabilities or on the --chmod fallback, so a Dockerfile is accepted or rejected the same way everywhere. Numeric IDs and "root" keep working. Document the restriction in the --chown section. Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
KR-Ravindra
force-pushed
the
fix/copy-link-chown-numeric
branch
from
September 10, 2026 23:07
9cc2f54 to
e3f5f64
Compare
Contributor
Author
|
@tonistiigi done in e3f5f64: the check is now |
tonistiigi
approved these changes
Sep 17, 2026
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, whenever--linkis set, 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). It does not look atopt.llbCapsor at the--chmodfallback: a Dockerfile with--link --chown=<name>is rejected the same way on every worker, instead of depending on which copy path the current daemon takes (review feedback). 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.