Merge pull request #43366 from corhere/finish-identitymapping-refactor

Finish refactor of UID/GID usage to a new struct
This commit is contained in:
Sebastiaan van Stijn 2022-03-25 14:51:05 +01:00 committed by GitHub
commit 0a3336fd7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 301 additions and 340 deletions

View File

@ -32,7 +32,7 @@ type Opt struct {
GraphDriver graphdriver.Driver GraphDriver graphdriver.Driver
LayerStore layer.Store LayerStore layer.Store
Root string Root string
IdentityMapping *idtools.IdentityMapping IdentityMapping idtools.IdentityMapping
} }
type graphIDRegistrar interface { type graphIDRegistrar interface {
@ -100,7 +100,12 @@ func (s *snapshotter) Name() string {
} }
func (s *snapshotter) IdentityMapping() *idtools.IdentityMapping { func (s *snapshotter) IdentityMapping() *idtools.IdentityMapping {
return s.opt.IdentityMapping // Returning a non-nil but empty *IdentityMapping breaks BuildKit:
// https://github.com/moby/moby/pull/39444
if s.opt.IdentityMapping.Empty() {
return nil
}
return &s.opt.IdentityMapping
} }
func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) error { func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) error {
@ -482,7 +487,7 @@ type mountable struct {
acquire func() ([]mount.Mount, func() error, error) acquire func() ([]mount.Mount, func() error, error)
release func() error release func() error
refCount int refCount int
idmap *idtools.IdentityMapping idmap idtools.IdentityMapping
} }
func (m *mountable) Mount() ([]mount.Mount, func() error, error) { func (m *mountable) Mount() ([]mount.Mount, func() error, error) {
@ -527,5 +532,10 @@ func (m *mountable) releaseMount() error {
} }
func (m *mountable) IdentityMapping() *idtools.IdentityMapping { func (m *mountable) IdentityMapping() *idtools.IdentityMapping {
return m.idmap // Returning a non-nil but empty *IdentityMapping breaks BuildKit:
// https://github.com/moby/moby/pull/39444
if m.idmap.Empty() {
return nil
}
return &m.idmap
} }

View File

@ -73,7 +73,7 @@ type Opt struct {
RegistryHosts docker.RegistryHosts RegistryHosts docker.RegistryHosts
BuilderConfig config.BuilderConfig BuilderConfig config.BuilderConfig
Rootless bool Rootless bool
IdentityMapping *idtools.IdentityMapping IdentityMapping idtools.IdentityMapping
DNSConfig config.DNSConfig DNSConfig config.DNSConfig
ApparmorProfile string ApparmorProfile string
} }
@ -91,10 +91,6 @@ type Builder struct {
func New(opt Opt) (*Builder, error) { func New(opt Opt) (*Builder, error) {
reqHandler := newReqBodyHandler(tracing.DefaultTransport) reqHandler := newReqBodyHandler(tracing.DefaultTransport)
if opt.IdentityMapping != nil && opt.IdentityMapping.Empty() {
opt.IdentityMapping = nil
}
c, err := newController(reqHandler, opt) c, err := newController(reqHandler, opt)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -25,7 +25,7 @@ import (
const networkName = "bridge" const networkName = "bridge"
func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dnsConfig *oci.DNSConfig, rootless bool, idmap *idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) { func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dnsConfig *oci.DNSConfig, rootless bool, idmap idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) {
netRoot := filepath.Join(root, "net") netRoot := filepath.Join(root, "net")
networkProviders := map[pb.NetMode]network.Provider{ networkProviders := map[pb.NetMode]network.Provider{
pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: netRoot}, pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: netRoot},
@ -44,13 +44,20 @@ func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dn
} }
} }
// Returning a non-nil but empty *IdentityMapping breaks BuildKit:
// https://github.com/moby/moby/pull/39444
pidmap := &idmap
if idmap.Empty() {
pidmap = nil
}
return runcexecutor.New(runcexecutor.Opt{ return runcexecutor.New(runcexecutor.Opt{
Root: filepath.Join(root, "executor"), Root: filepath.Join(root, "executor"),
CommandCandidates: []string{"runc"}, CommandCandidates: []string{"runc"},
DefaultCgroupParent: cgroupParent, DefaultCgroupParent: cgroupParent,
Rootless: rootless, Rootless: rootless,
NoPivot: os.Getenv("DOCKER_RAMDISK") != "", NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
IdentityMapping: idmap, IdentityMapping: pidmap,
DNS: dnsConfig, DNS: dnsConfig,
ApparmorProfile: apparmorProfile, ApparmorProfile: apparmorProfile,
}, networkProviders) }, networkProviders)

View File

@ -11,7 +11,7 @@ import (
"github.com/moby/buildkit/executor/oci" "github.com/moby/buildkit/executor/oci"
) )
func newExecutor(_, _ string, _ libnetwork.NetworkController, _ *oci.DNSConfig, _ bool, _ *idtools.IdentityMapping, _ string) (executor.Executor, error) { func newExecutor(_, _ string, _ libnetwork.NetworkController, _ *oci.DNSConfig, _ bool, _ idtools.IdentityMapping, _ string) (executor.Executor, error) {
return &winExecutor{}, nil return &winExecutor{}, nil
} }

View File

