summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--cmd/podman/main_local.go80
-rw-r--r--cmd/podman/sign.go32
-rw-r--r--contrib/msi/podman-logo.icobin0 -> 15086 bytes
-rw-r--r--contrib/msi/podman.bat43
-rw-r--r--contrib/msi/podman.wxs48
-rw-r--r--contrib/varlink/io.podman.service5
-rw-r--r--contrib/varlink/io.podman.socket1
-rw-r--r--libpod/container_internal_linux.go29
-rw-r--r--libpod/oci_internal_linux.go54
-rw-r--r--libpod/runtime_cstorage.go6
-rw-r--r--pkg/cgroups/cgroups_supported.go62
-rw-r--r--pkg/cgroups/cgroups_unsupported.go6
-rw-r--r--utils/utils_supported.go18
14 files changed, 342 insertions, 58 deletions
diff --git a/Makefile b/Makefile
index 840bfced7..482b2d2c2 100644
--- a/Makefile
+++ b/Makefile
@@ -83,7 +83,7 @@ LIBSECCOMP_COMMIT := release-2.3
GINKGOTIMEOUT ?= -timeout=90m
RELEASE_VERSION ?= $(shell hack/get_release_info.sh VERSION)
-RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER)
+RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER|sed -e 's/^v\(.*\)/\1/')
RELEASE_DIST ?= $(shell hack/get_release_info.sh DIST)
RELEASE_DIST_VER ?= $(shell hack/get_release_info.sh DIST_VER)
RELEASE_ARCH ?= $(shell hack/get_release_info.sh ARCH)
@@ -164,6 +164,10 @@ podman: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman
podman-remote: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote environment
$(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/$@ $(PROJECT)/cmd/podman
+.PHONY: podman.msi
+podman.msi: podman-remote-windows ## Will always rebuild exe as there is no podman-remote-windows.exe target to verify timestamp
+ wixl -D VERSION=$(RELEASE_NUMBER) -o bin/podman-v$(RELEASE_NUMBER).msi contrib/msi/podman.wxs
+
podman-remote-%: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build podman for a specific GOOS
$(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
CGO_ENABLED=0 GOOS=$* $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@$(BINSFX) $(PROJECT)/cmd/podman
@@ -328,9 +332,9 @@ release.txt:
echo -n " $$field"; done >> "$@"
echo "" >> "$@"
-podman-$(RELEASE_NUMBER).tar.gz: binaries docs release.txt
+podman-v$(RELEASE_NUMBER).tar.gz: binaries docs release.txt
$(eval TMPDIR := $(shell mktemp -d -p '' podman_XXXX))
- $(eval SUBDIR := podman-$(RELEASE_NUMBER))
+ $(eval SUBDIR := podman-v$(RELEASE_NUMBER))
mkdir -p "$(TMPDIR)/$(SUBDIR)"
$(MAKE) install.bin install.man install.cni install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
# release.txt location and content depended upon by automated tooling
@@ -339,7 +343,7 @@ podman-$(RELEASE_NUMBER).tar.gz: binaries docs release.txt
-rm -rf "$(TMPDIR)"
# Must call make in-line: Dependency-spec. w/ wild-card also consumes variable value.
-podman-remote-$(RELEASE_NUMBER)-%.zip:
+podman-remote-v$(RELEASE_NUMBER)-%.zip:
$(MAKE) podman-remote-$* install-podman-remote-docs release.txt \
RELEASE_BASENAME=$(shell hack/get_release_info.sh REMOTENAME) \
RELEASE_DIST=$* RELEASE_DIST_VER="-"
@@ -364,12 +368,12 @@ podman-remote-$(RELEASE_NUMBER)-%.zip:
.PHONY: podman-release
podman-release:
rm -f release.txt
- $(MAKE) podman-$(RELEASE_NUMBER).tar.gz
+ $(MAKE) podman-v$(RELEASE_NUMBER).tar.gz
.PHONY: podman-remote-%-release
podman-remote-%-release:
rm -f release.txt
- $(MAKE) podman-remote-$(RELEASE_NUMBER)-$*.zip
+ $(MAKE) podman-remote-v$(RELEASE_NUMBER)-$*.zip
docker-docs: docs
(cd docs; ./dckrman.sh *.1)
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index 0feba609b..cad256615 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -5,9 +5,12 @@ package main
import (
"context"
+ "fmt"
+ "io/ioutil"
"log/syslog"
"os"
"runtime/pprof"
+ "strconv"
"strings"
"syscall"
@@ -18,6 +21,7 @@ import (
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/tracing"
"github.com/containers/libpod/pkg/util"
+ "github.com/containers/libpod/utils"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -119,7 +123,29 @@ func profileOff(cmd *cobra.Command) error {
return nil
}
+func movePauseProcessToScope() error {
+ pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ if err != nil {
+ return errors.Wrapf(err, "could not get pause process pid file path")
+ }
+
+ data, err := ioutil.ReadFile(pausePidPath)
+ if err != nil {
+ return errors.Wrapf(err, "cannot read pause pid file")
+ }
+ pid, err := strconv.ParseUint(string(data), 10, 0)
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse pid file %s", pausePidPath)
+ }
+
+ return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope")
+}
+
func setupRootless(cmd *cobra.Command, args []string) error {
+ if !rootless.IsRootless() {
+ return nil
+ }
+
matches, err := rootless.ConfigurationMatches()
if err != nil {
return err
@@ -128,9 +154,6 @@ func setupRootless(cmd *cobra.Command, args []string) error {
logrus.Warningf("the current user namespace doesn't match the configuration in /etc/subuid or /etc/subgid")
logrus.Warningf("you can use `%s system migrate` to recreate the user namespace and restart the containers", os.Args[0])
}
- if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") {
- return nil
- }
podmanCmd := cliconfig.PodmanCommand{
Command: cmd,
@@ -139,6 +162,39 @@ func setupRootless(cmd *cobra.Command, args []string) error {
Remote: remoteclient,
}
+ runtime, err := libpodruntime.GetRuntime(getContext(), &podmanCmd)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.DeferredShutdown(false)
+
+ // do it only after podman has already re-execed and running with uid==0.
+ if os.Geteuid() == 0 {
+ ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
+ if err != nil {
+ return err
+ }
+
+ if !ownsCgroup {
+ unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
+ if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
+ conf, err := runtime.GetConfig()
+ if err != nil {
+ return err
+ }
+ if conf.CgroupManager == libpod.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ }
+ }
+ }
+ }
+
+ if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") {
+ return nil
+ }
+
pausePidPath, err := util.GetRootlessPauseProcessPidPath()
if err != nil {
return errors.Wrapf(err, "could not get pause process pid file path")
@@ -158,13 +214,6 @@ func setupRootless(cmd *cobra.Command, args []string) error {
}
// if there is no pid file, try to join existing containers, and create a pause process.
-
- runtime, err := libpodruntime.GetRuntime(getContext(), &podmanCmd)
- if err != nil {
- return errors.Wrapf(err, "could not get runtime")
- }
- defer runtime.DeferredShutdown(false)
-
ctrs, err := runtime.GetRunningContainers()
if err != nil {
logrus.Errorf(err.Error())
@@ -177,6 +226,17 @@ func setupRootless(cmd *cobra.Command, args []string) error {
}
became, ret, err := rootless.TryJoinFromFilePaths(pausePidPath, true, paths)
+ if err := movePauseProcessToScope(); err != nil {
+ conf, err := runtime.GetConfig()
+ if err != nil {
+ return err
+ }
+ if conf.CgroupManager == libpod.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ }
+ }
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index 63ba9b904..79bc3f02b 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/trust"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
@@ -130,22 +131,33 @@ func signCmd(c *cliconfig.SignValues) error {
return errors.Wrapf(err, "error pulling image %s", signimage)
}
- registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs)
- if registryInfo != nil {
+ if rootless.IsRootless() {
if sigStoreDir == "" {
- sigStoreDir = registryInfo.SigStoreStaging
+ runtimeConfig, err := runtime.GetConfig()
+ if err != nil {
+ return err
+ }
+
+ sigStoreDir = filepath.Join(filepath.Dir(runtimeConfig.StorageConfig.GraphRoot), "sigstore")
+ }
+ } else {
+ registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs)
+ if registryInfo != nil {
if sigStoreDir == "" {
- sigStoreDir = registryInfo.SigStore
+ sigStoreDir = registryInfo.SigStoreStaging
+ if sigStoreDir == "" {
+ sigStoreDir = registryInfo.SigStore
+ }
+ }
+ sigStoreDir, err = isValidSigStoreDir(sigStoreDir)
+ if err != nil {
+ return errors.Wrapf(err, "invalid signature storage %s", sigStoreDir)
}
}
- sigStoreDir, err = isValidSigStoreDir(sigStoreDir)
- if err != nil {
- return errors.Wrapf(err, "invalid signature storage %s", sigStoreDir)
+ if sigStoreDir == "" {
+ sigStoreDir = SignatureStoreDir
}
}
- if sigStoreDir == "" {
- sigStoreDir = SignatureStoreDir
- }
repos, err := newImage.RepoDigests()
if err != nil {
diff --git a/contrib/msi/podman-logo.ico b/contrib/msi/podman-logo.ico
new file mode 100644
index 000000000..cb1dab6a7
--- /dev/null
+++ b/contrib/msi/podman-logo.ico
Binary files differ
diff --git a/contrib/msi/podman.bat b/contrib/msi/podman.bat
new file mode 100644
index 000000000..091c1c4c4
--- /dev/null
+++ b/contrib/msi/podman.bat
@@ -0,0 +1,43 @@
+@echo off
+setlocal enableextensions
+
+title Podman
+
+:: If remote-host is given on command line -- use it
+setlocal enabledelayedexpansion
+for %%a in (%*) do (
+ echo "%%a" |find "--remote-host" >NUL
+ if !errorlevel! == 0 (
+ goto run_podman
+ )
+)
+
+:: If PODMAN_VARLINK_BRIDGE is set -- use it
+if defined PODMAN_VARLINK_BRIDGE (
+ goto run_podman
+)
+
+:: If the configuration file exists -- use it
+set config_home=%USERPROFILE%\AppData\podman
+set config_file=%config_home%\podman-remote.conf
+if exist "%config_file%" (
+ goto run_podman
+)
+
+:: Get connection information from user and build configuration file
+md "%config_home%"
+set /p host="Please enter the remote hosts name or IP address: "
+set /p user="Please enter the remote user name: "
+(
+ echo [connections]
+ echo [connections."%host%"]
+ echo destination = "%host%"
+ echo username = "%user%"
+ echo default = true
+) >"%config_file%"
+
+:run_podman
+endlocal
+podman-remote-windows.exe %*
+
+:End
diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs
new file mode 100644
index 000000000..77c6e2815
--- /dev/null
+++ b/contrib/msi/podman.wxs
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+
+ <?ifndef var.VERSION?>
+ <?error VERSION must be defined via command line argument?>
+ <?endif?>
+
+ <Product Name="Podman $(var.VERSION)" Id="*" UpgradeCode="696BAB5D-CA1F-4B05-B123-320F245B8D6D" Version="$(var.VERSION)" Language="1033" Manufacturer="Red Hat Inc.">
+
+ <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="100" Compressed="yes"/>
+ <Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/>
+ <Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/>
+
+ <Directory Id="TARGETDIR" Name="SourceDir">
+
+ <Directory Id="ProgramFilesFolder" Name="PFiles">
+ <Directory Id="RedHatPFiles" Name="RedHat">
+ <Directory Id="INSTALLDIR" Name="Podman">
+ <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82">
+ <CreateFolder/>
+ </Component>
+ <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714">
+ <File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman-remote-windows.exe" Source="bin/podman-remote-windows.exe"/>
+ <File Id="A14218A0-4180-44AC-B109-7C63B3099DCA" Name="podman.bat" Source="podman.bat" KeyPath="yes"/>
+ </Component>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <Property Id="setx" Value="setx.exe"/>
+ <CustomAction Id="ChangePath" ExeCommand='PATH "%PATH%;[INSTALLDIR]"' Property="setx" Execute="deferred" Impersonate="yes" Return="check"/>
+
+ <Feature Id="Complete" Level="1">
+ <ComponentRef Id="INSTALLDIR_Component"/>
+ <ComponentRef Id="MainExecutable"/>
+ </Feature>
+
+ <Icon Id="podman.ico" SourceFile="contrib/msi/podman-logo.ico"/>
+ <Property Id="ARPPRODUCTICON" Value="podman.ico"/>
+
+ <InstallExecuteSequence>
+ <RemoveExistingProducts Before="InstallInitialize"/>
+ <Custom Action="ChangePath" After="InstallServices">NOT Installed</Custom>
+ </InstallExecuteSequence>
+
+ </Product>
+</Wix>
diff --git a/contrib/varlink/io.podman.service b/contrib/varlink/io.podman.service
index 725198e79..5be5329f4 100644
--- a/contrib/varlink/io.podman.service
+++ b/contrib/varlink/io.podman.service
@@ -6,8 +6,9 @@ Documentation=man:podman-varlink(1)
[Service]
Type=simple
-ExecStart=/usr/bin/podman varlink unix:%t/podman/io.podman
-KillMode=none
+ExecStart=/usr/bin/podman varlink unix:%t/podman/io.podman --timeout=60000
+TimeoutStopSec=30
+KillMode=process
[Install]
WantedBy=multi-user.target
diff --git a/contrib/varlink/io.podman.socket b/contrib/varlink/io.podman.socket
index f6a3ddc49..629a5dd20 100644
--- a/contrib/varlink/io.podman.socket
+++ b/contrib/varlink/io.podman.socket
@@ -8,3 +8,4 @@ SocketMode=0600
[Install]
WantedBy=sockets.target
+Also=multi-user.target
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 9f16389e6..4bbbef5db 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -491,12 +491,29 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
if unified {
g.RemoveMount("/sys/fs/cgroup")
- sourcePath := filepath.Join("/sys/fs/cgroup")
- systemdMnt := spec.Mount{
- Destination: "/sys/fs/cgroup",
- Type: "bind",
- Source: sourcePath,
- Options: []string{"bind", "private", "rw"},
+ hasCgroupNs := false
+ for _, ns := range c.config.Spec.Linux.Namespaces {
+ if ns.Type == spec.CgroupNamespace {
+ hasCgroupNs = true
+ break
+ }
+ }
+
+ var systemdMnt spec.Mount
+ if hasCgroupNs {
+ systemdMnt = spec.Mount{
+ Destination: "/sys/fs/cgroup",
+ Type: "cgroup",
+ Source: "cgroup",
+ Options: []string{"private", "rw"},
+ }
+ } else {
+ systemdMnt = spec.Mount{
+ Destination: "/sys/fs/cgroup",
+ Type: "bind",
+ Source: "/sys/fs/cgroup",
+ Options: []string{"bind", "private", "rw"},
+ }
}
g.AddMount(systemdMnt)
} else {
diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go
index f9e935d86..4df1e4010 100644
--- a/libpod/oci_internal_linux.go
+++ b/libpod/oci_internal_linux.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/lookup"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/utils"
"github.com/coreos/go-systemd/activation"
@@ -359,35 +360,46 @@ func startCommandGivenSelinux(cmd *exec.Cmd) error {
// moveConmonToCgroupAndSignal gets a container's cgroupParent and moves the conmon process to that cgroup
// it then signals for conmon to start by sending nonse data down the start fd
func (r *OCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec.Cmd, startFd *os.File, uuid string) error {
+ mustCreateCgroup := true
// If cgroup creation is disabled - just signal.
if ctr.config.NoCgroups {
- return writeConmonPipeData(startFd)
+ mustCreateCgroup = false
}
- cgroupParent := ctr.CgroupParent()
- if r.cgroupManager == SystemdCgroupsManager {
- unitName := createUnitName("libpod-conmon", ctr.ID())
-
- realCgroupParent := cgroupParent
- splitParent := strings.Split(cgroupParent, "/")
- if strings.HasSuffix(cgroupParent, ".slice") && len(splitParent) > 1 {
- realCgroupParent = splitParent[len(splitParent)-1]
+ if rootless.IsRootless() {
+ ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
+ if err != nil {
+ return err
}
+ mustCreateCgroup = !ownsCgroup
+ }
- logrus.Infof("Running conmon under slice %s and unitName %s", realCgroupParent, unitName)
- if err := utils.RunUnderSystemdScope(cmd.Process.Pid, realCgroupParent, unitName); err != nil {
- logrus.Warnf("Failed to add conmon to systemd sandbox cgroup: %v", err)
- }
- } else {
- cgroupPath := filepath.Join(ctr.config.CgroupParent, "conmon")
- control, err := cgroups.New(cgroupPath, &spec.LinuxResources{})
- if err != nil {
- logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
+ if mustCreateCgroup {
+ cgroupParent := ctr.CgroupParent()
+ if r.cgroupManager == SystemdCgroupsManager {
+ unitName := createUnitName("libpod-conmon", ctr.ID())
+
+ realCgroupParent := cgroupParent
+ splitParent := strings.Split(cgroupParent, "/")
+ if strings.HasSuffix(cgroupParent, ".slice") && len(splitParent) > 1 {
+ realCgroupParent = splitParent[len(splitParent)-1]
+ }
+
+ logrus.Infof("Running conmon under slice %s and unitName %s", realCgroupParent, unitName)
+ if err := utils.RunUnderSystemdScope(cmd.Process.Pid, realCgroupParent, unitName); err != nil {
+ logrus.Warnf("Failed to add conmon to systemd sandbox cgroup: %v", err)
+ }
} else {
- // we need to remove this defer and delete the cgroup once conmon exits
- // maybe need a conmon monitor?
- if err := control.AddPid(cmd.Process.Pid); err != nil {
+ cgroupPath := filepath.Join(ctr.config.CgroupParent, "conmon")
+ control, err := cgroups.New(cgroupPath, &spec.LinuxResources{})
+ if err != nil {
logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
+ } else {
+ // we need to remove this defer and delete the cgroup once conmon exits
+ // maybe need a conmon monitor?
+ if err := control.AddPid(cmd.Process.Pid); err != nil {
+ logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
+ }
}
}
}
diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go
index 586db5a1e..1e84aef4b 100644
--- a/libpod/runtime_cstorage.go
+++ b/libpod/runtime_cstorage.go
@@ -1,6 +1,8 @@
package libpod
import (
+ "time"
+
"github.com/containers/libpod/libpod/define"
"github.com/containers/storage"
"github.com/pkg/errors"
@@ -12,6 +14,8 @@ import (
type StorageContainer struct {
ID string
Names []string
+ Image string
+ CreateTime time.Time
PresentInLibpod bool
}
@@ -31,6 +35,8 @@ func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) {
storageCtr := new(StorageContainer)
storageCtr.ID = ctr.ID
storageCtr.Names = ctr.Names
+ storageCtr.Image = ctr.ImageID
+ storageCtr.CreateTime = ctr.Created
// Look up if container is in state
hasCtr, err := r.state.HasContainer(ctr.ID)
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
+}
diff --git a/utils/utils_supported.go b/utils/utils_supported.go
index 8b0ba4438..8bc232179 100644
--- a/utils/utils_supported.go
+++ b/utils/utils_supported.go
@@ -3,6 +3,8 @@
package utils
import (
+ "github.com/containers/libpod/pkg/cgroups"
+ "github.com/containers/libpod/pkg/rootless"
systemdDbus "github.com/coreos/go-systemd/dbus"
"github.com/godbus/dbus"
)
@@ -10,9 +12,19 @@ import (
// RunUnderSystemdScope adds the specified pid to a systemd scope
func RunUnderSystemdScope(pid int, slice string, unitName string) error {
var properties []systemdDbus.Property
- conn, err := systemdDbus.New()
- if err != nil {
- return err
+ var conn *systemdDbus.Conn
+ var err error
+
+ if rootless.IsRootless() {
+ conn, err = cgroups.GetUserConnection(rootless.GetRootlessUID())
+ if err != nil {
+ return err
+ }
+ } else {
+ conn, err = systemdDbus.New()
+ if err != nil {
+ return err
+ }
}
properties = append(properties, systemdDbus.PropSlice(slice))
properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))