Skip to content

Commit 47019ce

Browse files
committed
cmd/tailscaled: pre-load wintun.dll using a fully-qualified path
In corp PR tailscale#14970 I updated the installer to set a security mitigation that always forces system32 to the front of the Windows dynamic linker's search path. Unfortunately there are other products out there that, partying like it's 1995, drop their own, older version of wintun.dll into system32. Since we look there first, we end up loading that old version. We can fix this by preloading wintun using a fully-qualified path. When wintun-go then loads wintun, the dynamic linker will hand it the module that was previously loaded by us. Fixes tailscale#10023, tailscale#10025, tailscale#10052 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
1 parent af49bca commit 47019ce

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

cmd/tailscaled/tailscaled_windows.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"os"
3131
"os/exec"
3232
"os/signal"
33+
"path/filepath"
3334
"sync"
3435
"syscall"
3536
"time"
@@ -299,6 +300,14 @@ func beWindowsSubprocess() bool {
299300
}
300301
}()
301302

303+
// Pre-load wintun.dll using a fully-qualified path so that wintun-go
304+
// loads our copy and not some (possibly outdated) copy dropped in system32.
305+
// (OSS Issue #10023)
306+
fqWintunPath := fullyQualifiedWintunPath(log.Printf)
307+
if _, err := windows.LoadDLL(fqWintunPath); err != nil {
308+
log.Printf("Error pre-loading \"%s\": %v", fqWintunPath, err)
309+
}
310+
302311
sys := new(tsd.System)
303312
netMon, err := netmon.New(log.Printf)
304313
if err != nil {
@@ -507,7 +516,7 @@ func babysitProc(ctx context.Context, args []string, logf logger.Logf) {
507516
}
508517

509518
func uninstallWinTun(logf logger.Logf) {
510-
dll := windows.NewLazyDLL("wintun.dll")
519+
dll := windows.NewLazyDLL(fullyQualifiedWintunPath(logf))
511520
if err := dll.Load(); err != nil {
512521
logf("Cannot load wintun.dll for uninstall: %v", err)
513522
return
@@ -517,3 +526,16 @@ func uninstallWinTun(logf logger.Logf) {
517526
err := wintun.Uninstall()
518527
logf("Uninstall: %v", err)
519528
}
529+
530+
func fullyQualifiedWintunPath(logf logger.Logf) string {
531+
var dir string
532+
var buf [windows.MAX_PATH]uint16
533+
length := uint32(len(buf))
534+
if err := windows.QueryFullProcessImageName(windows.CurrentProcess(), 0, &buf[0], &length); err != nil {
535+
logf("QueryFullProcessImageName failed: %v", err)
536+
} else {
537+
dir = filepath.Dir(windows.UTF16ToString(buf[:length]))
538+
}
539+
540+
return filepath.Join(dir, "wintun.dll")
541+
}

0 commit comments

Comments
 (0)