@ -46,13 +46,13 @@ const (
// BuildManager is shared across all Builder objects // BuildManager is shared across all Builder objects
type BuildManager struct { type BuildManager struct {
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
backend builder.Backend backend builder.Backend
pathCache pathCache // TODO: make this persistent pathCache pathCache // TODO: make this persistent
} }
// NewBuildManager creates a BuildManager // NewBuildManager creates a BuildManager
func NewBuildManager(b builder.Backend, identityMapping *idtools.IdentityMapping) (*BuildManager, error) { func NewBuildManager(b builder.Backend, identityMapping idtools.IdentityMapping) (*BuildManager, error) {
bm := &BuildManager{ bm := &BuildManager{
backend: b, backend: b,
pathCache: &syncmap.Map{}, pathCache: &syncmap.Map{},
@ -103,7 +103,7 @@ type builderOptions struct {
Backend builder.Backend Backend builder.Backend
ProgressWriter backend.ProgressWriter ProgressWriter backend.ProgressWriter
PathCache pathCache PathCache pathCache
IDMapping *idtools.IdentityMapping IDMapping idtools.IdentityMapping
} }
// Builder is a Dockerfile builder // Builder is a Dockerfile builder
@ -119,7 +119,7 @@ type Builder struct {
docker builder.Backend docker builder.Backend
clientCtx context.Context clientCtx context.Context
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
disableCommit bool disableCommit bool
imageSources *imageSources imageSources *imageSources
pathCache pathCache pathCache pathCache

View File

@ -33,7 +33,7 @@ type Archiver interface {
UntarPath(src, dst string) error UntarPath(src, dst string) error
CopyWithTar(src, dst string) error CopyWithTar(src, dst string) error
CopyFileWithTar(src, dst string) error CopyFileWithTar(src, dst string) error
IdentityMapping() *idtools.IdentityMapping IdentityMapping() idtools.IdentityMapping
} }
// The builder will use the following interfaces if the container fs implements // The builder will use the following interfaces if the container fs implements

View File

@ -11,7 +11,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping *idtools.IdentityMapping) (idtools.Identity, error) { func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
var userStr, grpStr string var userStr, grpStr string
parts := strings.Split(chown, ":") parts := strings.Split(chown, ":")
if len(parts) > 2 { if len(parts) > 2 {

View File

@ -34,8 +34,8 @@ othergrp:x:6666:
Size: 65536, Size: 65536,
}, },
} }
remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps) remapped := idtools.IdentityMapping{UIDMaps: idMaps, GIDMaps: idMaps}
unmapped := &idtools.IdentityMapping{} unmapped := idtools.IdentityMapping{}
contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test") contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
defer cleanup() defer cleanup()
@ -53,7 +53,7 @@ othergrp:x:6666:
builder *Builder builder *Builder
name string name string
chownStr string chownStr string
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
state *dispatchState state *dispatchState
expected idtools.Identity expected idtools.Identity
}{ }{
@ -126,7 +126,7 @@ othergrp:x:6666:
builder *Builder builder *Builder
name string name string
chownStr string chownStr string
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
state *dispatchState state *dispatchState
descr string descr string
}{ }{

View File

@ -14,7 +14,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping *idtools.IdentityMapping) (idtools.Identity, error) { func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
if builder.options.Platform == "windows" { if builder.options.Platform == "windows" {
return getAccountIdentity(builder, chown, ctrRootPath, state) return getAccountIdentity(builder, chown, ctrRootPath, state)
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/docker/docker/daemon/graphdriver/devmapper" "github.com/docker/docker/daemon/graphdriver/devmapper"
"github.com/docker/docker/pkg/devicemapper" "github.com/docker/docker/pkg/devicemapper"
"github.com/docker/docker/pkg/idtools"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -76,7 +77,7 @@ func main() {
args := flag.Args() args := flag.Args()
home := path.Join(*root, "devicemapper") home := path.Join(*root, "devicemapper")
devices, err := devmapper.NewDeviceSet(home, false, nil, nil, nil) devices, err := devmapper.NewDeviceSet(home, false, nil, idtools.IdentityMapping{})
if err != nil { if err != nil {
fmt.Println("Can't initialize device mapper: ", err) fmt.Println("Can't initialize device mapper: ", err)
os.Exit(1) os.Exit(1)

View File

@ -9,7 +9,6 @@ import (
func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions { func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions {
return &archive.TarOptions{ return &archive.TarOptions{
NoOverwriteDirNonDir: noOverwriteDirNonDir, NoOverwriteDirNonDir: noOverwriteDirNonDir,
UIDMaps: daemon.idMapping.UIDs(), IDMap: daemon.idMapping,
GIDMaps: daemon.idMapping.GIDs(),
} }
} }

View File

@ -98,7 +98,7 @@ type Daemon struct {
sysInfoOnce sync.Once sysInfoOnce sync.Once
sysInfo *sysinfo.SysInfo sysInfo *sysinfo.SysInfo
shutdown bool shutdown bool
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
graphDriver string // TODO: move graphDriver field to an InfoService graphDriver string // TODO: move graphDriver field to an InfoService
PluginStore *plugin.Store // TODO: remove PluginStore *plugin.Store // TODO: remove
pluginManager *plugin.Manager pluginManager *plugin.Manager
@ -1459,7 +1459,7 @@ func (daemon *Daemon) GetAttachmentStore() *network.AttachmentStore {
} }
// IdentityMapping returns uid/gid mapping or a SID (in the case of Windows) for the builder // IdentityMapping returns uid/gid mapping or a SID (in the case of Windows) for the builder
func (daemon *Daemon) IdentityMapping() *idtools.IdentityMapping { func (daemon *Daemon) IdentityMapping() idtools.IdentityMapping {
return daemon.idMapping return daemon.idMapping
} }

View File

@ -1062,7 +1062,7 @@ func removeDefaultBridgeInterface() {
} }
} }
func setupInitLayer(idMapping *idtools.IdentityMapping) func(containerfs.ContainerFS) error { func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error {
return func(initPath containerfs.ContainerFS) error { return func(initPath containerfs.ContainerFS) error {
return initlayer.Setup(initPath, idMapping.RootPair()) return initlayer.Setup(initPath, idMapping.RootPair())
} }
@ -1161,9 +1161,9 @@ func parseRemappedRoot(usergrp string) (string, string, error) {
return username, groupname, nil return username, groupname, nil
} }
func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) { func setupRemappedRoot(config *config.Config) (idtools.IdentityMapping, error) {
if runtime.GOOS != "linux" && config.RemappedRoot != "" { if runtime.GOOS != "linux" && config.RemappedRoot != "" {
return nil, fmt.Errorf("User namespaces are only supported on Linux") return idtools.IdentityMapping{}, fmt.Errorf("User namespaces are only supported on Linux")
} }
// if the daemon was started with remapped root option, parse // if the daemon was started with remapped root option, parse
@ -1171,25 +1171,25 @@ func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error)
if config.RemappedRoot != "" { if config.RemappedRoot != "" {
username, groupname, err := parseRemappedRoot(config.RemappedRoot) username, groupname, err := parseRemappedRoot(config.RemappedRoot)
if err != nil { if err != nil {
return nil, err return idtools.IdentityMapping{}, err
} }
if username == "root" { if username == "root" {
// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op // Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
// effectively // effectively
logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF") logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
return &idtools.IdentityMapping{}, nil return idtools.IdentityMapping{}, nil
} }
logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s", username) logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s", username)
// update remapped root setting now that we have resolved them to actual names // update remapped root setting now that we have resolved them to actual names
config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname) config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
mappings, err := idtools.NewIdentityMapping(username) mappings, err := idtools.LoadIdentityMapping(username)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Can't create ID mappings") return idtools.IdentityMapping{}, errors.Wrap(err, "Can't create ID mappings")
} }
return mappings, nil return mappings, nil
} }
return &idtools.IdentityMapping{}, nil return idtools.IdentityMapping{}, nil
} }
func setupDaemonRoot(config *config.Config, rootDir string, remappedRoot idtools.Identity) error { func setupDaemonRoot(config *config.Config, rootDir string, remappedRoot idtools.Identity) error {

View File

@ -63,7 +63,7 @@ func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfi
return nil return nil
} }
func setupInitLayer(idMapping *idtools.IdentityMapping) func(containerfs.ContainerFS) error { func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error {
return nil return nil
} }
@ -437,8 +437,8 @@ func recursiveUnmount(_ string) error {
return nil return nil
} }
func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) { func setupRemappedRoot(config *config.Config) (idtools.IdentityMapping, error) {
return &idtools.IdentityMapping{}, nil return idtools.IdentityMapping{}, nil
} }
func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error { func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error {

View File

@ -63,8 +63,7 @@ func (daemon *Daemon) containerExport(container *container.Container) (arch io.R
archv, err := archivePath(basefs, basefs.Path(), &archive.TarOptions{ archv, err := archivePath(basefs, basefs.Path(), &archive.TarOptions{
Compression: archive.Uncompressed, Compression: archive.Uncompressed,
UIDMaps: daemon.idMapping.UIDs(), IDMap: daemon.idMapping,
GIDMaps: daemon.idMapping.GIDs(),
}, basefs.Path()) }, basefs.Path())
if err != nil { if err != nil {
rwlayer.Unmount() rwlayer.Unmount()

View File

@ -71,8 +71,7 @@ func init() {
// Driver contains information about the filesystem mounted. // Driver contains information about the filesystem mounted.
type Driver struct { type Driver struct {
root string root string
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
pathCacheLock sync.Mutex pathCacheLock sync.Mutex
pathCache map[string]string pathCache map[string]string
@ -83,7 +82,7 @@ type Driver struct {
// Init returns a new AUFS driver. // Init returns a new AUFS driver.
// An error is returned if AUFS is not supported. // An error is returned if AUFS is not supported.
func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(root string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
// Try to load the aufs kernel module // Try to load the aufs kernel module
if err := supportsAufs(); err != nil { if err := supportsAufs(); err != nil {
logger.Error(err) logger.Error(err)
@ -121,21 +120,16 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
a := &Driver{ a := &Driver{
root: root, root: root,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
pathCache: make(map[string]string), pathCache: make(map[string]string),
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)), ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)),
locker: locker.New(), locker: locker.New(),
} }
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: rootGID, GID: a.idMap.RootPair().GID,
} }
// Create the root aufs driver dir // Create the root aufs driver dir
@ -170,7 +164,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
} }
} }
a.naiveDiff = graphdriver.NewNaiveDiffDriver(a, uidMaps, gidMaps) a.naiveDiff = graphdriver.NewNaiveDiffDriver(a, a.idMap)
return a, nil return a, nil
} }
@ -285,15 +279,11 @@ func (a *Driver) createDirsFor(id string) error {
"diff", "diff",
} }
rootUID, rootGID, err := idtools.GetRootUIDGID(a.uidMaps, a.gidMaps)
if err != nil {
return err
}
// Directory permission is 0755. // Directory permission is 0755.
// The path of directories are <aufs_root_path>/mnt/<image_id> // The path of directories are <aufs_root_path>/mnt/<image_id>
// and <aufs_root_path>/diff/<image_id> // and <aufs_root_path>/diff/<image_id>
for _, p := range paths { for _, p := range paths {
if err := idtools.MkdirAllAndChown(path.Join(a.rootPath(), p, id), 0755, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { if err := idtools.MkdirAllAndChown(path.Join(a.rootPath(), p, id), 0755, a.idMap.RootPair()); err != nil {
return err return err
} }
} }
@ -439,8 +429,7 @@ func (a *Driver) Diff(id, parent string) (io.ReadCloser, error) {
return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{ return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{
Compression: archive.Uncompressed, Compression: archive.Uncompressed,
ExcludePatterns: []string{archive.WhiteoutMetaPrefix + "*", "!" + archive.WhiteoutOpaqueDir}, ExcludePatterns: []string{archive.WhiteoutMetaPrefix + "*", "!" + archive.WhiteoutOpaqueDir},
UIDMaps: a.uidMaps, IDMap: a.idMap,
GIDMaps: a.gidMaps,
}) })
} }
@ -461,8 +450,7 @@ func (a *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
func (a *Driver) applyDiff(id string, diff io.Reader) error { func (a *Driver) applyDiff(id string, diff io.Reader) error {
return chrootarchive.UntarUncompressed(diff, path.Join(a.rootPath(), "diff", id), &archive.TarOptions{ return chrootarchive.UntarUncompressed(diff, path.Join(a.rootPath(), "diff", id), &archive.TarOptions{
UIDMaps: a.uidMaps, IDMap: a.idMap,
GIDMaps: a.gidMaps,
}) })
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/stringid"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
@ -31,7 +32,7 @@ func init() {
} }
func testInit(dir string, t testing.TB) graphdriver.Driver { func testInit(dir string, t testing.TB) graphdriver.Driver {
d, err := Init(dir, nil, nil, nil) d, err := Init(dir, nil, idtools.IdentityMapping{})
if err != nil { if err != nil {
if err == graphdriver.ErrNotSupported { if err == graphdriver.ErrNotSupported {
t.Skip(err) t.Skip(err)

View File

@ -50,7 +50,7 @@ type btrfsOptions struct {
// Init returns a new BTRFS driver. // Init returns a new BTRFS driver.
// An error is returned if BTRFS is not supported. // An error is returned if BTRFS is not supported.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
// Perform feature detection on /var/lib/docker/btrfs if it's an existing directory. // Perform feature detection on /var/lib/docker/btrfs if it's an existing directory.
// This covers situations where /var/lib/docker/btrfs is a mount, and on a different // This covers situations where /var/lib/docker/btrfs is a mount, and on a different
@ -70,11 +70,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, graphdriver.ErrPrerequisites return nil, graphdriver.ErrPrerequisites
} }
remappedRoot := idtools.NewIDMappingsFromMaps(uidMaps, gidMaps)
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: remappedRoot.RootPair().GID, GID: idMap.RootPair().GID,
} }
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
@ -97,8 +96,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
driver := &Driver{ driver := &Driver{
home: home, home: home,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
options: opt, options: opt,
} }
@ -108,7 +106,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
} }
} }
return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(driver, driver.idMap), nil
} }
func parseOptions(opt []string) (btrfsOptions, bool, error) { func parseOptions(opt []string) (btrfsOptions, bool, error) {
@ -139,8 +137,7 @@ func parseOptions(opt []string) (btrfsOptions, bool, error) {
type Driver struct { type Driver struct {
// root of the file system // root of the file system
home string home string
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
options btrfsOptions options btrfsOptions
quotaEnabled bool quotaEnabled bool
once sync.Once once sync.Once
@ -490,15 +487,12 @@ func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts
func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
quotas := path.Join(d.home, "quotas") quotas := path.Join(d.home, "quotas")
subvolumes := path.Join(d.home, "subvolumes") subvolumes := path.Join(d.home, "subvolumes")
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil {
return err
}
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: rootGID, GID: root.GID,
} }
if err := idtools.MkdirAllAndChown(subvolumes, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(subvolumes, 0710, dirID); err != nil {
@ -546,8 +540,8 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
// if we have a remapped root (user namespaces enabled), change the created snapshot // if we have a remapped root (user namespaces enabled), change the created snapshot
// dir ownership to match // dir ownership to match
if rootUID != 0 || rootGID != 0 { if root.UID != 0 || root.GID != 0 {
if err := os.Chown(path.Join(subvolumes, id), rootUID, rootGID); err != nil { if err := root.Chown(path.Join(subvolumes, id)); err != nil {
return err return err
} }
} }

View File

@ -117,8 +117,7 @@ type DeviceSet struct {
BaseDeviceFilesystem string // save filesystem of base device BaseDeviceFilesystem string // save filesystem of base device
nrDeletedDevices uint // number of deleted devices nrDeletedDevices uint // number of deleted devices
deletionWorkerTicker *time.Ticker deletionWorkerTicker *time.Ticker
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
minFreeSpacePercent uint32 // min free space percentage in thinpool minFreeSpacePercent uint32 // min free space percentage in thinpool
xfsNospaceRetries string // max retries when xfs receives ENOSPC xfsNospaceRetries string // max retries when xfs receives ENOSPC
lvmSetupConfig directLVMConfig lvmSetupConfig directLVMConfig
@ -264,11 +263,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
dirname := devices.loopbackDir() dirname := devices.loopbackDir()
filename := path.Join(dirname, name) filename := path.Join(dirname, name)
uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps) if err := idtools.MkdirAllAndChown(dirname, 0700, devices.idMap.RootPair()); err != nil {
if err != nil {
return "", err
}
if err := idtools.MkdirAllAndChown(dirname, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
return "", err return "", err
} }
@ -1694,11 +1689,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
// create the root dir of the devmapper driver ownership to match this // create the root dir of the devmapper driver ownership to match this
// daemon's remapped root uid/gid so containers can start properly // daemon's remapped root uid/gid so containers can start properly
uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps) if err := idtools.MkdirAndChown(devices.root, 0700, devices.idMap.RootPair()); err != nil {
if err != nil {
return err
}
if err := idtools.MkdirAndChown(devices.root, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
return err return err
} }
if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil { if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil {
@ -2622,7 +2613,7 @@ func (devices *DeviceSet) exportDeviceMetadata(hash string) (*deviceMetadata, er
} }
// NewDeviceSet creates the device set based on the options provided. // NewDeviceSet creates the device set based on the options provided.
func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps []idtools.IDMap) (*DeviceSet, error) { func NewDeviceSet(root string, doInit bool, options []string, idMap idtools.IdentityMapping) (*DeviceSet, error) {
devicemapper.SetDevDir("/dev") devicemapper.SetDevDir("/dev")
devices := &DeviceSet{ devices := &DeviceSet{
@ -2636,8 +2627,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
thinpBlockSize: defaultThinpBlockSize, thinpBlockSize: defaultThinpBlockSize,
deviceIDMap: make([]byte, deviceIDMapSz), deviceIDMap: make([]byte, deviceIDMapSz),
deletionWorkerTicker: time.NewTicker(time.Second * 30), deletionWorkerTicker: time.NewTicker(time.Second * 30),
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
minFreeSpacePercent: defaultMinFreeSpacePercent, minFreeSpacePercent: defaultMinFreeSpacePercent,
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/daemon/graphdriver/graphtest" "github.com/docker/docker/daemon/graphdriver/graphtest"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/parsers/kernel"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -115,7 +116,7 @@ func testChangeLoopBackSize(t *testing.T, delta, expectDataSize, expectMetaDataS
d, err := Init(driver.home, []string{ d, err := Init(driver.home, []string{
fmt.Sprintf("dm.loopdatasize=%d", defaultDataLoopbackSize+delta), fmt.Sprintf("dm.loopdatasize=%d", defaultDataLoopbackSize+delta),
fmt.Sprintf("dm.loopmetadatasize=%d", defaultMetaDataLoopbackSize+delta), fmt.Sprintf("dm.loopmetadatasize=%d", defaultMetaDataLoopbackSize+delta),
}, nil, nil) }, idtools.IdentityMapping{})
if err != nil { if err != nil {
t.Fatalf("error creating devicemapper driver: %v", err) t.Fatalf("error creating devicemapper driver: %v", err)
} }

View File

@ -27,16 +27,14 @@ func init() {
// Driver contains the device set mounted and the home directory // Driver contains the device set mounted and the home directory
type Driver struct { type Driver struct {
*DeviceSet *DeviceSet
home string home string
uidMaps []idtools.IDMap ctr *graphdriver.RefCounter
gidMaps []idtools.IDMap locker *locker.Locker
ctr *graphdriver.RefCounter
locker *locker.Locker
} }
// Init creates a driver with the given home and the set of options. // Init creates a driver with the given home and the set of options.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps) deviceSet, err := NewDeviceSet(home, true, options, idMap)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -44,13 +42,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
d := &Driver{ d := &Driver{
DeviceSet: deviceSet, DeviceSet: deviceSet,
home: home, home: home,
uidMaps: uidMaps,
gidMaps: gidMaps,
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
locker: locker.New(), locker: locker.New(),
} }
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(d, d.idMap), nil
} }
func (d *Driver) String() string { func (d *Driver) String() string {
@ -188,18 +184,14 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
return containerfs.NewLocalContainerFS(rootFs), nil return containerfs.NewLocalContainerFS(rootFs), nil
} }
uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil {
d.ctr.Decrement(mp)
return nil, err
}
// Create the target directories if they don't exist // Create the target directories if they don't exist
if err := idtools.MkdirAllAndChown(path.Join(d.home, "mnt"), 0755, idtools.Identity{UID: uid, GID: gid}); err != nil { if err := idtools.MkdirAllAndChown(path.Join(d.home, "mnt"), 0755, root); err != nil {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
return nil, err return nil, err
} }
if err := idtools.MkdirAndChown(mp, 0755, idtools.Identity{UID: uid, GID: gid}); err != nil && !os.IsExist(err) { if err := idtools.MkdirAndChown(mp, 0755, root); err != nil && !os.IsExist(err) {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
return nil, err return nil, err
} }
@ -210,7 +202,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
return nil, err return nil, err
} }
if err := idtools.MkdirAllAndChown(rootFs, 0755, idtools.Identity{UID: uid, GID: gid}); err != nil { if err := idtools.MkdirAllAndChown(rootFs, 0755, root); err != nil {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
d.DeviceSet.UnmountDevice(id, mp) d.DeviceSet.UnmountDevice(id, mp)
return nil, err return nil, err

View File

@ -37,7 +37,7 @@ type CreateOpts struct {
} }
// InitFunc initializes the storage driver. // InitFunc initializes the storage driver.
type InitFunc func(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) type InitFunc func(root string, options []string, idMap idtools.IdentityMapping) (Driver, error)
// ProtoDriver defines the basic capabilities of a driver. // ProtoDriver defines the basic capabilities of a driver.
// This interface exists solely to be a minimum set of methods // This interface exists solely to be a minimum set of methods
@ -162,7 +162,7 @@ func Register(name string, initFunc InitFunc) error {
// GetDriver initializes and returns the registered driver // GetDriver initializes and returns the registered driver
func GetDriver(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) { func GetDriver(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
if initFunc, exists := drivers[name]; exists { if initFunc, exists := drivers[name]; exists {
return initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) return initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.IDMap)
} }
pluginDriver, err := lookupPlugin(name, pg, config) pluginDriver, err := lookupPlugin(name, pg, config)
@ -174,9 +174,9 @@ func GetDriver(name string, pg plugingetter.PluginGetter, config Options) (Drive
} }
// getBuiltinDriver initializes and returns the registered driver, but does not try to load from plugins // getBuiltinDriver initializes and returns the registered driver, but does not try to load from plugins
func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) { func getBuiltinDriver(name, home string, options []string, idMap idtools.IdentityMapping) (Driver, error) {
if initFunc, exists := drivers[name]; exists { if initFunc, exists := drivers[name]; exists {
return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps) return initFunc(filepath.Join(home, name), options, idMap)
} }
logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home) logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home)
return nil, ErrNotSupported return nil, ErrNotSupported
@ -186,8 +186,7 @@ func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []id
type Options struct { type Options struct {
Root string Root string
DriverOptions []string DriverOptions []string
UIDMaps []idtools.IDMap IDMap idtools.IdentityMapping
GIDMaps []idtools.IDMap
ExperimentalEnabled bool ExperimentalEnabled bool
} }
@ -211,7 +210,7 @@ func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, err
if _, prior := driversMap[name]; prior { if _, prior := driversMap[name]; prior {
// of the state found from prior drivers, check in order of our priority // of the state found from prior drivers, check in order of our priority
// which we would prefer // which we would prefer
driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps) driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.IDMap)
if err != nil { if err != nil {
// unlike below, we will return error here, because there is prior // unlike below, we will return error here, because there is prior
// state, and now it is no longer supported/prereq/compatible, so // state, and now it is no longer supported/prereq/compatible, so
@ -240,7 +239,7 @@ func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, err
// Check for priority drivers first // Check for priority drivers first
for _, name := range list { for _, name := range list {
driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps) driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.IDMap)
if err != nil { if err != nil {
if IsDriverNotSupported(err) { if IsDriverNotSupported(err) {
continue continue
@ -258,7 +257,7 @@ func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, err
// can be selected through configuration. // can be selected through configuration.
continue continue
} }
driver, err := initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) driver, err := initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.IDMap)
if err != nil { if err != nil {
if IsDriverNotSupported(err) { if IsDriverNotSupported(err) {
continue continue

View File

@ -24,8 +24,7 @@ var (
// Notably, the AUFS driver doesn't need to be wrapped like this. // Notably, the AUFS driver doesn't need to be wrapped like this.
type NaiveDiffDriver struct { type NaiveDiffDriver struct {
ProtoDriver ProtoDriver
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
} }
// NewNaiveDiffDriver returns a fully functional driver that wraps the // NewNaiveDiffDriver returns a fully functional driver that wraps the
@ -35,10 +34,9 @@ type NaiveDiffDriver struct {
// Changes(id, parent string) ([]archive.Change, error) // Changes(id, parent string) ([]archive.Change, error)
// ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) // ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error)
// DiffSize(id, parent string) (size int64, err error) // DiffSize(id, parent string) (size int64, err error)
func NewNaiveDiffDriver(driver ProtoDriver, uidMaps, gidMaps []idtools.IDMap) Driver { func NewNaiveDiffDriver(driver ProtoDriver, idMap idtools.IdentityMapping) Driver {
return &NaiveDiffDriver{ProtoDriver: driver, return &NaiveDiffDriver{ProtoDriver: driver,
uidMaps: uidMaps, idMap: idMap}
gidMaps: gidMaps}
} }
// Diff produces an archive of the changes between the specified // Diff produces an archive of the changes between the specified
@ -84,7 +82,7 @@ func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch io.ReadCloser, err err
return nil, err return nil, err
} }
archive, err := archive.ExportChanges(layerFs, changes, gdw.uidMaps, gdw.gidMaps) archive, err := archive.ExportChanges(layerFs, changes, gdw.idMap)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -142,8 +140,7 @@ func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, diff io.Reader) (size i
defer driver.Put(id) defer driver.Put(id)
layerFs := layerRootFs.Path() layerFs := layerRootFs.Path()
options := &archive.TarOptions{UIDMaps: gdw.uidMaps, options := &archive.TarOptions{IDMap: gdw.idMap}
GIDMaps: gdw.gidMaps}
start := time.Now().UTC() start := time.Now().UTC()
logrus.WithField("id", id).Debug("Start untar layer") logrus.WithField("id", id).Debug("Start untar layer")
if size, err = ApplyUncompressedLayer(layerFs, diff, options); err != nil { if size, err = ApplyUncompressedLayer(layerFs, diff, options); err != nil {

View File

@ -60,8 +60,7 @@ const (
// mounts that are created using this driver. // mounts that are created using this driver.
type Driver struct { type Driver struct {
home string home string
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
naiveDiff graphdriver.DiffDriver naiveDiff graphdriver.DiffDriver
locker *locker.Locker locker *locker.Locker
@ -78,7 +77,7 @@ func init() {
// Init returns the naive diff driver for fuse-overlayfs. // Init returns the naive diff driver for fuse-overlayfs.
// If fuse-overlayfs is not supported on the host, the error // If fuse-overlayfs is not supported on the host, the error
// graphdriver.ErrNotSupported is returned. // graphdriver.ErrNotSupported is returned.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
if _, err := exec.LookPath(binary); err != nil { if _, err := exec.LookPath(binary); err != nil {
logger.Error(err) logger.Error(err)
return nil, graphdriver.ErrNotSupported return nil, graphdriver.ErrNotSupported
@ -87,11 +86,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, graphdriver.ErrNotSupported return nil, graphdriver.ErrNotSupported
} }
remappedRoot := idtools.NewIDMappingsFromMaps(uidMaps, gidMaps)
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: remappedRoot.RootPair().GID, GID: idMap.RootPair().GID,
} }
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
@ -102,14 +100,13 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
} }
d := &Driver{ d := &Driver{
home: home, home: home,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps, ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicFUSE)),
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicFUSE)), locker: locker.New(),
locker: locker.New(),
} }
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps) d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, idMap)
return d, nil return d, nil
} }
@ -175,22 +172,12 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) { func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) {
dir := d.dir(id) dir := d.dir(id)
root := d.idMap.RootPair()
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) if err := idtools.MkdirAllAndChown(path.Dir(dir), 0710, root); err != nil {
if err != nil {
return err return err
} }
root := idtools.Identity{UID: rootUID, GID: rootGID} if err := idtools.MkdirAndChown(dir, 0710, root); err != nil {
dirID := idtools.Identity{
UID: rootUID,
GID: rootGID,
}
if err := idtools.MkdirAllAndChown(path.Dir(dir), 0710, dirID); err != nil {
return err
}
if err := idtools.MkdirAndChown(dir, 0710, dirID); err != nil {
return err return err
} }
@ -224,7 +211,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
return nil return nil
} }
if err := idtools.MkdirAndChown(path.Join(dir, workDirName), 0710, dirID); err != nil { if err := idtools.MkdirAndChown(path.Join(dir, workDirName), 0710, root); err != nil {
return err return err
} }
@ -377,11 +364,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
mountData := label.FormatMountLabel(opts, mountLabel) mountData := label.FormatMountLabel(opts, mountLabel)
mountTarget := mergedDir mountTarget := mergedDir
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) if err := idtools.MkdirAndChown(mergedDir, 0700, d.idMap.RootPair()); err != nil {
if err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
return nil, err return nil, err
} }
@ -477,8 +460,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
logger.Debugf("Applying tar in %s", applyDir) logger.Debugf("Applying tar in %s", applyDir)
// Overlay doesn't need the parent id to apply the diff // Overlay doesn't need the parent id to apply the diff
if err := untar(diff, applyDir, &archive.TarOptions{ if err := untar(diff, applyDir, &archive.TarOptions{
UIDMaps: d.uidMaps, IDMap: d.idMap,
GIDMaps: d.gidMaps,
// Use AUFS whiteout format: https://github.com/containers/storage/blob/39a8d5ed9843844eafb5d2ba6e6a7510e0126f40/drivers/overlay/overlay.go#L1084-L1089 // Use AUFS whiteout format: https://github.com/containers/storage/blob/39a8d5ed9843844eafb5d2ba6e6a7510e0126f40/drivers/overlay/overlay.go#L1084-L1089
WhiteoutFormat: archive.AUFSWhiteoutFormat, WhiteoutFormat: archive.AUFSWhiteoutFormat,
InUserNS: userns.RunningInUserNS(), InUserNS: userns.RunningInUserNS(),

View File

@ -50,9 +50,9 @@ type naiveDiffDriverWithApply struct {
} }
// NaiveDiffDriverWithApply returns a NaiveDiff driver with custom ApplyDiff. // NaiveDiffDriverWithApply returns a NaiveDiff driver with custom ApplyDiff.
func NaiveDiffDriverWithApply(driver ApplyDiffProtoDriver, uidMaps, gidMaps []idtools.IDMap) graphdriver.Driver { func NaiveDiffDriverWithApply(driver ApplyDiffProtoDriver, idMap idtools.IdentityMapping) graphdriver.Driver {
return &naiveDiffDriverWithApply{ return &naiveDiffDriverWithApply{
Driver: graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), Driver: graphdriver.NewNaiveDiffDriver(driver, idMap),
applyDiff: driver, applyDiff: driver,
} }
} }
@ -99,8 +99,7 @@ type overlayOptions struct{}
// Driver contains information about the home directory and the list of active mounts that are created using this driver. // Driver contains information about the home directory and the list of active mounts that are created using this driver.
type Driver struct { type Driver struct {
home string home string
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
supportsDType bool supportsDType bool
locker *locker.Locker locker *locker.Locker
@ -115,7 +114,7 @@ func init() {
// graphdriver.ErrNotSupported is returned. // graphdriver.ErrNotSupported is returned.
// If an overlay filesystem is not supported over an existing filesystem then // If an overlay filesystem is not supported over an existing filesystem then
// error graphdriver.ErrIncompatibleFS is returned. // error graphdriver.ErrIncompatibleFS is returned.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
_, err := parseOptions(options) _, err := parseOptions(options)
if err != nil { if err != nil {
return nil, err return nil, err
@ -156,13 +155,9 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
} }
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: rootGID, GID: idMap.RootPair().GID,
} }
// Create the driver home dir // Create the driver home dir
@ -171,14 +166,13 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
} }
d := &Driver{ d := &Driver{
home: home, home: home,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)), ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
supportsDType: supportsDType, supportsDType: supportsDType,
locker: locker.New(), locker: locker.New(),
} }
return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil return NaiveDiffDriverWithApply(d, d.idMap), nil
} }
func parseOptions(options []string) (*overlayOptions, error) { func parseOptions(options []string) (*overlayOptions, error) {
@ -262,17 +256,12 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
} }
dir := d.dir(id) dir := d.dir(id)
root := d.idMap.RootPair()
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return err
}
root := idtools.Identity{UID: rootUID, GID: rootGID}
currentID := idtools.CurrentIdentity() currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: currentID.UID, UID: currentID.UID,
GID: rootGID, GID: root.GID,
} }
if err := idtools.MkdirAndChown(dir, 0710, dirID); err != nil { if err := idtools.MkdirAndChown(dir, 0710, dirID); err != nil {
return err return err
@ -388,11 +377,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil { if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
return nil, err return nil, err
} }
var ( var (
@ -406,7 +392,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
} }
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
// user namespace requires this to move a directory from lower to upper. // user namespace requires this to move a directory from lower to upper.
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { if err := root.Chown(path.Join(workDir, "work")); err != nil {
return nil, err return nil, err
} }
return containerfs.NewLocalContainerFS(mergedDir), nil return containerfs.NewLocalContainerFS(mergedDir), nil
@ -483,7 +469,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
return 0, err return 0, err
} }
options := &archive.TarOptions{UIDMaps: d.uidMaps, GIDMaps: d.gidMaps} options := &archive.TarOptions{IDMap: d.idMap}
if size, err = graphdriver.ApplyUncompressedLayer(tmpRootDir, diff, options); err != nil { if size, err = graphdriver.ApplyUncompressedLayer(tmpRootDir, diff, options); err != nil {
return 0, err return 0, err
} }

