diff --git a/go.mod b/go.mod index f995381af15..004a948aaba 100644 --- a/go.mod +++ b/go.mod @@ -109,4 +109,4 @@ replace github.com/prometheus/golang_client => github.com/prometheus/golang_clie replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1 // This fork is based on quic-go v0.45 -replace github.com/quic-go/quic-go => github.com/chungthuang/quic-go v0.45.1-0.20250428085412-43229ad201fd +replace github.com/quic-go/quic-go => github.com/stareezy-1/quic-go v0.0.0-20260806091559-d3ee2305a943 diff --git a/go.sum b/go.sum index 1252fd3b834..95274a8d200 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,6 @@ github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chungthuang/quic-go v0.45.1-0.20250428085412-43229ad201fd h1:VdYI5zFQ2h1/qzoC6rhyPx479bkF8i177Qpg4Q2n1vk= -github.com/chungthuang/quic-go v0.45.1-0.20250428085412-43229ad201fd/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ= github.com/cloudflare/backoff v0.0.0-20240920015135-e46b80a3a7d0 h1:pRcxfaAlK0vR6nOeQs7eAEvjJzdGXl8+KaBlcvpQTyQ= github.com/cloudflare/backoff v0.0.0-20240920015135-e46b80a3a7d0/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= @@ -189,6 +187,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stareezy-1/quic-go v0.0.0-20260806091559-d3ee2305a943 h1:67fF8SB/JinU0QavrnZ8I3+J6GMtK2b1I2IMQfUdF3U= +github.com/stareezy-1/quic-go v0.0.0-20260806091559-d3ee2305a943/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/token/lockfile_test.go b/token/lockfile_test.go index eec54276f7e..4cf6c6de5d6 100644 --- a/token/lockfile_test.go +++ b/token/lockfile_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/rs/zerolog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -112,3 +113,35 @@ func TestNewSelfLockContent(t *testing.T) { assert.Equal(t, int32(os.Getpid()), content.PID) // nolint: gosec assert.Positive(t, content.StartTime) } + +func TestReleaseLockFileAllowsReacquire(t *testing.T) { + // Regression test for the `access login` self-deadlock (issue #1692): + // the token lock was held for the whole process lifetime, so a second + // fetch in the same process (after an invalid token was removed) waited + // forever on its own lock. After release, the same process can acquire + // the lock again. + log := zerolog.Nop() + path := filepath.Join(t.TempDir(), "token") + + require.NoError(t, acquireLockFile(path, &log)) + releaseLockFile(path, &log) + require.NoError(t, acquireLockFile(path, &log), "must be able to re-acquire after release") + releaseLockFile(path, &log) +} + +func TestReleaseLockFileDoesNotRemoveOtherProcessLock(t *testing.T) { + // Releasing must not remove a lock owned by another process. + log := zerolog.Nop() + dir := t.TempDir() + path := filepath.Join(dir, "token") + lockPath := path + ".lock" + + other := lockContent{PID: 2147483647, StartTime: 1000000000000} + data, err := json.Marshal(other) + require.NoError(t, err) + require.NoError(t, os.WriteFile(lockPath, data, 0600)) + + releaseLockFile(path, &log) + _, err = os.Stat(lockPath) + require.NoError(t, err, "another process's lock must not be removed") +} diff --git a/token/token.go b/token/token.go index fab8d247532..9e0cb9fd95d 100644 --- a/token/token.go +++ b/token/token.go @@ -164,6 +164,32 @@ func acquireLockFile(tokenPath string, log *zerolog.Logger) error { } } +// releaseLockFile removes the lock file for the given token path if it is +// still owned by this process. Locks are held for the duration of a single +// token acquisition; releasing them lets a later re-fetch in the same +// process (e.g. after an invalid token was removed by the caller) acquire +// the lock again instead of deadlocking on its own lock. +func releaseLockFile(tokenPath string, log *zerolog.Logger) { + lockPath := tokenPath + ".lock" + _, content, err := isLockFileStale(lockPath) + if err != nil { + return + } + self, err := newSelfLockContent() + if err != nil { + return + } + if content.PID != self.PID || content.StartTime != self.StartTime { + // Another process reclaimed the lock; leave it alone. + return + } + if err := os.Remove(lockPath); err != nil && !os.IsNotExist(err) { + log.Debug().Err(err).Str("path", lockPath).Msg("failed to release lock file") + return + } + log.Debug().Str("path", lockPath).Msg("lock file released") +} + // readAuthURL reads the auth URL companion file for the given token path. // Returns the URL string, or empty string if the file doesn't exist or // can't be read. @@ -290,6 +316,10 @@ func getToken(appURL *url.URL, appInfo *AppInfo, useHostOnly bool, autoClose boo if err = acquireLockFile(appTokenPath, log); err != nil { return "", errors.Wrap(err, "failed to acquire app token lock") } + // Release the lock when this fetch completes: holding it for the whole + // process lifetime makes a same-process re-fetch (after an invalid token + // was removed) deadlock on its own lock (issue #1692). + defer releaseLockFile(appTokenPath, log) // check to see if another process has gotten a token while we waited for the lock if token, err := GetAppTokenIfExists(appInfo); token != "" && err == nil { @@ -308,6 +338,7 @@ func getToken(appURL *url.URL, appInfo *AppInfo, useHostOnly bool, autoClose boo if err = acquireLockFile(orgTokenPath, log); err != nil { return "", errors.Wrap(err, "failed to acquire org token lock") } + defer releaseLockFile(orgTokenPath, log) // check if an org token has been created since the lock was acquired orgToken, err = GetOrgTokenIfExists(appInfo.AuthDomain) } diff --git a/vendor/github.com/quic-go/quic-go/connection.go b/vendor/github.com/quic-go/quic-go/connection.go index 413266a5c12..b055666ccef 100644 --- a/vendor/github.com/quic-go/quic-go/connection.go +++ b/vendor/github.com/quic-go/quic-go/connection.go @@ -851,6 +851,13 @@ func (s *connection) handleHandshakeComplete(now time.Time) error { } func (s *connection) handleHandshakeConfirmed(now time.Time) error { + // Drop initial keys. + // On the client side, this should have happened when sending the first Handshake packet, + // but this is not guaranteed if the server misbehaves. + // See CVE-2025-59530 for more details. + if err := s.dropEncryptionLevel(protocol.EncryptionInitial, now); err != nil { + return err + } if err := s.dropEncryptionLevel(protocol.EncryptionHandshake, now); err != nil { return err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2b4b8d61c88..e5dbcd235b6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -203,7 +203,7 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/quic-go/quic-go v0.52.0 => github.com/chungthuang/quic-go v0.45.1-0.20250428085412-43229ad201fd +# github.com/quic-go/quic-go v0.52.0 => github.com/stareezy-1/quic-go v0.0.0-20260806091559-d3ee2305a943 ## explicit; go 1.23 github.com/quic-go/quic-go github.com/quic-go/quic-go/internal/ackhandler @@ -571,4 +571,4 @@ zombiezen.com/go/capnproto2/std/capnp/rpc # github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.20210324024421-b6ea8234fe3d # github.com/prometheus/golang_client => github.com/prometheus/golang_client v1.12.1 # gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1 -# github.com/quic-go/quic-go => github.com/chungthuang/quic-go v0.45.1-0.20250428085412-43229ad201fd +# github.com/quic-go/quic-go => github.com/stareezy-1/quic-go v0.0.0-20260806091559-d3ee2305a943