From 115a4b0ddc94f37465f1f9626483ed67c80a85c7 Mon Sep 17 00:00:00 2001 From: Quan Tian Date: Sat, 22 Aug 2020 01:34:38 +0800 Subject: [PATCH] Fix race condition in GetCurrentNS temporarily (#1131) In GetCurrentNS, If there is a context-switch between getCurrentThreadNetNSPath and GetNS, another goroutine may execute in the original thread and change its network namespace, then the original goroutine would get the updated network namespace, which could lead to unexpected behavior, especially when GetCurrentNS is used to get the host network namespace in netNS.Do. Instead of using the provided netns argument, this patch fixes it by getting the hostNS in advance with the OS thread locked. --- .../cniserver/interface_configuration_linux.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/agent/cniserver/interface_configuration_linux.go b/pkg/agent/cniserver/interface_configuration_linux.go index b22877fa9f4..ff413a3620e 100644 --- a/pkg/agent/cniserver/interface_configuration_linux.go +++ b/pkg/agent/cniserver/interface_configuration_linux.go @@ -19,6 +19,7 @@ package cniserver import ( "fmt" "net" + "runtime" "time" "github.com/Mellanox/sriovnet" @@ -194,7 +195,22 @@ func (ic *ifConfigurator) configureContainerLinkVeth( hostIface := ¤t.Interface{Name: hostIfaceName} containerIface := ¤t.Interface{Name: containerIfaceName, Sandbox: containerNetNS} result.Interfaces = []*current.Interface{hostIface, containerIface} - if err := ns.WithNetNSPath(containerNetNS, func(hostNS ns.NetNS) error { + + // This is a workaround for issue #1113, which is caused by https://github.com/containernetworking/plugins/issues/524. + // Instead of using the provided netns argument, which might not be the real hostNS, it fixes it by getting the + // hostNS in advance with the OS thread locked. + // TODO: remove this once the upstream issue is fixed. + hostNS, err := func() (ns.NetNS, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + return ns.GetCurrentNS() + }() + if err != nil { + return fmt.Errorf("failed to get host netns: %v", err) + } + defer hostNS.Close() + + if err := ns.WithNetNSPath(containerNetNS, func(_ ns.NetNS) error { klog.V(2).Infof("Creating veth devices (%s, %s) for container %s", containerIfaceName, hostIfaceName, containerID) hostVeth, containerVeth, err := ip.SetupVethWithName(containerIfaceName, hostIfaceName, mtu, hostNS) if err != nil {