diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index 883fdd956..261b6cb99 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -20,6 +20,7 @@ package netns import ( "crypto/rand" + "errors" "fmt" "os" "path" @@ -51,13 +52,24 @@ func GetNSRunDir() (string, error) { // NewNS creates a new persistent (bind-mounted) network namespace and returns // an object representing that namespace, without switching to it. func NewNS() (ns.NetNS, error) { - b := make([]byte, 16) - _, err := rand.Reader.Read(b) - if err != nil { - return nil, fmt.Errorf("failed to generate random netns name: %v", err) + for i := 0; i < 1000000; i++ { + b := make([]byte, 16) + _, err := rand.Reader.Read(b) + if err != nil { + return nil, fmt.Errorf("failed to generate random netns name: %v", err) + } + nsName := fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + ns, err := NewNSWithName(nsName) + if err == nil { + return ns, nil + } + // retry when the name already exists + if errors.Is(err, os.ErrExist) { + continue + } + return nil, err } - nsName := fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - return NewNSWithName(nsName) + return nil, errors.New("failed to find free netns path name") } // NewNSWithName creates a new persistent (bind-mounted) network namespace and returns @@ -101,7 +113,7 @@ func NewNSWithName(name string) (ns.NetNS, error) { // create an empty file at the mount point nsPath := path.Join(nsRunDir, name) - mountPointFd, err := os.Create(nsPath) + mountPointFd, err := os.OpenFile(name, os.O_RDONLY|os.O_CREATE|os.O_EXCL, 0o600) if err != nil { return nil, err }