From afd0818326aa37f03a3bc74f0269a06a403db16d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 6 Sep 2019 15:30:30 +0200 Subject: rootless: automatically create a systemd scope when running in rootless mode and using systemd as cgroup manager create automatically a systemd scope when the user doesn't own the current cgroup. This solves a couple of issues: on cgroup v2 it is necessary that a process before it can moved to a different cgroup tree must be in a directory owned by the unprivileged user. This is not always true, e.g. when creating a session with su -l. Closes: https://github.com/containers/libpod/issues/3937 Also, for running systemd in a container it was before necessary to specify "systemd-run --scope --user podman ...", now this is done automatically as part of this PR. Signed-off-by: Giuseppe Scrivano --- pkg/cgroups/cgroups_supported.go | 62 ++++++++++++++++++++++++++++++++++++++ pkg/cgroups/cgroups_unsupported.go | 6 ++++ 2 files changed, 68 insertions(+) (limited to 'pkg/cgroups') diff --git a/pkg/cgroups/cgroups_supported.go b/pkg/cgroups/cgroups_supported.go index fcd44dfc8..2a36777d4 100644 --- a/pkg/cgroups/cgroups_supported.go +++ b/pkg/cgroups/cgroups_supported.go @@ -3,8 +3,15 @@ package cgroups import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" "sync" "syscall" + + "github.com/pkg/errors" ) var ( @@ -25,3 +32,58 @@ func IsCgroup2UnifiedMode() (bool, error) { }) return isUnified, isUnifiedErr } + +// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the +// current cgroup. +func UserOwnsCurrentSystemdCgroup() (bool, error) { + uid := os.Geteuid() + + cgroup2, err := IsCgroup2UnifiedMode() + if err != nil { + return false, err + } + + f, err := os.Open("/proc/self/cgroup") + if err != nil { + return false, errors.Wrapf(err, "open file /proc/self/cgroup") + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + parts := strings.SplitN(line, ":", 3) + + if len(parts) < 3 { + continue + } + + var cgroupPath string + + if cgroup2 { + cgroupPath = filepath.Join(cgroupRoot, parts[2]) + } else { + if parts[1] != "name=systemd" { + continue + } + cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2]) + } + + st, err := os.Stat(cgroupPath) + if err != nil { + return false, err + } + s := st.Sys() + if s == nil { + return false, fmt.Errorf("error stat cgroup path %s", cgroupPath) + } + + if int(s.(*syscall.Stat_t).Uid) != uid { + return false, nil + } + } + if err := scanner.Err(); err != nil { + return false, errors.Wrapf(err, "parsing file /proc/self/cgroup") + } + return true, nil +} diff --git a/pkg/cgroups/cgroups_unsupported.go b/pkg/cgroups/cgroups_unsupported.go index 9dc196e42..cd140fbf3 100644 --- a/pkg/cgroups/cgroups_unsupported.go +++ b/pkg/cgroups/cgroups_unsupported.go @@ -6,3 +6,9 @@ package cgroups func IsCgroup2UnifiedMode() (bool, error) { return false, nil } + +// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the +// current cgroup. +func UserOwnsCurrentSystemdCgroup() (bool, error) { + return false, nil +} -- cgit v1.2.3-54-g00ecf