From 3fd162d800d1f423a7020c556c6671719bbec450 Mon Sep 17 00:00:00 2001 From: Shreya Vidyadhar Keshatti Date: Tue, 11 Aug 2026 23:19:13 +0530 Subject: [PATCH] libnetwork: avoid restarting rootless helper during teardown Signed-off-by: Shreya Vidyadhar Keshatti --- .../internal/rootlessnetns/netns_linux.go | 23 ++++++++++---- .../rootlessnetns/netns_linux_test.go | 30 +++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/common/libnetwork/internal/rootlessnetns/netns_linux.go b/common/libnetwork/internal/rootlessnetns/netns_linux.go index d8e77f35f1..1f9c540344 100644 --- a/common/libnetwork/internal/rootlessnetns/netns_linux.go +++ b/common/libnetwork/internal/rootlessnetns/netns_linux.go @@ -105,10 +105,17 @@ func (n *Netns) getPath(path string) string { // getOrCreateNetns returns the rootless netns, if it created a new one the // returned bool is set to true. -func (n *Netns) getOrCreateNetns() (netns.NetNS, bool, error) { +func (n *Netns) getOrCreateNetns(create bool) (netns.NetNS, bool, error) { nsPath := n.getPath(rootlessNetnsDir) nsRef, err := netns.GetNS(nsPath) if err == nil { + if !create { + if err := n.deserializeInfo(); err != nil { + return nil, false, wrapError("deserialize info", err) + } + return nsRef, false, nil + } + pidPath := n.getPath(rootlessNetNsConnPidFile) pid, err := readPidFile(pidPath) if err == nil { @@ -133,6 +140,10 @@ func (n *Netns) getOrCreateNetns() (netns.NetNS, bool, error) { } // In case of errors continue and setup the network cmd again. } else { + if !create { + return nil, false, err + } + // Special case, the file might exist already but is not a valid netns. // One reason could be that a previous setup was killed between creating // the file and mounting it. Or if the file is not on tmpfs (deleted on boot) @@ -539,8 +550,8 @@ func (n *Netns) setupMounts() error { return nil } -func (n *Netns) runInner(toRun func() error, cleanup bool) (err error) { - nsRef, newNs, err := n.getOrCreateNetns() +func (n *Netns) runInner(toRun func() error, cleanup bool, create bool) (err error) { + nsRef, newNs, err := n.getOrCreateNetns(create) if err != nil { return err } @@ -568,7 +579,7 @@ func (n *Netns) runInner(toRun func() error, cleanup bool) (err error) { } func (n *Netns) Setup(nets int, toRun func() error) error { - err := n.runInner(toRun, true) + err := n.runInner(toRun, true, true) if err != nil { return err } @@ -577,7 +588,7 @@ func (n *Netns) Setup(nets int, toRun func() error) error { } func (n *Netns) Teardown(nets int, toRun func() error) error { - err := n.runInner(toRun, true) + err := n.runInner(toRun, true, false) if err != nil { return err } @@ -614,7 +625,7 @@ func (n *Netns) Run(lock *lockfile.LockFile, toRun func() error) error { return err } - inErr := n.runInner(inner, false) + inErr := n.runInner(inner, false, true) // make sure to always reset the ref counter afterwards count, err := refCount(n.dir, -1) if err != nil { diff --git a/common/libnetwork/internal/rootlessnetns/netns_linux_test.go b/common/libnetwork/internal/rootlessnetns/netns_linux_test.go index 3562c70bfc..143bc9de11 100644 --- a/common/libnetwork/internal/rootlessnetns/netns_linux_test.go +++ b/common/libnetwork/internal/rootlessnetns/netns_linux_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.podman.io/common/pkg/config" ) func Test_refCount(t *testing.T) { @@ -75,3 +76,32 @@ func Test_refCount(t *testing.T) { }) } } + +func Test_getOrCreateNetnsNoCreateDoesNotRestartHelper(t *testing.T) { + dir := t.TempDir() + + conf, err := config.Default() + assert.NoError(t, err) + + n, err := New(dir, conf) + assert.NoError(t, err) + + nsPath := n.getPath(rootlessNetnsDir) + err = os.Symlink("/proc/self/ns/net", nsPath) + assert.NoError(t, err) + + err = os.WriteFile( + n.getPath(rootlessNetNsConnPidFile), + []byte("99999999"), + 0o600, + ) + assert.NoError(t, err) + + ns, created, err := n.getOrCreateNetns(false) + assert.NoError(t, err) + assert.False(t, created) + + if ns != nil { + assert.NoError(t, ns.Close()) + } +}