tailscale/ipn/ipnauth/ipnauth_unix_creds.go
Alex Chan 304dabce17 ipn/ipnauth: fix a null pointer panic in GetConnIdentity
When running integration tests on macOS, we get a panic from a nil
pointer dereference when calling `ci.creds.PID()`.

This panic occurs because the `ci.creds != nil` check is insufficient
after a recent refactoring (c45f881) that changed `ci.creds` from a
pointer to the `PeerCreds` interface. Now `ci.creds` always compares as
non-nil, so we enter this block even when the underlying value is nil.

The integration tests fail on macOS when `peercred.Get()` returns the
error `unix.GetsockoptInt: socket is not connected`. This error isn't
new, and the previous code was ignoring it correctly.

Since we trust that `peercred` returns either a usable value or an error,
checking for a nil error is a sufficient and correct gate to prevent the
method call and avoid the panic.

Fixes #17421

Signed-off-by: Alex Chan <alexc@tailscale.com>
2025-10-03 16:21:34 +01:00

38 lines
1.1 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !windows && !ts_omit_unixsocketidentity
package ipnauth
import (
"net"
"github.com/tailscale/peercred"
"tailscale.com/types/logger"
)
// GetConnIdentity extracts the identity information from the connection
// based on the user who owns the other end of the connection.
// and couldn't. The returned connIdentity has NotWindows set to true.
func GetConnIdentity(_ logger.Logf, c net.Conn) (ci *ConnIdentity, err error) {
ci = &ConnIdentity{conn: c, notWindows: true}
_, ci.isUnixSock = c.(*net.UnixConn)
if creds, err := peercred.Get(c); err == nil {
ci.creds = creds
ci.pid, _ = ci.creds.PID()
} else if err == peercred.ErrNotImplemented {
// peercred.Get is not implemented on this OS (such as OpenBSD)
// Just leave creds as nil, as documented.
} else {
return nil, err
}
return ci, nil
}
// WindowsToken is unsupported when GOOS != windows and always returns
// ErrNotImplemented.
func (ci *ConnIdentity) WindowsToken() (WindowsToken, error) {
return nil, ErrNotImplemented
}