Skip to content

Commit

Permalink
Merge pull request #13159 from Luap99/slirp4-scope
Browse files Browse the repository at this point in the history
move rootless netns slirp4netns process to systemd user.slice
  • Loading branch information
openshift-merge-robot committed Feb 8, 2022
2 parents 46d9a25 + 8d0fb0a commit cbd0980
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
7 changes: 7 additions & 0 deletions libpod/networking_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
30 changes: 30 additions & 0 deletions test/system/250-systemd.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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
22 changes: 18 additions & 4 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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
}
Expand Down

0 comments on commit cbd0980

Please sign in to comment.