Skip to content

Commit

Permalink
libnetwork/rootlessnetns: fix netns leak on errors
Browse files Browse the repository at this point in the history
When the netns program fails to configure the netns or we fail for any
other reason during the setup we must make sure to remove the netns
mount again. Without it the next command sees the existing mount and
thinks the netns was setup correctly but than later fails during the
custom resolv.conf mount because the resolv.conf source file was never
created.

For future we should consider adding checks due ensure pasta/slirp4netns
is still running when we access the netns to make it more fault
tolerant.

The reason this is a common problem is that on boot pasta can likely
fail if it was started before the networking was fully configured (i.e.
no default route).

Fixes containers/podman#22168

Signed-off-by: Paul Holzinger <[email protected]>
  • Loading branch information
Luap99 committed Apr 12, 2024
1 parent 36904a0 commit feb2281
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions libnetwork/internal/rootlessnetns/netns_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) {
nsPath := n.getPath(rootlessNetnsDir)
nsRef, err := ns.GetNS(nsPath)
if err == nil {
// TODO check if slirp4netns is alive
// TODO check if pasta/slirp4netns is alive
return nsRef, false, nil
}
logrus.Debugf("Creating rootless network namespace at %q", nsPath)
Expand All @@ -109,7 +109,7 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) {
if err := os.MkdirAll(n.dir, 0o700); err != nil {
return nil, false, wrapError("", err)
}
netns, err := netns.NewNSAtPath(nsPath)
nsRef, err = netns.NewNSAtPath(nsPath)
if err != nil {
return nil, false, wrapError("create netns", err)
}
Expand All @@ -121,7 +121,17 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) {
default:
err = fmt.Errorf("invalid rootless network command %q", n.config.Network.DefaultRootlessNetworkCmd)
}
return netns, true, err
// If pasta or slirp4netns fail here we need to get rid of the netns again to not leak it,
// otherwise the next command thinks the netns was successfully setup.
if err != nil {
if nerr := netns.UnmountNS(nsPath); nerr != nil {
logrus.Error(nerr)
}
_ = nsRef.Close()
return nil, false, err
}

return nsRef, true, nil
}

func (n *Netns) cleanup() error {
Expand Down

0 comments on commit feb2281

Please sign in to comment.