!18 fix CVE-2020-28914
From: @xinghe_1 Reviewed-by: @flyflyflypeng Signed-off-by: @flyflyflypeng
This commit is contained in:
commit
25ec45d46d
@ -2,7 +2,7 @@
|
|||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
|
|
||||||
%define VERSION v1.11.1
|
%define VERSION v1.11.1
|
||||||
%define RELEASE 9
|
%define RELEASE 10
|
||||||
|
|
||||||
Name: kata-containers
|
Name: kata-containers
|
||||||
Version: %{VERSION}
|
Version: %{VERSION}
|
||||||
@ -90,6 +90,12 @@ install -p -m 640 -D ./runtime/cli/config/configuration-qemu.toml %{buildroot}/u
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Feb 19 2021 xinghe <xinghe1@huawei.com> - 1.11.1-10
|
||||||
|
- Type:CVE
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix CVE-2020-28914
|
||||||
|
|
||||||
* Fri Jan 8 2021 LiangZhang<zhangliang5@huawei.com> - 1.11.1-9
|
* Fri Jan 8 2021 LiangZhang<zhangliang5@huawei.com> - 1.11.1-9
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
78
runtime/patches/0066-CVE-2020-28914-1.patch
Normal file
78
runtime/patches/0066-CVE-2020-28914-1.patch
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
From 228e6eb4b9c000fb105e3bf1401ac3938588fae2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peng Tao <bergwolf@hyper.sh>
|
||||||
|
Date: Fri, 30 Oct 2020 14:54:49 +0800
|
||||||
|
Subject: [PATCH] runtime: readonly mounts should be readonly bindmount on the
|
||||||
|
host
|
||||||
|
|
||||||
|
So that we get protected at the VM boundary not just the guest kernel.
|
||||||
|
|
||||||
|
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
|
||||||
|
Reference: https://github.com/kata-containers/runtime/commit/228e6eb4b9c000fb105e3bf1401ac3938588fae2
|
||||||
|
https://github.com/kata-containers/community/blob/master/VMT/KCSA/KCSA-CVE-2020-28914.md
|
||||||
|
(cherry picked from commit 509eb6f850c0ceb60eb91a6095cceb8e4c7150f5)
|
||||||
|
---
|
||||||
|
virtcontainers/container.go | 14 ++------------
|
||||||
|
virtcontainers/pkg/oci/utils.go | 8 ++++++++
|
||||||
|
2 files changed, 10 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/virtcontainers/container.go b/virtcontainers/container.go
|
||||||
|
index 88863ec42..6973c8328 100644
|
||||||
|
--- a/virtcontainers/container.go
|
||||||
|
+++ b/virtcontainers/container.go
|
||||||
|
@@ -481,7 +481,7 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
|
||||||
|
} else {
|
||||||
|
// These mounts are created in the shared dir
|
||||||
|
mountDest := filepath.Join(hostSharedDir, filename)
|
||||||
|
- if err := bindMount(c.ctx, m.Source, mountDest, false, "private"); err != nil {
|
||||||
|
+ if err := bindMount(c.ctx, m.Source, mountDest, m.ReadOnly, "private"); err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
// Save HostPath mount value into the mount list of the container.
|
||||||
|
@@ -557,22 +557,12 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Check if mount is readonly, let the agent handle the readonly mount
|
||||||
|
- // within the VM.
|
||||||
|
- readonly := false
|
||||||
|
- for _, flag := range m.Options {
|
||||||
|
- if flag == "ro" {
|
||||||
|
- readonly = true
|
||||||
|
- break
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
sharedDirMount := Mount{
|
||||||
|
Source: guestDest,
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Options: m.Options,
|
||||||
|
- ReadOnly: readonly,
|
||||||
|
+ ReadOnly: m.ReadOnly,
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedDirMounts[sharedDirMount.Destination] = sharedDirMount
|
||||||
|
diff --git a/virtcontainers/pkg/oci/utils.go b/virtcontainers/pkg/oci/utils.go
|
||||||
|
index 0832a757c..9701df3d5 100644
|
||||||
|
--- a/virtcontainers/pkg/oci/utils.go
|
||||||
|
+++ b/virtcontainers/pkg/oci/utils.go
|
||||||
|
@@ -162,11 +162,19 @@ func cmdEnvs(spec specs.Spec, envs []types.EnvVar) []types.EnvVar {
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMount(m specs.Mount) vc.Mount {
|
||||||
|
+ readonly := false
|
||||||
|
+ for _, flag := range m.Options {
|
||||||
|
+ if flag == "ro" {
|
||||||
|
+ readonly = true
|
||||||
|
+ break
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
return vc.Mount{
|
||||||
|
Source: m.Source,
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Options: m.Options,
|
||||||
|
+ ReadOnly: readonly,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
141
runtime/patches/0067-CVE-2020-28914-2.patch
Normal file
141
runtime/patches/0067-CVE-2020-28914-2.patch
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
From 3f0e61c010556846e2f96811059d86cb10309748 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peng Tao <bergwolf@hyper.sh>
|
||||||
|
Date: Fri, 30 Oct 2020 17:40:12 +0800
|
||||||
|
Subject: [PATCH] runtime: mount shared mountpoint readonly
|
||||||
|
|
||||||
|
bindmount remount events are not propagated through mount subtrees,
|
||||||
|
so we have to remount the shared dir mountpoint directly.
|
||||||
|
|
||||||
|
E.g.,
|
||||||
|
```
|
||||||
|
mkdir -p source dest foo source/foo
|
||||||
|
|
||||||
|
mount -o bind --make-shared source dest
|
||||||
|
|
||||||
|
mount -o bind foo source/foo
|
||||||
|
echo bind mount rw
|
||||||
|
mount | grep foo
|
||||||
|
echo remount ro
|
||||||
|
mount -o remount,bind,ro source/foo
|
||||||
|
mount | grep foo
|
||||||
|
```
|
||||||
|
would result in:
|
||||||
|
```
|
||||||
|
bind mount rw
|
||||||
|
/dev/xvda1 on /home/ubuntu/source/foo type ext4 (rw,relatime,discard,data=ordered)
|
||||||
|
/dev/xvda1 on /home/ubuntu/dest/foo type ext4 (rw,relatime,discard,data=ordered)
|
||||||
|
remount ro
|
||||||
|
/dev/xvda1 on /home/ubuntu/source/foo type ext4 (ro,relatime,discard,data=ordered)
|
||||||
|
/dev/xvda1 on /home/ubuntu/dest/foo type ext4 (rw,relatime,discard,data=ordered)
|
||||||
|
```
|
||||||
|
|
||||||
|
The reason is that bind mount creats new mount structs and attaches them to different mount subtrees.
|
||||||
|
However, MS_REMOUNT only looks for existing mount structs to modify and does not try to propagate the
|
||||||
|
change to mount structs in other subtrees.
|
||||||
|
|
||||||
|
Fixes: #3041
|
||||||
|
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
|
||||||
|
Reference: https://github.com/kata-containers/runtime/commit/3f0e61c010556846e2f96811059d86cb10309748
|
||||||
|
https://github.com/kata-containers/community/blob/master/VMT/KCSA/KCSA-CVE-2020-28914.md
|
||||||
|
(cherry picked from commit 77399058bf3ded60aaeb08978073d000f178478f)
|
||||||
|
---
|
||||||
|
virtcontainers/container.go | 15 +++++++++++----
|
||||||
|
virtcontainers/kata_agent.go | 2 +-
|
||||||
|
virtcontainers/mount.go | 5 +++++
|
||||||
|
virtcontainers/sandbox_test.go | 2 +-
|
||||||
|
4 files changed, 18 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/virtcontainers/container.go b/virtcontainers/container.go
|
||||||
|
index 6973c8328..37117d7e3 100644
|
||||||
|
--- a/virtcontainers/container.go
|
||||||
|
+++ b/virtcontainers/container.go
|
||||||
|
@@ -446,7 +446,7 @@ func (c *Container) setContainerState(state types.StateString) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
-func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir string) (string, bool, error) {
|
||||||
|
+func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, hostMountDir, guestSharedDir string) (string, bool, error) {
|
||||||
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
@@ -480,12 +480,19 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// These mounts are created in the shared dir
|
||||||
|
- mountDest := filepath.Join(hostSharedDir, filename)
|
||||||
|
+ mountDest := filepath.Join(hostMountDir, filename)
|
||||||
|
if err := bindMount(c.ctx, m.Source, mountDest, m.ReadOnly, "private"); err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
// Save HostPath mount value into the mount list of the container.
|
||||||
|
c.mounts[idx].HostPath = mountDest
|
||||||
|
+ // bindmount remount event is not propagated to mount subtrees, so we have to remount the shared dir mountpoint directly.
|
||||||
|
+ if m.ReadOnly {
|
||||||
|
+ mountDest = filepath.Join(hostSharedDir, filename)
|
||||||
|
+ if err := remountRo(c.ctx, mountDest); err != nil {
|
||||||
|
+ return "", false, err
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
return guestDest, false, nil
|
||||||
|
@@ -496,7 +503,7 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
|
||||||
|
// It also updates the container mount list with the HostPath info, and store
|
||||||
|
// container mounts to the storage. This way, we will have the HostPath info
|
||||||
|
// available when we will need to unmount those mounts.
|
||||||
|
-func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (sharedDirMounts map[string]Mount, ignoredMounts map[string]Mount, err error) {
|
||||||
|
+func (c *Container) mountSharedDirMounts(hostSharedDir, hostMountDir, guestSharedDir string) (sharedDirMounts map[string]Mount, ignoredMounts map[string]Mount, err error) {
|
||||||
|
sharedDirMounts = make(map[string]Mount)
|
||||||
|
ignoredMounts = make(map[string]Mount)
|
||||||
|
var devicesToDetach []string
|
||||||
|
@@ -546,7 +553,7 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (
|
||||||
|
|
||||||
|
var ignore bool
|
||||||
|
var guestDest string
|
||||||
|
- guestDest, ignore, err = c.shareFiles(m, idx, hostSharedDir, guestSharedDir)
|
||||||
|
+ guestDest, ignore, err = c.shareFiles(m, idx, hostSharedDir, hostMountDir, guestSharedDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go
|
||||||
|
index a308952a8..a26e0411b 100644
|
||||||
|
--- a/virtcontainers/kata_agent.go
|
||||||
|
+++ b/virtcontainers/kata_agent.go
|
||||||
|
@@ -1387,7 +1387,7 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle container mounts
|
||||||
|
- newMounts, ignoredMounts, err := c.mountSharedDirMounts(getMountPath(sandbox.id), kataGuestSharedDir())
|
||||||
|
+ newMounts, ignoredMounts, err := c.mountSharedDirMounts(getSharePath(sandbox.id), getMountPath(sandbox.id), kataGuestSharedDir())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
diff --git a/virtcontainers/mount.go b/virtcontainers/mount.go
|
||||||
|
index ab9e9f8d0..2f9846e80 100644
|
||||||
|
--- a/virtcontainers/mount.go
|
||||||
|
+++ b/virtcontainers/mount.go
|
||||||
|
@@ -273,6 +273,11 @@ func remount(ctx context.Context, mountflags uintptr, src string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
+// remount a mount point as readonly
|
||||||
|
+func remountRo(ctx context.Context, src string) error {
|
||||||
|
+ return remount(ctx, syscall.MS_BIND|syscall.MS_RDONLY, src)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// bindMountContainerRootfs bind mounts a container rootfs into a 9pfs shared
|
||||||
|
// directory between the guest and the host.
|
||||||
|
func bindMountContainerRootfs(ctx context.Context, shareDir, cid, cRootFs string, readonly bool) error {
|
||||||
|
diff --git a/virtcontainers/sandbox_test.go b/virtcontainers/sandbox_test.go
|
||||||
|
index 55e0ffea0..9f9d50ac1 100644
|
||||||
|
--- a/virtcontainers/sandbox_test.go
|
||||||
|
+++ b/virtcontainers/sandbox_test.go
|
||||||
|
@@ -1377,7 +1377,7 @@ func TestPreAddDevice(t *testing.T) {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
- mounts, ignoreMounts, err := container.mountSharedDirMounts("", "")
|
||||||
|
+ mounts, ignoreMounts, err := container.mountSharedDirMounts("", "", "")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, len(mounts), 0,
|
||||||
|
"mounts should contain nothing because it only contains a block device")
|
||||||
Loading…
x
Reference in New Issue
Block a user