diff --git a/virtcontainers/container.go b/virtcontainers/container.go index 38dfab88a..b9bf4b329 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -290,7 +290,7 @@ func (c *Container) createContainersDirs() error { func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) ([]Mount, error) { var sharedDirMounts []Mount for idx, m := range c.mounts { - if m.Type != "bind" { + if isSystemMount(m.Destination) || m.Type != "bind" { continue } @@ -327,6 +327,13 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) ( continue } + // Ignore /dev, directories and all other device files. We handle + // only regular files in /dev. It does not make sense to pass the host + // device nodes to the guest. + if isHostDevice(m.Destination) { + continue + } + randBytes, err := generateRandomBytes(8) if err != nil { return nil, err diff --git a/virtcontainers/mount.go b/virtcontainers/mount.go index da512779a..13e6c3098 100644 --- a/virtcontainers/mount.go +++ b/virtcontainers/mount.go @@ -18,6 +18,46 @@ import ( var rootfsDir = "rootfs" +var systemMountPrefixes = []string{"/proc", "/sys"} + +func isSystemMount(m string) bool { + for _, p := range systemMountPrefixes { + if m == p || strings.HasPrefix(m, p+"/") { + return true + } + } + + return false +} + +func isHostDevice(m string) bool { + if m == "/dev" { + return true + } + + if strings.HasPrefix(m, "/dev/") { + // Check if regular file + s, err := os.Stat(m) + + // This should not happen. In case file does not exist let the + // error be handled by the agent, simply return false here. + if err != nil { + return false + } + + if s.Mode().IsRegular() { + return false + } + + // This is not a regular file in /dev. It is either a + // device file, directory or any other special file which is + // specific to the host system. + return true + } + + return false +} + func major(dev uint64) int { return int((dev >> 8) & 0xfff) } diff --git a/virtcontainers/mount_test.go b/virtcontainers/mount_test.go index d907b1125..25f00dbc2 100644 --- a/virtcontainers/mount_test.go +++ b/virtcontainers/mount_test.go @@ -18,6 +18,66 @@ import ( "testing" ) +func TestIsSystemMount(t *testing.T) { + tests := []struct { + mnt string + expected bool + }{ + {"/sys", true}, + {"/sys/", true}, + {"/sys//", true}, + {"/sys/fs", true}, + {"/sys/fs/", true}, + {"/sys/fs/cgroup", true}, + {"/sysfoo", false}, + {"/home", false}, + {"/dev/block/", false}, + {"/mnt/dev/foo", false}, + } + + for _, test := range tests { + result := isSystemMount(test.mnt) + if result != test.expected { + t.Fatalf("Expected result for path %s : %v, got %v", test.mnt, test.expected, result) + } + } +} + +func TestIsHostDevice(t *testing.T) { + tests := []struct { + mnt string + expected bool + }{ + {"/dev", true}, + {"/dev/zero", true}, + {"/dev/block", true}, + {"/mnt/dev/block", false}, + } + + for _, test := range tests { + result := isHostDevice(test.mnt) + if result != test.expected { + t.Fatalf("Expected result for path %s : %v, got %v", test.mnt, test.expected, result) + } + } + + // Create regular file in /dev + path := "/dev/foobar" + f, err := os.Create(path) + if err != nil { + t.Fatal(err) + } + f.Close() + + if isHostDevice(path) != false { + t.Fatalf("Expected result for path %s : %v, got %v", path, false, true) + } + + if err := os.Remove(path); err != nil { + t.Fatal(err) + } +} + func TestMajorMinorNumber(t *testing.T) { devices := []string{"/dev/zero", "/dev/net/tun"}