View File

@ -93,8 +93,7 @@ type overlayOptions struct {
// mounts that are created using this driver. // mounts that are created using this driver.
type Driver struct { type Driver struct {
home string home string
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
quotaCtl *quota.Control quotaCtl *quota.Control
options overlayOptions options overlayOptions
@ -124,7 +123,7 @@ func init() {
// graphdriver.ErrNotSupported is returned. // graphdriver.ErrNotSupported is returned.
// If an overlay filesystem is not supported over an existing filesystem then // If an overlay filesystem is not supported over an existing filesystem then
// the error graphdriver.ErrIncompatibleFS is returned. // the error graphdriver.ErrIncompatibleFS is returned.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
opts, err := parseOptions(options) opts, err := parseOptions(options)
if err != nil { if err != nil {
return nil, err return nil, err
@ -164,15 +163,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
logger.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs)) logger.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs))
} }
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
cur := idtools.CurrentIdentity() cur := idtools.CurrentIdentity()
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: cur.UID, UID: cur.UID,
GID: rootGID, GID: idMap.RootPair().GID,
} }
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
return nil, err return nil, err
@ -183,15 +177,14 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
d := &Driver{ d := &Driver{
home: home, home: home,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)), ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
supportsDType: supportsDType, supportsDType: supportsDType,
locker: locker.New(), locker: locker.New(),
options: *opts, options: *opts,
} }
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps) d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, idMap)
if backingFs == "xfs" { if backingFs == "xfs" {
// Try to enable project quota support over xfs. // Try to enable project quota support over xfs.
@ -351,14 +344,10 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) { func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) {
dir := d.dir(id) dir := d.dir(id)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil {
return err
}
root := idtools.Identity{UID: rootUID, GID: rootGID}
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID, UID: idtools.CurrentIdentity().UID,
GID: rootGID, GID: root.GID,
} }
if err := idtools.MkdirAllAndChown(path.Dir(dir), 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(path.Dir(dir), 0710, dirID); err != nil {
@ -580,11 +569,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
mount := unix.Mount mount := unix.Mount
mountTarget := mergedDir mountTarget := mergedDir
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil { if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
return nil, err return nil, err
} }
@ -618,7 +604,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
if !readonly { if !readonly {
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
// user namespace requires this to move a directory from lower to upper. // user namespace requires this to move a directory from lower to upper.
if err := os.Chown(path.Join(workDir, workDirName), rootUID, rootGID); err != nil { if err := root.Chown(path.Join(workDir, workDirName)); err != nil {
return nil, err return nil, err
} }
} }
@ -702,8 +688,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
logger.Debugf("Applying tar in %s", applyDir) logger.Debugf("Applying tar in %s", applyDir)
// Overlay doesn't need the parent id to apply the diff // Overlay doesn't need the parent id to apply the diff
if err := untar(diff, applyDir, &archive.TarOptions{ if err := untar(diff, applyDir, &archive.TarOptions{
UIDMaps: d.uidMaps, IDMap: d.idMap,
GIDMaps: d.gidMaps,
WhiteoutFormat: archive.OverlayWhiteoutFormat, WhiteoutFormat: archive.OverlayWhiteoutFormat,
}); err != nil { }); err != nil {
return 0, err return 0, err
@ -740,8 +725,7 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) {
logger.Debugf("Tar with options on %s", diffPath) logger.Debugf("Tar with options on %s", diffPath)
return archive.TarWithOptions(diffPath, &archive.TarOptions{ return archive.TarWithOptions(diffPath, &archive.TarOptions{
Compression: archive.Uncompressed, Compression: archive.Uncompressed,
UIDMaps: d.uidMaps, IDMap: d.idMap,
GIDMaps: d.gidMaps,
WhiteoutFormat: archive.OverlayWhiteoutFormat, WhiteoutFormat: archive.OverlayWhiteoutFormat,
}) })
} }

View File

@ -51,5 +51,5 @@ func newPluginDriver(name string, pl plugingetter.CompatPlugin, config Options)
return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", pt)) return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", pt))
} }
return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.IDMap)
} }

