mirror of
https://github.com/containers/podman.git
synced 2025-05-17 23:26:08 +08:00
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 <pholzing@redhat.com>
This commit is contained in:
@ -3,11 +3,8 @@
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
@ -17,7 +14,6 @@ import (
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// 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
|
||||
// Configure the network namespace using the container process
|
||||
func (r *Runtime) setupNetNS(ctr *Container) error {
|
||||
nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID)
|
||||
|
||||
b := make([]byte, 16)
|
||||
|
||||
if _, err := rand.Reader.Read(b); err != nil {
|
||||
return fmt.Errorf("failed to generate random netns name: %w", err)
|
||||
}
|
||||
nsPath, err := netns.GetNSRunDir()
|
||||
nsPath, err := netns.NewNSFrom(nsProcess)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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:]))
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mountPointFd, err := os.Create(nsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mountPointFd.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := unix.Mount(nsProcess, nsPath, "none", unix.MS_BIND, ""); err != nil {
|
||||
return fmt.Errorf("cannot mount %s: %w", nsPath, err)
|
||||
}
|
||||
|
||||
networkStatus, err := r.configureNetNS(ctr, nsPath)
|
||||
|
||||
|
@ -149,3 +149,22 @@ function _check_pause_process() {
|
||||
|
||||
run_podman rm -f -t0 $cname1
|
||||
}
|
||||
|
||||
# regression test for https://issues.redhat.com/browse/RHEL-59620
|
||||
@test "rootless userns can unmount netns properly" {
|
||||
skip_if_not_rootless "pause process is only used as rootless"
|
||||
skip_if_remote "system migrate not supported via remote"
|
||||
|
||||
# Use podman system migrate to stop the currently running pause process
|
||||
run_podman system migrate
|
||||
|
||||
# First run a container with a custom userns as this uses different netns setup logic.
|
||||
local cname=c-$(safename)
|
||||
run_podman run --userns keep-id --name $cname -d $IMAGE sleep 100
|
||||
|
||||
# Now run a "normal" container without userns
|
||||
run_podman run --rm $IMAGE true
|
||||
|
||||
# This used to hang trying to unmount the netns.
|
||||
run_podman rm -f -t0 $cname
|
||||
}
|
||||
|
Reference in New Issue
Block a user