Merge pull request #43366 from corhere/finish-identitymapping-refactor
Finish refactor of UID/GID usage to a new struct
This commit is contained in:
commit
0a3336fd7d
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}{
|
}{
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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]))
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, "")
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Reference in New Issue