diff --git a/components/workspacekit/cmd/rings.go b/components/workspacekit/cmd/rings.go index 7d4a8c4d9e26f4..ef4e52a30677df 100644 --- a/components/workspacekit/cmd/rings.go +++ b/components/workspacekit/cmd/rings.go @@ -104,7 +104,7 @@ var ring0Cmd = &cobra.Command{ cmd := exec.Command("/proc/self/exe", "ring1") cmd.SysProcAttr = &syscall.SysProcAttr{ Pdeathsig: syscall.SIGKILL, - Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS, + Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS | unix.CLONE_NEWCGROUP, } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -288,6 +288,12 @@ var ring1Cmd = &cobra.Command{ } mnts = append(mnts, mnte{Target: "/tmp", Source: "tmpfs", FSType: "tmpfs"}) + // If this is a cgroupv2 machine, we'll want to mount the cgroup2 FS ourselves + if _, err := os.Stat("/sys/fs/cgroup/cgroup.controllers"); err == nil { + mnts = append(mnts, mnte{Target: "/sys/fs/cgroup", Source: "tmpfs", FSType: "tmpfs"}) + mnts = append(mnts, mnte{Target: "/sys/fs/cgroup", Source: "cgroup", FSType: "cgroup2"}) + } + if adds := os.Getenv("GITPOD_WORKSPACEKIT_BIND_MOUNTS"); adds != "" { var additionalMounts []string err = json.Unmarshal([]byte(adds), &additionalMounts) @@ -335,14 +341,13 @@ var ring1Cmd = &cobra.Command{ }).Debug("mounting new rootfs") err = unix.Mount(m.Source, dst, m.FSType, m.Flags, "") if err != nil { - log.WithError(err).WithField("dest", dst).Error("cannot establish mount") + log.WithError(err).WithField("dest", dst).WithField("fsType", m.FSType).Error("cannot establish mount") return } } // We deliberately do not bind mount `/etc/resolv.conf` and `/etc/hosts`, but instead place a copy // so that users in the workspace can modify the file. - copyPaths := []string{"/etc/resolv.conf", "/etc/hosts"} for _, fn := range copyPaths { err = copyRing2Root(ring2Root, fn) @@ -411,12 +416,18 @@ var ring1Cmd = &cobra.Command{ Target: procLoc, Pid: int64(cmd.Process.Pid), }) - client.Close() - if err != nil { + client.Close() log.WithError(err).Error("cannot mount proc") return } + _, err = client.EvacuateCGroup(ctx, &daemonapi.EvacuateCGroupRequest{}) + if err != nil { + client.Close() + log.WithError(err).Error("cannot evacuate cgroup") + return + } + client.Close() // We have to wait for ring2 to come back to us and connect to the socket we've passed along. // There's a chance that ring2 crashes or misbehaves, so we don't want to wait forever, hence @@ -618,7 +629,7 @@ func findBindMountCandidates(procMounts io.Reader, readlink func(path string) (d reject bool ) switch fs { - case "cgroup", "devpts", "mqueue", "shm", "proc", "sysfs": + case "cgroup", "devpts", "mqueue", "shm", "proc", "sysfs", "cgroup2": reject = true } if reject {