mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Partial refactor of UID/GID usage to use a unified struct.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
d2a83863ed
commit
09cd96c5ad
28 changed files with 180 additions and 141 deletions
|
@ -216,7 +216,7 @@ func (container *Container) WriteHostConfig() error {
|
|||
}
|
||||
|
||||
// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
|
||||
func (container *Container) SetupWorkingDirectory(rootUID, rootGID int) error {
|
||||
func (container *Container) SetupWorkingDirectory(rootIDs idtools.IDPair) error {
|
||||
if container.Config.WorkingDir == "" {
|
||||
return nil
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ func (container *Container) SetupWorkingDirectory(rootUID, rootGID int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := idtools.MkdirAllNewAs(pth, 0755, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChownNew(pth, 0755, rootIDs); err != nil {
|
||||
pthInfo, err2 := os.Stat(pth)
|
||||
if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
|
||||
return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
|
||||
|
|
|
@ -375,7 +375,7 @@ func (daemon *Daemon) CopyOnBuild(cID, destPath, srcRoot, srcPath string, decomp
|
|||
|
||||
destExists := true
|
||||
destDir := false
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
|
||||
// Work in daemon-local OS specific file paths
|
||||
destPath = filepath.FromSlash(destPath)
|
||||
|
@ -413,11 +413,10 @@ func (daemon *Daemon) CopyOnBuild(cID, destPath, srcRoot, srcPath string, decomp
|
|||
destExists = false
|
||||
}
|
||||
|
||||
uidMaps, gidMaps := daemon.GetUIDGIDMaps()
|
||||
archiver := &archive.Archiver{
|
||||
Untar: chrootarchive.Untar,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
UIDMaps: daemon.idMappings.UIDs(),
|
||||
GIDMaps: daemon.idMappings.GIDs(),
|
||||
}
|
||||
|
||||
src, err := os.Stat(fullSrcPath)
|
||||
|
@ -430,7 +429,7 @@ func (daemon *Daemon) CopyOnBuild(cID, destPath, srcRoot, srcPath string, decomp
|
|||
if err := archiver.CopyWithTar(fullSrcPath, destPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return fixPermissions(fullSrcPath, destPath, rootUID, rootGID, destExists)
|
||||
return fixPermissions(fullSrcPath, destPath, rootIDs.UID, rootIDs.GID, destExists)
|
||||
}
|
||||
if decompress && archive.IsArchivePath(fullSrcPath) {
|
||||
// Only try to untar if it is a file and that we've been told to decompress (when ADD-ing a remote file)
|
||||
|
@ -459,12 +458,12 @@ func (daemon *Daemon) CopyOnBuild(cID, destPath, srcRoot, srcPath string, decomp
|
|||
destPath = filepath.Join(destPath, filepath.Base(srcPath))
|
||||
}
|
||||
|
||||
if err := idtools.MkdirAllNewAs(filepath.Dir(destPath), 0755, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChownNew(filepath.Dir(destPath), 0755, rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := archiver.CopyFileWithTar(fullSrcPath, destPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fixPermissions(fullSrcPath, destPath, rootUID, rootGID, destExists)
|
||||
return fixPermissions(fullSrcPath, destPath, rootIDs.UID, rootIDs.GID, destExists)
|
||||
}
|
||||
|
|
|
@ -7,10 +7,9 @@ import (
|
|||
// defaultTarCopyOptions is the setting that is used when unpacking an archive
|
||||
// for a copy API event.
|
||||
func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions {
|
||||
uidMaps, gidMaps := daemon.GetUIDGIDMaps()
|
||||
return &archive.TarOptions{
|
||||
NoOverwriteDirNonDir: noOverwriteDirNonDir,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
UIDMaps: daemon.idMappings.UIDs(),
|
||||
GIDMaps: daemon.idMappings.GIDs(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,14 +109,14 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
|||
}
|
||||
c.ShmPath = "/dev/shm"
|
||||
} else {
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
if !c.HasMountFor("/dev/shm") {
|
||||
shmPath, err := c.ShmResourcePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(shmPath, 0700, rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
|||
if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {
|
||||
return fmt.Errorf("mounting shm tmpfs: %s", err)
|
||||
}
|
||||
if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
|
||||
if err := os.Chown(shmPath, rootIDs.UID, rootIDs.GID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -147,9 +147,9 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
|||
logrus.Debugf("secrets: setting up secret dir: %s", localMountPath)
|
||||
|
||||
// retrieve possible remapped range start for root UID, GID
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
// create tmpfs
|
||||
if err := idtools.MkdirAllAs(localMountPath, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(localMountPath, 0700, rootIDs); err != nil {
|
||||
return errors.Wrap(err, "error creating secret local mount path")
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
|||
}
|
||||
}()
|
||||
|
||||
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootUID, rootGID)
|
||||
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootIDs.UID, rootIDs.GID)
|
||||
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev,nosuid,noexec,"+tmpfsOwnership); err != nil {
|
||||
return errors.Wrap(err, "unable to setup secret mount")
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
|||
// secrets are created in the SecretMountPath on the host, at a
|
||||
// single level
|
||||
fPath := c.SecretFilePath(*s)
|
||||
if err := idtools.MkdirAllAs(filepath.Dir(fPath), 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0700, rootIDs); err != nil {
|
||||
return errors.Wrap(err, "error creating secret mount path")
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := os.Chown(fPath, rootUID+uid, rootGID+gid); err != nil {
|
||||
if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil {
|
||||
return errors.Wrap(err, "error setting ownership for secret")
|
||||
}
|
||||
}
|
||||
|
@ -232,9 +232,9 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
|
|||
logrus.Debugf("configs: setting up config dir: %s", localPath)
|
||||
|
||||
// retrieve possible remapped range start for root UID, GID
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
// create tmpfs
|
||||
if err := idtools.MkdirAllAs(localPath, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(localPath, 0700, rootIDs); err != nil {
|
||||
return errors.Wrap(err, "error creating config dir")
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
|
|||
|
||||
log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath})
|
||||
|
||||
if err := idtools.MkdirAllAs(filepath.Dir(fPath), 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0700, rootIDs); err != nil {
|
||||
return errors.Wrap(err, "error creating config path")
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := os.Chown(fPath, rootUID+uid, rootGID+gid); err != nil {
|
||||
if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil {
|
||||
return errors.Wrap(err, "error setting ownership for config")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,14 +117,14 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
|
|||
return nil, err
|
||||
}
|
||||
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
|
||||
rootIDs, err := daemon.idMappings.RootPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := idtools.MkdirAs(container.Root, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAndChown(container.Root, 0700, rootIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := idtools.MkdirAs(container.CheckpointDir(), 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAndChown(container.CheckpointDir(), 0700, rootIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ func (daemon *Daemon) createContainerPlatformSpecificSettings(container *contain
|
|||
}
|
||||
defer daemon.Unmount(container)
|
||||
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
if err := container.SetupWorkingDirectory(rootUID, rootGID); err != nil {
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
if err := container.SetupWorkingDirectory(rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,7 @@ type Daemon struct {
|
|||
seccompEnabled bool
|
||||
apparmorEnabled bool
|
||||
shutdown bool
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
idMappings *idtools.IDMappings
|
||||
layerStore layer.Store
|
||||
imageStore image.Store
|
||||
PluginStore *plugin.Store // todo: remove
|
||||
|
@ -524,11 +523,11 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
uidMaps, gidMaps, err := setupRemappedRoot(config)
|
||||
idMappings, err := setupRemappedRoot(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
||||
rootIDs, err := idMappings.RootPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -538,7 +537,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
}
|
||||
|
||||
// set up the tmpDir to use a canonical path
|
||||
tmp, err := prepareTempDir(config.Root, rootUID, rootGID)
|
||||
tmp, err := prepareTempDir(config.Root, rootIDs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
|
||||
}
|
||||
|
@ -587,7 +586,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
}
|
||||
|
||||
daemonRepo := filepath.Join(config.Root, "containers")
|
||||
if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
if err := idtools.MkdirAllAndChown(daemonRepo, 0700, rootIDs); err != nil && !os.IsExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -632,8 +631,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
|
||||
GraphDriver: driverName,
|
||||
GraphDriverOptions: config.GraphOptions,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
IDMappings: idMappings,
|
||||
PluginGetter: d.PluginStore,
|
||||
ExperimentalEnabled: config.Experimental,
|
||||
})
|
||||
|
@ -665,7 +663,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
}
|
||||
|
||||
// Configure the volumes driver
|
||||
volStore, err := d.configureVolumes(rootUID, rootGID)
|
||||
volStore, err := d.configureVolumes(rootIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -728,8 +726,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
|||
d.EventsService = eventsService
|
||||
d.volumes = volStore
|
||||
d.root = config.Root
|
||||
d.uidMaps = uidMaps
|
||||
d.gidMaps = gidMaps
|
||||
d.idMappings = idMappings
|
||||
d.seccompEnabled = sysInfo.Seccomp
|
||||
d.apparmorEnabled = sysInfo.AppArmor
|
||||
|
||||
|
@ -970,25 +967,10 @@ func (daemon *Daemon) GraphDriverName() string {
|
|||
return daemon.layerStore.DriverName()
|
||||
}
|
||||
|
||||
// GetUIDGIDMaps returns the current daemon's user namespace settings
|
||||
// for the full uid and gid maps which will be applied to containers
|
||||
// started in this instance.
|
||||
func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) {
|
||||
return daemon.uidMaps, daemon.gidMaps
|
||||
}
|
||||
|
||||
// GetRemappedUIDGID returns the current daemon's uid and gid values
|
||||
// if user namespaces are in use for this daemon instance. If not
|
||||
// this function will return "real" root values of 0, 0.
|
||||
func (daemon *Daemon) GetRemappedUIDGID() (int, int) {
|
||||
uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
|
||||
return uid, gid
|
||||
}
|
||||
|
||||
// prepareTempDir prepares and returns the default directory to use
|
||||
// for temporary files.
|
||||
// If it doesn't exist, it is created. If it exists, its content is removed.
|
||||
func prepareTempDir(rootDir string, rootUID, rootGID int) (string, error) {
|
||||
func prepareTempDir(rootDir string, rootIDs idtools.IDPair) (string, error) {
|
||||
var tmpDir string
|
||||
if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
|
||||
tmpDir = filepath.Join(rootDir, "tmp")
|
||||
|
@ -1008,12 +990,12 @@ func prepareTempDir(rootDir string, rootUID, rootGID int) (string, error) {
|
|||
}
|
||||
// We don't remove the content of tmpdir if it's not the default,
|
||||
// it may hold things that do not belong to us.
|
||||
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
|
||||
return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0700, rootIDs)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) setupInitLayer(initPath string) error {
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
return initlayer.Setup(initPath, rootUID, rootGID)
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
return initlayer.Setup(initPath, rootIDs)
|
||||
}
|
||||
|
||||
func setDefaultMtu(conf *config.Config) {
|
||||
|
@ -1024,8 +1006,8 @@ func setDefaultMtu(conf *config.Config) {
|
|||
conf.Mtu = config.DefaultNetworkMtu
|
||||
}
|
||||
|
||||
func (daemon *Daemon) configureVolumes(rootUID, rootGID int) (*store.VolumeStore, error) {
|
||||
volumesDriver, err := local.New(daemon.configStore.Root, rootUID, rootGID)
|
||||
func (daemon *Daemon) configureVolumes(rootIDs idtools.IDPair) (*store.VolumeStore, error) {
|
||||
volumesDriver, err := local.New(daemon.configStore.Root, rootIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1171,16 +1153,16 @@ func CreateDaemonRoot(config *config.Config) error {
|
|||
}
|
||||
}
|
||||
|
||||
uidMaps, gidMaps, err := setupRemappedRoot(config)
|
||||
idMappings, err := setupRemappedRoot(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
||||
rootIDs, err := idMappings.RootPair()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil {
|
||||
if err := setupDaemonRoot(config, realRoot, rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/container"
|
||||
_ "github.com/docker/docker/pkg/discovery/memory"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/registrar"
|
||||
"github.com/docker/docker/pkg/truncindex"
|
||||
"github.com/docker/docker/volume"
|
||||
|
@ -127,7 +128,7 @@ func initDaemonWithVolumeStore(tmp string) (*Daemon, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(tmp, 0, 0)
|
||||
volumesDriver, err := local.New(tmp, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1026,40 +1026,38 @@ func parseRemappedRoot(usergrp string) (string, string, error) {
|
|||
return username, groupname, nil
|
||||
}
|
||||
|
||||
func setupRemappedRoot(config *config.Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
||||
func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
|
||||
if runtime.GOOS != "linux" && config.RemappedRoot != "" {
|
||||
return nil, nil, fmt.Errorf("User namespaces are only supported on Linux")
|
||||
return nil, fmt.Errorf("User namespaces are only supported on Linux")
|
||||
}
|
||||
|
||||
// if the daemon was started with remapped root option, parse
|
||||
// the config option to the int uid,gid values
|
||||
var (
|
||||
uidMaps, gidMaps []idtools.IDMap
|
||||
)
|
||||
if config.RemappedRoot != "" {
|
||||
username, groupname, err := parseRemappedRoot(config.RemappedRoot)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
if username == "root" {
|
||||
// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
|
||||
// effectively
|
||||
logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
|
||||
return uidMaps, gidMaps, nil
|
||||
return &idtools.IDMappings{}, nil
|
||||
}
|
||||
logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname)
|
||||
// update remapped root setting now that we have resolved them to actual names
|
||||
config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
|
||||
|
||||
uidMaps, gidMaps, err = idtools.CreateIDMappings(username, groupname)
|
||||
mappings, err := idtools.NewIDMappings(username, groupname)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Can't create ID mappings: %v", err)
|
||||
return nil, errors.Wrapf(err, "Can't create ID mappings: %v")
|
||||
}
|
||||
return mappings, nil
|
||||
}
|
||||
return uidMaps, gidMaps, nil
|
||||
return &idtools.IDMappings{}, nil
|
||||
}
|
||||
|
||||
func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int) error {
|
||||
func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error {
|
||||
config.Root = rootDir
|
||||
// the docker root metadata directory needs to have execute permissions for all users (g+x,o+x)
|
||||
// so that syscalls executing as non-root, operating on subdirectories of the graph root
|
||||
|
@ -1084,10 +1082,10 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int
|
|||
// a new subdirectory with ownership set to the remapped uid/gid (so as to allow
|
||||
// `chdir()` to work for containers namespaced to that uid/gid)
|
||||
if config.RemappedRoot != "" {
|
||||
config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootUID, rootGID))
|
||||
config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootIDs.UID, rootIDs.GID))
|
||||
logrus.Debugf("Creating user namespaced daemon root: %s", config.Root)
|
||||
// Create the root directory if it doesn't exist
|
||||
if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(config.Root, 0700, rootIDs); err != nil {
|
||||
return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
|
||||
}
|
||||
// we also need to verify that any pre-existing directories in the path to
|
||||
|
@ -1100,7 +1098,7 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int
|
|||
if dirPath == "/" {
|
||||
break
|
||||
}
|
||||
if !idtools.CanAccess(dirPath, rootUID, rootGID) {
|
||||
if !idtools.CanAccess(dirPath, rootIDs) {
|
||||
return fmt.Errorf("A subdirectory in your graphroot path (%s) restricts access to the remapped root uid/gid; please fix by allowing 'o+x' permissions on existing directories.", config.Root)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
|
@ -277,7 +278,7 @@ func TestMigratePre17Volumes(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
drv, err := local.New(volumeRoot, 0, 0)
|
||||
drv, err := local.New(volumeRoot, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -454,11 +454,11 @@ func (daemon *Daemon) cleanupMounts() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func setupRemappedRoot(config *config.Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
||||
return nil, nil, nil
|
||||
func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
|
||||
return &idtools.IDMappings{}, nil
|
||||
}
|
||||
|
||||
func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int) error {
|
||||
func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error {
|
||||
config.Root = rootDir
|
||||
// Create the root directory if it doesn't exists
|
||||
if err := system.MkdirAllWithACL(config.Root, 0); err != nil && !os.IsExist(err) {
|
||||
|
|
|
@ -40,11 +40,10 @@ func (daemon *Daemon) containerExport(container *container.Container) (io.ReadCl
|
|||
return nil, err
|
||||
}
|
||||
|
||||
uidMaps, gidMaps := daemon.GetUIDGIDMaps()
|
||||
archive, err := archive.TarWithOptions(container.BaseFS, &archive.TarOptions{
|
||||
Compression: archive.Uncompressed,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
UIDMaps: daemon.idMappings.UIDs(),
|
||||
GIDMaps: daemon.idMappings.GIDs(),
|
||||
})
|
||||
if err != nil {
|
||||
daemon.Unmount(container)
|
||||
|
|
|
@ -72,8 +72,8 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
if selinuxEnabled() {
|
||||
securityOptions = append(securityOptions, "name=selinux")
|
||||
}
|
||||
uid, gid := daemon.GetRemappedUIDGID()
|
||||
if uid != 0 || gid != 0 {
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
if rootIDs.UID != 0 || rootIDs.GID != 0 {
|
||||
securityOptions = append(securityOptions, "name=userns")
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
//
|
||||
// This extra layer is used by all containers as the top-most ro layer. It protects
|
||||
// the container from unwanted side-effects on the rw layer.
|
||||
func Setup(initLayer string, rootUID, rootGID int) error {
|
||||
func Setup(initLayer string, rootIDs idtools.IDPair) error {
|
||||
for pth, typ := range map[string]string{
|
||||
"/dev/pts": "dir",
|
||||
"/dev/shm": "dir",
|
||||
|
@ -38,12 +38,12 @@ func Setup(initLayer string, rootUID, rootGID int) error {
|
|||
|
||||
if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := idtools.MkdirAllNewAs(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
switch typ {
|
||||
case "dir":
|
||||
if err := idtools.MkdirAllNewAs(filepath.Join(initLayer, pth), 0755, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, pth), 0755, rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
case "file":
|
||||
|
@ -51,7 +51,7 @@ func Setup(initLayer string, rootUID, rootGID int) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Chown(rootUID, rootGID)
|
||||
f.Chown(rootIDs.UID, rootIDs.GID)
|
||||
f.Close()
|
||||
default:
|
||||
if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
package initlayer
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
)
|
||||
|
||||
// Setup populates a directory with mountpoints suitable
|
||||
// for bind-mounting dockerinit into the container. The mountpoint is simply an
|
||||
// empty file at /.dockerinit
|
||||
//
|
||||
// This extra layer is used by all containers as the top-most ro layer. It protects
|
||||
// the container from unwanted side-effects on the rw layer.
|
||||
func Setup(initLayer string, rootUID, rootGID int) error {
|
||||
func Setup(initLayer string, rootIDs idtools.IDPair) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -271,13 +271,13 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error
|
|||
userNS := false
|
||||
// user
|
||||
if c.HostConfig.UsernsMode.IsPrivate() {
|
||||
uidMap, gidMap := daemon.GetUIDGIDMaps()
|
||||
uidMap := daemon.idMappings.UIDs()
|
||||
if uidMap != nil {
|
||||
userNS = true
|
||||
ns := specs.LinuxNamespace{Type: "user"}
|
||||
setNamespace(s, ns)
|
||||
s.Linux.UIDMappings = specMapping(uidMap)
|
||||
s.Linux.GIDMappings = specMapping(gidMap)
|
||||
s.Linux.GIDMappings = specMapping(daemon.idMappings.GIDs())
|
||||
}
|
||||
}
|
||||
// network
|
||||
|
@ -591,7 +591,7 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
|
|||
|
||||
// TODO: until a kernel/mount solution exists for handling remount in a user namespace,
|
||||
// we must clear the readonly flag for the cgroups mount (@mrunalp concurs)
|
||||
if uidMap, _ := daemon.GetUIDGIDMaps(); uidMap != nil || c.HostConfig.Privileged {
|
||||
if uidMap := daemon.idMappings.UIDs(); uidMap != nil || c.HostConfig.Privileged {
|
||||
for i, m := range s.Mounts {
|
||||
if m.Type == "cgroup" {
|
||||
clearReadOnly(&s.Mounts[i])
|
||||
|
@ -611,8 +611,8 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
|
|||
Path: c.BaseFS,
|
||||
Readonly: c.HostConfig.ReadonlyRootfs,
|
||||
}
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil {
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
if err := c.SetupWorkingDirectory(rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
cwd := c.Config.WorkingDir
|
||||
|
|
|
@ -130,8 +130,8 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
|
|||
Path: filepath.Dir(c.BaseFS),
|
||||
Readonly: c.HostConfig.ReadonlyRootfs,
|
||||
}
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil {
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
if err := c.SetupWorkingDirectory(rootIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
cwd := c.Config.WorkingDir
|
||||
|
|
|
@ -54,8 +54,8 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
|
|||
return nil
|
||||
}
|
||||
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
path, err := m.Setup(c.MountLabel, rootUID, rootGID, checkfunc)
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
path, err := m.Setup(c.MountLabel, rootIDs, checkfunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -85,9 +85,9 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
|
|||
// if we are going to mount any of the network files from container
|
||||
// metadata, the ownership must be set properly for potential container
|
||||
// remapped root (user namespaces)
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
for _, mount := range netMounts {
|
||||
if err := os.Chown(mount.Source, rootUID, rootGID); err != nil {
|
||||
if err := os.Chown(mount.Source, rootIDs.UID, rootIDs.GID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/volume"
|
||||
)
|
||||
|
||||
|
@ -24,7 +25,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
|
|||
if err := daemon.lazyInitializeVolume(c.ID, mount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := mount.Setup(c.MountLabel, 0, 0, nil)
|
||||
s, err := mount.Setup(c.MountLabel, idtools.IDPair{0, 0}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ func (daemon *Daemon) ContainerCreateWorkdir(cID string) error {
|
|||
return err
|
||||
}
|
||||
defer daemon.Unmount(container)
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
return container.SetupWorkingDirectory(rootUID, rootGID)
|
||||
rootIDs, _ := daemon.idMappings.RootPair()
|
||||
return container.SetupWorkingDirectory(rootIDs)
|
||||
}
|
||||
|
|
|
@ -44,8 +44,7 @@ type StoreOptions struct {
|
|||
MetadataStorePathTemplate string
|
||||
GraphDriver string
|
||||
GraphDriverOptions []string
|
||||
UIDMaps []idtools.IDMap
|
||||
GIDMaps []idtools.IDMap
|
||||
IDMappings *idtools.IDMappings
|
||||
PluginGetter plugingetter.PluginGetter
|
||||
ExperimentalEnabled bool
|
||||
}
|
||||
|
@ -55,8 +54,8 @@ func NewStoreFromOptions(options StoreOptions) (Store, error) {
|
|||
driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
|
||||
Root: options.StorePath,
|
||||
DriverOptions: options.GraphDriverOptions,
|
||||
UIDMaps: options.UIDMaps,
|
||||
GIDMaps: options.GIDMaps,
|
||||
UIDMaps: options.IDMappings.UIDs(),
|
||||
GIDMaps: options.IDMappings.GIDs(),
|
||||
ExperimentalEnabled: options.ExperimentalEnabled,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -37,6 +37,7 @@ const (
|
|||
// MkdirAllAs creates a directory (include any along the path) and then modifies
|
||||
// ownership to the requested uid/gid. If the directory already exists, this
|
||||
// function will still change ownership to the requested uid/gid pair.
|
||||
// Deprecated: Use MkdirAllAndChown
|
||||
func MkdirAllAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
|
||||
return mkdirAs(path, mode, ownerUID, ownerGID, true, true)
|
||||
}
|
||||
|
@ -44,16 +45,38 @@ func MkdirAllAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
|
|||
// MkdirAllNewAs creates a directory (include any along the path) and then modifies
|
||||
// ownership ONLY of newly created directories to the requested uid/gid. If the
|
||||
// directories along the path exist, no change of ownership will be performed
|
||||
// Deprecated: Use MkdirAllAndChownNew
|
||||
func MkdirAllNewAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
|
||||
return mkdirAs(path, mode, ownerUID, ownerGID, true, false)
|
||||
}
|
||||
|
||||
// MkdirAs creates a directory and then modifies ownership to the requested uid/gid.
|
||||
// If the directory already exists, this function still changes ownership
|
||||
// Deprecated: Use MkdirAndChown with a IDPair
|
||||
func MkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
|
||||
return mkdirAs(path, mode, ownerUID, ownerGID, false, true)
|
||||
}
|
||||
|
||||
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
|
||||
// ownership to the requested uid/gid. If the directory already exists, this
|
||||
// function will still change ownership to the requested uid/gid pair.
|
||||
func MkdirAllAndChown(path string, mode os.FileMode, ids IDPair) error {
|
||||
return mkdirAs(path, mode, ids.UID, ids.GID, true, true)
|
||||
}
|
||||
|
||||
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
|
||||
// If the directory already exists, this function still changes ownership
|
||||
func MkdirAndChown(path string, mode os.FileMode, ids IDPair) error {
|
||||
return mkdirAs(path, mode, ids.UID, ids.GID, false, true)
|
||||
}
|
||||
|
||||
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
|
||||
// ownership ONLY of newly created directories to the requested uid/gid. If the
|
||||
// directories along the path exist, no change of ownership will be performed
|
||||
func MkdirAllAndChownNew(path string, mode os.FileMode, ids IDPair) error {
|
||||
return mkdirAs(path, mode, ids.UID, ids.GID, true, false)
|
||||
}
|
||||
|
||||
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
|
||||
// If the maps are empty, then the root uid/gid will default to "real" 0/0
|
||||
func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
|
||||
|
@ -108,26 +131,59 @@ func ToHost(contID int, idMap []IDMap) (int, error) {
|
|||
return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID)
|
||||
}
|
||||
|
||||
// CreateIDMappings takes a requested user and group name and
|
||||
// IDPair is a UID and GID pair
|
||||
type IDPair struct {
|
||||
UID int
|
||||
GID int
|
||||
}
|
||||
|
||||
// IDMappings contains a mappings of UIDs and GIDs
|
||||
type IDMappings struct {
|
||||
uids []IDMap
|
||||
gids []IDMap
|
||||
}
|
||||
|
||||
// NewIDMappings takes a requested user and group name and
|
||||
// using the data from /etc/sub{uid,gid} ranges, creates the
|
||||
// proper uid and gid remapping ranges for that user/group pair
|
||||
func CreateIDMappings(username, groupname string) ([]IDMap, []IDMap, error) {
|
||||
func NewIDMappings(username, groupname string) (*IDMappings, error) {
|
||||
subuidRanges, err := parseSubuid(username)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
subgidRanges, err := parseSubgid(groupname)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
if len(subuidRanges) == 0 {
|
||||
return nil, nil, fmt.Errorf("No subuid ranges found for user %q", username)
|
||||
return nil, fmt.Errorf("No subuid ranges found for user %q", username)
|
||||
}
|
||||
if len(subgidRanges) == 0 {
|
||||
return nil, nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
|
||||
return nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
|
||||
}
|
||||
|
||||
return createIDMap(subuidRanges), createIDMap(subgidRanges), nil
|
||||
return &IDMappings{
|
||||
uids: createIDMap(subuidRanges),
|
||||
gids: createIDMap(subgidRanges),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RootPair returns a uid and gid pair for the root user
|
||||
func (i *IDMappings) RootPair() (IDPair, error) {
|
||||
uid, gid, err := GetRootUIDGID(i.uids, i.gids)
|
||||
return IDPair{UID: uid, GID: gid}, err
|
||||
}
|
||||
|
||||
// UIDs return the UID mapping
|
||||
// TODO: remove this once everything has been refactored to use pairs
|
||||
func (i *IDMappings) UIDs() []IDMap {
|
||||
return i.uids
|
||||
}
|
||||
|
||||
// GIDs return the UID mapping
|
||||
// TODO: remove this once everything has been refactored to use pairs
|
||||
func (i *IDMappings) GIDs() []IDMap {
|
||||
return i.gids
|
||||
}
|
||||
|
||||
func createIDMap(subidRanges ranges) []IDMap {
|
||||
|
|
|
@ -69,15 +69,15 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
|
|||
|
||||
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
|
||||
// if that uid, gid pair has access (execute bit) to the directory
|
||||
func CanAccess(path string, uid, gid int) bool {
|
||||
func CanAccess(path string, pair IDPair) bool {
|
||||
statInfo, err := system.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
fileMode := os.FileMode(statInfo.Mode())
|
||||
permBits := fileMode.Perm()
|
||||
return accessible(statInfo.UID() == uint32(uid),
|
||||
statInfo.GID() == uint32(gid), permBits)
|
||||
return accessible(statInfo.UID() == uint32(pair.UID),
|
||||
statInfo.GID() == uint32(pair.GID), permBits)
|
||||
}
|
||||
|
||||
func accessible(isOwner, isGroup bool, perms os.FileMode) bool {
|
||||
|
|
|
@ -20,6 +20,6 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
|
|||
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
|
||||
// if that uid, gid pair has access (execute bit) to the directory
|
||||
// Windows does not require/support this function, so always return true
|
||||
func CanAccess(path string, uid, gid int) bool {
|
||||
func CanAccess(path string, pair IDPair) bool {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/daemon/initlayer"
|
||||
"github.com/docker/docker/libcontainerd"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
|
@ -58,7 +59,7 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := initlayer.Setup(filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName), 0, 0); err != nil {
|
||||
if err := initlayer.Setup(filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName), idtools.IDPair{0, 0}); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -55,10 +55,10 @@ type activeMount struct {
|
|||
// New instantiates a new Root instance with the provided scope. Scope
|
||||
// is the base path that the Root instance uses to store its
|
||||
// volumes. The base path is created here if it does not exist.
|
||||
func New(scope string, rootUID, rootGID int) (*Root, error) {
|
||||
func New(scope string, rootIDs idtools.IDPair) (*Root, error) {
|
||||
rootDirectory := filepath.Join(scope, volumesPathName)
|
||||
|
||||
if err := idtools.MkdirAllAs(rootDirectory, 0700, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(rootDirectory, 0700, rootIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,7 @@ func New(scope string, rootUID, rootGID int) (*Root, error) {
|
|||
scope: scope,
|
||||
path: rootDirectory,
|
||||
volumes: make(map[string]*localVolume),
|
||||
rootUID: rootUID,
|
||||
rootGID: rootGID,
|
||||
rootIDs: rootIDs,
|
||||
}
|
||||
|
||||
dirs, err := ioutil.ReadDir(rootDirectory)
|
||||
|
@ -125,8 +124,7 @@ type Root struct {
|
|||
scope string
|
||||
path string
|
||||
volumes map[string]*localVolume
|
||||
rootUID int
|
||||
rootGID int
|
||||
rootIDs idtools.IDPair
|
||||
}
|
||||
|
||||
// List lists all the volumes
|
||||
|
@ -167,7 +165,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error
|
|||
}
|
||||
|
||||
path := r.DataPath(name)
|
||||
if err := idtools.MkdirAllAs(path, 0755, r.rootUID, r.rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(path, 0755, r.rootIDs); err != nil {
|
||||
if os.IsExist(err) {
|
||||
return nil, fmt.Errorf("volume already exists under %s", filepath.Dir(path))
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
)
|
||||
|
||||
|
@ -40,7 +41,7 @@ func TestRemove(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(rootDir)
|
||||
|
||||
r, err := New(rootDir, 0, 0)
|
||||
r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ func TestInitializeWithVolumes(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(rootDir)
|
||||
|
||||
r, err := New(rootDir, 0, 0)
|
||||
r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ func TestInitializeWithVolumes(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r, err = New(rootDir, 0, 0)
|
||||
r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -114,7 +115,7 @@ func TestCreate(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(rootDir)
|
||||
|
||||
r, err := New(rootDir, 0, 0)
|
||||
r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ func TestCreate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
r, err = New(rootDir, 0, 0)
|
||||
r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -189,7 +190,7 @@ func TestCreateWithOpts(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(rootDir)
|
||||
|
||||
r, err := New(rootDir, 0, 0)
|
||||
r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -270,7 +271,7 @@ func TestCreateWithOpts(t *testing.T) {
|
|||
t.Fatal("expected mount to still be active")
|
||||
}
|
||||
|
||||
r, err = New(rootDir, 0, 0)
|
||||
r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -292,7 +293,7 @@ func TestRealodNoOpts(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(rootDir)
|
||||
|
||||
r, err := New(rootDir, 0, 0)
|
||||
r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -320,7 +321,7 @@ func TestRealodNoOpts(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r, err = New(rootDir, 0, 0)
|
||||
r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ func (m *MountPoint) Cleanup() error {
|
|||
// configured, or creating the source directory if supplied.
|
||||
// The, optional, checkFun parameter allows doing additional checking
|
||||
// before creating the source directory on the host.
|
||||
func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int, checkFun func(m *MountPoint) error) (path string, err error) {
|
||||
func (m *MountPoint) Setup(mountLabel string, rootIDs idtools.IDPair, checkFun func(m *MountPoint) error) (path string, err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
if label.RelabelNeeded(m.Mode) {
|
||||
|
@ -196,7 +196,7 @@ func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int, checkFun fun
|
|||
}
|
||||
// idtools.MkdirAllNewAs() produces an error if m.Source exists and is a file (not a directory)
|
||||
// also, makes sure that if the directory is created, the correct remapped rootUID/rootGID will own it
|
||||
if err := idtools.MkdirAllNewAs(m.Source, 0755, rootUID, rootGID); err != nil {
|
||||
if err := idtools.MkdirAllAndChownNew(m.Source, 0755, rootIDs); err != nil {
|
||||
if perr, ok := err.(*os.PathError); ok {
|
||||
if perr.Err != syscall.ENOTDIR {
|
||||
return "", errors.Wrapf(err, "error while creating mount source path '%s'", m.Source)
|
||||
|
|
Loading…
Reference in a new issue