Finish refactor of UID/GID usage to a new struct
Finish the refactor which was partially completed with commit
34536c498d
, passing around IdentityMapping structs instead of pairs of
[]IDMap slices.
Existing code which uses []IDMap relies on zero-valued fields to be
valid, empty mappings. So in order to successfully finish the
refactoring without introducing bugs, their replacement therefore also
needs to have a useful zero value which represents an empty mapping.
Change IdentityMapping to be a pass-by-value type so that there are no
nil pointers to worry about.
The functionality provided by the deprecated NewIDMappingsFromMaps
function is required by unit tests to to construct arbitrary
IdentityMapping values. And the daemon will always need to access the
mappings to pass them to the Linux kernel. Accommodate these use cases
by exporting the struct fields instead. BuildKit currently depends on
the UIDs and GIDs methods so we cannot get rid of them yet.
Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
parent
16009830c2
commit
098a44c07f
51 changed files with 301 additions and 340 deletions
|
@ -31,7 +31,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 {
|
||||||
|
@ -99,7 +99,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 {
|
||||||
|
@ -481,7 +486,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) {
|
||||||
|
@ -526,5 +531,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
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,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
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,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
|
||||||
|
@ -1460,7 +1460,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1063,7 +1063,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())
|
||||||
}
|
}
|
||||||
|
@ -1162,9 +1162,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
|
||||||
|
@ -1172,25 +1172,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 {
|
||||||
|
|
|
@ -62,7 +62,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,8 +436,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 {
|
||||||
|
|
43
daemon/graphdriver/proxy_test.go
Normal file
43
daemon/graphdriver/proxy_test.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package graphdriver // import "github.com/docker/docker/daemon/graphdriver"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGraphDriverInitRequestIsCompatible(t *testing.T) {
|
||||||
|
// Graph driver plugins may unmarshal into this version of the init
|
||||||
|
// request struct. Verify that the serialization of
|
||||||
|
// graphDriverInitRequest is fully backwards compatible.
|
||||||
|
|
||||||
|
type graphDriverInitRequestV1 struct {
|
||||||
|
Home string
|
||||||
|
Opts []string `json:"Opts"`
|
||||||
|
UIDMaps []idtools.IDMap `json:"UIDMaps"`
|
||||||
|
GIDMaps []idtools.IDMap `json:"GIDMaps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
args := graphDriverInitRequest{
|
||||||
|
Home: "homedir",
|
||||||
|
Opts: []string{"option1", "option2"},
|
||||||
|
IdentityMapping: idtools.IdentityMapping{
|
||||||
|
UIDMaps: []idtools.IDMap{{ContainerID: 123, HostID: 456, Size: 42}},
|
||||||
|
GIDMaps: []idtools.IDMap{{ContainerID: 789, HostID: 1011, Size: 16}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
v, err := json.Marshal(&args)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
var got graphDriverInitRequestV1
|
||||||
|
assert.NilError(t, json.Unmarshal(v, &got))
|
||||||
|
want := graphDriverInitRequestV1{
|
||||||
|
Home: args.Home,
|
||||||
|
Opts: args.Opts,
|
||||||
|
UIDMaps: args.UIDMaps,
|
||||||
|
GIDMaps: args.GIDMaps,
|
||||||
|
}
|
||||||
|
assert.DeepEqual(t, got, want)
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -49,7 +49,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
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,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 a new issue