diff --git a/VERSION-openeuler b/VERSION-openeuler index 4c8886863f01a5514cb85ae56a51eba6b9108007..d20060fab9bf679126f3aa9b84aac7befe3c4f84 100644 --- a/VERSION-openeuler +++ b/VERSION-openeuler @@ -1 +1 @@ -18.09.0.105 +18.09.0.201 diff --git a/docker-engine-openeuler.spec b/docker-engine-openeuler.spec index 82f596909d32d1ada671cfef99d8a40a7fcd565c..f6be62fa9499fd4e5457924d81bb4bf3b3e045e6 100644 --- a/docker-engine-openeuler.spec +++ b/docker-engine-openeuler.spec @@ -1,6 +1,6 @@ Name: docker-engine Version: 18.09.0 -Release: 105 +Release: 201 Summary: The open-source application container engine Group: Tools/Docker @@ -200,6 +200,20 @@ fi %endif %changelog +* Wed Feb 24 2021 xiadanni - 18.09.0-201 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Fix Access to remapped root allows privilege escalation to real root (CVE-2021-21284) + +* Wed Feb 9 2021 xiadanni - 18.09.0-200 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:sync bugfix and bump version to 200, bugfix include + 1. fix execCommands leak in health-check. + 2. check containerd pid before kill it. + * Mon Jan 18 2021 jingrui - 18.09.0-105 - Type:bugfix - ID:NA diff --git a/patch/0186-docker-fix-execCommands-leak-in-health-check.patch b/patch/0186-docker-fix-execCommands-leak-in-health-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..48ab5c0231e02bdca4ec327281ac495885f7b2f0 --- /dev/null +++ b/patch/0186-docker-fix-execCommands-leak-in-health-check.patch @@ -0,0 +1,67 @@ +From 83ef8cfec0df0388bb92788d9c3ec2a306ab7f20 Mon Sep 17 00:00:00 2001 +From: jingrui +Date: Wed, 20 Jan 2021 17:07:12 +0800 +Subject: [PATCH] docker: fix execCommands leak in health-check + +Change-Id: I6bd02bc4a8e08b8de58bc454be8944c73175b3ae +Signed-off-by: jingrui +--- + components/engine/daemon/daemon.go | 5 +---- + components/engine/daemon/exec/exec.go | 7 +++++++ + components/engine/daemon/health.go | 2 +- + 3 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go +index ed268d2c4f..57ad832eb2 100644 +--- a/components/engine/daemon/daemon.go ++++ b/components/engine/daemon/daemon.go +@@ -404,10 +404,6 @@ func (daemon *Daemon) restore() error { + if c.IsRunning() || c.IsPaused() { + c.RestartManager().Cancel() // manually start containers because some need to wait for swarm networking + +- c.Lock() +- daemon.initHealthMonitor(c) +- c.Unlock() +- + if c.IsPaused() && alive { + s, err := daemon.containerd.Status(context.Background(), c.ID) + if err != nil { +@@ -450,6 +446,7 @@ func (daemon *Daemon) restore() error { + + if getProbe(c) != nil { + c.Lock() ++ daemon.initHealthMonitor(c) + if err := c.CheckpointTo(daemon.containersReplica); err != nil { + logrus.WithError(err).WithField("container", c.ID). + Error("Failed to checkpoint container state") +diff --git a/components/engine/daemon/exec/exec.go b/components/engine/daemon/exec/exec.go +index 08fc87c4b0..47644fc158 100644 +--- a/components/engine/daemon/exec/exec.go ++++ b/components/engine/daemon/exec/exec.go +@@ -145,3 +145,10 @@ func (e *Store) List() []string { + e.RUnlock() + return IDs + } ++ ++func (e *Store) Size() int { ++ e.RLock() ++ num := len(e.byID) ++ e.RUnlock() ++ return num ++} +diff --git a/components/engine/daemon/health.go b/components/engine/daemon/health.go +index 5f26ee5db8..c181850309 100644 +--- a/components/engine/daemon/health.go ++++ b/components/engine/daemon/health.go +@@ -202,7 +202,7 @@ func monitor(d *Daemon, c *container.Container, stop chan struct{}, probe probe) + result, err := probe.run(ctx, d, c) + if err != nil { + healthChecksFailedCounter.Inc() +- logrus.Warnf("Health check for container %s error: %v", c.ID, err) ++ logrus.Warnf("exec-cmds=%d Health check for container %s error: %v", c.ExecCommands.Size(), c.ID, err) + results <- &types.HealthcheckResult{ + ExitCode: -1, + Output: err.Error(), +-- +2.17.1 + diff --git a/patch/0188-docker-check-containerd-pid-before-kill-it.patch b/patch/0188-docker-check-containerd-pid-before-kill-it.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e623579707d9d5bed995788dec3ade04a891e59 --- /dev/null +++ b/patch/0188-docker-check-containerd-pid-before-kill-it.patch @@ -0,0 +1,121 @@ +From eda3fe6001fcf911e4630818514df6ad6531417d Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Thu, 28 Jan 2021 16:02:47 +0800 +Subject: [PATCH] docker: check containerd pid before kill it + +Signed-off-by: xiadanni +--- + .../libcontainerd/supervisor/remote_daemon.go | 6 ++++++ + .../libcontainerd/supervisor/remote_daemon_linux.go | 15 +++++++++++---- + components/engine/utils/utils.go | 21 +++++++++++++++++++++ + 3 files changed, 38 insertions(+), 4 deletions(-) + +diff --git a/components/engine/libcontainerd/supervisor/remote_daemon.go b/components/engine/libcontainerd/supervisor/remote_daemon.go +index 19582cd..5cb6de0 100644 +--- a/components/engine/libcontainerd/supervisor/remote_daemon.go ++++ b/components/engine/libcontainerd/supervisor/remote_daemon.go +@@ -18,6 +18,7 @@ import ( + "github.com/containerd/containerd" + "github.com/containerd/containerd/services/server" + "github.com/docker/docker/pkg/system" ++ "github.com/docker/docker/utils" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" +@@ -139,6 +140,11 @@ func (r *remote) getContainerdPid() (int, error) { + if err != nil { + return -1, err + } ++ ++ if !utils.IsContainerdPid(int(pid)) { ++ return -1, nil ++ } ++ + if system.IsProcessAlive(int(pid)) { + return int(pid), nil + } +diff --git a/components/engine/libcontainerd/supervisor/remote_daemon_linux.go b/components/engine/libcontainerd/supervisor/remote_daemon_linux.go +index 799399c..3ccd38b 100644 +--- a/components/engine/libcontainerd/supervisor/remote_daemon_linux.go ++++ b/components/engine/libcontainerd/supervisor/remote_daemon_linux.go +@@ -8,6 +8,7 @@ import ( + + "github.com/containerd/containerd/defaults" + "github.com/docker/docker/pkg/system" ++ "github.com/docker/docker/utils" + ) + + const ( +@@ -42,7 +43,7 @@ func (r *remote) setDefaults() { + + func (r *remote) stopDaemon() { + // Ask the daemon to quit +- syscall.Kill(r.daemonPid, syscall.SIGTERM) ++ DoKillContainerd(r.daemonPid, syscall.SIGTERM) + // Wait up to 15secs for it to stop + for i := time.Duration(0); i < shutdownTimeout; i += time.Second { + if !system.IsProcessAlive(r.daemonPid) { +@@ -53,15 +54,21 @@ func (r *remote) stopDaemon() { + + if system.IsProcessAlive(r.daemonPid) { + r.logger.WithField("pid", r.daemonPid).Warn("daemon didn't stop within 15 secs, killing it") +- syscall.Kill(r.daemonPid, syscall.SIGKILL) ++ DoKillContainerd(r.daemonPid, syscall.SIGKILL) ++ } ++} ++ ++func DoKillContainerd(pid int, sig syscall.Signal) { ++ if utils.IsContainerdPid(pid) { ++ syscall.Kill(pid, sig) + } + } + + func (r *remote) killDaemon() { + // Try to get a stack trace +- syscall.Kill(r.daemonPid, syscall.SIGUSR1) ++ DoKillContainerd(r.daemonPid, syscall.SIGUSR1) + <-time.After(100 * time.Millisecond) +- system.KillProcess(r.daemonPid) ++ DoKillContainerd(r.daemonPid, syscall.SIGKILL) + } + + func (r *remote) platformCleanup() { +diff --git a/components/engine/utils/utils.go b/components/engine/utils/utils.go +index 53893fc..c394456 100644 +--- a/components/engine/utils/utils.go ++++ b/components/engine/utils/utils.go +@@ -19,6 +19,12 @@ int mysemctl(int cmd, struct seminfo *p){ + import "C" + import ( + "fmt" ++ "io/ioutil" ++ "path/filepath" ++ "strconv" ++ "strings" ++ ++ "github.com/sirupsen/logrus" + ) + + func CheckSemSetStat() (int, int, error) { +@@ -30,3 +36,18 @@ func CheckSemSetStat() (int, int, error) { + } + return int(seminfo.semusz), int(seminfo.semmni), err + } ++ ++func IsContainerdPid(pid int) bool { ++ if pid <= 1 { ++ logrus.Warnf("pid %d is not containerd", pid) ++ return false ++ } ++ ++ cmdlineBytes, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "cmdline")) ++ if err == nil && !strings.Contains(string(cmdlineBytes), "containerd") { ++ logrus.Warnf("pid %d is not containerd, cmdline: %s", pid, string(cmdlineBytes)) ++ return false ++ } ++ ++ return true ++} +-- +1.8.3.1 + diff --git a/patch/0189-docker-fix-Access-to-remapped-root-allows-privilege-.patch b/patch/0189-docker-fix-Access-to-remapped-root-allows-privilege-.patch new file mode 100644 index 0000000000000000000000000000000000000000..bd64cdb5a78336236edda343d3971d73efa428ad --- /dev/null +++ b/patch/0189-docker-fix-Access-to-remapped-root-allows-privilege-.patch @@ -0,0 +1,446 @@ +From 870a0fb061a51d96b3e4f56c12a3819c3865182c Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Wed, 24 Feb 2021 16:27:51 +0800 +Subject: [PATCH] Fix Access to remapped root allows privilege escalation to + real root(CVE-2021-21284) + +Signed-off-by: xiadanni +--- + components/engine/daemon/container_operations_unix.go | 2 +- + components/engine/daemon/create.go | 5 ++--- + components/engine/daemon/daemon.go | 10 ++++------ + components/engine/daemon/daemon_unix.go | 14 ++++++++++---- + components/engine/daemon/graphdriver/aufs/aufs.go | 9 +++------ + components/engine/daemon/graphdriver/btrfs/btrfs.go | 10 +++------- + components/engine/daemon/graphdriver/overlay/overlay.go | 16 +++++++--------- + components/engine/daemon/graphdriver/overlay2/overlay.go | 12 ++++-------- + components/engine/daemon/graphdriver/vfs/driver.go | 5 ++--- + components/engine/daemon/graphdriver/zfs/zfs.go | 6 +----- + components/engine/pkg/idtools/idtools.go | 11 ++++++++--- + components/engine/pkg/idtools/idtools_unix.go | 14 ++++++++++---- + components/engine/volume/local/local.go | 11 +++++++++-- + 13 files changed, 64 insertions(+), 61 deletions(-) + +diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go +index df2f326..ff2d772 100644 +--- a/components/engine/daemon/container_operations_unix.go ++++ b/components/engine/daemon/container_operations_unix.go +@@ -425,5 +425,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/components/engine/daemon/create.go b/components/engine/daemon/create.go +index 7733d7b..4d083e7 100644 +--- a/components/engine/daemon/create.go ++++ b/components/engine/daemon/create.go +@@ -190,11 +190,10 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) ( + return nil, err + } + +- rootIDs := daemon.idMapping.RootPair() +- if err := idtools.MkdirAndChown(container.Root, 0700, rootIDs); err != nil { ++ if err := idtools.MkdirAndChown(container.Root, 0701, idtools.CurrentIdentity()); err != nil { + return nil, err + } +- if err := idtools.MkdirAndChown(container.CheckpointDir(), 0700, rootIDs); err != nil { ++ if err := idtools.MkdirAndChown(container.CheckpointDir(), 0700, idtools.CurrentIdentity()); err != nil { + return nil, err + } + +diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go +index 57ad832..b3039ab 100644 +--- a/components/engine/daemon/daemon.go ++++ b/components/engine/daemon/daemon.go +@@ -849,7 +849,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) + } +@@ -913,7 +913,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 + } + +@@ -1422,7 +1422,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") +@@ -1440,9 +1440,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 { +diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go +index af50fa3..07a0aa0 100644 +--- a/components/engine/daemon/daemon_unix.go ++++ b/components/engine/daemon/daemon_unix.go +@@ -1271,7 +1271,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 +@@ -1296,10 +1296,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 +@@ -1312,7 +1318,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/components/engine/daemon/graphdriver/aufs/aufs.go b/components/engine/daemon/graphdriver/aufs/aufs.go +index eef8387..4ee3682 100644 +--- a/components/engine/daemon/graphdriver/aufs/aufs.go ++++ b/components/engine/daemon/graphdriver/aufs/aufs.go +@@ -130,18 +130,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/components/engine/daemon/graphdriver/btrfs/btrfs.go b/components/engine/daemon/graphdriver/btrfs/btrfs.go +index 7d1f9dc..d76e144 100644 +--- a/components/engine/daemon/graphdriver/btrfs/btrfs.go ++++ b/components/engine/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 + } + +@@ -535,7 +531,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 == "" { +@@ -570,7 +566,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/components/engine/daemon/graphdriver/overlay/overlay.go b/components/engine/daemon/graphdriver/overlay/overlay.go +index 7dbeec5..a9e65a3 100644 +--- a/components/engine/daemon/graphdriver/overlay/overlay.go ++++ b/components/engine/daemon/graphdriver/overlay/overlay.go +@@ -163,12 +163,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 + } + +@@ -303,10 +299,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 + } + +@@ -319,6 +316,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) + } + +@@ -339,7 +337,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 +@@ -349,7 +347,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/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go +index 7fac2c3..7576320 100644 +--- a/components/engine/daemon/graphdriver/overlay2/overlay.go ++++ b/components/engine/daemon/graphdriver/overlay2/overlay.go +@@ -197,12 +197,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 + } + +@@ -429,11 +424,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/components/engine/daemon/graphdriver/vfs/driver.go b/components/engine/daemon/graphdriver/vfs/driver.go +index 6b9e92e..15ac251 100644 +--- a/components/engine/daemon/graphdriver/vfs/driver.go ++++ b/components/engine/daemon/graphdriver/vfs/driver.go +@@ -30,8 +30,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap + home: home, + idMapping: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), + } +- 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 + } + +@@ -116,7 +115,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/components/engine/daemon/graphdriver/zfs/zfs.go b/components/engine/daemon/graphdriver/zfs/zfs.go +index e595809..4484c51 100644 +--- a/components/engine/daemon/graphdriver/zfs/zfs.go ++++ b/components/engine/daemon/graphdriver/zfs/zfs.go +@@ -102,11 +102,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/components/engine/pkg/idtools/idtools.go b/components/engine/pkg/idtools/idtools.go +index 230422e..3e2ce75 100644 +--- a/components/engine/pkg/idtools/idtools.go ++++ b/components/engine/pkg/idtools/idtools.go +@@ -36,13 +36,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 { +@@ -51,7 +51,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) + } +@@ -265,3 +265,8 @@ func parseSubidFile(path, username string) (ranges, error) { + } + return rangeList, nil + } ++ ++// CurrentIdentity returns the identity of the current process ++func CurrentIdentity() Identity { ++ return Identity{UID: os.Getuid(), GID: os.Getegid()} ++} +diff --git a/components/engine/pkg/idtools/idtools_unix.go b/components/engine/pkg/idtools/idtools_unix.go +index fb23974..329d5d0 100644 +--- a/components/engine/pkg/idtools/idtools_unix.go ++++ b/components/engine/pkg/idtools/idtools_unix.go +@@ -39,7 +39,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) { +@@ -70,7 +70,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(args 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 + } +diff --git a/components/engine/volume/local/local.go b/components/engine/volume/local/local.go +index ffdc61a..585f910 100644 +--- a/components/engine/volume/local/local.go ++++ b/components/engine/volume/local/local.go +@@ -49,7 +49,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 +-- +1.8.3.1 + diff --git a/series.conf b/series.conf index 13fd73b4201a12d790845768a07571f307dfd103..f836d773c2cf579a3492d688419856856e81d143 100644 --- a/series.conf +++ b/series.conf @@ -180,4 +180,7 @@ patch/0181-docker-do-not-return-when-matched-registry-mirror.patch patch/0183-add-masked-paths-pagealloc_module-and-slaballoc_stat.patch patch/0184-docker-wait-io-with-timeout-when-process-Start-faile.patch patch/0185-docker-delete-image-reference-when-failed-to-get-ima.patch +patch/0186-docker-fix-execCommands-leak-in-health-check.patch +patch/0188-docker-check-containerd-pid-before-kill-it.patch +patch/0189-docker-fix-Access-to-remapped-root-allows-privilege-.patch #end