Skip to content

fix: release the app token lock when the fetch completes - #1713

Open
stareezy-1 wants to merge 2 commits into
cloudflare:masterfrom
stareezy-1:fix/1692-access-login-deadlock
Open

fix: release the app token lock when the fetch completes#1713
stareezy-1 wants to merge 2 commits into
cloudflare:masterfrom
stareezy-1:fix/1692-access-login-deadlock

Conversation

@stareezy-1

Copy link
Copy Markdown

Summary

Fixes #1692

Problem

cloudflared access login deadlocks forever against its own token lock file whenever the token minted during login fails the edge verification step (most commonly when the Access application has Enable Binding Cookie enabled). Every retry hangs the same way, and the "Another cloudflared process (pid N) is already waiting for authentication" banner names the process's own PID.

Root cause: getToken acquires the per-app token lock via acquireLockFile and holds it for the whole process lifetime. The login flow (verifyTokenAtEdge) fetches a token, verifies it at the edge, finds it invalid, calls RemoveTokenIfExists, and fetches again in the same processacquireLockFile then finds its own lock (own PID alive, so the stale-reclaim never fires) and waits until lockTimeout, self-deadlocked.

Fix

Release the app and org token locks when the fetch completes:

  • New releaseLockFile removes the lock file only if it is still owned by this process (PID and start time match), so a lock reclaimed by another process is left alone.
  • getToken now defers the release for both the app-token and org-token locks.

The lock still serializes concurrent transfers across processes; a same-process re-fetch can now acquire it again instead of deadlocking.

Tests

Two new tests in token/lockfile_test.go:

Test Verifies
TestReleaseLockFileAllowsReacquire the same process can re-acquire after release (previously hung until lockTimeout)
TestReleaseLockFileDoesNotRemoveOtherProcessLock another process's lock is never removed

Full token package tests pass; go vet ./token/ clean.

The replace directive pins the QUIC stack to a fork based on quic-go v0.45,
which predates the fix for CVE-2025-59530 (GHSA-47m2-4cr7-mhcw): a server
that sends HANDSHAKE_DONE before the handshake actually finishes makes the
client drop Handshake keys before Initial keys, and the next undecryptable
packet trips a panic in the connection path (remote client crash).

The fork pin is bumped to a commit that backports quic-go#5354 onto the
exact previously-pinned fork state (verified: the only source change is the
7-line drop-initial-keys fix in connection.go).
getToken acquired the per-app lock file and held it for the whole process
lifetime. When access login fetches a token, verifies it at the edge, and
finds it invalid (e.g. with Enable Binding Cookie enabled), it removes the
token and fetches again in the same process — acquireLockFile then found
its own lock (own PID alive), printed 'Another cloudflared process (pid
N)' with its own PID, and hung until lockTimeout.

Release the app and org token locks when the fetch completes. The lock
still serializes concurrent transfers across processes; a same-process
re-fetch can now acquire it again. releaseLockFile only removes the lock
if it is still owned by this process (PID and start time match), so a
lock reclaimed by another process is left alone.

Closes cloudflare#1692.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

access login self-deadlocks on its own token lock file when edge token verification fails (e.g. binding cookie enabled)

1 participant