docker:sync bugfix and fix CVE-2021-21284 2021-21285
1.fix execCommands leak in health-check 2.check containerd pid before kill it 3.fix CVE-2021-21284 4.fix CVE-2021-21285 Change-Id: I2fe1dd40281f1786ecc63ff19d416b113710e611 Signed-off-by: xiadanni <xiadanni1@huawei.com>
This commit is contained in:
parent
773302aeb3
commit
1bae2e5ea3
12
docker.spec
12
docker.spec
@ -1,6 +1,6 @@
|
||||
Name: docker-engine
|
||||
Version: 18.09.0
|
||||
Release: 113
|
||||
Release: 114
|
||||
Summary: The open-source application container engine
|
||||
Group: Tools/Docker
|
||||
|
||||
@ -211,6 +211,16 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Mar 18 2021 xiadanni<xiadanni1@huawei.com> - 18.09.0-114
|
||||
- Type:bugfix
|
||||
- CVE:CVE-2021-21284,CVE-2021-21285
|
||||
- SUG:NA
|
||||
- DESC:sync bugfix, include:
|
||||
1.fix execCommands leak in health-check
|
||||
2.check containerd pid before kill it
|
||||
3.fix CVE-2021-21284
|
||||
4.fix CVE-2021-21285
|
||||
|
||||
* Tue Feb 09 2021 lixiang<lixiang172@huawei.com> - 18.09.0-113
|
||||
- Type:enhancement
|
||||
- CVE:NA
|
||||
|
||||
@ -1 +1 @@
|
||||
e9d595711a6ccf4cc603740dddbb3655c6b7d922
|
||||
I2fe1dd40281f1786ecc63ff19d416b113710e611
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
From 83ef8cfec0df0388bb92788d9c3ec2a306ab7f20 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
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 <jingrui@huawei.com>
|
||||
---
|
||||
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
|
||||
|
||||
121
patch/0188-docker-check-containerd-pid-before-kill-it.patch
Normal file
121
patch/0188-docker-check-containerd-pid-before-kill-it.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From eda3fe6001fcf911e4630818514df6ad6531417d Mon Sep 17 00:00:00 2001
|
||||
From: xiadanni <xiadanni1@huawei.com>
|
||||
Date: Thu, 28 Jan 2021 16:02:47 +0800
|
||||
Subject: [PATCH] docker: check containerd pid before kill it
|
||||
|
||||
Signed-off-by: xiadanni <xiadanni1@huawei.com>
|
||||
---
|
||||
.../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
|
||||
|
||||
@ -0,0 +1,446 @@
|
||||
From 870a0fb061a51d96b3e4f56c12a3819c3865182c Mon Sep 17 00:00:00 2001
|
||||
From: xiadanni <xiadanni1@huawei.com>
|
||||
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 <xiadanni1@huawei.com>
|
||||
---
|
||||
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
|
||||
|
||||
54
patch/0190-docker-fix-CVE-2021-21285.patch
Normal file
54
patch/0190-docker-fix-CVE-2021-21285.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From c6870e57fa9f7667c59dd21abd6e8034509b6ada Mon Sep 17 00:00:00 2001
|
||||
From: xiadanni <xiadanni1@huawei.com>
|
||||
Date: Thu, 18 Mar 2021 14:41:15 +0800
|
||||
Subject: [PATCH] docker: prevent an invalid image from crashing docker daemon
|
||||
(CVE-2021-21285)
|
||||
|
||||
Change-Id: I0cf6a1b268e500a2a004c9d9d33f01a3d4ad5b47
|
||||
Signed-off-by: xiadanni <xiadanni1@huawei.com>
|
||||
---
|
||||
.../engine/builder/builder-next/adapters/containerimage/pull.go | 3 +++
|
||||
components/engine/distribution/pull_v2.go | 6 ++++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/components/engine/builder/builder-next/adapters/containerimage/pull.go b/components/engine/builder/builder-next/adapters/containerimage/pull.go
|
||||
index f6e55f4..4b6eb04 100644
|
||||
--- a/components/engine/builder/builder-next/adapters/containerimage/pull.go
|
||||
+++ b/components/engine/builder/builder-next/adapters/containerimage/pull.go
|
||||
@@ -493,6 +493,9 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
|
||||
layers := make([]xfer.DownloadDescriptor, 0, len(mfst.Layers))
|
||||
|
||||
for i, desc := range mfst.Layers {
|
||||
+ if err := desc.Digest.Validate(); err != nil {
|
||||
+ return nil, errors.Wrap(err, "layer digest could not be validated")
|
||||
+ }
|
||||
ongoing.add(desc)
|
||||
layers = append(layers, &layerDescriptor{
|
||||
desc: desc,
|
||||
diff --git a/components/engine/distribution/pull_v2.go b/components/engine/distribution/pull_v2.go
|
||||
index 4150241..98714fd 100644
|
||||
--- a/components/engine/distribution/pull_v2.go
|
||||
+++ b/components/engine/distribution/pull_v2.go
|
||||
@@ -480,6 +480,9 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unv
|
||||
// to top-most, so that the downloads slice gets ordered correctly.
|
||||
for i := len(verifiedManifest.FSLayers) - 1; i >= 0; i-- {
|
||||
blobSum := verifiedManifest.FSLayers[i].BlobSum
|
||||
+ if err = blobSum.Validate(); err != nil {
|
||||
+ return "", "", errors.Wrapf(err, "could not validate layer digest %q", blobSum)
|
||||
+ }
|
||||
|
||||
var throwAway struct {
|
||||
ThrowAway bool `json:"throwaway,omitempty"`
|
||||
@@ -596,6 +599,9 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
|
||||
// Note that the order of this loop is in the direction of bottom-most
|
||||
// to top-most, so that the downloads slice gets ordered correctly.
|
||||
for _, d := range mfst.Layers {
|
||||
+ if err := d.Digest.Validate(); err != nil {
|
||||
+ return "", "", errors.Wrapf(err, "could not validate layer digest %q", d.Digest)
|
||||
+ }
|
||||
layerDescriptor := &v2LayerDescriptor{
|
||||
digest: d.Digest,
|
||||
repo: p.repo,
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -184,5 +184,8 @@ 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
|
||||
patch/0190-docker-fix-CVE-2021-21285.patch
|
||||
#end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user