Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move rootless netns slirp4netns process to systemd user.slice #13159

Merged
merged 1 commit into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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" {
Luap99 marked this conversation as resolved.
Show resolved Hide resolved
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

Luap99 marked this conversation as resolved.
Show resolved Hide resolved
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