121 lines
3.7 KiB
Diff
121 lines
3.7 KiB
Diff
|
|
From 0b0bb50e4ecdebfb2646adb57e53972663947320 Mon Sep 17 00:00:00 2001
|
||
|
|
From: wangfengtu <wangfengtu@huawei.com>
|
||
|
|
Date: Wed, 27 Mar 2019 15:28:03 +0800
|
||
|
|
Subject: [PATCH] runc: Fix mountpoint leak and pivot_root error
|
||
|
|
|
||
|
|
reason:We have no way to get exact /proc/self/mountinfo infomation
|
||
|
|
because it can change if other process mount/umount mountpoint. So
|
||
|
|
runc sometimes cannot get container's mountpoint when runc try to
|
||
|
|
make mountpoint private. This can cause mountpoint leak and pivot_root
|
||
|
|
error, runc error out like this:
|
||
|
|
```
|
||
|
|
Handler for POST
|
||
|
|
/v1.23/containers/1d265651cb1d5475bcb7d5db21679757d5527d44a41c102c6aa4bddaa518c547/start
|
||
|
|
returned error: oci runtime error: container_linux.go:317: starting
|
||
|
|
container process caused \"process_linux.go:358: container init caused
|
||
|
|
\\\"rootfs_linux.go:105: jailing process inside rootfs caused
|
||
|
|
\\\\\\\"pivot_root invalid argument\\\\\\\"\\\"\"\n
|
||
|
|
```
|
||
|
|
|
||
|
|
Change-Id: Icde1638af6ad45c762c11fc8a2b8a969b6306ca5
|
||
|
|
Signed-off-by: wangfengtu <wangfengtu@huawei.com>
|
||
|
|
---
|
||
|
|
libcontainer/rootfs_linux.go | 32 ++++++++++++----------
|
||
|
|
.../docker/docker/pkg/mount/mountinfo_linux.go | 7 +++--
|
||
|
|
2 files changed, 21 insertions(+), 18 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
|
||
|
|
index 3dd5113..53797e9 100644
|
||
|
|
--- a/libcontainer/rootfs_linux.go
|
||
|
|
+++ b/libcontainer/rootfs_linux.go
|
||
|
|
@@ -24,7 +24,10 @@ import (
|
||
|
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||
|
|
)
|
||
|
|
|
||
|
|
-const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
|
||
|
|
+const (
|
||
|
|
+ defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
|
||
|
|
+ maxRetryTimes = 5
|
||
|
|
+)
|
||
|
|
|
||
|
|
// needsSetupDev returns true if /dev needs to be set up.
|
||
|
|
func needsSetupDev(config *configs.Config) bool {
|
||
|
|
@@ -545,23 +548,16 @@ func getMountInfo(mountinfo []*mount.Info, dir string) *mount.Info {
|
||
|
|
// Get the parent mount point of directory passed in as argument. Also return
|
||
|
|
// optional fields.
|
||
|
|
func getParentMount(rootfs string) (string, string, error) {
|
||
|
|
- var path string
|
||
|
|
-
|
||
|
|
- mountinfos, err := mount.GetMounts()
|
||
|
|
- if err != nil {
|
||
|
|
- return "", "", err
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- mountinfo := getMountInfo(mountinfos, rootfs)
|
||
|
|
- if mountinfo != nil {
|
||
|
|
- return rootfs, mountinfo.Optional, nil
|
||
|
|
- }
|
||
|
|
+ retryTimes := maxRetryTimes
|
||
|
|
+ path := rootfs
|
||
|
|
|
||
|
|
- path = rootfs
|
||
|
|
for {
|
||
|
|
- path = filepath.Dir(path)
|
||
|
|
+ mountinfos, err := mount.GetMounts()
|
||
|
|
+ if err != nil {
|
||
|
|
+ return "", "", err
|
||
|
|
+ }
|
||
|
|
|
||
|
|
- mountinfo = getMountInfo(mountinfos, path)
|
||
|
|
+ mountinfo := getMountInfo(mountinfos, path)
|
||
|
|
if mountinfo != nil {
|
||
|
|
return path, mountinfo.Optional, nil
|
||
|
|
}
|
||
|
|
@@ -569,6 +565,12 @@ func getParentMount(rootfs string) (string, string, error) {
|
||
|
|
if path == "/" {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+ retryTimes--
|
||
|
|
+ if retryTimes == 0 {
|
||
|
|
+ retryTimes = maxRetryTimes
|
||
|
|
+ path = filepath.Dir(path)
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
|
||
|
|
// If we are here, we did not find parent mount. Something is wrong.
|
||
|
|
diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go
|
||
|
|
index be69fee..b74773f 100644
|
||
|
|
--- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go
|
||
|
|
+++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go
|
||
|
|
@@ -4,8 +4,10 @@ package mount
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
+ "bytes"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
+ "io/ioutil"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
@@ -31,13 +33,12 @@ const (
|
||
|
|
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from
|
||
|
|
// bind mounts
|
||
|
|
func parseMountTable() ([]*Info, error) {
|
||
|
|
- f, err := os.Open("/proc/self/mountinfo")
|
||
|
|
+ content, err := ioutil.ReadFile("/proc/self/mountinfo")
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
- defer f.Close()
|
||
|
|
|
||
|
|
- return parseInfoFile(f)
|
||
|
|
+ return parseInfoFile(bytes.NewReader(content))
|
||
|
|
}
|
||
|
|
|
||
|
|
func parseInfoFile(r io.Reader) ([]*Info, error) {
|
||
|
|
--
|
||
|
|
2.7.4
|
||
|
|
|