View File

@ -38,13 +38,12 @@ type graphDriverResponse struct {
} }
type graphDriverInitRequest struct { type graphDriverInitRequest struct {
Home string Home string
Opts []string `json:"Opts"` Opts []string `json:"Opts"`
UIDMaps []idtools.IDMap `json:"UIDMaps"` idtools.IdentityMapping
GIDMaps []idtools.IDMap `json:"GIDMaps"`
} }
func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []idtools.IDMap) error { func (d *graphDriverProxy) Init(home string, opts []string, idMap idtools.IdentityMapping) error {
if !d.p.IsV1() { if !d.p.IsV1() {
if cp, ok := d.p.(plugingetter.CountedPlugin); ok { if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
// always acquire here, it will be cleaned up on daemon shutdown // always acquire here, it will be cleaned up on daemon shutdown
@ -52,10 +51,9 @@ func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []i
} }
} }
args := &graphDriverInitRequest{ args := &graphDriverInitRequest{
Home: home, Home: home,
Opts: opts, Opts: opts,
UIDMaps: uidMaps, IdentityMapping: idMap,
GIDMaps: gidMaps,
} }
var ret graphDriverResponse var ret graphDriverResponse
if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil { if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {

View File

@ -0,0 +1,43 @@
package graphdriver // import "github.com/docker/docker/daemon/graphdriver"
import (
"encoding/json"
"testing"
"github.com/docker/docker/pkg/idtools"
"gotest.tools/v3/assert"
)
func TestGraphDriverInitRequestIsCompatible(t *testing.T) {
// Graph driver plugins may unmarshal into this version of the init
// request struct. Verify that the serialization of
// graphDriverInitRequest is fully backwards compatible.
type graphDriverInitRequestV1 struct {
Home string
Opts []string `json:"Opts"`
UIDMaps []idtools.IDMap `json:"UIDMaps"`
GIDMaps []idtools.IDMap `json:"GIDMaps"`
}
args := graphDriverInitRequest{
Home: "homedir",
Opts: []string{"option1", "option2"},
IdentityMapping: idtools.IdentityMapping{
UIDMaps: []idtools.IDMap{{ContainerID: 123, HostID: 456, Size: 42}},
GIDMaps: []idtools.IDMap{{ContainerID: 789, HostID: 1011, Size: 16}},
},
}
v, err := json.Marshal(&args)
assert.NilError(t, err)
var got graphDriverInitRequestV1
assert.NilError(t, json.Unmarshal(v, &got))
want := graphDriverInitRequestV1{
Home: args.Home,
Opts: args.Opts,
UIDMaps: args.UIDMaps,
GIDMaps: args.GIDMaps,
}
assert.DeepEqual(t, got, want)
}

View File

@ -3,8 +3,11 @@
package vfs // import "github.com/docker/docker/daemon/graphdriver/vfs" package vfs // import "github.com/docker/docker/daemon/graphdriver/vfs"
import "github.com/docker/docker/pkg/chrootarchive" import (
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/idtools"
)
func dirCopy(srcDir, dstDir string) error { func dirCopy(srcDir, dstDir string) error {
return chrootarchive.NewArchiver(nil).CopyWithTar(srcDir, dstDir) return chrootarchive.NewArchiver(idtools.IdentityMapping{}).CopyWithTar(srcDir, dstDir)
} }

View File

@ -27,23 +27,19 @@ func init() {
// Init returns a new VFS driver. // Init returns a new VFS driver.
// This sets the home directory for the driver and returns NaiveDiffDriver. // This sets the home directory for the driver and returns NaiveDiffDriver.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
d := &Driver{ d := &Driver{
home: home, home: home,
idMapping: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), idMapping: idMap,
} }
if err := d.parseOptions(options); err != nil { if err := d.parseOptions(options); err != nil {
return nil, err return nil, err
} }
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID, UID: idtools.CurrentIdentity().UID,
GID: rootGID, GID: d.idMapping.RootPair().GID,
} }
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
return nil, err return nil, err
@ -55,7 +51,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, quota.ErrQuotaNotSupported return nil, quota.ErrQuotaNotSupported
} }
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(d, d.idMapping), nil
} }
// Driver holds information about the driver, home directory of the driver. // Driver holds information about the driver, home directory of the driver.
@ -65,7 +61,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
type Driver struct { type Driver struct {
driverQuota driverQuota
home string home string
idMapping *idtools.IdentityMapping idMapping idtools.IdentityMapping
} }
func (d *Driver) String() string { func (d *Driver) String() string {

View File

@ -97,7 +97,7 @@ type Driver struct {
} }
// InitFilter returns a new Windows storage filter driver. // InitFilter returns a new Windows storage filter driver.
func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func InitFilter(home string, options []string, _ idtools.IdentityMapping) (graphdriver.Driver, error) {
logrus.Debugf("WindowsGraphDriver InitFilter at %s", home) logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
fsType, err := getFileSystemType(string(home[0])) fsType, err := getFileSystemType(string(home[0]))

View File

@ -47,7 +47,7 @@ func (*Logger) Log(cmd []string) {
// Init returns a new ZFS driver. // Init returns a new ZFS driver.
// It takes base mount path and an array of options which are represented as key value pairs. // It takes base mount path and an array of options which are represented as key value pairs.
// Each option is in the for key=value. 'zfs.fsname' is expected to be a valid key in the options. // Each option is in the for key=value. 'zfs.fsname' is expected to be a valid key in the options.
func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { func Init(base string, opt []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
var err error var err error
logger := logrus.WithField("storage-driver", "zfs") logger := logrus.WithField("storage-driver", "zfs")
@ -106,14 +106,9 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
return nil, fmt.Errorf("BUG: zfs get all -t filesystem -rHp '%s' should contain '%s'", options.fsName, options.fsName) return nil, fmt.Errorf("BUG: zfs get all -t filesystem -rHp '%s' should contain '%s'", options.fsName, options.fsName)
} }
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{ dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID, UID: idtools.CurrentIdentity().UID,
GID: rootGID, GID: idMap.RootPair().GID,
} }
if err := idtools.MkdirAllAndChown(base, 0710, dirID); err != nil { if err := idtools.MkdirAllAndChown(base, 0710, dirID); err != nil {
return nil, fmt.Errorf("Failed to create '%s': %v", base, err) return nil, fmt.Errorf("Failed to create '%s': %v", base, err)
@ -123,12 +118,11 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
dataset: rootDataset, dataset: rootDataset,
options: options, options: options,
filesystemsCache: filesystemsCache, filesystemsCache: filesystemsCache,
uidMaps: uidMaps, idMap: idMap,
gidMaps: gidMaps,
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
locker: locker.New(), locker: locker.New(),
} }
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(d, idMap), nil
} }
func parseOptions(opt []string) (zfsOptions, error) { func parseOptions(opt []string) (zfsOptions, error) {
@ -181,8 +175,7 @@ type Driver struct {
options zfsOptions options zfsOptions
sync.Mutex // protects filesystem cache against concurrent access sync.Mutex // protects filesystem cache against concurrent access
filesystemsCache map[string]bool filesystemsCache map[string]bool
uidMaps []idtools.IDMap idMap idtools.IdentityMapping
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
locker *locker.Locker locker *locker.Locker
} }
@ -395,12 +388,9 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
options := label.FormatMountLabel("", mountLabel) options := label.FormatMountLabel("", mountLabel)
logrus.WithField("storage-driver", "zfs").Debugf(`mount("%s", "%s", "%s")`, filesystem, mountpoint, options) logrus.WithField("storage-driver", "zfs").Debugf(`mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) root := d.idMap.RootPair()
if err != nil {
return nil, err
}
// Create the target directories if they don't exist // Create the target directories if they don't exist
if err := idtools.MkdirAllAndChown(mountpoint, 0755, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { if err := idtools.MkdirAllAndChown(mountpoint, 0755, root); err != nil {
return nil, err return nil, err
} }
@ -410,7 +400,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
// this could be our first mount after creation of the filesystem, and the root dir may still have root // this could be our first mount after creation of the filesystem, and the root dir may still have root
// permissions instead of the remapped root uid:gid (if user namespaces are enabled): // permissions instead of the remapped root uid:gid (if user namespaces are enabled):
if err := os.Chown(mountpoint, rootUID, rootGID); err != nil { if err := root.Chown(mountpoint); err != nil {
return nil, fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) return nil, fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
} }

View File

@ -227,13 +227,13 @@ func WithNamespaces(daemon *Daemon, c *container.Container) coci.SpecOpts {
userNS := false userNS := false
// user // user
if c.HostConfig.UsernsMode.IsPrivate() { if c.HostConfig.UsernsMode.IsPrivate() {
uidMap := daemon.idMapping.UIDs() uidMap := daemon.idMapping.UIDMaps
if uidMap != nil { if uidMap != nil {
userNS = true userNS = true
ns := specs.LinuxNamespace{Type: "user"} ns := specs.LinuxNamespace{Type: "user"}
setNamespace(s, ns) setNamespace(s, ns)
s.Linux.UIDMappings = specMapping(uidMap) s.Linux.UIDMappings = specMapping(uidMap)
s.Linux.GIDMappings = specMapping(daemon.idMapping.GIDs()) s.Linux.GIDMappings = specMapping(daemon.idMapping.GIDMaps)
} }
} }
// network // network
@ -689,7 +689,7 @@ func WithMounts(daemon *Daemon, c *container.Container) coci.SpecOpts {
// TODO: until a kernel/mount solution exists for handling remount in a user namespace, // TODO: until a kernel/mount solution exists for handling remount in a user namespace,
// we must clear the readonly flag for the cgroups mount (@mrunalp concurs) // we must clear the readonly flag for the cgroups mount (@mrunalp concurs)
if uidMap := daemon.idMapping.UIDs(); uidMap != nil || c.HostConfig.Privileged { if uidMap := daemon.idMapping.UIDMaps; uidMap != nil || c.HostConfig.Privileged {
for i, m := range s.Mounts { for i, m := range s.Mounts {
if m.Type == "cgroup" { if m.Type == "cgroup" {
clearReadOnly(&s.Mounts[i]) clearReadOnly(&s.Mounts[i])

View File

@ -11,7 +11,6 @@ import (
"github.com/docker/docker/daemon/network" "github.com/docker/docker/daemon/network"
"github.com/docker/docker/libnetwork" "github.com/docker/docker/libnetwork"
"github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/containerfs"
"github.com/docker/docker/pkg/idtools"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip" "gotest.tools/v3/skip"
@ -31,7 +30,6 @@ func setupFakeDaemon(t *testing.T, c *container.Container) *Daemon {
d := &Daemon{ d := &Daemon{
// some empty structs to avoid getting a panic // some empty structs to avoid getting a panic
// caused by a null pointer dereference // caused by a null pointer dereference
idMapping: &idtools.IdentityMapping{},
configStore: &config.Config{}, configStore: &config.Config{},
linkIndex: newLinkIndex(), linkIndex: newLinkIndex(),
netController: netController, netController: netController,

View File

@ -49,7 +49,7 @@ func TestRemoveImageGarbageCollector(t *testing.T) {
MetadataStorePathTemplate: filepath.Join(d.RootDir(), "image", "%s", "layerdb"), MetadataStorePathTemplate: filepath.Join(d.RootDir(), "image", "%s", "layerdb"),
GraphDriver: d.StorageDriver(), GraphDriver: d.StorageDriver(),
GraphDriverOptions: nil, GraphDriverOptions: nil,
IDMapping: &idtools.IdentityMapping{}, IDMapping: idtools.IdentityMapping{},
PluginGetter: nil, PluginGetter: nil,
ExperimentalEnabled: false, ExperimentalEnabled: false,
}) })

View File

@ -19,6 +19,7 @@ import (
"github.com/docker/docker/integration/internal/container" "github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/requirement" "github.com/docker/docker/integration/internal/requirement"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/plugins"
"github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/daemon"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
@ -146,9 +147,9 @@ func setupPlugin(t *testing.T, ec map[string]*graphEventsCounter, ext string, mu
base, err := os.MkdirTemp("", name) base, err := os.MkdirTemp("", name)
assert.NilError(t, err) assert.NilError(t, err)
vfsProto, err := vfs.Init(base, []string{}, nil, nil) vfsProto, err := vfs.Init(base, []string{}, idtools.IdentityMapping{})
assert.NilError(t, err, "error initializing graph driver") assert.NilError(t, err, "error initializing graph driver")
driver := graphdriver.NewNaiveDiffDriver(vfsProto, nil, nil) driver := graphdriver.NewNaiveDiffDriver(vfsProto, idtools.IdentityMapping{})
ec[ext] = &graphEventsCounter{} ec[ext] = &graphEventsCounter{}
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {

View File

@ -48,7 +48,7 @@ type StoreOptions struct {
MetadataStorePathTemplate string MetadataStorePathTemplate string
GraphDriver string GraphDriver string
GraphDriverOptions []string GraphDriverOptions []string
IDMapping *idtools.IdentityMapping IDMapping idtools.IdentityMapping
PluginGetter plugingetter.PluginGetter PluginGetter plugingetter.PluginGetter
ExperimentalEnabled bool ExperimentalEnabled bool
} }
@ -58,8 +58,7 @@ func NewStoreFromOptions(options StoreOptions) (Store, error) {
driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{ driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
Root: options.Root, Root: options.Root,
DriverOptions: options.GraphDriverOptions, DriverOptions: options.GraphDriverOptions,
UIDMaps: options.IDMapping.UIDs(), IDMap: options.IDMapping,
GIDMaps: options.IDMapping.GIDs(),
ExperimentalEnabled: options.ExperimentalEnabled, ExperimentalEnabled: options.ExperimentalEnabled,
}) })
if err != nil { if err != nil {

View File

@ -41,7 +41,7 @@ func newVFSGraphDriver(td string) (graphdriver.Driver, error) {
}, },
} }
options := graphdriver.Options{Root: td, UIDMaps: uidMap, GIDMaps: gidMap} options := graphdriver.Options{Root: td, IDMap: idtools.IdentityMapping{UIDMaps: uidMap, GIDMaps: gidMap}}
return graphdriver.GetDriver("vfs", nil, options) return graphdriver.GetDriver("vfs", nil, options)
} }

View File

@ -40,8 +40,7 @@ type (
ExcludePatterns []string ExcludePatterns []string
Compression Compression Compression Compression
NoLchown bool NoLchown bool
UIDMaps []idtools.IDMap IDMap idtools.IdentityMapping
GIDMaps []idtools.IDMap
ChownOpts *idtools.Identity ChownOpts *idtools.Identity
IncludeSourceDir bool IncludeSourceDir bool
// WhiteoutFormat is the expected on disk format for whiteout files. // WhiteoutFormat is the expected on disk format for whiteout files.
@ -63,12 +62,12 @@ type (
// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations. // mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations.
type Archiver struct { type Archiver struct {
Untar func(io.Reader, string, *TarOptions) error Untar func(io.Reader, string, *TarOptions) error
IDMapping *idtools.IdentityMapping IDMapping idtools.IdentityMapping
} }
// NewDefaultArchiver returns a new Archiver without any IdentityMapping // NewDefaultArchiver returns a new Archiver without any IdentityMapping
func NewDefaultArchiver() *Archiver { func NewDefaultArchiver() *Archiver {
return &Archiver{Untar: Untar, IDMapping: &idtools.IdentityMapping{}} return &Archiver{Untar: Untar}
} }
// breakoutError is used to differentiate errors related to breaking out // breakoutError is used to differentiate errors related to breaking out
@ -534,7 +533,7 @@ type tarAppender struct {
// for hardlink mapping // for hardlink mapping
SeenFiles map[uint64]string SeenFiles map[uint64]string
IdentityMapping *idtools.IdentityMapping IdentityMapping idtools.IdentityMapping
ChownOpts *idtools.Identity ChownOpts *idtools.Identity
// For packing and unpacking whiteout files in the // For packing and unpacking whiteout files in the
@ -544,7 +543,7 @@ type tarAppender struct {
WhiteoutConverter tarWhiteoutConverter WhiteoutConverter tarWhiteoutConverter
} }
func newTarAppender(idMapping *idtools.IdentityMapping, writer io.Writer, chownOpts *idtools.Identity) *tarAppender { func newTarAppender(idMapping idtools.IdentityMapping, writer io.Writer, chownOpts *idtools.Identity) *tarAppender {
return &tarAppender{ return &tarAppender{
SeenFiles: make(map[uint64]string), SeenFiles: make(map[uint64]string),
TarWriter: tar.NewWriter(writer), TarWriter: tar.NewWriter(writer),
@ -860,7 +859,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
go func() { go func() {
ta := newTarAppender( ta := newTarAppender(
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), options.IDMap,
compressWriter, compressWriter,
options.ChownOpts, options.ChownOpts,
) )
@ -1044,8 +1043,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
defer pools.BufioReader32KPool.Put(trBuf) defer pools.BufioReader32KPool.Put(trBuf)
var dirs []*tar.Header var dirs []*tar.Header
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) rootIDs := options.IDMap.RootPair()
rootIDs := idMapping.RootPair()
whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS) whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS)
if err != nil { if err != nil {
return err return err
@ -1134,7 +1132,7 @@ loop:
} }
trBuf.Reset(tr) trBuf.Reset(tr)
if err := remapIDs(idMapping, hdr); err != nil { if err := remapIDs(options.IDMap, hdr); err != nil {
return err return err
} }
@ -1221,8 +1219,7 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
} }
defer archive.Close() defer archive.Close()
options := &TarOptions{ options := &TarOptions{
UIDMaps: archiver.IDMapping.UIDs(), IDMap: archiver.IDMapping,
GIDMaps: archiver.IDMapping.GIDs(),
} }
return archiver.Untar(archive, dst, options) return archiver.Untar(archive, dst, options)
} }
@ -1235,8 +1232,7 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
} }
defer archive.Close() defer archive.Close()
options := &TarOptions{ options := &TarOptions{
UIDMaps: archiver.IDMapping.UIDs(), IDMap: archiver.IDMapping,
GIDMaps: archiver.IDMapping.GIDs(),
} }
return archiver.Untar(archive, dst, options) return archiver.Untar(archive, dst, options)
} }
@ -1343,11 +1339,11 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
} }
// IdentityMapping returns the IdentityMapping of the archiver. // IdentityMapping returns the IdentityMapping of the archiver.
func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping { func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
return archiver.IDMapping return archiver.IDMapping
} }
func remapIDs(idMapping *idtools.IdentityMapping, hdr *tar.Header) error { func remapIDs(idMapping idtools.IdentityMapping, hdr *tar.Header) error {
ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid}) ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
hdr.Uid, hdr.Gid = ids.UID, ids.GID hdr.Uid, hdr.Gid = ids.UID, ids.GID
return err return err

View File

@ -791,7 +791,7 @@ func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) {
expectedGID int expectedGID int
}{ }{
{&TarOptions{ChownOpts: &idtools.Identity{UID: 1337, GID: 42}}, 1337, 42}, {&TarOptions{ChownOpts: &idtools.Identity{UID: 1337, GID: 42}}, 1337, 42},
{&TarOptions{ChownOpts: &idtools.Identity{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001}, {&TarOptions{ChownOpts: &idtools.Identity{UID: 100001, GID: 100001}, IDMap: idtools.IdentityMapping{UIDMaps: idMaps, GIDMaps: idMaps}}, 100001, 100001},
{&TarOptions{ChownOpts: &idtools.Identity{UID: 0, GID: 0}, NoLchown: false}, 0, 0}, {&TarOptions{ChownOpts: &idtools.Identity{UID: 0, GID: 0}, NoLchown: false}, 0, 0},
{&TarOptions{ChownOpts: &idtools.Identity{UID: 1, GID: 1}, NoLchown: true}, 1, 1}, {&TarOptions{ChownOpts: &idtools.Identity{UID: 1, GID: 1}, NoLchown: true}, 1, 1},
{&TarOptions{ChownOpts: &idtools.Identity{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000}, {&TarOptions{ChownOpts: &idtools.Identity{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000},

View File

@ -394,10 +394,10 @@ func ChangesSize(newDir string, changes []Change) int64 {
} }
// ExportChanges produces an Archive from the provided changes, relative to dir. // ExportChanges produces an Archive from the provided changes, relative to dir.
func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) { func ExportChanges(dir string, changes []Change, idMap idtools.IdentityMapping) (io.ReadCloser, error) {
reader, writer := io.Pipe() reader, writer := io.Pipe()
go func() { go func() {
ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil) ta := newTarAppender(idMap, writer, nil)
// this buffer is needed for the duration of this piped stream // this buffer is needed for the duration of this piped stream
defer pools.BufioWriter32KPool.Put(ta.Buffer) defer pools.BufioWriter32KPool.Put(ta.Buffer)

View File

@ -8,6 +8,8 @@ import (
"path" "path"
"sort" "sort"
"testing" "testing"
"github.com/docker/docker/pkg/idtools"
) )
func TestHardLinkOrder(t *testing.T) { func TestHardLinkOrder(t *testing.T) {
@ -60,7 +62,7 @@ func TestHardLinkOrder(t *testing.T) {
sort.Sort(changesByPath(changes)) sort.Sort(changesByPath(changes))
// ExportChanges // ExportChanges
ar, err := ExportChanges(dest, changes, nil, nil) ar, err := ExportChanges(dest, changes, idtools.IdentityMapping{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -72,7 +74,7 @@ func TestHardLinkOrder(t *testing.T) {
// reverse sort // reverse sort
sort.Sort(sort.Reverse(changesByPath(changes))) sort.Sort(sort.Reverse(changesByPath(changes)))
// ExportChanges // ExportChanges
arRev, err := ExportChanges(dest, changes, nil, nil) arRev, err := ExportChanges(dest, changes, idtools.IdentityMapping{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -14,6 +14,7 @@ import (
"time" "time"
"github.com/Microsoft/hcsshim/osversion" "github.com/Microsoft/hcsshim/osversion"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
@ -444,7 +445,7 @@ func TestApplyLayer(t *testing.T) {
changes, err := ChangesDirs(dst, src) changes, err := ChangesDirs(dst, src)
assert.NilError(t, err) assert.NilError(t, err)
layer, err := ExportChanges(dst, changes, nil, nil) layer, err := ExportChanges(dst, changes, idtools.IdentityMapping{})
assert.NilError(t, err) assert.NilError(t, err)
layerCopy, err := NewTempArchive(layer, "") layerCopy, err := NewTempArchive(layer, "")

View File

@ -9,7 +9,6 @@ import (
"runtime" "runtime"
"strings" "strings"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/pools"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -32,7 +31,6 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
if options.ExcludePatterns == nil { if options.ExcludePatterns == nil {
options.ExcludePatterns = []string{} options.ExcludePatterns = []string{}
} }
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
aufsTempdir := "" aufsTempdir := ""
aufsHardlinks := make(map[string]*tar.Header) aufsHardlinks := make(map[string]*tar.Header)
@ -192,7 +190,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
srcData = tmpFile srcData = tmpFile
} }
if err := remapIDs(idMapping, srcHdr); err != nil { if err := remapIDs(options.IDMap, srcHdr); err != nil {
return 0, err return 0, err
} }

View File

@ -20,10 +20,7 @@ func init() {
} }
// NewArchiver returns a new Archiver which uses chrootarchive.Untar // NewArchiver returns a new Archiver which uses chrootarchive.Untar
func NewArchiver(idMapping *idtools.IdentityMapping) *archive.Archiver { func NewArchiver(idMapping idtools.IdentityMapping) *archive.Archiver {
if idMapping == nil {
idMapping = &idtools.IdentityMapping{}
}
return &archive.Archiver{ return &archive.Archiver{
Untar: Untar, Untar: Untar,
IDMapping: idMapping, IDMapping: idMapping,
@ -76,8 +73,7 @@ func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions
// If dest is inside a root then directory is created within chroot by extractor. // If dest is inside a root then directory is created within chroot by extractor.
// This case is only currently used by cp. // This case is only currently used by cp.
if dest == root { if dest == root {
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) rootIDs := options.IDMap.RootPair()
rootIDs := idMapping.RootPair()
dest = filepath.Clean(dest) dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) { if _, err := os.Stat(dest); os.IsNotExist(err) {

View File

@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
"gotest.tools/v3/skip" "gotest.tools/v3/skip"
@ -22,7 +23,7 @@ func init() {
reexec.Init() reexec.Init()
} }
var chrootArchiver = NewArchiver(nil) var chrootArchiver = NewArchiver(idtools.IdentityMapping{})
func TarUntar(src, dst string) error { func TarUntar(src, dst string) error {
return chrootArchiver.TarUntar(src, dst) return chrootArchiver.TarUntar(src, dst)

View File

@ -26,7 +26,7 @@ type Archiver struct {
DstDriver Driver DstDriver Driver
Tar TarFunc Tar TarFunc
Untar UntarFunc Untar UntarFunc
IDMapping *idtools.IdentityMapping IDMapping idtools.IdentityMapping
} }
// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. // TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
@ -39,8 +39,7 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
} }
defer tarArchive.Close() defer tarArchive.Close()
options := &archive.TarOptions{ options := &archive.TarOptions{
UIDMaps: archiver.IDMapping.UIDs(), IDMap: archiver.IDMapping,
GIDMaps: archiver.IDMapping.GIDs(),
} }
return archiver.Untar(tarArchive, dst, options) return archiver.Untar(tarArchive, dst, options)
} }
@ -53,8 +52,7 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
} }
defer tarArchive.Close() defer tarArchive.Close()
options := &archive.TarOptions{ options := &archive.TarOptions{
UIDMaps: archiver.IDMapping.UIDs(), IDMap: archiver.IDMapping,
GIDMaps: archiver.IDMapping.GIDs(),
} }
return archiver.Untar(tarArchive, dst, options) return archiver.Untar(tarArchive, dst, options)
} }
@ -181,11 +179,11 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (retErr error) {
} }
// IdentityMapping returns the IdentityMapping of the archiver. // IdentityMapping returns the IdentityMapping of the archiver.
func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping { func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
return archiver.IDMapping return archiver.IDMapping
} }
func remapIDs(idMapping *idtools.IdentityMapping, hdr *tar.Header) error { func remapIDs(idMapping idtools.IdentityMapping, hdr *tar.Header) error {
ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid}) ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
hdr.Uid, hdr.Gid = ids.UID, ids.GID hdr.Uid, hdr.Gid = ids.UID, ids.GID
return err return err

View File

@ -108,70 +108,72 @@ type Identity struct {
SID string SID string
} }
// IdentityMapping contains a mappings of UIDs and GIDs // Chown changes the numeric uid and gid of the named file to id.UID and id.GID.
type IdentityMapping struct { func (id Identity) Chown(name string) error {
uids []IDMap return os.Chown(name, id.UID, id.GID)
gids []IDMap
} }
// NewIDMappingsFromMaps creates a new mapping from two slices // IdentityMapping contains a mappings of UIDs and GIDs.
// Deprecated: this is a temporary shim while transitioning to IDMapping // The zero value represents an empty mapping.
func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IdentityMapping { type IdentityMapping struct {
return &IdentityMapping{uids: uids, gids: gids} UIDMaps []IDMap `json:"UIDMaps"`
GIDMaps []IDMap `json:"GIDMaps"`
} }
// RootPair returns a uid and gid pair for the root user. The error is ignored // 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 // because a root user always exists, and the defaults are correct when the uid
// and gid maps are empty. // and gid maps are empty.
func (i *IdentityMapping) RootPair() Identity { func (i IdentityMapping) RootPair() Identity {
uid, gid, _ := GetRootUIDGID(i.uids, i.gids) uid, gid, _ := GetRootUIDGID(i.UIDMaps, i.GIDMaps)
return Identity{UID: uid, GID: gid} return Identity{UID: uid, GID: gid}
} }
// ToHost returns the host UID and GID for the container 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 // Remapping is only performed if the ids aren't already the remapped root ids
func (i *IdentityMapping) ToHost(pair Identity) (Identity, error) { func (i IdentityMapping) ToHost(pair Identity) (Identity, error) {
var err error var err error
target := i.RootPair() target := i.RootPair()
if pair.UID != target.UID { if pair.UID != target.UID {
target.UID, err = toHost(pair.UID, i.uids) target.UID, err = toHost(pair.UID, i.UIDMaps)
if err != nil { if err != nil {
return target, err return target, err
} }
} }
if pair.GID != target.GID { if pair.GID != target.GID {
target.GID, err = toHost(pair.GID, i.gids) target.GID, err = toHost(pair.GID, i.GIDMaps)
} }
return target, err return target, err
} }
// ToContainer returns the container UID and GID for the host uid and gid // ToContainer returns the container UID and GID for the host uid and gid
func (i *IdentityMapping) ToContainer(pair Identity) (int, int, error) { func (i IdentityMapping) ToContainer(pair Identity) (int, int, error) {
uid, err := toContainer(pair.UID, i.uids) uid, err := toContainer(pair.UID, i.UIDMaps)
if err != nil { if err != nil {
return -1, -1, err return -1, -1, err
} }
gid, err := toContainer(pair.GID, i.gids) gid, err := toContainer(pair.GID, i.GIDMaps)
return uid, gid, err return uid, gid, err
} }
// Empty returns true if there are no id mappings // Empty returns true if there are no id mappings
func (i *IdentityMapping) Empty() bool { func (i IdentityMapping) Empty() bool {
return len(i.uids) == 0 && len(i.gids) == 0 return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
} }
// UIDs return the UID mapping // UIDs returns the mapping for UID.
// TODO: remove this once everything has been refactored to use pairs //
func (i *IdentityMapping) UIDs() []IDMap { // Deprecated: reference the UIDMaps field directly.
return i.uids func (i IdentityMapping) UIDs() []IDMap {
return i.UIDMaps
} }
// GIDs return the UID mapping // GIDs returns the mapping for GID.
// TODO: remove this once everything has been refactored to use pairs //
func (i *IdentityMapping) GIDs() []IDMap { // Deprecated: reference the GIDMaps field directly.
return i.gids func (i IdentityMapping) GIDs() []IDMap {
return i.GIDMaps
} }
func createIDMap(subidRanges ranges) []IDMap { func createIDMap(subidRanges ranges) []IDMap {

View File

@ -240,24 +240,37 @@ func setPermissions(p string, mode os.FileMode, uid, gid int, stat *system.StatT
// NewIdentityMapping takes a requested username and // NewIdentityMapping takes a requested username and
// using the data from /etc/sub{uid,gid} ranges, creates the // using the data from /etc/sub{uid,gid} ranges, creates the
// proper uid and gid remapping ranges for that user/group pair // proper uid and gid remapping ranges for that user/group pair
//
// Deprecated: Use LoadIdentityMapping.
func NewIdentityMapping(name string) (*IdentityMapping, error) { func NewIdentityMapping(name string) (*IdentityMapping, error) {
m, err := LoadIdentityMapping(name)
if err != nil {
return nil, err
}
return &m, err
}
// 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) {
usr, err := LookupUser(name) usr, err := LookupUser(name)
if err != nil { if err != nil {
return nil, fmt.Errorf("Could not get user for username %s: %v", name, err) return IdentityMapping{}, fmt.Errorf("Could not get user for username %s: %v", name, err)
} }
subuidRanges, err := lookupSubUIDRanges(usr) subuidRanges, err := lookupSubUIDRanges(usr)
if err != nil { if err != nil {
return nil, err return IdentityMapping{}, err
} }
subgidRanges, err := lookupSubGIDRanges(usr) subgidRanges, err := lookupSubGIDRanges(usr)
if err != nil { if err != nil {
return nil, err return IdentityMapping{}, err
} }
return &IdentityMapping{ return IdentityMapping{
uids: subuidRanges, UIDMaps: subuidRanges,
gids: subgidRanges, GIDMaps: subgidRanges,
}, nil }, nil
} }

View File

@ -321,10 +321,10 @@ func TestNewIDMappings(t *testing.T) {
tempUser, err := user.Lookup(tempUser) tempUser, err := user.Lookup(tempUser)
assert.Check(t, err) assert.Check(t, err)
idMapping, err := NewIdentityMapping(tempUser.Username) idMapping, err := LoadIdentityMapping(tempUser.Username)
assert.Check(t, err) assert.Check(t, err)
rootUID, rootGID, err := GetRootUIDGID(idMapping.UIDs(), idMapping.GIDs()) rootUID, rootGID, err := GetRootUIDGID(idMapping.UIDMaps, idMapping.GIDMaps)
assert.Check(t, err) assert.Check(t, err)
dirName, err := os.MkdirTemp("", "mkdirall") dirName, err := os.MkdirTemp("", "mkdirall")