Skip to content

Commit 7927961

Browse files
committed
libpod: setupNetNS() correctly mount netns
The netns dir has a special logic to bind mout itself and make itslef shared. This code here didn't which lead to catastrophic bug during netns unmounting as we were unable to unmount the netns as the mount got duplicated and had the wrong parent mount. This caused us to loop forever trying to remove the file. Fixes https://issues.redhat.com/browse/RHEL-59620 Fixes #23685 Signed-off-by: Paul Holzinger <[email protected]>
1 parent f6bda78 commit 7927961

File tree

2 files changed

+20
-28
lines changed

2 files changed

+20
-28
lines changed

libpod/networking_linux.go

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
package libpod
44

55
import (
6-
"crypto/rand"
76
"fmt"
87
"net"
9-
"os"
10-
"path/filepath"
118

129
"github.com/containernetworking/plugins/pkg/ns"
1310
"github.com/containers/common/libnetwork/types"
@@ -17,7 +14,6 @@ import (
1714
"github.com/opencontainers/runtime-spec/specs-go"
1815
"github.com/sirupsen/logrus"
1916
"github.com/vishvananda/netlink"
20-
"golang.org/x/sys/unix"
2117
)
2218

2319
// Create and configure a new network namespace for a container
@@ -104,33 +100,10 @@ func (r *Runtime) createNetNS(ctr *Container) (n string, q map[string]types.Stat
104100
// Configure the network namespace using the container process
105101
func (r *Runtime) setupNetNS(ctr *Container) error {
106102
nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID)
107-
108-
b := make([]byte, 16)
109-
110-
if _, err := rand.Reader.Read(b); err != nil {
111-
return fmt.Errorf("failed to generate random netns name: %w", err)
112-
}
113-
nsPath, err := netns.GetNSRunDir()
114-
if err != nil {
115-
return err
116-
}
117-
nsPath = filepath.Join(nsPath, fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]))
118-
119-
if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
120-
return err
121-
}
122-
123-
mountPointFd, err := os.Create(nsPath)
103+
nsPath, err := netns.NewNSFrom(nsProcess)
124104
if err != nil {
125105
return err
126106
}
127-
if err := mountPointFd.Close(); err != nil {
128-
return err
129-
}
130-
131-
if err := unix.Mount(nsProcess, nsPath, "none", unix.MS_BIND, ""); err != nil {
132-
return fmt.Errorf("cannot mount %s: %w", nsPath, err)
133-
}
134107

135108
networkStatus, err := r.configureNetNS(ctr, nsPath)
136109

test/system/550-pause-process.bats

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,22 @@ function _check_pause_process() {
149149

150150
run_podman rm -f -t0 $cname1
151151
}
152+
153+
# regression test for https://issues.redhat.com/browse/RHEL-59620
154+
@test "rootless userns can unmount netns properly" {
155+
skip_if_not_rootless "pause process is only used as rootless"
156+
skip_if_remote "system migrate not supported via remote"
157+
158+
# Use podman system migrate to stop the currently running pause process
159+
run_podman system migrate
160+
161+
# First run a container with a custom userns as this uses different netns setup logic.
162+
local cname=c-$(safename)
163+
run_podman run --userns keep-id --name $cname -d $IMAGE sleep 100
164+
165+
# Now run a "normal" container without userns
166+
run_podman run --rm $IMAGE true
167+
168+
# This used to hang trying to unmount the netns.
169+
run_podman rm -f -t0 $cname
170+
}

0 commit comments

Comments
 (0)