1
0
mirror of https://github.com/moby/buildkit.git synced 2025-04-18 18:04:03 +03:00

vendor: switch from idtools to moby/sys/user

Convert usages of `github.com/docker/docker/pkg/idtools` to
`github.com/moby/sys/user` in order to break the dependency between
buildkit and docker.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
Jonathan A. Sternberg 2025-03-28 09:21:37 -05:00
parent 648ec56d9b
commit 66016a8c63
No known key found for this signature in database
GPG Key ID: 6603D4B96394F6B1
40 changed files with 503 additions and 205 deletions

6
cache/manager.go vendored
View File

@ -16,7 +16,6 @@ import (
"github.com/containerd/containerd/v2/pkg/gc"
"github.com/containerd/containerd/v2/pkg/labels"
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/cache/metadata"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
@ -26,6 +25,7 @@ import (
"github.com/moby/buildkit/util/disk"
"github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/buildkit/util/progress"
"github.com/moby/sys/user"
digest "github.com/opencontainers/go-digest"
imagespecidentity "github.com/opencontainers/image-spec/identity"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
@ -62,7 +62,7 @@ type Accessor interface {
New(ctx context.Context, parent ImmutableRef, s session.Group, opts ...RefOption) (MutableRef, error)
GetMutable(ctx context.Context, id string, opts ...RefOption) (MutableRef, error) // Rebase?
IdentityMapping() *idtools.IdentityMapping
IdentityMapping() *user.IdentityMapping
Merge(ctx context.Context, parents []ImmutableRef, pg progress.Controller, opts ...RefOption) (ImmutableRef, error)
Diff(ctx context.Context, lower, upper ImmutableRef, pg progress.Controller, opts ...RefOption) (ImmutableRef, error)
}
@ -338,7 +338,7 @@ func (cm *cacheManager) init(ctx context.Context) error {
}
// IdentityMapping returns the userns remapping used for refs
func (cm *cacheManager) IdentityMapping() *idtools.IdentityMapping {
func (cm *cacheManager) IdentityMapping() *user.IdentityMapping {
return cm.Snapshotter.IdentityMapping()
}

6
cache/refs.go vendored
View File

@ -18,7 +18,6 @@ import (
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/pkg/labels"
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/pkg/idtools"
"github.com/hashicorp/go-multierror"
"github.com/moby/buildkit/cache/config"
"github.com/moby/buildkit/identity"
@ -35,6 +34,7 @@ import (
"github.com/moby/buildkit/util/tracing"
"github.com/moby/buildkit/util/winlayers"
"github.com/moby/sys/mountinfo"
"github.com/moby/sys/user"
"github.com/moby/sys/userns"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
@ -52,7 +52,7 @@ type Ref interface {
Mountable
RefMetadata
Release(context.Context) error
IdentityMapping() *idtools.IdentityMapping
IdentityMapping() *user.IdentityMapping
DescHandler(digest.Digest) *DescHandler
}
@ -313,7 +313,7 @@ func (cr *cacheRecord) isLazy(ctx context.Context) (bool, error) {
return false, nil
}
func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping {
func (cr *cacheRecord) IdentityMapping() *user.IdentityMapping {
return cr.cm.IdentityMapping()
}

View File

@ -3,12 +3,12 @@ package main
import (
"strings"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
func parseIdentityMapping(str string) (*idtools.IdentityMapping, error) {
func parseIdentityMapping(str string) (*user.IdentityMapping, error) {
if str == "" {
return nil, nil
}
@ -22,7 +22,7 @@ func parseIdentityMapping(str string) (*idtools.IdentityMapping, error) {
bklog.L.Debugf("user namespaces: ID ranges will be mapped to subuid ranges of: %s", username)
mappings, err := idtools.LoadIdentityMapping(username)
mappings, err := user.LoadIdentityMapping(username)
if err != nil {
return nil, errors.Wrap(err, "failed to create ID mappings")
}

View File

@ -154,7 +154,7 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M
defer releasers()
}
if err := w.ensureCWD(ctx, details, meta); err != nil {
if err := w.ensureCWD(details, meta); err != nil {
return nil, err
}

View File

@ -11,7 +11,6 @@ import (
"github.com/containerd/containerd/v2/core/mount"
containerdoci "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
"github.com/moby/buildkit/snapshot"
@ -19,6 +18,7 @@ import (
"github.com/moby/buildkit/util/bklog"
"github.com/moby/buildkit/util/network"
rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
"github.com/moby/sys/user"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -101,7 +101,7 @@ func (w *containerdExecutor) prepareExecutionEnv(ctx context.Context, rootMount
return resolvConf, hostsFile, releaseAll, nil
}
func (w *containerdExecutor) ensureCWD(_ context.Context, details *containerState, meta executor.Meta) error {
func (w *containerdExecutor) ensureCWD(details *containerState, meta executor.Meta) error {
newp, err := fs.RootPath(details.rootfsPath, meta.Cwd)
if err != nil {
return errors.Wrapf(err, "working dir %s points to invalid target", newp)
@ -112,13 +112,8 @@ func (w *containerdExecutor) ensureCWD(_ context.Context, details *containerStat
return err
}
identity := idtools.Identity{
UID: int(uid),
GID: int(gid),
}
if _, err := os.Stat(newp); err != nil {
if err := idtools.MkdirAllAndChown(newp, 0755, identity); err != nil {
if err := user.MkdirAllAndChown(newp, 0755, int(uid), int(gid)); err != nil {
return errors.Wrapf(err, "failed to create working directory %s", newp)
}
}

View File

@ -8,13 +8,12 @@ import (
ctd "github.com/containerd/containerd/v2/client"
containerdoci "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/network"
"github.com/moby/buildkit/util/windows"
"github.com/moby/sys/user"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -48,13 +47,7 @@ func (w *containerdExecutor) prepareExecutionEnv(ctx context.Context, rootMount
return "", "", releaseAll, nil
}
func (w *containerdExecutor) ensureCWD(ctx context.Context, details *containerState, meta executor.Meta) (err error) {
// TODO(gabriel-samfira): Use a snapshot?
identity, err := windows.ResolveUsernameToSID(ctx, w, details.rootMounts, meta.User)
if err != nil {
return errors.Wrap(err, "getting user SID")
}
func (w *containerdExecutor) ensureCWD(details *containerState, meta executor.Meta) (err error) {
lm := snapshot.LocalMounterWithMounts(details.rootMounts)
rootfsPath, err := lm.Mount()
if err != nil {
@ -68,7 +61,8 @@ func (w *containerdExecutor) ensureCWD(ctx context.Context, details *containerSt
}
if _, err := os.Stat(newp); err != nil {
if err := idtools.MkdirAllAndChown(newp, 0755, identity); err != nil {
// uid and gid are not used on windows.
if err := user.MkdirAllAndChown(newp, 0755, 0, 0); err != nil {
return errors.Wrapf(err, "failed to create working directory %s", newp)
}
}

View File

@ -7,9 +7,9 @@ import (
"syscall"
"github.com/containerd/containerd/v2/core/mount"
"github.com/docker/docker/pkg/idtools"
resourcestypes "github.com/moby/buildkit/executor/resources/types"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/sys/user"
)
type Meta struct {
@ -33,7 +33,7 @@ type Meta struct {
type MountableRef interface {
Mount() ([]mount.Mount, func() error, error)
IdentityMapping() *idtools.IdentityMapping
IdentityMapping() *user.IdentityMapping
}
type Mountable interface {

View File

@ -7,15 +7,15 @@ import (
"os"
"path/filepath"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/identity"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
const defaultHostname = "buildkitsandbox"
func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *user.IdentityMapping, hostname string) (string, func(), error) {
if len(extraHosts) != 0 || hostname != defaultHostname {
return makeHostsFile(stateDir, extraHosts, idmap, hostname)
}
@ -30,7 +30,7 @@ func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.Ho
return filepath.Join(stateDir, "hosts"), func() {}, nil
}
func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *user.IdentityMapping, hostname string) (string, func(), error) {
p := filepath.Join(stateDir, "hosts")
if len(extraHosts) != 0 || hostname != defaultHostname {
p += "." + identity.NewID()
@ -60,8 +60,8 @@ func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools
}
if idmap != nil {
root := idmap.RootPair()
if err := os.Chown(tmpPath, root.UID, root.GID); err != nil {
uid, gid := idmap.RootPair()
if err := os.Chown(tmpPath, uid, gid); err != nil {
return "", nil, errors.WithStack(err)
}
}

View File

@ -6,15 +6,17 @@ import (
"path/filepath"
"github.com/docker/docker/libnetwork/resolvconf"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
var g flightcontrol.Group[struct{}]
var notFirstRun bool
var lastNotEmpty bool
var (
g flightcontrol.Group[struct{}]
notFirstRun bool
lastNotEmpty bool
)
// overridden by tests
var resolvconfPath = func(netMode pb.NetMode) string {
@ -36,7 +38,7 @@ type DNSConfig struct {
SearchDomains []string
}
func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.IdentityMapping, dns *DNSConfig, netMode pb.NetMode) (string, error) {
func GetResolvConf(ctx context.Context, stateDir string, idmap *user.IdentityMapping, dns *DNSConfig, netMode pb.NetMode) (string, error) {
p := filepath.Join(stateDir, "resolv.conf")
if netMode == pb.NetMode_HOST {
p = filepath.Join(stateDir, "resolv-host.conf")
@ -116,8 +118,8 @@ func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.Identity
}
if idmap != nil {
root := idmap.RootPair()
if err := os.Chown(tmpPath, root.UID, root.GID); err != nil {
uid, gid := idmap.RootPair()
if err := os.Chown(tmpPath, uid, gid); err != nil {
return struct{}{}, errors.WithStack(err)
}
}

View File

@ -13,7 +13,6 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/containerd/containerd/v2/pkg/oci"
"github.com/docker/docker/pkg/idtools"
"github.com/mitchellh/hashstructure/v2"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/snapshot"
@ -22,6 +21,7 @@ import (
rootlessmountopts "github.com/moby/buildkit/util/rootless/mountopts"
"github.com/moby/buildkit/util/system"
traceexec "github.com/moby/buildkit/util/tracing/exec"
"github.com/moby/sys/user"
"github.com/moby/sys/userns"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
@ -61,7 +61,7 @@ func (pm ProcessMode) String() string {
// GenerateSpec generates spec using containerd functionality.
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, selinuxB bool, tracingSocket string, cdiManager *cdidevices.Manager, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *user.IdentityMapping, apparmorProfile string, selinuxB bool, tracingSocket string, cdiManager *cdidevices.Manager, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
c := &containers.Container{
ID: id,
}

View File

@ -4,9 +4,9 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/sys/user"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -27,7 +27,7 @@ func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
return nil, nil
}
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
func generateIDmapOpts(idmap *user.IdentityMapping) ([]oci.SpecOpts, error) {
if idmap == nil {
return nil, nil
}

View File

@ -4,9 +4,9 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/sys/user"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -35,7 +35,7 @@ func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
return nil, nil
}
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
func generateIDmapOpts(idmap *user.IdentityMapping) ([]oci.SpecOpts, error) {
if idmap == nil {
return nil, nil
}

View File

@ -14,13 +14,13 @@ import (
"github.com/containerd/containerd/v2/pkg/oci"
cdseccomp "github.com/containerd/containerd/v2/pkg/seccomp"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/profiles/seccomp"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/buildkit/util/entitlements/security"
"github.com/moby/sys/user"
specs "github.com/opencontainers/runtime-spec/specs-go"
selinux "github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
@ -106,7 +106,7 @@ func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
return nil, nil
}
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
func generateIDmapOpts(idmap *user.IdentityMapping) ([]oci.SpecOpts, error) {
if idmap == nil {
return nil, nil
}
@ -115,13 +115,13 @@ func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
}, nil
}
func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
func specMapping(s []user.IDMap) []specs.LinuxIDMapping {
var ids []specs.LinuxIDMapping
for _, item := range s {
ids = append(ids, specs.LinuxIDMapping{
HostID: uint32(item.HostID),
ContainerID: uint32(item.ContainerID),
Size: uint32(item.Size),
HostID: uint32(item.ParentID),
ContainerID: uint32(item.ID),
Size: uint32(item.Count),
})
}
return ids
@ -286,7 +286,7 @@ func cgroupV2NamespaceSupported() bool {
}
func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) {
var retries = 10
retries := 10
root := m.Source
for {
src, err := fs.RootPath(root, subPath)

View File

@ -13,9 +13,9 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/sys/user"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -73,7 +73,7 @@ func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
return nil, nil
}
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
func generateIDmapOpts(idmap *user.IdentityMapping) ([]oci.SpecOpts, error) {
if idmap == nil {
return nil, nil
}

View File

@ -23,7 +23,6 @@ import (
containerdoci "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/continuity/fs"
runc "github.com/containerd/go-runc"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
"github.com/moby/buildkit/executor/resources"
@ -35,6 +34,7 @@ import (
"github.com/moby/buildkit/util/network"
rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
"github.com/moby/buildkit/util/stack"
"github.com/moby/sys/user"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@ -49,7 +49,7 @@ type Opt struct {
DefaultCgroupParent string
// ProcessMode
ProcessMode oci.ProcessMode
IdentityMapping *idtools.IdentityMapping
IdentityMapping *user.IdentityMapping
// runc run --no-pivot (unrecommended)
NoPivot bool
DNS *oci.DNSConfig
@ -70,7 +70,7 @@ type runcExecutor struct {
rootless bool
networkProviders map[pb.NetMode]network.Provider
processMode oci.ProcessMode
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
noPivot bool
dns *oci.DNSConfig
oomScoreAdj *int
@ -227,13 +227,13 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount,
}
defer os.RemoveAll(bundle)
identity := idtools.Identity{}
var rootUID, rootGID int
if w.idmap != nil {
identity = w.idmap.RootPair()
rootUID, rootGID = w.idmap.RootPair()
}
rootFSPath := filepath.Join(bundle, "rootfs")
if err := idtools.MkdirAllAndChown(rootFSPath, 0o700, identity); err != nil {
if err := user.MkdirAllAndChown(rootFSPath, 0o700, rootUID, rootGID); err != nil {
return nil, errors.WithStack(err)
}
if err := mount.All(rootMount, rootFSPath); err != nil {
@ -260,12 +260,9 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount,
opts = append(opts, containerdoci.WithRootFSReadonly())
}
identity = idtools.Identity{
UID: int(uid),
GID: int(gid),
}
rootUID, rootGID = int(uid), int(gid)
if w.idmap != nil {
identity, err = w.idmap.ToHost(identity)
rootUID, rootGID, err = w.idmap.ToHost(rootUID, rootGID)
if err != nil {
return nil, err
}
@ -287,7 +284,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount,
return nil, errors.Wrapf(err, "working dir %s points to invalid target", newp)
}
if _, err := os.Stat(newp); err != nil {
if err := idtools.MkdirAllAndChown(newp, 0o755, identity); err != nil {
if err := user.MkdirAllAndChown(newp, 0o755, rootUID, rootGID); err != nil {
return nil, errors.Wrapf(err, "failed to create working directory %s", newp)
}
}

View File

@ -12,7 +12,6 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/idtools"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/exporter"
@ -22,6 +21,7 @@ import (
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/result"
"github.com/moby/buildkit/util/staticfs"
"github.com/moby/sys/user"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/tonistiigi/fsutil"
@ -73,7 +73,7 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
var cleanup func() error
var src string
var err error
var idmap *idtools.IdentityMapping
var idmap *user.IdentityMapping
if ref == nil {
src, err = os.MkdirTemp("", "buildkit")
if err != nil {
@ -108,10 +108,7 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
var idMapFunc func(p string, st *fstypes.Stat) fsutil.MapResult
if idmap != nil {
idMapFunc = func(p string, st *fstypes.Stat) fsutil.MapResult {
uid, gid, err := idmap.ToContainer(idtools.Identity{
UID: int(st.Uid),
GID: int(st.Gid),
})
uid, gid, err := idmap.ToContainer(int(st.Uid), int(st.Gid))
if err != nil {
return fsutil.MapResultExclude
}

View File

@ -19,7 +19,6 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/defaults"
"github.com/distribution/reference"
"github.com/docker/docker/pkg/idtools"
apitypes "github.com/moby/buildkit/api/types"
"github.com/moby/buildkit/cache"
cacheutil "github.com/moby/buildkit/cache/util"
@ -49,6 +48,7 @@ import (
"github.com/moby/buildkit/worker"
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
"github.com/moby/sys/signal"
"github.com/moby/sys/user"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@ -411,7 +411,7 @@ func (b *bindMount) Mount() ([]mount.Mount, func() error, error) {
}}, func() error { return nil }, nil
}
func (b *bindMount) IdentityMapping() *idtools.IdentityMapping {
func (b *bindMount) IdentityMapping() *user.IdentityMapping {
return nil
}

2
go.mod
View File

@ -53,7 +53,7 @@ require (
github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/reexec v0.1.0
github.com/moby/sys/signal v0.7.1
github.com/moby/sys/user v0.3.0
github.com/moby/sys/user v0.3.1-0.20250227193707-71f0c5ead442
github.com/moby/sys/userns v0.1.0
github.com/morikuni/aec v1.0.0
github.com/opencontainers/go-digest v1.0.0

4
go.sum
View File

@ -288,8 +288,8 @@ github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7z
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/user v0.3.1-0.20250227193707-71f0c5ead442 h1:1sbX2CeW23ljS5+eKSeIzU5XJk3RTZITcZcJJ0fDQBc=
github.com/moby/sys/user v0.3.1-0.20250227193707-71f0c5ead442/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

View File

@ -6,12 +6,12 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/snapshot"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
func NewSnapshotter(name string, snapshotter snapshots.Snapshotter, ns string, idmap *idtools.IdentityMapping) snapshot.Snapshotter {
func NewSnapshotter(name string, snapshotter snapshots.Snapshotter, ns string, idmap *user.IdentityMapping) snapshot.Snapshotter {
return snapshot.FromContainerdSnapshotter(name, &nsSnapshotter{ns, snapshotter}, idmap)
}
@ -38,25 +38,31 @@ func (s *nsSnapshotter) Usage(ctx context.Context, key string) (snapshots.Usage,
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.Usage(ctx, key)
}
func (s *nsSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.Mounts(ctx, key)
}
func (s *nsSnapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.Prepare(ctx, key, parent, opts...)
}
func (s *nsSnapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.View(ctx, key, parent, opts...)
}
func (s *nsSnapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.Commit(ctx, name, key, opts...)
}
func (s *nsSnapshotter) Remove(ctx context.Context, key string) error {
return errors.Errorf("calling snapshotter.Remove is forbidden")
}
func (s *nsSnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, filters ...string) error {
ctx = namespaces.WithNamespace(ctx, s.ns)
return s.Snapshotter.Walk(ctx, fn, filters...)

View File

@ -8,8 +8,8 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/sys/user"
"github.com/moby/sys/userns"
"github.com/pkg/errors"
)
@ -30,17 +30,17 @@ type Snapshotter interface {
Remove(ctx context.Context, key string) error
Walk(ctx context.Context, fn snapshots.WalkFunc, filters ...string) error
Close() error
IdentityMapping() *idtools.IdentityMapping
IdentityMapping() *user.IdentityMapping
}
func FromContainerdSnapshotter(name string, s snapshots.Snapshotter, idmap *idtools.IdentityMapping) Snapshotter {
func FromContainerdSnapshotter(name string, s snapshots.Snapshotter, idmap *user.IdentityMapping) Snapshotter {
return &fromContainerd{name: name, Snapshotter: s, idmap: idmap}
}
type fromContainerd struct {
name string
snapshots.Snapshotter
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (s *fromContainerd) Name() string {
@ -59,6 +59,7 @@ func (s *fromContainerd) Prepare(ctx context.Context, key, parent string, opts .
_, err := s.Snapshotter.Prepare(ctx, key, parent, opts...)
return err
}
func (s *fromContainerd) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) (Mountable, error) {
mounts, err := s.Snapshotter.View(ctx, key, parent, opts...)
if err != nil {
@ -66,7 +67,8 @@ func (s *fromContainerd) View(ctx context.Context, key, parent string, opts ...s
}
return &staticMountable{mounts: mounts, idmap: s.idmap, id: key}, nil
}
func (s *fromContainerd) IdentityMapping() *idtools.IdentityMapping {
func (s *fromContainerd) IdentityMapping() *user.IdentityMapping {
return s.idmap
}
@ -132,6 +134,7 @@ func (cs *containerdSnapshotter) Prepare(ctx context.Context, key, parent string
}
return cs.Mounts(ctx, key)
}
func (cs *containerdSnapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
mf, err := cs.Snapshotter.View(ctx, key, parent, opts...)
if err != nil {
@ -140,8 +143,10 @@ func (cs *containerdSnapshotter) View(ctx context.Context, key, parent string, o
return cs.returnMounts(mf)
}
var redirectDirOption string
var redirectDirOptionOnce sync.Once
var (
redirectDirOption string
redirectDirOptionOnce sync.Once
)
func getRedirectDirOption() string {
redirectDirOptionOnce.Do(func() {

View File

@ -5,14 +5,14 @@ import (
"sync/atomic"
"github.com/containerd/containerd/v2/core/mount"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/user"
)
type staticMountable struct {
count int32
id string
mounts []mount.Mount
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (cm *staticMountable) Mount() ([]mount.Mount, func() error, error) {
@ -36,6 +36,6 @@ func (cm *staticMountable) Mount() ([]mount.Mount, func() error, error) {
}, nil
}
func (cm *staticMountable) IdentityMapping() *idtools.IdentityMapping {
func (cm *staticMountable) IdentityMapping() *user.IdentityMapping {
return cm.idmap
}

View File

@ -9,10 +9,10 @@ import (
"time"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/sys/user"
"github.com/pkg/errors"
copy "github.com/tonistiigi/fsutil/copy"
)
@ -25,7 +25,7 @@ func timestampToTime(ts int64) *time.Time {
return &tm
}
func mkdir(d string, action *pb.FileActionMkDir, user *copy.User, idmap *idtools.IdentityMapping) (err error) {
func mkdir(d string, action *pb.FileActionMkDir, user *copy.User, idmap *user.IdentityMapping) (err error) {
defer func() {
var osErr *os.PathError
if errors.As(err, &osErr) {
@ -65,7 +65,7 @@ func mkdir(d string, action *pb.FileActionMkDir, user *copy.User, idmap *idtools
return nil
}
func symlink(d string, action *pb.FileActionSymlink, user *copy.User, idmap *idtools.IdentityMapping) (err error) {
func symlink(d string, action *pb.FileActionSymlink, user *copy.User, idmap *user.IdentityMapping) (err error) {
defer func() {
var osErr *os.PathError
if errors.As(err, &osErr) {
@ -99,7 +99,7 @@ func symlink(d string, action *pb.FileActionSymlink, user *copy.User, idmap *idt
return nil
}
func mkfile(d string, action *pb.FileActionMkFile, user *copy.User, idmap *idtools.IdentityMapping) (err error) {
func mkfile(d string, action *pb.FileActionMkFile, user *copy.User, idmap *user.IdentityMapping) (err error) {
defer func() {
var osErr *os.PathError
if errors.As(err, &osErr) {
@ -184,7 +184,7 @@ func rmPath(root, src string, allowNotFound bool) error {
return errors.WithStack(os.RemoveAll(p))
}
func docopy(ctx context.Context, src, dest string, action *pb.FileActionCopy, u *copy.User, idmap *idtools.IdentityMapping) (err error) {
func docopy(ctx context.Context, src, dest string, action *pb.FileActionCopy, u *copy.User, idmap *user.IdentityMapping) (err error) {
srcPath := cleanPath(action.Src)
destPath := cleanPath(action.Dest)

View File

@ -3,12 +3,12 @@
package file
import (
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/user"
"github.com/pkg/errors"
copy "github.com/tonistiigi/fsutil/copy"
)
func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) {
func mapUserToChowner(user *copy.User, idmap *user.IdentityMapping) (copy.Chowner, error) {
if user == nil {
return func(old *copy.User) (*copy.User, error) {
if old == nil {
@ -18,14 +18,11 @@ func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Cho
old = &copy.User{} // root
// non-nil old is already mapped
if idmap != nil {
identity, err := idmap.ToHost(idtools.Identity{
UID: old.UID,
GID: old.GID,
})
uid, gid, err := idmap.ToHost(old.UID, old.GID)
if err != nil {
return nil, errors.WithStack(err)
}
return &copy.User{UID: identity.UID, GID: identity.GID}, nil
return &copy.User{UID: uid, GID: gid}, nil
}
}
return old, nil
@ -33,15 +30,12 @@ func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Cho
}
u := *user
if idmap != nil {
identity, err := idmap.ToHost(idtools.Identity{
UID: user.UID,
GID: user.GID,
})
uid, gid, err := idmap.ToHost(user.UID, user.GID)
if err != nil {
return nil, errors.WithStack(err)
}
u.UID = identity.UID
u.GID = identity.GID
u.UID = uid
u.GID = gid
}
return func(*copy.User) (*copy.User, error) {
return &u, nil

View File

@ -1,16 +1,17 @@
package file
import (
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/util/windows"
"github.com/moby/sys/user"
copy "github.com/tonistiigi/fsutil/copy"
)
func mapUserToChowner(user *copy.User, _ *idtools.IdentityMapping) (copy.Chowner, error) {
func mapUserToChowner(user *copy.User, _ *user.IdentityMapping) (copy.Chowner, error) {
if user == nil || user.SID == "" {
return func(old *copy.User) (*copy.User, error) {
if old == nil || old.SID == "" {
old = &copy.User{
SID: idtools.ContainerAdministratorSidString,
SID: windows.ContainerAdministratorSidString,
}
}
return old, nil

View File

@ -9,10 +9,11 @@ import (
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/user"
copy "github.com/tonistiigi/fsutil/copy"
)
func unpack(srcRoot string, src string, destRoot string, dest string, ch copy.Chowner, tm *time.Time, idmap *idtools.IdentityMapping) (bool, error) {
func unpack(srcRoot string, src string, destRoot string, dest string, ch copy.Chowner, tm *time.Time, idmap *user.IdentityMapping) (bool, error) {
src, err := fs.RootPath(srcRoot, src)
if err != nil {
return false, err
@ -39,7 +40,23 @@ func unpack(srcRoot string, src string, destRoot string, dest string, ch copy.Ch
BestEffortXattrs: true,
}
if idmap != nil {
opts.IDMap = *idmap
// TODO: chrootarchive should be moved into moby/sys like idtools
// was moved into moby/sys/user. This section can be removed
// when chrootarchive accepts moby/sys/user arguments.
for _, uid := range idmap.UIDMaps {
opts.IDMap.UIDMaps = append(opts.IDMap.UIDMaps, idtools.IDMap{
ContainerID: int(uid.ID),
HostID: int(uid.ParentID),
Size: int(uid.Count),
})
}
for _, gid := range idmap.GIDMaps {
opts.IDMap.GIDMaps = append(opts.IDMap.GIDMaps, idtools.IDMap{
ContainerID: int(gid.ID),
HostID: int(gid.ParentID),
Size: int(gid.Count),
})
}
}
return true, chrootarchive.Untar(file, dest, opts)
}

View File

@ -9,10 +9,7 @@ import (
"sync"
"time"
"github.com/moby/buildkit/util/bklog"
"github.com/containerd/containerd/v2/core/mount"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
@ -21,8 +18,10 @@ import (
"github.com/moby/buildkit/session/sshforward"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/buildkit/util/grpcerrors"
"github.com/moby/locker"
"github.com/moby/sys/user"
"github.com/moby/sys/userns"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
@ -187,7 +186,7 @@ func (mm *MountManager) getSSHMountable(ctx context.Context, m *pb.Mount, g sess
type sshMount struct {
mount *pb.Mount
caller session.Caller
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (sm *sshMount) Mount(ctx context.Context, readonly bool, g session.Group) (snapshot.Mountable, error) {
@ -196,7 +195,7 @@ func (sm *sshMount) Mount(ctx context.Context, readonly bool, g session.Group) (
type sshMountInstance struct {
sm *sshMount
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (sm *sshMountInstance) Mount() ([]mount.Mount, func() error, error) {
@ -206,16 +205,12 @@ func (sm *sshMountInstance) Mount() ([]mount.Mount, func() error, error) {
gid := int(sm.sm.mount.SSHOpt.Gid)
if sm.idmap != nil {
identity, err := sm.idmap.ToHost(idtools.Identity{
UID: uid,
GID: gid,
})
var err error
uid, gid, err = sm.idmap.ToHost(uid, gid)
if err != nil {
cancel(err)
return nil, nil, err
}
uid = identity.UID
gid = identity.GID
}
sock, cleanup, err := sshforward.MountSSHSocket(ctx, sm.sm.caller, sshforward.SocketOpt{
@ -244,7 +239,7 @@ func (sm *sshMountInstance) Mount() ([]mount.Mount, func() error, error) {
}}, release, nil
}
func (sm *sshMountInstance) IdentityMapping() *idtools.IdentityMapping {
func (sm *sshMountInstance) IdentityMapping() *user.IdentityMapping {
return sm.idmap
}
@ -278,7 +273,7 @@ func (mm *MountManager) getSecretMountable(ctx context.Context, m *pb.Mount, g s
type secretMount struct {
mount *pb.Mount
data []byte
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (sm *secretMount) Mount(ctx context.Context, readonly bool, g session.Group) (snapshot.Mountable, error) {
@ -288,7 +283,7 @@ func (sm *secretMount) Mount(ctx context.Context, readonly bool, g session.Group
type secretMountInstance struct {
sm *secretMount
root string
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
@ -344,16 +339,11 @@ func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
gid := int(sm.sm.mount.SecretOpt.Gid)
if sm.idmap != nil {
identity, err := sm.idmap.ToHost(idtools.Identity{
UID: uid,
GID: gid,
})
uid, gid, err = sm.idmap.ToHost(uid, gid)
if err != nil {
cleanup()
return nil, nil, err
}
uid = identity.UID
gid = identity.GID
}
if err := os.Chown(fp, uid, gid); err != nil {
@ -373,7 +363,7 @@ func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
}}, cleanup, nil
}
func (sm *secretMountInstance) IdentityMapping() *idtools.IdentityMapping {
func (sm *secretMountInstance) IdentityMapping() *user.IdentityMapping {
return sm.idmap
}
@ -396,12 +386,12 @@ func (mm *MountManager) MountableSSH(ctx context.Context, m *pb.Mount, g session
return mm.getSSHMountable(ctx, m, g)
}
func newTmpfs(idmap *idtools.IdentityMapping, opt *pb.TmpfsOpt) cache.Mountable {
func newTmpfs(idmap *user.IdentityMapping, opt *pb.TmpfsOpt) cache.Mountable {
return &tmpfs{idmap: idmap, opt: opt}
}
type tmpfs struct {
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
opt *pb.TmpfsOpt
}
@ -411,7 +401,7 @@ func (f *tmpfs) Mount(ctx context.Context, readonly bool, g session.Group) (snap
type tmpfsMount struct {
readonly bool
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
opt *pb.TmpfsOpt
}
@ -432,7 +422,7 @@ func (m *tmpfsMount) Mount() ([]mount.Mount, func() error, error) {
}}, func() error { return nil }, nil
}
func (m *tmpfsMount) IdentityMapping() *idtools.IdentityMapping {
func (m *tmpfsMount) IdentityMapping() *user.IdentityMapping {
return m.idmap
}

View File

@ -9,11 +9,11 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/platforms"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/archutil"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/sys/user"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
copy "github.com/tonistiigi/fsutil/copy"
@ -33,7 +33,7 @@ var qemuArchMap = map[string]string{
type emulator struct {
path string
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (e *emulator) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
@ -42,7 +42,7 @@ func (e *emulator) Mount(ctx context.Context, readonly bool) (snapshot.Mountable
type staticEmulatorMount struct {
path string
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (m *staticEmulatorMount) Mount() ([]mount.Mount, func() error, error) {
@ -59,9 +59,7 @@ func (m *staticEmulatorMount) Mount() ([]mount.Mount, func() error, error) {
var uid, gid int
if m.idmap != nil {
root := m.idmap.RootPair()
uid = root.UID
gid = root.GID
uid, gid = m.idmap.RootPair()
}
if err := copy.Copy(context.TODO(), filepath.Dir(m.path), filepath.Base(m.path), tmpdir, qemuMountName, func(ci *copy.CopyInfo) {
m := 0555
@ -80,7 +78,7 @@ func (m *staticEmulatorMount) Mount() ([]mount.Mount, func() error, error) {
}, nil
}
func (m *staticEmulatorMount) IdentityMapping() *idtools.IdentityMapping {
func (m *staticEmulatorMount) IdentityMapping() *user.IdentityMapping {
return m.idmap
}

View File

@ -3,7 +3,6 @@ package ops
import (
"context"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/windows"
@ -35,14 +34,14 @@ func readUser(chopt *pb.ChownOpt, mu, _ snapshot.Mountable, worker worker.Worker
return nil, err
}
defer release()
ident, err := windows.ResolveUsernameToSID(context.Background(), worker.Executor(), rootMounts, u.ByName.Name)
sid, err := windows.ResolveUsernameToSID(context.Background(), worker.Executor(), rootMounts, u.ByName.Name)
if err != nil {
return nil, err
}
return &copy.User{SID: ident.SID}, nil
return &copy.User{SID: sid}, nil
default:
return &copy.User{SID: idtools.ContainerAdministratorSidString}, nil
return &copy.User{SID: windows.ContainerAdministratorSidString}, nil
}
}
return &copy.User{SID: idtools.ContainerAdministratorSidString}, nil
return &copy.User{SID: windows.ContainerAdministratorSidString}, nil
}

View File

@ -641,9 +641,9 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
}
if idmap := mount.IdentityMapping(); idmap != nil {
u := idmap.RootPair()
uid, gid := idmap.RootPair()
err := filepath.WalkDir(gitDir, func(p string, _ os.DirEntry, _ error) error {
return os.Lchown(p, u.UID, u.GID)
return os.Lchown(p, uid, gid)
})
if err != nil {
return nil, errors.Wrap(err, "failed to remap git checkout")
@ -749,10 +749,12 @@ func getDefaultBranch(ctx context.Context, git *gitutil.GitCLI, remoteURL string
return ss[0][1], nil
}
const keyGitRemote = "git-remote"
const gitRemoteIndex = keyGitRemote + "::"
const keyGitSnapshot = "git-snapshot"
const gitSnapshotIndex = keyGitSnapshot + "::"
const (
keyGitRemote = "git-remote"
gitRemoteIndex = keyGitRemote + "::"
keyGitSnapshot = "git-snapshot"
gitSnapshotIndex = keyGitSnapshot + "::"
)
func search(ctx context.Context, store cache.MetadataStore, key string, idx string) ([]cacheRefMetadata, error) {
var results []cacheRefMetadata

View File

@ -19,7 +19,6 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/secrets"
@ -399,15 +398,10 @@ func (hs *httpSourceHandler) save(ctx context.Context, resp *http.Response, s se
uid := hs.src.UID
gid := hs.src.GID
if idmap := mount.IdentityMapping(); idmap != nil {
identity, err := idmap.ToHost(idtools.Identity{
UID: int(uid),
GID: int(gid),
})
uid, gid, err = idmap.ToHost(int(uid), int(gid))
if err != nil {
return nil, "", err
}
uid = identity.UID
gid = identity.GID
}
if gid != 0 || uid != 0 {
@ -523,7 +517,6 @@ func (hs *httpSourceHandler) newHTTPRequest(ctx context.Context, g session.Group
return nil
})
if err != nil {
return nil, errors.Wrapf(err, "failed to retrieve HTTP auth secret %s", hs.src.AuthHeaderSecret)
}
@ -572,9 +565,11 @@ type cacheRefMetadata struct {
cache.RefMetadata
}
const keyHTTPChecksum = "http.checksum"
const keyETag = "etag"
const keyModTime = "http.modtime"
const (
keyHTTPChecksum = "http.checksum"
keyETag = "etag"
keyModTime = "http.modtime"
)
func (md cacheRefMetadata) getHTTPChecksum() digest.Digest {
return digest.Digest(md.GetString(keyHTTPChecksum))

View File

@ -7,11 +7,6 @@ import (
"strings"
"time"
"github.com/moby/buildkit/solver/pb"
srctypes "github.com/moby/buildkit/source/types"
"github.com/moby/buildkit/util/bklog"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/contenthash"
"github.com/moby/buildkit/client"
@ -19,8 +14,12 @@ import (
"github.com/moby/buildkit/session/filesync"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/source"
srctypes "github.com/moby/buildkit/source/types"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/buildkit/util/progress"
"github.com/moby/sys/user"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/tonistiigi/fsutil"
@ -248,15 +247,12 @@ func (ls *localSourceHandler) snapshot(ctx context.Context, caller session.Calle
if idmap := mount.IdentityMapping(); idmap != nil {
opt.Filter = func(p string, stat *fstypes.Stat) bool {
identity, err := idmap.ToHost(idtools.Identity{
UID: int(stat.Uid),
GID: int(stat.Gid),
})
uid, gid, err := idmap.ToHost(int(stat.Uid), int(stat.Gid))
if err != nil {
return false
}
stat.Uid = uint32(identity.UID)
stat.Gid = uint32(identity.GID)
stat.Uid = uint32(uid)
stat.Gid = uint32(gid)
return true
}
}
@ -319,7 +315,7 @@ func newProgressHandler(ctx context.Context, id string) func(int, bool) {
type cacheUpdater struct {
contenthash.CacheContext
idmap *idtools.IdentityMapping
idmap *user.IdentityMapping
}
func (cu *cacheUpdater) MarkSupported(bool) {
@ -329,8 +325,10 @@ func (cu *cacheUpdater) ContentHasher() fsutil.ContentHasher {
return contenthash.NewFromStat
}
const keySharedKey = "local.sharedKey"
const sharedKeyIndex = keySharedKey + ":"
const (
keySharedKey = "local.sharedKey"
sharedKeyIndex = keySharedKey + ":"
)
func searchSharedKey(ctx context.Context, store cache.MetadataStore, k string) ([]cacheRefMetadata, error) {
var results []cacheRefMetadata

View File

@ -7,7 +7,6 @@ import (
"golang.org/x/sys/windows"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/reexec"
)
@ -31,9 +30,10 @@ func userInfoMain() {
os.Exit(3)
}
ident := idtools.Identity{
SID: sid.String(),
var ident struct {
SID string
}
ident.SID = sid.String()
asJSON, err := json.Marshal(ident)
if err != nil {

View File

@ -8,20 +8,28 @@ import (
"syscall"
"github.com/containerd/containerd/v2/core/mount"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/snapshot"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
func ResolveUsernameToSID(ctx context.Context, exec executor.Executor, rootMount []mount.Mount, userName string) (idtools.Identity, error) {
// Constants for well-known SIDs in the Windows container.
// These are currently undocumented.
// See https://github.com/moby/buildkit/pull/5791#discussion_r1976652227 for more information.
const (
ContainerAdministratorSidString = "S-1-5-93-2-1"
ContainerUserSidString = "S-1-5-93-2-2"
)
func ResolveUsernameToSID(ctx context.Context, exec executor.Executor, rootMount []mount.Mount, userName string) (string, error) {
// This is a shortcut in case the user is one of the builtin users that should exist
// in any WCOW container. While these users do exist in containers, they don't exist on the
// host. We check them before trying to look them up using LookupSID().
if strings.EqualFold(userName, "ContainerAdministrator") || userName == "" {
return idtools.Identity{SID: idtools.ContainerAdministratorSidString}, nil
return ContainerAdministratorSidString, nil
} else if strings.EqualFold(userName, "ContainerUser") {
return idtools.Identity{SID: idtools.ContainerUserSidString}, nil
return ContainerUserSidString, nil
}
// We might have a SID set as username. There is no guarantee that this SID will exist
@ -29,7 +37,7 @@ func ResolveUsernameToSID(ctx context.Context, exec executor.Executor, rootMount
// that the user has made sure it does map to an identity inside the container.
if strings.HasPrefix(strings.ToLower(userName), "s-") {
if _, err := syscall.StringToSid(userName); err == nil {
return idtools.Identity{SID: userName}, nil
return userName, nil
}
}
@ -44,7 +52,7 @@ func ResolveUsernameToSID(ctx context.Context, exec executor.Executor, rootMount
if accountType == syscall.SidTypeAlias || accountType == syscall.SidTypeWellKnownGroup {
sidAsString, err := sid.String()
if err == nil {
return idtools.Identity{SID: sidAsString}, nil
return sidAsString, nil
}
}
}
@ -66,16 +74,18 @@ func ResolveUsernameToSID(ctx context.Context, exec executor.Executor, rootMount
// TODO(gsamfira): Should we use a snapshot of the rootMount?
ident, err := GetUserIdentFromContainer(ctx, exec, rootMount, userName)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "getting account SID from container")
return "", errors.Wrap(err, "getting account SID from container")
}
return ident, nil
}
func GetUserIdentFromContainer(ctx context.Context, exec executor.Executor, rootMounts []mount.Mount, userName string) (idtools.Identity, error) {
var ident idtools.Identity
func GetUserIdentFromContainer(ctx context.Context, exec executor.Executor, rootMounts []mount.Mount, userName string) (string, error) {
var ident struct {
SID string
}
if len(rootMounts) > 1 {
return ident, errors.Errorf("unexpected number of root mounts: %d", len(rootMounts))
return "", errors.Errorf("unexpected number of root mounts: %d", len(rootMounts))
}
stdout := &bytesReadWriteCloser{
@ -100,15 +110,15 @@ func GetUserIdentFromContainer(ctx context.Context, exec executor.Executor, root
}
if _, err := exec.Run(ctx, "", newStubMountable(rootMounts), nil, procInfo, nil); err != nil {
return ident, errors.Wrap(err, "executing command")
return "", errors.Wrap(err, "executing command")
}
data := stdout.bw.Bytes()
if err := json.Unmarshal(data, &ident); err != nil {
return ident, errors.Wrap(err, "reading user info")
return "", errors.Wrap(err, "reading user info")
}
return ident, nil
return ident.SID, nil
}
type bytesReadWriteCloser struct {
@ -138,7 +148,8 @@ func (m *snapshotMountable) Mount() ([]mount.Mount, func() error, error) {
cleanup := func() error { return nil }
return m.m, cleanup, nil
}
func (m *snapshotMountable) IdentityMapping() *idtools.IdentityMapping {
func (m *snapshotMountable) IdentityMapping() *user.IdentityMapping {
return nil
}

141
vendor/github.com/moby/sys/user/idtools.go generated vendored Normal file
View File

@ -0,0 +1,141 @@
package user
import (
"fmt"
"os"
)
// MkdirOpt is a type for options to pass to Mkdir calls
type MkdirOpt func(*mkdirOptions)
type mkdirOptions struct {
onlyNew bool
}
// WithOnlyNew is an option for MkdirAllAndChown that will only change ownership and permissions
// on newly created directories. If the directory already exists, it will not be modified
func WithOnlyNew(o *mkdirOptions) {
o.onlyNew = true
}
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
// ownership to the requested uid/gid. By default, if the directory already exists, this
// function will still change ownership and permissions. If WithOnlyNew is passed as an
// option, then only the newly created directories will have ownership and permissions changed.
func MkdirAllAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
var options mkdirOptions
for _, opt := range opts {
opt(&options)
}
return mkdirAs(path, mode, uid, gid, true, options.onlyNew)
}
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
// By default, if the directory already exists, this function still changes ownership and permissions.
// If WithOnlyNew is passed as an option, then only the newly created directory will have ownership
// and permissions changed.
// Note that unlike os.Mkdir(), this function does not return IsExist error
// in case path already exists.
func MkdirAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
var options mkdirOptions
for _, opt := range opts {
opt(&options)
}
return mkdirAs(path, mode, uid, gid, false, options.onlyNew)
}
// getRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// If the maps are empty, then the root uid/gid will default to "real" 0/0
func getRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
uid, err := toHost(0, uidMap)
if err != nil {
return -1, -1, err
}
gid, err := toHost(0, gidMap)
if err != nil {
return -1, -1, err
}
return uid, gid, nil
}
// toContainer takes an id mapping, and uses it to translate a
// host ID to the remapped ID. If no map is provided, then the translation
// assumes a 1-to-1 mapping and returns the passed in id
func toContainer(hostID int, idMap []IDMap) (int, error) {
if idMap == nil {
return hostID, nil
}
for _, m := range idMap {
if (int64(hostID) >= m.ParentID) && (int64(hostID) <= (m.ParentID + m.Count - 1)) {
contID := int(m.ID + (int64(hostID) - m.ParentID))
return contID, nil
}
}
return -1, fmt.Errorf("host ID %d cannot be mapped to a container ID", hostID)
}
// toHost takes an id mapping and a remapped ID, and translates the
// ID to the mapped host ID. If no map is provided, then the translation
// assumes a 1-to-1 mapping and returns the passed in id #
func toHost(contID int, idMap []IDMap) (int, error) {
if idMap == nil {
return contID, nil
}
for _, m := range idMap {
if (int64(contID) >= m.ID) && (int64(contID) <= (m.ID + m.Count - 1)) {
hostID := int(m.ParentID + (int64(contID) - m.ID))
return hostID, nil
}
}
return -1, fmt.Errorf("container ID %d cannot be mapped to a host ID", contID)
}
// IdentityMapping contains a mappings of UIDs and GIDs.
// The zero value represents an empty mapping.
type IdentityMapping struct {
UIDMaps []IDMap `json:"UIDMaps"`
GIDMaps []IDMap `json:"GIDMaps"`
}
// RootPair returns a uid and gid pair for the root user. The error is ignored
// because a root user always exists, and the defaults are correct when the uid
// and gid maps are empty.
func (i IdentityMapping) RootPair() (int, int) {
uid, gid, _ := getRootUIDGID(i.UIDMaps, i.GIDMaps)
return uid, gid
}
// ToHost returns the host UID and GID for the container uid, gid.
// Remapping is only performed if the ids aren't already the remapped root ids
func (i IdentityMapping) ToHost(uid, gid int) (int, int, error) {
var err error
ruid, rgid := i.RootPair()
if uid != ruid {
ruid, err = toHost(uid, i.UIDMaps)
if err != nil {
return ruid, rgid, err
}
}
if gid != rgid {
rgid, err = toHost(gid, i.GIDMaps)
}
return ruid, rgid, err
}
// ToContainer returns the container UID and GID for the host uid and gid
func (i IdentityMapping) ToContainer(uid, gid int) (int, int, error) {
ruid, err := toContainer(uid, i.UIDMaps)
if err != nil {
return -1, -1, err
}
rgid, err := toContainer(gid, i.GIDMaps)
return ruid, rgid, err
}
// Empty returns true if there are no id mappings
func (i IdentityMapping) Empty() bool {
return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
}

143
vendor/github.com/moby/sys/user/idtools_unix.go generated vendored Normal file
View File

@ -0,0 +1,143 @@
//go:build !windows
package user
import (
"fmt"
"os"
"path/filepath"
"strconv"
"syscall"
)
func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll, onlyNew bool) error {
path, err := filepath.Abs(path)
if err != nil {
return err
}
stat, err := os.Stat(path)
if err == nil {
if !stat.IsDir() {
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
}
if onlyNew {
return nil
}
// short-circuit -- we were called with an existing directory and chown was requested
return setPermissions(path, mode, uid, gid, stat)
}
// make an array containing the original path asked for, plus (for mkAll == true)
// all path components leading up to the complete path that don't exist before we MkdirAll
// so that we can chown all of them properly at the end. If onlyNew is true, we won't
// chown the full directory path if it exists
var paths []string
if os.IsNotExist(err) {
paths = append(paths, path)
}
if mkAll {
// walk back to "/" looking for directories which do not exist
// and add them to the paths array for chown after creation
dirPath := path
for {
dirPath = filepath.Dir(dirPath)
if dirPath == "/" {
break
}
if _, err = os.Stat(dirPath); os.IsNotExist(err) {
paths = append(paths, dirPath)
}
}
if err = os.MkdirAll(path, mode); err != nil {
return err
}
} else if err = os.Mkdir(path, mode); err != nil {
return err
}
// even if it existed, we will chown the requested path + any subpaths that
// didn't exist when we called MkdirAll
for _, pathComponent := range paths {
if err = setPermissions(pathComponent, mode, uid, gid, nil); err != nil {
return err
}
}
return nil
}
// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
// Likewise for setting permissions.
func setPermissions(p string, mode os.FileMode, uid, gid int, stat os.FileInfo) error {
if stat == nil {
var err error
stat, err = os.Stat(p)
if err != nil {
return err
}
}
if stat.Mode().Perm() != mode.Perm() {
if err := os.Chmod(p, mode.Perm()); err != nil {
return err
}
}
ssi := stat.Sys().(*syscall.Stat_t)
if ssi.Uid == uint32(uid) && ssi.Gid == uint32(gid) {
return nil
}
return os.Chown(p, uid, gid)
}
// LoadIdentityMapping takes a requested username and
// using the data from /etc/sub{uid,gid} ranges, creates the
// proper uid and gid remapping ranges for that user/group pair
func LoadIdentityMapping(name string) (IdentityMapping, error) {
// TODO: Consider adding support for calling out to "getent"
usr, err := LookupUser(name)
if err != nil {
return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %w", name, err)
}
subuidRanges, err := lookupSubRangesFile("/etc/subuid", usr)
if err != nil {
return IdentityMapping{}, err
}
subgidRanges, err := lookupSubRangesFile("/etc/subgid", usr)
if err != nil {
return IdentityMapping{}, err
}
return IdentityMapping{
UIDMaps: subuidRanges,
GIDMaps: subgidRanges,
}, nil
}
func lookupSubRangesFile(path string, usr User) ([]IDMap, error) {
uidstr := strconv.Itoa(usr.Uid)
rangeList, err := ParseSubIDFileFilter(path, func(sid SubID) bool {
return sid.Name == usr.Name || sid.Name == uidstr
})
if err != nil {
return nil, err
}
if len(rangeList) == 0 {
return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name)
}
idMap := []IDMap{}
var containerID int64
for _, idrange := range rangeList {
idMap = append(idMap, IDMap{
ID: containerID,
ParentID: idrange.SubID,
Count: idrange.Count,
})
containerID = containerID + idrange.Count
}
return idMap, nil
}

13
vendor/github.com/moby/sys/user/idtools_windows.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package user
import (
"os"
)
// This is currently a wrapper around [os.MkdirAll] since currently
// permissions aren't set through this path, the identity isn't utilized.
// Ownership is handled elsewhere, but in the future could be support here
// too.
func mkdirAs(path string, _ os.FileMode, _, _ int, _, _ bool) error {
return os.MkdirAll(path, 0)
}

2
vendor/modules.txt vendored
View File

@ -648,7 +648,7 @@ github.com/moby/sys/sequential
# github.com/moby/sys/signal v0.7.1
## explicit; go 1.17
github.com/moby/sys/signal
# github.com/moby/sys/user v0.3.0
# github.com/moby/sys/user v0.3.1-0.20250227193707-71f0c5ead442
## explicit; go 1.17
github.com/moby/sys/user
# github.com/moby/sys/userns v0.1.0

View File

@ -13,7 +13,6 @@ import (
"github.com/containerd/containerd/v2/core/remotes/docker"
"github.com/containerd/containerd/v2/pkg/gc"
"github.com/containerd/platforms"
"github.com/docker/docker/pkg/idtools"
"github.com/hashicorp/go-multierror"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/metadata"
@ -48,6 +47,7 @@ import (
"github.com/moby/buildkit/util/network"
"github.com/moby/buildkit/util/progress"
"github.com/moby/buildkit/util/progress/controller"
"github.com/moby/sys/user"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@ -76,7 +76,7 @@ type WorkerOpt struct {
Differ diff.Comparer
ImageStore images.Store // optional
RegistryHosts docker.RegistryHosts
IdentityMapping *idtools.IdentityMapping
IdentityMapping *user.IdentityMapping
LeaseManager *leaseutil.Manager
GarbageCollect func(context.Context) (gc.Stats, error)
ParallelismSem *semaphore.Weighted

View File

@ -15,7 +15,6 @@ import (
"github.com/containerd/containerd/v2/plugins/content/local"
"github.com/containerd/containerd/v2/plugins/diff/walking"
"github.com/containerd/platforms"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/metadata"
"github.com/moby/buildkit/executor/oci"
@ -28,6 +27,7 @@ import (
"github.com/moby/buildkit/util/winlayers"
"github.com/moby/buildkit/worker/base"
wlabel "github.com/moby/buildkit/worker/label"
"github.com/moby/sys/user"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
bolt "go.etcd.io/bbolt"
"golang.org/x/sync/semaphore"
@ -40,7 +40,7 @@ type SnapshotterFactory struct {
}
// NewWorkerOpt creates a WorkerOpt.
func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping, nopt netproviders.Opt, dns *oci.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string, cdiManager *cdidevices.Manager) (base.WorkerOpt, error) {
func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *user.IdentityMapping, nopt netproviders.Opt, dns *oci.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string, cdiManager *cdidevices.Manager) (base.WorkerOpt, error) {
var opt base.WorkerOpt
name := "runc-" + snFactory.Name
root = filepath.Join(root, name)