From 66dffbec86dbea1b04180699106d5b8a73d5424b Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Tue, 6 Oct 2020 19:30:07 +0000 Subject: [PATCH 1/3] Ensure MkdirAllAndChown also sets perms Generally if we ever need to change perms of a dir, between versions, this ensures the permissions actually change when we think it should change without having to handle special cases if it already existed. Signed-off-by: Brian Goff (cherry picked from commit edb62a3ace8c4303822a391b38231e577f8c2ee8) Signed-off-by: Sebastiaan van Stijn --- pkg/idtools/idtools.go | 11 ++++++++--- pkg/idtools/idtools_unix.go | 14 ++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/pkg/idtools/idtools.go b/pkg/idtools/idtools.go index 7569ac15dd..25a57b231e 100644 --- a/pkg/idtools/idtools.go +++ b/pkg/idtools/idtools.go @@ -35,13 +35,13 @@ const ( // 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. +// function will still change ownership and permissions. func MkdirAllAndChown(path string, mode os.FileMode, owner Identity) error { return mkdirAs(path, mode, owner, 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. +// If the directory already exists, this function still changes ownership and permissions. // Note that unlike os.Mkdir(), this function does not return IsExist error // in case path already exists. func MkdirAndChown(path string, mode os.FileMode, owner Identity) error { @@ -50,7 +50,7 @@ func MkdirAndChown(path string, mode os.FileMode, owner Identity) error { // 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 +// directories along the path exist, no change of ownership or permissions will be performed func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error { return mkdirAs(path, mode, owner, true, false) } @@ -234,3 +234,8 @@ func parseSubidFile(path, username string) (ranges, error) { return rangeList, s.Err() } + +// CurrentIdentity returns the identity of the current process +func CurrentIdentity() Identity { + return Identity{UID: os.Getuid(), GID: os.Getegid()} +} diff --git a/pkg/idtools/idtools_unix.go b/pkg/idtools/idtools_unix.go index 5defe6459f..a03af12045 100644 --- a/pkg/idtools/idtools_unix.go +++ b/pkg/idtools/idtools_unix.go @@ -40,7 +40,7 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting } // short-circuit--we were called with an existing directory and chown was requested - return lazyChown(path, owner.UID, owner.GID, stat) + return setPermissions(path, mode, owner.UID, owner.GID, stat) } if os.IsNotExist(err) { @@ -71,7 +71,7 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting // even if it existed, we will chown the requested path + any subpaths that // didn't exist when we called MkdirAll for _, pathComponent := range paths { - if err := lazyChown(pathComponent, owner.UID, owner.GID, nil); err != nil { + if err := setPermissions(pathComponent, mode, owner.UID, owner.GID, nil); err != nil { return err } } @@ -213,10 +213,11 @@ func callGetent(database, key string) (io.Reader, error) { return bytes.NewReader(out), nil } -// lazyChown performs a chown only if the uid/gid don't match what's requested +// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested // Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the // dir is on an NFS share, so don't call chown unless we absolutely must. -func lazyChown(p string, uid, gid int, stat *system.StatT) error { +// Likewise for setting permissions. +func setPermissions(p string, mode os.FileMode, uid, gid int, stat *system.StatT) error { if stat == nil { var err error stat, err = system.Stat(p) @@ -224,6 +225,11 @@ func lazyChown(p string, uid, gid int, stat *system.StatT) error { return err } } + if os.FileMode(stat.Mode()).Perm() != mode.Perm() { + if err := os.Chmod(p, mode.Perm()); err != nil { + return err + } + } if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) { return nil } From 4b5aa28f2466308acab98fc35586723492347fc5 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Tue, 6 Oct 2020 19:40:30 +0000 Subject: [PATCH 2/3] Do not set DOCKER_TMP to be owned by remapped root The remapped root does not need access to this dir. Having this owned by the remapped root opens the host up to an uprivileged user on the host being able to escalate privileges. While it would not be normal for the remapped UID to be used outside of the container context, it could happen. Signed-off-by: Brian Goff (cherry picked from commit bfedd2725971303efb7a2fe5d6990317b381622f) Signed-off-by: Sebastiaan van Stijn --- daemon/daemon.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/daemon/daemon.go b/daemon/daemon.go index 66df2fc98a..2d6d69cef5 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -795,7 +795,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S } // set up the tmpDir to use a canonical path - tmp, err := prepareTempDir(config.Root, rootIDs) + tmp, err := prepareTempDir(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } @@ -1374,7 +1374,7 @@ func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) { // 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, rootIdentity idtools.Identity) (string, error) { +func prepareTempDir(rootDir string) (string, error) { var tmpDir string if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { tmpDir = filepath.Join(rootDir, "tmp") @@ -1392,9 +1392,7 @@ func prepareTempDir(rootDir string, rootIdentity idtools.Identity) (string, erro } } } - // 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.MkdirAllAndChown(tmpDir, 0700, rootIdentity) + return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0700, idtools.CurrentIdentity()) } func (daemon *Daemon) setGenericResources(conf *config.Config) error { From 7f5e39bd4f92ce6fcf9946aa8ccea91815c321c2 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Tue, 6 Oct 2020 19:43:24 +0000 Subject: [PATCH 3/3] Use real root with 0701 perms Various dirs in /var/lib/docker contain data that needs to be mounted into a container. For this reason, these dirs are set to be owned by the remapped root user, otherwise there can be permissions issues. However, this uneccessarily exposes these dirs to an unprivileged user on the host. Instead, set the ownership of these dirs to the real root (or rather the UID/GID of dockerd) with 0701 permissions, which allows the remapped root to enter the directories but not read/write to them. The remapped root needs to enter these dirs so the container's rootfs can be configured... e.g. to mount /etc/resolve.conf. This prevents an unprivileged user from having read/write access to these dirs on the host. The flip side of this is now any user can enter these directories. Signed-off-by: Brian Goff (cherry picked from commit e908cc39018c015084ffbffbc5703ccba5c2fbb7) Signed-off-by: Sebastiaan van Stijn --- daemon/container_operations_unix.go | 2 +- daemon/create.go | 6 ++---- daemon/daemon.go | 2 +- daemon/daemon_unix.go | 14 ++++++++++---- daemon/graphdriver/aufs/aufs.go | 9 +++------ daemon/graphdriver/btrfs/btrfs.go | 10 +++------- .../graphdriver/fuse-overlayfs/fuseoverlayfs.go | 14 +++++--------- daemon/graphdriver/overlay/overlay.go | 16 +++++++--------- daemon/graphdriver/overlay2/overlay.go | 12 ++++-------- daemon/graphdriver/vfs/driver.go | 5 ++--- daemon/graphdriver/zfs/zfs.go | 6 +----- volume/local/local.go | 11 +++++++++-- 12 files changed, 48 insertions(+), 59 deletions(-) diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index f4f1bd2c0b..5521adbd27 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -466,5 +466,5 @@ func (daemon *Daemon) setupContainerMountsRoot(c *container.Container) error { if err != nil { return err } - return idtools.MkdirAllAndChown(p, 0700, daemon.idMapping.RootPair()) + return idtools.MkdirAllAndChown(p, 0701, idtools.CurrentIdentity()) } diff --git a/daemon/create.go b/daemon/create.go index a190ab4e3d..1d77d237eb 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -194,12 +194,10 @@ func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr } ctr.RWLayer = rwLayer - rootIDs := daemon.idMapping.RootPair() - - if err := idtools.MkdirAndChown(ctr.Root, 0700, rootIDs); err != nil { + if err := idtools.MkdirAndChown(ctr.Root, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } - if err := idtools.MkdirAndChown(ctr.CheckpointDir(), 0700, rootIDs); err != nil { + if err := idtools.MkdirAndChown(ctr.CheckpointDir(), 0700, idtools.CurrentIdentity()); err != nil { return nil, err } diff --git a/daemon/daemon.go b/daemon/daemon.go index 2d6d69cef5..3d8cca2880 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -861,7 +861,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S } daemonRepo := filepath.Join(config.Root, "containers") - if err := idtools.MkdirAllAndChown(daemonRepo, 0700, rootIDs); err != nil { + if err := idtools.MkdirAllAndChown(daemonRepo, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index bead7e7273..8754d4f972 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -1196,7 +1196,7 @@ func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) return &idtools.IdentityMapping{}, nil } -func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error { +func setupDaemonRoot(config *config.Config, rootDir string, remappedRoot idtools.Identity) 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 @@ -1221,10 +1221,16 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools // 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", rootIdentity.UID, rootIdentity.GID)) + id := idtools.CurrentIdentity() + // First make sure the current root dir has the correct perms. + if err := idtools.MkdirAllAndChown(config.Root, 0701, id); err != nil { + return errors.Wrapf(err, "could not create or set daemon root permissions: %s", config.Root) + } + + config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", remappedRoot.UID, remappedRoot.GID)) logrus.Debugf("Creating user namespaced daemon root: %s", config.Root) // Create the root directory if it doesn't exist - if err := idtools.MkdirAllAndChown(config.Root, 0700, rootIdentity); err != nil { + if err := idtools.MkdirAllAndChown(config.Root, 0701, id); 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 @@ -1237,7 +1243,7 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools if dirPath == "/" { break } - if !idtools.CanAccess(dirPath, rootIdentity) { + if !idtools.CanAccess(dirPath, remappedRoot) { 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) } } diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index 4ecc647bdd..b007274e13 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -129,18 +129,15 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap locker: locker.New(), } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } + currentID := idtools.CurrentIdentity() // Create the root aufs driver dir - if err := idtools.MkdirAllAndChown(root, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(root, 0701, currentID); err != nil { return nil, err } // Populate the dir structure for _, p := range paths { - if err := idtools.MkdirAllAndChown(path.Join(root, p), 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(path.Join(root, p), 0701, currentID); err != nil { return nil, err } } diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go index 1866b07b88..f9127472f8 100644 --- a/daemon/graphdriver/btrfs/btrfs.go +++ b/daemon/graphdriver/btrfs/btrfs.go @@ -70,11 +70,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, graphdriver.ErrPrerequisites } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - if err := idtools.MkdirAllAndChown(home, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(home, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -525,7 +521,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { if err != nil { return err } - if err := idtools.MkdirAllAndChown(subvolumes, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(subvolumes, 0701, idtools.CurrentIdentity()); err != nil { return err } if parent == "" { @@ -560,7 +556,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil { return err } - if err := idtools.MkdirAllAndChown(quotas, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(quotas, 0700, idtools.CurrentIdentity()); err != nil { return err } if err := ioutil.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0644); err != nil { diff --git a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go index e906cda74d..782e8be984 100644 --- a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go +++ b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go @@ -88,12 +88,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, graphdriver.ErrNotSupported } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - // Create the driver home dir - if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -178,10 +173,11 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr } root := idtools.Identity{UID: rootUID, GID: rootGID} - if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil { + currentID := idtools.CurrentIdentity() + if err := idtools.MkdirAllAndChown(path.Dir(dir), 0701, currentID); err != nil { return err } - if err := idtools.MkdirAndChown(dir, 0700, root); err != nil { + if err := idtools.MkdirAndChown(dir, 0701, currentID); err != nil { return err } @@ -215,7 +211,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr return nil } - if err := idtools.MkdirAndChown(path.Join(dir, workDirName), 0700, root); err != nil { + if err := idtools.MkdirAndChown(path.Join(dir, workDirName), 0701, currentID); err != nil { return err } diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go index 1cffc1b896..90be0e3d64 100644 --- a/daemon/graphdriver/overlay/overlay.go +++ b/daemon/graphdriver/overlay/overlay.go @@ -156,12 +156,8 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap logrus.WithField("storage-driver", "overlay").Warn(overlayutils.ErrDTypeNotSupported("overlay", backingFs)) } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } // Create the driver home dir - if err := idtools.MkdirAllAndChown(home, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(home, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -265,10 +261,11 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr } root := idtools.Identity{UID: rootUID, GID: rootGID} - if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil { + currentID := idtools.CurrentIdentity() + if err := idtools.MkdirAllAndChown(path.Dir(dir), 0701, currentID); err != nil { return err } - if err := idtools.MkdirAndChown(dir, 0700, root); err != nil { + if err := idtools.MkdirAndChown(dir, 0701, currentID); err != nil { return err } @@ -281,6 +278,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr // Toplevel images are just a "root" dir if parent == "" { + // This must be 0755 otherwise unprivileged users will in the container will not be able to read / in the container return idtools.MkdirAndChown(path.Join(dir, "root"), 0755, root) } @@ -301,7 +299,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil { return err } - return ioutil.WriteFile(path.Join(dir, "lower-id"), []byte(parent), 0666) + return ioutil.WriteFile(path.Join(dir, "lower-id"), []byte(parent), 0600) } // Otherwise, copy the upper and the lower-id from the parent @@ -311,7 +309,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr return err } - if err := ioutil.WriteFile(path.Join(dir, "lower-id"), lowerID, 0666); err != nil { + if err := ioutil.WriteFile(path.Join(dir, "lower-id"), lowerID, 0600); err != nil { return err } diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index 11d53029ca..e26fa07c82 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -165,12 +165,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap logger.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs)) } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - // Create the driver home dir - if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -339,11 +334,12 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr return err } root := idtools.Identity{UID: rootUID, GID: rootGID} + current := idtools.CurrentIdentity() - if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil { + if err := idtools.MkdirAllAndChown(path.Dir(dir), 0701, current); err != nil { return err } - if err := idtools.MkdirAndChown(dir, 0700, root); err != nil { + if err := idtools.MkdirAndChown(dir, 0701, current); err != nil { return err } diff --git a/daemon/graphdriver/vfs/driver.go b/daemon/graphdriver/vfs/driver.go index b341de5b89..af9b107609 100644 --- a/daemon/graphdriver/vfs/driver.go +++ b/daemon/graphdriver/vfs/driver.go @@ -38,8 +38,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } - rootIDs := d.idMapping.RootPair() - if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil { + if err := idtools.MkdirAllAndChown(home, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -141,7 +140,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { func (d *Driver) create(id, parent string, size uint64) error { dir := d.dir(id) rootIDs := d.idMapping.RootPair() - if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil { + if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0701, idtools.CurrentIdentity()); err != nil { return err } if err := idtools.MkdirAndChown(dir, 0755, rootIDs); err != nil { diff --git a/daemon/graphdriver/zfs/zfs.go b/daemon/graphdriver/zfs/zfs.go index 21c271e2ec..f9099a2094 100644 --- a/daemon/graphdriver/zfs/zfs.go +++ b/daemon/graphdriver/zfs/zfs.go @@ -104,11 +104,7 @@ 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) } - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, fmt.Errorf("Failed to get root uid/guid: %v", err) - } - if err := idtools.MkdirAllAndChown(base, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil { + if err := idtools.MkdirAllAndChown(base, 0701, idtools.CurrentIdentity()); err != nil { return nil, fmt.Errorf("Failed to create '%s': %v", base, err) } diff --git a/volume/local/local.go b/volume/local/local.go index 89252cf627..088502f43b 100644 --- a/volume/local/local.go +++ b/volume/local/local.go @@ -50,7 +50,7 @@ type activeMount struct { func New(scope string, rootIdentity idtools.Identity) (*Root, error) { rootDirectory := filepath.Join(scope, volumesPathName) - if err := idtools.MkdirAllAndChown(rootDirectory, 0700, rootIdentity); err != nil { + if err := idtools.MkdirAllAndChown(rootDirectory, 0701, idtools.CurrentIdentity()); err != nil { return nil, err } @@ -153,8 +153,15 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error } path := r.DataPath(name) + volRoot := filepath.Dir(path) + // Root dir does not need to be accessed by the remapped root + if err := idtools.MkdirAllAndChown(volRoot, 0701, idtools.CurrentIdentity()); err != nil { + return nil, errors.Wrapf(errdefs.System(err), "error while creating volume root path '%s'", volRoot) + } + + // Remapped root does need access to the data path if err := idtools.MkdirAllAndChown(path, 0755, r.rootIdentity); err != nil { - return nil, errors.Wrapf(errdefs.System(err), "error while creating volume path '%s'", path) + return nil, errors.Wrapf(errdefs.System(err), "error while creating volume data path '%s'", path) } var err error