Merge pull request #2475 from bergwolf/umount

vc: do not follow symlink when umounting contanier host path
This commit is contained in:
Xu Wang
2020-02-21 18:09:32 +08:00
committed by GitHub
2 changed files with 22 additions and 2 deletions

View File

@@ -590,7 +590,7 @@ func (c *Container) unmountHostMounts() error {
span, _ := c.trace("unmount") span, _ := c.trace("unmount")
span.SetTag("host-path", m.HostPath) span.SetTag("host-path", m.HostPath)
if err := syscall.Unmount(m.HostPath, syscall.MNT_DETACH); err != nil { if err := syscall.Unmount(m.HostPath, syscall.MNT_DETACH|UmountNoFollow); err != nil {
c.Logger().WithFields(logrus.Fields{ c.Logger().WithFields(logrus.Fields{
"host-path": m.HostPath, "host-path": m.HostPath,
"error": err, "error": err,

View File

@@ -24,6 +24,9 @@ import (
// IPC is used. // IPC is used.
const DefaultShmSize = 65536 * 1024 const DefaultShmSize = 65536 * 1024
// Sadly golang/sys doesn't have UmountNoFollow although it's there since Linux 2.6.34
const UmountNoFollow = 0x8
var rootfsDir = "rootfs" var rootfsDir = "rootfs"
var systemMountPrefixes = []string{"/proc", "/sys"} var systemMountPrefixes = []string{"/proc", "/sys"}
@@ -328,12 +331,25 @@ type Mount struct {
BlockDeviceID string BlockDeviceID string
} }
func isSymlink(path string) bool {
stat, err := os.Stat(path)
if err != nil {
return false
}
return stat.Mode()&os.ModeSymlink != 0
}
func bindUnmountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID string) error { func bindUnmountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID string) error {
span, _ := trace(ctx, "bindUnmountContainerRootfs") span, _ := trace(ctx, "bindUnmountContainerRootfs")
defer span.Finish() defer span.Finish()
rootfsDest := filepath.Join(sharedDir, sandboxID, cID, rootfsDir) rootfsDest := filepath.Join(sharedDir, sandboxID, cID, rootfsDir)
err := syscall.Unmount(rootfsDest, syscall.MNT_DETACH) if isSymlink(filepath.Join(sharedDir, sandboxID, cID)) || isSymlink(rootfsDest) {
logrus.Warnf("container dir %s is a symlink, malicious guest?", cID)
return nil
}
err := syscall.Unmount(rootfsDest, syscall.MNT_DETACH|UmountNoFollow)
if err == syscall.ENOENT { if err == syscall.ENOENT {
logrus.Warnf("%s: %s", err, rootfsDest) logrus.Warnf("%s: %s", err, rootfsDest)
return nil return nil
@@ -347,6 +363,10 @@ func bindUnmountAllRootfs(ctx context.Context, sharedDir string, sandbox *Sandbo
var errors *merr.Error var errors *merr.Error
for _, c := range sandbox.containers { for _, c := range sandbox.containers {
if isSymlink(filepath.Join(sharedDir, sandbox.id, c.id)) {
logrus.Warnf("container dir %s is a symlink, malicious guest?", c.id)
continue
}
c.unmountHostMounts() c.unmountHostMounts()
if c.state.Fstype == "" { if c.state.Fstype == "" {
// even if error found, don't break out of loop until all mounts attempted // even if error found, don't break out of loop until all mounts attempted