From f002a0c8898bf187d5071b86ee0d1c5e07cf6416 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <gscrivan@redhat.com>
Date: Thu, 3 Mar 2022 13:23:07 +0100
Subject: libpod: pods do not use cgroups if --cgroups=disabled

do not attempt to use cgroups with pods if the cgroups are disabled.
A similar check is already in place for containers.

Closes: https://github.com/containers/podman/issues/13411

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
 libpod/runtime_pod_linux.go      | 71 +++++++++++++++++++++-------------------
 test/e2e/containers_conf_test.go |  5 +++
 2 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 155ad5c2d..230491c1a 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
 // +build linux
 
 package libpod
@@ -59,50 +60,52 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option
 	pod.valid = true
 
 	// Check Cgroup parent sanity, and set it if it was not set
-	switch r.config.Engine.CgroupManager {
-	case config.CgroupfsCgroupsManager:
-		canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
-		if canUseCgroup {
+	if r.config.Cgroups() != "disabled" {
+		switch r.config.Engine.CgroupManager {
+		case config.CgroupfsCgroupsManager:
+			canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
+			if canUseCgroup {
+				if pod.config.CgroupParent == "" {
+					pod.config.CgroupParent = CgroupfsDefaultCgroupParent
+				} else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
+					return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs")
+				}
+				// If we are set to use pod cgroups, set the cgroup parent that
+				// all containers in the pod will share
+				// No need to create it with cgroupfs - the first container to
+				// launch should do it for us
+				if pod.config.UsePodCgroup {
+					pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
+					if p.InfraContainerSpec != nil {
+						p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
+					}
+				}
+			}
+		case config.SystemdCgroupsManager:
 			if pod.config.CgroupParent == "" {
-				pod.config.CgroupParent = CgroupfsDefaultCgroupParent
-			} else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
-				return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs")
+				if rootless.IsRootless() {
+					pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
+				} else {
+					pod.config.CgroupParent = SystemdDefaultCgroupParent
+				}
+			} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
+				return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups")
 			}
 			// If we are set to use pod cgroups, set the cgroup parent that
 			// all containers in the pod will share
-			// No need to create it with cgroupfs - the first container to
-			// launch should do it for us
 			if pod.config.UsePodCgroup {
-				pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
+				cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()))
+				if err != nil {
+					return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
+				}
+				pod.state.CgroupPath = cgroupPath
 				if p.InfraContainerSpec != nil {
 					p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
 				}
 			}
+		default:
+			return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
 		}
-	case config.SystemdCgroupsManager:
-		if pod.config.CgroupParent == "" {
-			if rootless.IsRootless() {
-				pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
-			} else {
-				pod.config.CgroupParent = SystemdDefaultCgroupParent
-			}
-		} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
-			return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups")
-		}
-		// If we are set to use pod cgroups, set the cgroup parent that
-		// all containers in the pod will share
-		if pod.config.UsePodCgroup {
-			cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()))
-			if err != nil {
-				return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
-			}
-			pod.state.CgroupPath = cgroupPath
-			if p.InfraContainerSpec != nil {
-				p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
-			}
-		}
-	default:
-		return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
 	}
 
 	if pod.config.UsePodCgroup {
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index bfed01854..09cd68042 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -562,6 +562,11 @@ var _ = Describe("Verify podman containers.conf usage", func() {
 		inspect = podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()})
 		inspect.WaitWithDefaultTimeout()
 		Expect(inspect.OutputToString()).To(Equal("disabled"))
+
+		// Check we can also create a pod when cgroups=disabled
+		result = podmanTest.Podman([]string{"pod", "create"})
+		result.WaitWithDefaultTimeout()
+		Expect(result).Should(Exit(0))
 	})
 
 	It("podman containers.conf runtime", func() {
-- 
cgit v1.2.3-54-g00ecf