Skip to content

Commit

Permalink
pkg/netns: NewNS() check if file name already exists
Browse files Browse the repository at this point in the history
The code picks a random name but never checked if this name was already
in use. If the RNG creates generates the same name again we will end up
with containers sharing the same netns which can be very bad.
It is very unlikely to happen but this the only explanation I find for
containers/podman#17903.

Signed-off-by: Paul Holzinger <[email protected]>
  • Loading branch information
Luap99 committed Mar 24, 2023
1 parent 03a2cc0 commit 43ab981
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions pkg/netns/netns_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package netns

import (
"crypto/rand"
"errors"
"fmt"
"os"
"path"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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, 0666)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 43ab981

Please sign in to comment.