From 9d818be7329929b05b93e432c408ee65726ec2c0 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Sun, 21 Feb 2021 16:27:25 +0100 Subject: Fix podman network IDs handling The libpod network logic knows about networks IDs but OCICNI does not. We cannot pass the network ID to OCICNI. Instead we need to make sure we only use network names internally. This is also important for libpod since we also only store the network names in the state. If we would add a ID there the same networks could accidentally be added twice. Fixes #9451 Signed-off-by: Paul Holzinger --- libpod/network/files.go | 4 ++-- libpod/network/network.go | 19 +++++++++++++++++-- libpod/networking_linux.go | 14 ++++++-------- libpod/runtime_ctr.go | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 12 deletions(-) (limited to 'libpod') diff --git a/libpod/network/files.go b/libpod/network/files.go index f869d32c3..fe483e25c 100644 --- a/libpod/network/files.go +++ b/libpod/network/files.go @@ -81,9 +81,9 @@ func GetCNIConfigPathByNameOrID(config *config.Config, name string) (string, err return "", errors.Wrap(define.ErrNoSuchNetwork, fmt.Sprintf("unable to find network configuration for %s", name)) } -// ReadRawCNIConfByName reads the raw CNI configuration for a CNI +// ReadRawCNIConfByNameOrID reads the raw CNI configuration for a CNI // network by name -func ReadRawCNIConfByName(config *config.Config, name string) ([]byte, error) { +func ReadRawCNIConfByNameOrID(config *config.Config, name string) ([]byte, error) { confFile, err := GetCNIConfigPathByNameOrID(config, name) if err != nil { return nil, err diff --git a/libpod/network/network.go b/libpod/network/network.go index b347ec0e2..f19a764ef 100644 --- a/libpod/network/network.go +++ b/libpod/network/network.go @@ -7,6 +7,7 @@ import ( "net" "os" + "github.com/containernetworking/cni/libcni" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" "github.com/containers/common/pkg/config" @@ -222,7 +223,7 @@ func RemoveNetwork(config *config.Config, name string) error { // InspectNetwork reads a CNI config and returns its configuration func InspectNetwork(config *config.Config, name string) (map[string]interface{}, error) { - b, err := ReadRawCNIConfByName(config, name) + b, err := ReadRawCNIConfByNameOrID(config, name) if err != nil { return nil, err } @@ -234,7 +235,7 @@ func InspectNetwork(config *config.Config, name string) (map[string]interface{}, // Exists says whether a given network exists or not; it meant // specifically for restful responses so 404s can be used func Exists(config *config.Config, name string) (bool, error) { - _, err := ReadRawCNIConfByName(config, name) + _, err := ReadRawCNIConfByNameOrID(config, name) if err != nil { if errors.Cause(err) == define.ErrNoSuchNetwork { return false, nil @@ -277,3 +278,17 @@ func PruneNetworks(rtc *config.Config, usedNetworks map[string]bool) ([]*entitie } return reports, nil } + +// NormalizeName translates a network ID into a name. +// If the input is a name the name is returned. +func NormalizeName(config *config.Config, nameOrID string) (string, error) { + path, err := GetCNIConfigPathByNameOrID(config, nameOrID) + if err != nil { + return "", err + } + conf, err := libcni.ConfListFromFile(path) + if err != nil { + return "", err + } + return conf.Name, nil +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 5f9ad0e27..c1b2c694d 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -1139,13 +1139,12 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro return err } - exists, err := network.Exists(c.runtime.config, netName) + // check if network exists and if the input is a ID we get the name + // ocicni only uses names so it is important that we only use the name + netName, err = network.NormalizeName(c.runtime.config, netName) if err != nil { return err } - if !exists { - return errors.Wrap(define.ErrNoSuchNetwork, netName) - } index, nameExists := networks[netName] if !nameExists && len(networks) > 0 { @@ -1196,13 +1195,12 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e return err } - exists, err := network.Exists(c.runtime.config, netName) + // check if network exists and if the input is a ID we get the name + // ocicni only uses names so it is important that we only use the name + netName, err = network.NormalizeName(c.runtime.config, netName) if err != nil { return err } - if !exists { - return errors.Wrap(define.ErrNoSuchNetwork, netName) - } c.lock.Lock() defer c.lock.Unlock() diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index af87ccca1..8bf862bf2 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/events" + "github.com/containers/podman/v3/libpod/network" "github.com/containers/podman/v3/libpod/shutdown" "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/podman/v3/pkg/domain/entities/reports" @@ -285,6 +286,21 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai return nil, err } + // normalize the networks to names + // ocicni only knows about cni names so we have to make + // sure we do not use ids internally + if len(ctr.config.Networks) > 0 { + netNames := make([]string, 0, len(ctr.config.Networks)) + for _, nameOrID := range ctr.config.Networks { + netName, err := network.NormalizeName(r.config, nameOrID) + if err != nil { + return nil, err + } + netNames = append(netNames, netName) + } + ctr.config.Networks = netNames + } + // Inhibit shutdown until creation succeeds shutdown.Inhibit() defer shutdown.Uninhibit() -- cgit v1.2.3-54-g00ecf