Go version

go version go1.22.0 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN='/home/mike/.local/bin'
GOCACHE='/home/mike/.cache/go-build'
GOENV='/home/mike/.config/go/env'
GOEXE=''
GOEXPERIMENT='boringcrypto'
GOFLAGS='-trimpath -tags=opa_no_oci'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/mike/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/mike/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/mike/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.linux-amd64'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/mike/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.linux-amd64/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.0'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='0'
GOMOD='/home/mike/projects/project/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1264452044=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Tried to connect to a postgres DB over TLS using jackc/pgx (see stack trace).

What did you see happen?

A panic when crypto/tls calls internal/godebug.(*Setting).IncNonDefault:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x552252]
goroutine 1 [running]:
internal/godebug.(*Setting).IncNonDefault(0x32c3a60?)
    internal/godebug/godebug.go:102 +0x12
crypto/tls.(*clientHandshakeState).pickCipherSuite(0xc00103f450)
    crypto/tls/handshake_client.go:530 +0xbd
crypto/tls.(*clientHandshakeState).processServerHello(0xc00103f450)
    crypto/tls/handshake_client.go:755 +0x25
crypto/tls.(*clientHandshakeState).handshake(0xc00103f450)
    crypto/tls/handshake_client.go:442 +0x35
crypto/tls.(*Conn).clientHandshake(0xc000694e08, {0x475baf8, 0xc00054b1d0})
    crypto/tls/handshake_client.go:274 +0x685
crypto/tls.(*Conn).handshakeContext(0xc000694e08, {0x475b8c8, 0x6d0e820})
    crypto/tls/conn.go:1553 +0x3cb
crypto/tls.(*Conn).HandshakeContext(...)
    crypto/tls/conn.go:1493
crypto/tls.(*Conn).Handshake(...)
    crypto/tls/conn.go:1477
crypto/tls.(*Conn).Write(0x30d31c0?, {0xc001002e40, 0x21, 0x40})
    crypto/tls/conn.go:1194 +0xe5
github.com/jackc/pgx/v5/pgproto3.(*Frontend).Flush(0xc0007ca008)
    github.com/jackc/pgx/v5@v5.5.3/pgproto3/frontend.go:88 +0x3d
github.com/jackc/pgx/v5/pgconn.(*PgConn).flushWithPotentialWriteReadDeadlock(0xc001230008)
    github.com/jackc/pgx/v5@v5.5.3/pgconn/pgconn.go:1818 +0x73
github.com/jackc/pgx/v5/pgconn.connect({0x475bb68, 0xc000020070}, 0xc0007ab680, 0xc000b2c160, 0x0)
    github.com/jackc/pgx/v5@v5.5.3/pgconn/pgconn.go:337 +0xbd3
github.com/jackc/pgx/v5/pgconn.ConnectConfig({0x475b8c8, 0x6d0e820}, 0xc0007ab680)
    github.com/jackc/pgx/v5@v5.5.3/pgconn/pgconn.go:176 +0x4f3
github.com/jackc/pgx/v5.connect({0x475b8c8?, 0x6d0e820?}, 0xc0007ab680)
    github.com/jackc/pgx/v5@v5.5.3/conn.go:257 +0x34b
github.com/jackc/pgx/v5.ConnectConfig({0x475b8c8, 0x6d0e820}, 0xc0007ab560)
    github.com/jackc/pgx/v5@v5.5.3/conn.go:141 +0xf0
github.com/jackc/pgx/v5/stdlib.(*driverConnector).Connect(0xc000fd6b28, {0x475b8c8, 0x6d0e820})
    github.com/jackc/pgx/v5@v5.5.3/stdlib/sql.go:365 +0xcd
database/sql.(*DB).conn(0xc000c7d790, {0x475b8c8, 0x6d0e820}, 0x1)
    database/sql/sql.go:1415 +0x71e
database/sql.(*DB).PingContext.func1(0xc8?)
    database/sql/sql.go:883 +0x3a
database/sql.(*DB).retry(0xc001087288?, 0xc001087258)
    database/sql/sql.go:1566 +0x42
database/sql.(*DB).PingContext(0xc000c7d790, {0x475b8c8, 0x6d0e820})
    database/sql/sql.go:882 +0x89
database/sql.(*DB).Ping(...)
    database/sql/sql.go:900
...

What did you expect to see?

Expected no segfault/panic. Looking at crypto/tls, it's my suspicion that, due to having goboring enabled and thus needing FIPS, tlsrsakex.Value() has not been called when tlsrsakex.IncNonDefault() is called. This could probably be triggered by having non default .CipherSuites set as well. Perhaps the underlying issue is that RSA ciphers aren't filtered out of fipsCipherSuites() in the first place, which is what allows the branch with IncNonDefault() to even be taken.

Comment From: seankhliao

cc @golang/security

Comment From: FiloSottile

The good news is that the IncNonDefault call is gated by hs.c.config.CipherSuites == nil, so it's not reachable by having non default CipherSuites.

Definitely an oversight in Go+BoringCrypto mode.

Comment From: FiloSottile

@gopherbot please open a Go 1.22 backport issue. This is a severe regression in Go+BoringCrypto mode.

Comment From: gopherbot

Backport issue(s) opened: #65994 (for 1.22).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases.

Comment From: michaelbeaumont

@FiloSottile Not sure who to ping on this, would it be enough to just solve the segfault?

Comment From: gopherbot

Change https://go.dev/cl/582315 mentions this issue: crypto/tls: don't call tlsrsakex.IncNonDefault with FIPS

Comment From: gopherbot

Change https://go.dev/cl/586755 mentions this issue: crypto/tls: ensure GODEBUGs are initialized

Comment From: lyoung-confluent

FYI for anyone scrolling to the bottom of this the cherry-pick/backport of this patch into a 1.22 release is being tracked in #65994

Comment From: gopherbot

Change https://go.dev/cl/593395 mentions this issue: [release-branch.go1.22] crypto/tls: don't call tlsrsakex.IncNonDefault with FIPS