From 8404507b9b17982dec2e4bc44e8c360d2b31a383 Mon Sep 17 00:00:00 2001 From: Cory Snider Date: Fri, 4 Nov 2022 20:41:03 -0400 Subject: [PATCH] libnet/osl: stop assuming caller thread is clean (*networkNamespace).InvokeFunc() cleaned up the state of the locked thread by setting its network namespace to the netns of the goroutine which called InvokeFunc(). If InvokeFunc() was to be called after the caller had modified its thread's network namespace, InvokeFunc() would incorrectly "restore" the state of its goroutine thread to the wrong namespace, violating the invariant that unlocked threads are fungible. Change the implementation to restore the thread's netns to the netns that particular thread had before InvokeFunc() modified it. Signed-off-by: Cory Snider --- libnetwork/osl/namespace_linux.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libnetwork/osl/namespace_linux.go b/libnetwork/osl/namespace_linux.go index 87228b043f..1e89deff72 100644 --- a/libnetwork/osl/namespace_linux.go +++ b/libnetwork/osl/namespace_linux.go @@ -420,12 +420,6 @@ func (n *networkNamespace) DisableARPForVIP(srcName string) (Err error) { } func (n *networkNamespace) InvokeFunc(f func()) error { - origNS, err := netns.Get() - if err != nil { - return fmt.Errorf("failed to get original network namespace: %w", err) - } - defer origNS.Close() - path := n.nsPath() newNS, err := netns.GetFromPath(path) if err != nil { @@ -436,6 +430,18 @@ func (n *networkNamespace) InvokeFunc(f func()) error { done := make(chan error, 1) go func() { runtime.LockOSThread() + // InvokeFunc() could have been called from a goroutine with + // tampered thread state, e.g. from another InvokeFunc() + // callback. The outer goroutine's thread state cannot be + // trusted. + origNS, err := netns.Get() + if err != nil { + runtime.UnlockOSThread() + done <- fmt.Errorf("failed to get original network namespace: %w", err) + return + } + defer origNS.Close() + if err := netns.Set(newNS); err != nil { runtime.UnlockOSThread() done <- err