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 9 months ago committed by Nick Khyl
parent 82c569a83a
commit b42b9817b0

@ -14,6 +14,7 @@ import (
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"sync"
"syscall" "syscall"
"time" "time"
@ -38,6 +39,9 @@ type windowsManager struct {
guid string guid string
nrptDB *nrptRuleDatabase nrptDB *nrptRuleDatabase
wslManager *wslManager wslManager *wslManager
mu sync.Mutex
closing bool
} }
func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) { 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) { func (m *windowsManager) openInterfaceKey(pfx winutil.RegistryPathPrefix) (registry.Key, error) {
var key registry.Key
var err error
path := pfx.WithSuffix(m.guid) 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 { if err != nil {
return 0, fmt.Errorf("opening %s: %w", path, err) return 0, fmt.Errorf("opening %s: %w", path, err)
} }
return key, nil 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 { func delValue(key registry.Key, name string) error {
if err := key.DeleteValue(name); err != nil && err != registry.ErrNotExist { if err := key.DeleteValue(name); err != nil && err != registry.ErrNotExist {
return err return err
@ -205,7 +232,7 @@ func (m *windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname
key4, err := m.openInterfaceKey(winutil.IPv4TCPIPInterfacePrefix) key4, err := m.openInterfaceKey(winutil.IPv4TCPIPInterfacePrefix)
if err != nil { if err != nil {
return err return m.muteKeyNotFoundIfClosing(err)
} }
defer key4.Close() defer key4.Close()
@ -227,7 +254,7 @@ func (m *windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname
key6, err := m.openInterfaceKey(winutil.IPv6TCPIPInterfacePrefix) key6, err := m.openInterfaceKey(winutil.IPv6TCPIPInterfacePrefix)
if err != nil { if err != nil {
return err return m.muteKeyNotFoundIfClosing(err)
} }
defer key6.Close() defer key6.Close()
@ -387,6 +414,14 @@ func (m *windowsManager) SupportsSplitDNS() bool {
} }
func (m *windowsManager) Close() error { 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{}) err := m.SetDNS(OSConfig{})
if m.nrptDB != nil { if m.nrptDB != nil {
m.nrptDB.Close() m.nrptDB.Close()
@ -407,7 +442,7 @@ func (m *windowsManager) disableDynamicUpdates() error {
for _, prefix := range prefixen { for _, prefix := range prefixen {
k, err := m.openInterfaceKey(prefix) k, err := m.openInterfaceKey(prefix)
if err != nil { if err != nil {
return err return m.muteKeyNotFoundIfClosing(err)
} }
defer k.Close() defer k.Close()
@ -426,7 +461,7 @@ func (m *windowsManager) disableDynamicUpdates() error {
func (m *windowsManager) setSingleDWORD(prefix winutil.RegistryPathPrefix, value string, data uint32) error { func (m *windowsManager) setSingleDWORD(prefix winutil.RegistryPathPrefix, value string, data uint32) error {
k, err := m.openInterfaceKey(prefix) k, err := m.openInterfaceKey(prefix)
if err != nil { if err != nil {
return err return m.muteKeyNotFoundIfClosing(err)
} }
defer k.Close() defer k.Close()
return k.SetDWordValue(value, data) return k.SetDWordValue(value, data)

Loading…
Cancel
Save