net/dns: do not wait for the interface registry key to appear if the windowsManager is being closed

The WinTun adapter may have been removed by the time we're closing
the dns.windowsManager, and its associated interface registry key might
also have been deleted. We shouldn't use winutil.OpenKeyWait and wait
for the interface key to appear when performing a cleanup as a part of
the windowsManager shutdown.

Updates #11222

Signed-off-by: Nick Khyl <nickk@tailscale.com>
pull/11239/head
Nick Khyl 3 months ago committed by Nick Khyl
parent 82c569a83a
commit b42b9817b0

@ -14,6 +14,7 @@ import (
"path/filepath"
"sort"
"strings"
"sync"
"syscall"
"time"
@ -38,6 +39,9 @@ type windowsManager struct {
guid string
nrptDB *nrptRuleDatabase
wslManager *wslManager
mu sync.Mutex
closing bool
}
func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) {
@ -64,14 +68,37 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator,
}
func (m *windowsManager) openInterfaceKey(pfx winutil.RegistryPathPrefix) (registry.Key, error) {
var key registry.Key
var err error
path := pfx.WithSuffix(m.guid)
key, err := winutil.OpenKeyWait(registry.LOCAL_MACHINE, path, registry.SET_VALUE)
m.mu.Lock()
closing := m.closing
m.mu.Unlock()
if closing {
// Do not wait for the interface key to appear if the manager is being closed.
// If it's being closed due to the removal of the wintun adapter,
// the key would already be gone by now and will not reappear until tailscaled is restarted.
key, err = registry.OpenKey(registry.LOCAL_MACHINE, string(path), registry.SET_VALUE)
} else {
key, err = winutil.OpenKeyWait(registry.LOCAL_MACHINE, path, registry.SET_VALUE)
}
if err != nil {
return 0, fmt.Errorf("opening %s: %w", path, err)
}
return key, nil
}
func (m *windowsManager) muteKeyNotFoundIfClosing(err error) error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.closing || (err != windows.ERROR_FILE_NOT_FOUND && err != windows.ERROR_PATH_NOT_FOUND) {
return err
}
return nil
}
func delValue(key registry.Key, name string) error {
if err := key.DeleteValue(name); err != nil && err != registry.ErrNotExist {
return err
@ -205,7 +232,7 @@ func (m *windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname
key4, err := m.openInterfaceKey(winutil.IPv4TCPIPInterfacePrefix)
if err != nil {
return err
return m.muteKeyNotFoundIfClosing(err)
}
defer key4.Close()
@ -227,7 +254,7 @@ func (m *windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname
key6, err := m.openInterfaceKey(winutil.IPv6TCPIPInterfacePrefix)
if err != nil {
return err
return m.muteKeyNotFoundIfClosing(err)
}
defer key6.Close()
@ -387,6 +414,14 @@ func (m *windowsManager) SupportsSplitDNS() bool {
}
func (m *windowsManager) Close() error {
m.mu.Lock()
if m.closing {
m.mu.Unlock()
return nil
}
m.closing = true
m.mu.Unlock()
err := m.SetDNS(OSConfig{})
if m.nrptDB != nil {
m.nrptDB.Close()
@ -407,7 +442,7 @@ func (m *windowsManager) disableDynamicUpdates() error {
for _, prefix := range prefixen {
k, err := m.openInterfaceKey(prefix)
if err != nil {
return err
return m.muteKeyNotFoundIfClosing(err)
}
defer k.Close()
@ -426,7 +461,7 @@ func (m *windowsManager) disableDynamicUpdates() error {
func (m *windowsManager) setSingleDWORD(prefix winutil.RegistryPathPrefix, value string, data uint32) error {
k, err := m.openInterfaceKey(prefix)
if err != nil {
return err
return m.muteKeyNotFoundIfClosing(err)
}
defer k.Close()
return k.SetDWordValue(value, data)

Loading…
Cancel
Save