diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 815d8062bb..302f4036de 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -12,12 +12,10 @@ import ( "os" "path/filepath" - "github.com/containers/common/pkg/cgroups" "github.com/containers/podman/v4/cmd/podman/registry" api "github.com/containers/podman/v4/pkg/api/server" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra" - "github.com/containers/podman/v4/pkg/rootless" "github.com/coreos/go-systemd/v22/activation" "github.com/sirupsen/logrus" "github.com/spf13/pflag" @@ -125,16 +123,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities // Close the fd right away to not leak it during the entire time of the service. devNullfile.Close() - cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() - if rootless.IsRootless() && !cgroupv2 { - logrus.Warnf("Running 'system service' in rootless mode without cgroup v2, containers won't survive a 'system service' restart") - } - - if err := cgroups.MaybeMoveToSubCgroup(); err != nil { - // it is a best effort operation, so just print the - // error for debugging purposes. - logrus.Debugf("Could not move to subcgroup: %v", err) - } + maybeMoveToSubCgroup() maybeStartServiceReaper() infra.StartWatcher(libpodRuntime) diff --git a/cmd/podman/system/service_abi_common.go b/cmd/podman/system/service_abi_common.go index 999f90fbe9..697e8b66e8 100644 --- a/cmd/podman/system/service_abi_common.go +++ b/cmd/podman/system/service_abi_common.go @@ -5,3 +5,6 @@ package system // Currently, we only need servicereaper on Linux to support slirp4netns. func maybeStartServiceReaper() { } + +// There is no cgroup on non linux. +func maybeMoveToSubCgroup() {} diff --git a/cmd/podman/system/service_abi_linux.go b/cmd/podman/system/service_abi_linux.go index d0da1594ad..ff8efa3118 100644 --- a/cmd/podman/system/service_abi_linux.go +++ b/cmd/podman/system/service_abi_linux.go @@ -3,10 +3,26 @@ package system import ( + "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/servicereaper" + "github.com/containers/podman/v4/pkg/rootless" + "github.com/sirupsen/logrus" ) // Currently, we only need servicereaper on Linux to support slirp4netns. func maybeStartServiceReaper() { servicereaper.Start() } + +func maybeMoveToSubCgroup() { + cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() + if rootless.IsRootless() && !cgroupv2 { + logrus.Warnf("Running 'system service' in rootless mode without cgroup v2, containers won't survive a 'system service' restart") + } + + if err := cgroups.MaybeMoveToSubCgroup(); err != nil { + // it is a best effort operation, so just print the + // error for debugging purposes. + logrus.Debugf("Could not move to subcgroup: %v", err) + } +} diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 6811311619..112a332b20 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -9,17 +9,12 @@ import ( "os/exec" "path/filepath" - "github.com/containers/common/pkg/cgroups" - "github.com/containers/common/pkg/config" - "github.com/containers/common/pkg/systemd" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" - "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage" "github.com/containers/storage/pkg/directory" - "github.com/containers/storage/pkg/unshare" "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -66,95 +61,6 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { return info, err } -func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) error { - runsUnderSystemd := systemd.RunsOnSystemd() - if !runsUnderSystemd { - isPid1 := os.Getpid() == 1 - if _, found := os.LookupEnv("container"); isPid1 || found { - if err := cgroups.MaybeMoveToSubCgroup(); err != nil { - // it is a best effort operation, so just print the - // error for debugging purposes. - logrus.Debugf("Could not move to subcgroup: %v", err) - } - } - } - - if !rootless.IsRootless() { - return nil - } - - // do it only after podman has already re-execed and running with uid==0. - hasCapSysAdmin, err := unshare.HasCapSysAdmin() - if err != nil { - return err - } - // check for both euid == 0 and CAP_SYS_ADMIN because we may be running in a container with CAP_SYS_ADMIN set. - if os.Geteuid() == 0 && hasCapSysAdmin { - ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup() - if err != nil { - logrus.Infof("Failed to detect the owner for the current cgroup: %v", err) - } - if !ownsCgroup { - conf, err := ic.Config(context.Background()) - if err != nil { - return err - } - unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) - if runsUnderSystemd || conf.Engine.CgroupManager == config.SystemdCgroupsManager { - if err := systemd.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { - logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) - } - } - } - return nil - } - - pausePidPath, err := util.GetRootlessPauseProcessPidPath() - if err != nil { - return fmt.Errorf("could not get pause process pid file path: %w", err) - } - - became, ret, err := rootless.TryJoinPauseProcess(pausePidPath) - if err != nil { - return err - } - if became { - os.Exit(ret) - } - if noMoveProcess { - return nil - } - - // if there is no pid file, try to join existing containers, and create a pause process. - ctrs, err := ic.Libpod.GetRunningContainers() - if err != nil { - logrus.Error(err.Error()) - os.Exit(1) - } - - paths := []string{} - for _, ctr := range ctrs { - paths = append(paths, ctr.ConfigNoCopy().ConmonPidFile) - } - - if len(paths) > 0 { - became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths) - } else { - became, ret, err = rootless.BecomeRootInUserNS(pausePidPath) - if err == nil { - systemd.MovePauseProcessToScope(pausePidPath) - } - } - if err != nil { - logrus.Error(fmt.Errorf("invalid internal status, try resetting the pause process with %q: %w", os.Args[0]+" system migrate", err)) - os.Exit(1) - } - if became { - os.Exit(ret) - } - return nil -} - // SystemPrune removes unused data from the system. Pruning pods, containers, networks, volumes and images. func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) { var systemPruneReport = new(entities.SystemPruneReport) diff --git a/pkg/domain/infra/abi/system_freebsd.go b/pkg/domain/infra/abi/system_freebsd.go index 33ccebbb37..c6ec91943e 100644 --- a/pkg/domain/infra/abi/system_freebsd.go +++ b/pkg/domain/infra/abi/system_freebsd.go @@ -1,4 +1,13 @@ package abi +import ( + "context" +) + // Default path for system runtime state const defaultRunPath = "/var/run" + +// SetupRootless in a NOP for freebsd as it only configures the rootless userns on linux. +func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) error { + return nil +} diff --git a/pkg/domain/infra/abi/system_linux.go b/pkg/domain/infra/abi/system_linux.go index 6a13f07050..2c0f5a79eb 100644 --- a/pkg/domain/infra/abi/system_linux.go +++ b/pkg/domain/infra/abi/system_linux.go @@ -1,4 +1,107 @@ package abi +import ( + "context" + "fmt" + "os" + + "github.com/containers/common/pkg/cgroups" + "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/systemd" + "github.com/containers/podman/v4/pkg/rootless" + "github.com/containers/podman/v4/pkg/util" + "github.com/containers/storage/pkg/unshare" + "github.com/sirupsen/logrus" +) + // Default path for system runtime state const defaultRunPath = "/run" + +func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) error { + runsUnderSystemd := systemd.RunsOnSystemd() + if !runsUnderSystemd { + isPid1 := os.Getpid() == 1 + if _, found := os.LookupEnv("container"); isPid1 || found { + if err := cgroups.MaybeMoveToSubCgroup(); err != nil { + // it is a best effort operation, so just print the + // error for debugging purposes. + logrus.Debugf("Could not move to subcgroup: %v", err) + } + } + } + + if !rootless.IsRootless() { + return nil + } + + // do it only after podman has already re-execed and running with uid==0. + hasCapSysAdmin, err := unshare.HasCapSysAdmin() + if err != nil { + return err + } + // check for both euid == 0 and CAP_SYS_ADMIN because we may be running in a container with CAP_SYS_ADMIN set. + if os.Geteuid() == 0 && hasCapSysAdmin { + ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup() + if err != nil { + logrus.Infof("Failed to detect the owner for the current cgroup: %v", err) + } + if !ownsCgroup { + conf, err := ic.Config(context.Background()) + if err != nil { + return err + } + unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) + if runsUnderSystemd || conf.Engine.CgroupManager == config.SystemdCgroupsManager { + if err := systemd.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { + logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) + } + } + } + return nil + } + + pausePidPath, err := util.GetRootlessPauseProcessPidPath() + if err != nil { + return fmt.Errorf("could not get pause process pid file path: %w", err) + } + + became, ret, err := rootless.TryJoinPauseProcess(pausePidPath) + if err != nil { + return err + } + if became { + os.Exit(ret) + } + if noMoveProcess { + return nil + } + + // if there is no pid file, try to join existing containers, and create a pause process. + ctrs, err := ic.Libpod.GetRunningContainers() + if err != nil { + logrus.Error(err.Error()) + os.Exit(1) + } + + paths := []string{} + for _, ctr := range ctrs { + paths = append(paths, ctr.ConfigNoCopy().ConmonPidFile) + } + + if len(paths) > 0 { + became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths) + } else { + became, ret, err = rootless.BecomeRootInUserNS(pausePidPath) + if err == nil { + systemd.MovePauseProcessToScope(pausePidPath) + } + } + if err != nil { + logrus.Error(fmt.Errorf("invalid internal status, try resetting the pause process with %q: %w", os.Args[0]+" system migrate", err)) + os.Exit(1) + } + if became { + os.Exit(ret) + } + return nil +}