From 5f9a77cccc82fdfcb3f01423d1fc7b2ec51d9271 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 19 Feb 2020 06:40:58 -0800 Subject: [PATCH] vc: validate container path when cleaning up A malicious can trick us with a crafted container rootfs symlink and make runtime umount other mountpoints. Make sure we do not walk through symlinks when umounting. Signed-off-by: Peng Tao --- virtcontainers/mount.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/virtcontainers/mount.go b/virtcontainers/mount.go index a8f036f59e..9987a9b177 100644 --- a/virtcontainers/mount.go +++ b/virtcontainers/mount.go @@ -331,11 +331,24 @@ type Mount struct { 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 { span, _ := trace(ctx, "bindUnmountContainerRootfs") defer span.Finish() rootfsDest := filepath.Join(sharedDir, sandboxID, cID, rootfsDir) + 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 { logrus.Warnf("%s: %s", err, rootfsDest) @@ -350,6 +363,10 @@ func bindUnmountAllRootfs(ctx context.Context, sharedDir string, sandbox *Sandbo var errors *merr.Error 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() if c.state.Fstype == "" { // even if error found, don't break out of loop until all mounts attempted