summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/networking_linux.go7
-rw-r--r--test/system/250-systemd.bats30
-rw-r--r--utils/utils.go22
3 files changed, 55 insertions, 4 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index f490ac626..e55e9d114 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -28,6 +28,7 @@ import (
"github.com/containers/podman/v4/pkg/resolvconf"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/util"
+ "github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
@@ -495,6 +496,12 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
return nil, err
}
+ // move to systemd scope to prevent systemd from killing it
+ err = utils.MoveRootlessNetnsSlirpProcessToUserSlice(cmd.Process.Pid)
+ if err != nil {
+ logrus.Errorf("failed to move the rootless netns slirp4netns process to the systemd user.slice: %v", err)
+ }
+
// build a new resolv.conf file which uses the slirp4netns dns server address
resolveIP, err := GetSlirp4netnsDNS(nil)
if err != nil {
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index c47679904..3847d9510 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -281,4 +281,34 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
is "$output" "" "output should be empty"
}
+# https://github.com/containers/podman/issues/13153
+@test "podman rootless-netns slirp4netns process should be in different cgroup" {
+ is_rootless || skip "only meaningful for rootless"
+
+ cname=$(random_string)
+ local netname=testnet-$(random_string 10)
+
+ # create network and container with network
+ run_podman network create $netname
+ run_podman create --name $cname --network $netname $IMAGE top
+
+ # run container in systemd unit
+ service_setup
+
+ # run second container with network
+ cname2=$(random_string)
+ run_podman run -d --name $cname2 --network $netname $IMAGE top
+
+ # stop systemd container
+ service_cleanup
+
+ # now check that the rootless netns slirp4netns process is still alive and working
+ run_podman unshare --rootless-netns ip addr
+ is "$output" ".*tap0.*" "slirp4netns interface exists in the netns"
+ run_podman exec $cname2 nslookup google.com
+
+ run_podman rm -f -t0 $cname2
+ run_podman network rm -f $netname
+}
+
# vim: filetype=sh
diff --git a/utils/utils.go b/utils/utils.go
index 52586b937..22f0cb12f 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -174,7 +174,7 @@ func RunsOnSystemd() bool {
return runsOnSystemd
}
-func moveProcessToScope(pidPath, slice, scope string) error {
+func moveProcessPIDFileToScope(pidPath, slice, scope string) error {
data, err := ioutil.ReadFile(pidPath)
if err != nil {
// do not raise an error if the file doesn't exist
@@ -187,18 +187,32 @@ func moveProcessToScope(pidPath, slice, scope string) error {
if err != nil {
return errors.Wrapf(err, "cannot parse pid file %s", pidPath)
}
- err = RunUnderSystemdScope(int(pid), slice, scope)
+ return moveProcessToScope(int(pid), slice, scope)
+}
+
+func moveProcessToScope(pid int, slice, scope string) error {
+ err := RunUnderSystemdScope(int(pid), slice, scope)
// If the PID is not valid anymore, do not return an error.
if dbusErr, ok := err.(dbus.Error); ok {
if dbusErr.Name == "org.freedesktop.DBus.Error.UnixProcessIdUnknown" {
return nil
}
}
-
return err
}
+// MoveRootlessNetnsSlirpProcessToUserSlice moves the slirp4netns process for the rootless netns
+// into a different scope so that systemd does not kill it with a container.
+func MoveRootlessNetnsSlirpProcessToUserSlice(pid int) error {
+ randBytes := make([]byte, 4)
+ _, err := rand.Read(randBytes)
+ if err != nil {
+ return err
+ }
+ return moveProcessToScope(pid, "user.slice", fmt.Sprintf("rootless-netns-%x.scope", randBytes))
+}
+
// MovePauseProcessToScope moves the pause process used for rootless mode to keep the namespaces alive to
// a separate scope.
func MovePauseProcessToScope(pausePidPath string) {
@@ -211,7 +225,7 @@ func MovePauseProcessToScope(pausePidPath string) {
logrus.Errorf("failed to read random bytes: %v", err)
continue
}
- err = moveProcessToScope(pausePidPath, "user.slice", fmt.Sprintf("podman-pause-%x.scope", randBytes))
+ err = moveProcessPIDFileToScope(pausePidPath, "user.slice", fmt.Sprintf("podman-pause-%x.scope", randBytes))
if err == nil {
return
}