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
LayerStore layer.Store
Root string
IdentityMapping *idtools.IdentityMapping
IdentityMapping idtools.IdentityMapping
}
type graphIDRegistrar interface {
@ -100,7 +100,12 @@ func (s *snapshotter) Name() string {
}
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 {
@ -482,7 +487,7 @@ type mountable struct {
acquire func() ([]mount.Mount, func() error, error)
release func() error
refCount int
idmap *idtools.IdentityMapping
idmap idtools.IdentityMapping
}
func (m *mountable) Mount() ([]mount.Mount, func() error, error) {
@ -527,5 +532,10 @@ func (m *mountable) releaseMount() error {
}
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
BuilderConfig config.BuilderConfig
Rootless bool
IdentityMapping *idtools.IdentityMapping
IdentityMapping idtools.IdentityMapping
DNSConfig config.DNSConfig
ApparmorProfile string
}
@ -91,10 +91,6 @@ type Builder struct {
func New(opt Opt) (*Builder, error) {
reqHandler := newReqBodyHandler(tracing.DefaultTransport)
if opt.IdentityMapping != nil && opt.IdentityMapping.Empty() {
opt.IdentityMapping = nil
}
c, err := newController(reqHandler, opt)
if err != nil {
return nil, err

View file

@ -25,7 +25,7 @@ import (
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")
networkProviders := map[pb.NetMode]network.Provider{
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{
Root: filepath.Join(root, "executor"),
CommandCandidates: []string{"runc"},
DefaultCgroupParent: cgroupParent,
Rootless: rootless,
NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
IdentityMapping: idmap,
IdentityMapping: pidmap,
DNS: dnsConfig,
ApparmorProfile: apparmorProfile,
}, networkProviders)

View file

@ -11,7 +11,7 @@ import (
"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
}

View file

@ -46,13 +46,13 @@ const (
// BuildManager is shared across all Builder objects
type BuildManager struct {
idMapping *idtools.IdentityMapping
idMapping idtools.IdentityMapping
backend builder.Backend
pathCache pathCache // TODO: make this persistent
}
// 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{
backend: b,
pathCache: &syncmap.Map{},
@ -103,7 +103,7 @@ type builderOptions struct {
Backend builder.Backend
ProgressWriter backend.ProgressWriter
PathCache pathCache
IDMapping *idtools.IdentityMapping
IDMapping idtools.IdentityMapping
}
// Builder is a Dockerfile builder
@ -119,7 +119,7 @@ type Builder struct {
docker builder.Backend
clientCtx context.Context
idMapping *idtools.IdentityMapping
idMapping idtools.IdentityMapping
disableCommit bool
imageSources *imageSources
pathCache pathCache

View file

@ -33,7 +33,7 @@ type Archiver interface {
UntarPath(src, dst string) error
CopyWithTar(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

View file

@ -11,7 +11,7 @@ import (
"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
parts := strings.Split(chown, ":")
if len(parts) > 2 {

View file

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

View file

@ -14,7 +14,7 @@ import (
"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" {
return getAccountIdentity(builder, chown, ctrRootPath, state)
}

View file

@ -14,6 +14,7 @@ import (
"github.com/docker/docker/daemon/graphdriver/devmapper"
"github.com/docker/docker/pkg/devicemapper"
"github.com/docker/docker/pkg/idtools"
"github.com/sirupsen/logrus"
)
@ -76,7 +77,7 @@ func main() {
args := flag.Args()
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 {
fmt.Println("Can't initialize device mapper: ", err)
os.Exit(1)

View file

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

View file

@ -98,7 +98,7 @@ type Daemon struct {
sysInfoOnce sync.Once
sysInfo *sysinfo.SysInfo
shutdown bool
idMapping *idtools.IdentityMapping
idMapping idtools.IdentityMapping
graphDriver string // TODO: move graphDriver field to an InfoService
PluginStore *plugin.Store // TODO: remove
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
func (daemon *Daemon) IdentityMapping() *idtools.IdentityMapping {
func (daemon *Daemon) IdentityMapping() idtools.IdentityMapping {
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 initlayer.Setup(initPath, idMapping.RootPair())
}
@ -1161,9 +1161,9 @@ func parseRemappedRoot(usergrp string) (string, string, error) {
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 != "" {
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
@ -1171,25 +1171,25 @@ func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error)
if config.RemappedRoot != "" {
username, groupname, err := parseRemappedRoot(config.RemappedRoot)
if err != nil {
return nil, err
return idtools.IdentityMapping{}, err
}
if username == "root" {
// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
// effectively
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)
// update remapped root setting now that we have resolved them to actual names
config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
mappings, err := idtools.NewIdentityMapping(username)
mappings, err := idtools.LoadIdentityMapping(username)
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 &idtools.IdentityMapping{}, nil
return idtools.IdentityMapping{}, nil
}
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
}
func setupInitLayer(idMapping *idtools.IdentityMapping) func(containerfs.ContainerFS) error {
func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error {
return nil
}
@ -437,8 +437,8 @@ func recursiveUnmount(_ string) error {
return nil
}
func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) {
return &idtools.IdentityMapping{}, nil
func setupRemappedRoot(config *config.Config) (idtools.IdentityMapping, error) {
return idtools.IdentityMapping{}, nil
}
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{
Compression: archive.Uncompressed,
UIDMaps: daemon.idMapping.UIDs(),
GIDMaps: daemon.idMapping.GIDs(),
IDMap: daemon.idMapping,
}, basefs.Path())
if err != nil {
rwlayer.Unmount()

View file

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

View file

@ -15,6 +15,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/stringid"
"gotest.tools/v3/assert"
@ -31,7 +32,7 @@ func init() {
}
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 == graphdriver.ErrNotSupported {
t.Skip(err)

View file

@ -50,7 +50,7 @@ type btrfsOptions struct {
// Init returns a new BTRFS driver.
// 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.
// 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
}
remappedRoot := idtools.NewIDMappingsFromMaps(uidMaps, gidMaps)
currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{
UID: currentID.UID,
GID: remappedRoot.RootPair().GID,
GID: idMap.RootPair().GID,
}
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{
home: home,
uidMaps: uidMaps,
gidMaps: gidMaps,
idMap: idMap,
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) {
@ -139,8 +137,7 @@ func parseOptions(opt []string) (btrfsOptions, bool, error) {
type Driver struct {
// root of the file system
home string
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
idMap idtools.IdentityMapping
options btrfsOptions
quotaEnabled bool
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 {
quotas := path.Join(d.home, "quotas")
subvolumes := path.Join(d.home, "subvolumes")
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return err
}
root := d.idMap.RootPair()
currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{
UID: currentID.UID,
GID: rootGID,
GID: root.GID,
}
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
// dir ownership to match
if rootUID != 0 || rootGID != 0 {
if err := os.Chown(path.Join(subvolumes, id), rootUID, rootGID); err != nil {
if root.UID != 0 || root.GID != 0 {
if err := root.Chown(path.Join(subvolumes, id)); err != nil {
return err
}
}

View file

@ -117,8 +117,7 @@ type DeviceSet struct {
BaseDeviceFilesystem string // save filesystem of base device
nrDeletedDevices uint // number of deleted devices
deletionWorkerTicker *time.Ticker
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
idMap idtools.IdentityMapping
minFreeSpacePercent uint32 // min free space percentage in thinpool
xfsNospaceRetries string // max retries when xfs receives ENOSPC
lvmSetupConfig directLVMConfig
@ -264,11 +263,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
dirname := devices.loopbackDir()
filename := path.Join(dirname, name)
uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps)
if err != nil {
return "", err
}
if err := idtools.MkdirAllAndChown(dirname, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
if err := idtools.MkdirAllAndChown(dirname, 0700, devices.idMap.RootPair()); err != nil {
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
// daemon's remapped root uid/gid so containers can start properly
uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps)
if err != nil {
return err
}
if err := idtools.MkdirAndChown(devices.root, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
if err := idtools.MkdirAndChown(devices.root, 0700, devices.idMap.RootPair()); err != nil {
return err
}
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.
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")
devices := &DeviceSet{
@ -2636,8 +2627,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
thinpBlockSize: defaultThinpBlockSize,
deviceIDMap: make([]byte, deviceIDMapSz),
deletionWorkerTicker: time.NewTicker(time.Second * 30),
uidMaps: uidMaps,
gidMaps: gidMaps,
idMap: idMap,
minFreeSpacePercent: defaultMinFreeSpacePercent,
}

View file

@ -13,6 +13,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/daemon/graphdriver/graphtest"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/parsers/kernel"
"golang.org/x/sys/unix"
)
@ -115,7 +116,7 @@ func testChangeLoopBackSize(t *testing.T, delta, expectDataSize, expectMetaDataS
d, err := Init(driver.home, []string{
fmt.Sprintf("dm.loopdatasize=%d", defaultDataLoopbackSize+delta),
fmt.Sprintf("dm.loopmetadatasize=%d", defaultMetaDataLoopbackSize+delta),
}, nil, nil)
}, idtools.IdentityMapping{})
if err != nil {
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
type Driver struct {
*DeviceSet
home string
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter
locker *locker.Locker
home string
ctr *graphdriver.RefCounter
locker *locker.Locker
}
// 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) {
deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps)
func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdriver.Driver, error) {
deviceSet, err := NewDeviceSet(home, true, options, idMap)
if err != nil {
return nil, err
}
@ -44,13 +42,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
d := &Driver{
DeviceSet: deviceSet,
home: home,
uidMaps: uidMaps,
gidMaps: gidMaps,
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
locker: locker.New(),
}
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
return graphdriver.NewNaiveDiffDriver(d, d.idMap), nil
}
func (d *Driver) String() string {
@ -188,18 +184,14 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
return containerfs.NewLocalContainerFS(rootFs), nil
}
uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
d.ctr.Decrement(mp)
return nil, err
}
root := d.idMap.RootPair()
// 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)
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)
return nil, err
}
@ -210,7 +202,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
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.DeviceSet.UnmountDevice(id, mp)
return nil, err

View file

@ -37,7 +37,7 @@ type CreateOpts struct {
}
// 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.
// 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
func GetDriver(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
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)
@ -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
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 {
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)
return nil, ErrNotSupported
@ -186,8 +186,7 @@ func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []id
type Options struct {
Root string
DriverOptions []string
UIDMaps []idtools.IDMap
GIDMaps []idtools.IDMap
IDMap idtools.IdentityMapping
ExperimentalEnabled bool
}
@ -211,7 +210,7 @@ func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, err
if _, prior := driversMap[name]; prior {
// of the state found from prior drivers, check in order of our priority
// 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 {
// unlike below, we will return error here, because there is prior
// 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
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 IsDriverNotSupported(err) {
continue
@ -258,7 +257,7 @@ func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, err
// can be selected through configuration.
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 IsDriverNotSupported(err) {
continue

View file

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

View file

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

View file

@ -50,9 +50,9 @@ type naiveDiffDriverWithApply struct {
}
// 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{
Driver: graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps),
Driver: graphdriver.NewNaiveDiffDriver(driver, idMap),
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.
type Driver struct {
home string
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
idMap idtools.IdentityMapping
ctr *graphdriver.RefCounter
supportsDType bool
locker *locker.Locker
@ -115,7 +114,7 @@ func init() {
// graphdriver.ErrNotSupported is returned.
// If an overlay filesystem is not supported over an existing filesystem then
// 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)
if err != nil {
return nil, err
@ -156,13 +155,9 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
}
currentID := idtools.CurrentIdentity()
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{
UID: currentID.UID,
GID: rootGID,
GID: idMap.RootPair().GID,
}
// Create the driver home dir
@ -171,14 +166,13 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
}
d := &Driver{
home: home,
uidMaps: uidMaps,
gidMaps: gidMaps,
idMap: idMap,
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
supportsDType: supportsDType,
locker: locker.New(),
}
return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil
return NaiveDiffDriverWithApply(d, d.idMap), nil
}
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)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return err
}
root := idtools.Identity{UID: rootUID, GID: rootGID}
root := d.idMap.RootPair()
currentID := idtools.CurrentIdentity()
dirID := idtools.Identity{
UID: currentID.UID,
GID: rootGID,
GID: root.GID,
}
if err := idtools.MkdirAndChown(dir, 0710, dirID); err != nil {
return err
@ -388,11 +377,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
if err != nil {
return nil, err
}
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
root := d.idMap.RootPair()
if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil {
return nil, err
}
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
// 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 containerfs.NewLocalContainerFS(mergedDir), nil
@ -483,7 +469,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
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 {
return 0, err
}

View file

@ -93,8 +93,7 @@ type overlayOptions struct {
// mounts that are created using this driver.
type Driver struct {
home string
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
idMap idtools.IdentityMapping
ctr *graphdriver.RefCounter
quotaCtl *quota.Control
options overlayOptions
@ -124,7 +123,7 @@ func init() {
// graphdriver.ErrNotSupported is returned.
// If an overlay filesystem is not supported over an existing filesystem then
// 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)
if err != nil {
return nil, err
@ -164,15 +163,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
logger.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs))
}
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
cur := idtools.CurrentIdentity()
dirID := idtools.Identity{
UID: cur.UID,
GID: rootGID,
GID: idMap.RootPair().GID,
}
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
return nil, err
@ -183,15 +177,14 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
d := &Driver{
home: home,
uidMaps: uidMaps,
gidMaps: gidMaps,
idMap: idMap,
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
supportsDType: supportsDType,
locker: locker.New(),
options: *opts,
}
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps)
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, idMap)
if backingFs == "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) {
dir := d.dir(id)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return err
}
root := idtools.Identity{UID: rootUID, GID: rootGID}
root := d.idMap.RootPair()
dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID,
GID: rootGID,
GID: root.GID,
}
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
mountTarget := mergedDir
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
root := d.idMap.RootPair()
if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil {
return nil, err
}
@ -618,7 +604,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
if !readonly {
// 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.
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
}
}
@ -702,8 +688,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
logger.Debugf("Applying tar in %s", applyDir)
// Overlay doesn't need the parent id to apply the diff
if err := untar(diff, applyDir, &archive.TarOptions{
UIDMaps: d.uidMaps,
GIDMaps: d.gidMaps,
IDMap: d.idMap,
WhiteoutFormat: archive.OverlayWhiteoutFormat,
}); err != nil {
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)
return archive.TarWithOptions(diffPath, &archive.TarOptions{
Compression: archive.Uncompressed,
UIDMaps: d.uidMaps,
GIDMaps: d.gidMaps,
IDMap: d.idMap,
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 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 {
Home string
Opts []string `json:"Opts"`
UIDMaps []idtools.IDMap `json:"UIDMaps"`
GIDMaps []idtools.IDMap `json:"GIDMaps"`
Home string
Opts []string `json:"Opts"`
idtools.IdentityMapping
}
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 cp, ok := d.p.(plugingetter.CountedPlugin); ok {
// 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{
Home: home,
Opts: opts,
UIDMaps: uidMaps,
GIDMaps: gidMaps,
Home: home,
Opts: opts,
IdentityMapping: idMap,
}
var ret graphDriverResponse
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"
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 {
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.
// 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{
home: home,
idMapping: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps),
idMapping: idMap,
}
if err := d.parseOptions(options); err != nil {
return nil, err
}
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID,
GID: rootGID,
GID: d.idMapping.RootPair().GID,
}
if err := idtools.MkdirAllAndChown(home, 0710, dirID); err != nil {
return nil, err
@ -55,7 +51,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
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.
@ -65,7 +61,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
type Driver struct {
driverQuota
home string
idMapping *idtools.IdentityMapping
idMapping idtools.IdentityMapping
}
func (d *Driver) String() string {

View file

@ -97,7 +97,7 @@ type Driver struct {
}
// 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)
fsType, err := getFileSystemType(string(home[0]))

View file

@ -47,7 +47,7 @@ func (*Logger) Log(cmd []string) {
// Init returns a new ZFS driver.
// 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.
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
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)
}
_, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
}
dirID := idtools.Identity{
UID: idtools.CurrentIdentity().UID,
GID: rootGID,
GID: idMap.RootPair().GID,
}
if err := idtools.MkdirAllAndChown(base, 0710, dirID); err != nil {
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,
options: options,
filesystemsCache: filesystemsCache,
uidMaps: uidMaps,
gidMaps: gidMaps,
idMap: idMap,
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
locker: locker.New(),
}
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
return graphdriver.NewNaiveDiffDriver(d, idMap), nil
}
func parseOptions(opt []string) (zfsOptions, error) {
@ -181,8 +175,7 @@ type Driver struct {
options zfsOptions
sync.Mutex // protects filesystem cache against concurrent access
filesystemsCache map[string]bool
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
idMap idtools.IdentityMapping
ctr *graphdriver.RefCounter
locker *locker.Locker
}
@ -395,12 +388,9 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
options := label.FormatMountLabel("", mountLabel)
logrus.WithField("storage-driver", "zfs").Debugf(`mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
return nil, err
}
root := d.idMap.RootPair()
// 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
}
@ -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
// 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)
}

View file

@ -227,13 +227,13 @@ func WithNamespaces(daemon *Daemon, c *container.Container) coci.SpecOpts {
userNS := false
// user
if c.HostConfig.UsernsMode.IsPrivate() {
uidMap := daemon.idMapping.UIDs()
uidMap := daemon.idMapping.UIDMaps
if uidMap != nil {
userNS = true
ns := specs.LinuxNamespace{Type: "user"}
setNamespace(s, ns)
s.Linux.UIDMappings = specMapping(uidMap)
s.Linux.GIDMappings = specMapping(daemon.idMapping.GIDs())
s.Linux.GIDMappings = specMapping(daemon.idMapping.GIDMaps)
}
}
// 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,
// 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 {
if m.Type == "cgroup" {
clearReadOnly(&s.Mounts[i])

View file

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

View file

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

View file

@ -19,6 +19,7 @@ import (
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/requirement"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/plugins"
"github.com/docker/docker/testutil/daemon"
"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)
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")
driver := graphdriver.NewNaiveDiffDriver(vfsProto, nil, nil)
driver := graphdriver.NewNaiveDiffDriver(vfsProto, idtools.IdentityMapping{})
ec[ext] = &graphEventsCounter{}
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {

View file

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

View file

@ -40,8 +40,7 @@ type (
ExcludePatterns []string
Compression Compression
NoLchown bool
UIDMaps []idtools.IDMap
GIDMaps []idtools.IDMap
IDMap idtools.IdentityMapping
ChownOpts *idtools.Identity
IncludeSourceDir bool
// 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.
type Archiver struct {
Untar func(io.Reader, string, *TarOptions) error
IDMapping *idtools.IdentityMapping
IDMapping idtools.IdentityMapping
}
// NewDefaultArchiver returns a new Archiver without any IdentityMapping
func NewDefaultArchiver() *Archiver {
return &Archiver{Untar: Untar, IDMapping: &idtools.IdentityMapping{}}
return &Archiver{Untar: Untar}
}
// breakoutError is used to differentiate errors related to breaking out
@ -534,7 +533,7 @@ type tarAppender struct {
// for hardlink mapping
SeenFiles map[uint64]string
IdentityMapping *idtools.IdentityMapping
IdentityMapping idtools.IdentityMapping
ChownOpts *idtools.Identity
// For packing and unpacking whiteout files in the
@ -544,7 +543,7 @@ type tarAppender struct {
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{
SeenFiles: make(map[uint64]string),
TarWriter: tar.NewWriter(writer),
@ -860,7 +859,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
go func() {
ta := newTarAppender(
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps),
options.IDMap,
compressWriter,
options.ChownOpts,
)
@ -1044,8 +1043,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
defer pools.BufioReader32KPool.Put(trBuf)
var dirs []*tar.Header
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
rootIDs := idMapping.RootPair()
rootIDs := options.IDMap.RootPair()
whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS)
if err != nil {
return err
@ -1134,7 +1132,7 @@ loop:
}
trBuf.Reset(tr)
if err := remapIDs(idMapping, hdr); err != nil {
if err := remapIDs(options.IDMap, hdr); err != nil {
return err
}
@ -1221,8 +1219,7 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
}
defer archive.Close()
options := &TarOptions{
UIDMaps: archiver.IDMapping.UIDs(),
GIDMaps: archiver.IDMapping.GIDs(),
IDMap: archiver.IDMapping,
}
return archiver.Untar(archive, dst, options)
}
@ -1235,8 +1232,7 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
}
defer archive.Close()
options := &TarOptions{
UIDMaps: archiver.IDMapping.UIDs(),
GIDMaps: archiver.IDMapping.GIDs(),
IDMap: archiver.IDMapping,
}
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.
func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping {
func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
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})
hdr.Uid, hdr.Gid = ids.UID, ids.GID
return err

View file

@ -791,7 +791,7 @@ func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) {
expectedGID int
}{
{&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: 1, GID: 1}, NoLchown: true}, 1, 1},
{&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.
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()
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
defer pools.BufioWriter32KPool.Put(ta.Buffer)

View file

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

View file

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

View file

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

View file

@ -20,10 +20,7 @@ func init() {
}
// NewArchiver returns a new Archiver which uses chrootarchive.Untar
func NewArchiver(idMapping *idtools.IdentityMapping) *archive.Archiver {
if idMapping == nil {
idMapping = &idtools.IdentityMapping{}
}
func NewArchiver(idMapping idtools.IdentityMapping) *archive.Archiver {
return &archive.Archiver{
Untar: Untar,
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.
// This case is only currently used by cp.
if dest == root {
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
rootIDs := idMapping.RootPair()
rootIDs := options.IDMap.RootPair()
dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) {

View file

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

View file

@ -26,7 +26,7 @@ type Archiver struct {
DstDriver Driver
Tar TarFunc
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.
@ -39,8 +39,7 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
}
defer tarArchive.Close()
options := &archive.TarOptions{
UIDMaps: archiver.IDMapping.UIDs(),
GIDMaps: archiver.IDMapping.GIDs(),
IDMap: archiver.IDMapping,
}
return archiver.Untar(tarArchive, dst, options)
}
@ -53,8 +52,7 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
}
defer tarArchive.Close()
options := &archive.TarOptions{
UIDMaps: archiver.IDMapping.UIDs(),
GIDMaps: archiver.IDMapping.GIDs(),
IDMap: archiver.IDMapping,
}
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.
func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping {
func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
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})
hdr.Uid, hdr.Gid = ids.UID, ids.GID
return err

View file

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

View file

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