libnetwork/osl: restore the right thread's netns
osl.setIPv6 mistakenly captured the calling goroutine's thread's network namespace instead of the network namespace of the thread getting its namespace temporarily changed. As this function appears to only be called from contexts in the process's initial network namespace, this mistake would be of little consequence at runtime. The libnetwork unit tests, on the other hand, unshare network namespaces so as not to interfere with each other or the host's network namespace. But due to this bug, the isolation backfires and the network namespace of goroutines used by a test which are expected to be in the initial network namespace can randomly become the isolated network namespace of some other test. Symptoms include a loopback network server running in one goroutine being inexplicably and randomly being unreachable by a client in another goroutine. Capture the original network namespace of the thread from the thread to be tampered with, after locking the goroutine to the thread. Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
parent
d4f3858a40
commit
6d79864135
1 changed files with 17 additions and 12 deletions
|
@ -600,24 +600,29 @@ func (n *networkNamespace) checkLoV6() {
|
|||
}
|
||||
|
||||
func setIPv6(nspath, iface string, enable bool) error {
|
||||
origNS, err := netns.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get current network namespace: %w", err)
|
||||
}
|
||||
defer origNS.Close()
|
||||
|
||||
namespace, err := netns.GetFromPath(nspath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed get network namespace %q: %w", nspath, err)
|
||||
}
|
||||
defer namespace.Close()
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(errCh)
|
||||
|
||||
namespace, err := netns.GetFromPath(nspath)
|
||||
if err != nil {
|
||||
errCh <- fmt.Errorf("failed get network namespace %q: %w", nspath, err)
|
||||
return
|
||||
}
|
||||
defer namespace.Close()
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
||||
origNS, err := netns.Get()
|
||||
if err != nil {
|
||||
runtime.UnlockOSThread()
|
||||
errCh <- fmt.Errorf("failed to get current network namespace: %w", err)
|
||||
return
|
||||
}
|
||||
defer origNS.Close()
|
||||
|
||||
if err = netns.Set(namespace); err != nil {
|
||||
runtime.UnlockOSThread()
|
||||
errCh <- fmt.Errorf("setting into container netns %q failed: %w", nspath, err)
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue