Bug #121341 Concurrent authentication_policy update can free the plugin name used by a handshake
Submitted: 21 Sep 14:34
Reporter: HE Y Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: Security: Encryption Severity:S1 (Critical)
Version:MySQL 8.4 branch, commit `99960bf74fa919 OS:Any
Assigned to: CPU Architecture:Any

[21 Sep 14:34] HE Y
Description:
The initial authentication path obtains a pointer to the globally owned
`initial_auth_plugin_name`. An `authentication_policy` update allocates a new
name, publishes it, and then frees the old name. The handshake can continue to
use its borrowed old pointer after the updater frees it.

The policy mutex protects construction of the policy factors, but the lifetime
of the returned C string is not extended for the consuming handshake.

How to repeat:
1. Build MySQL 8.4 with AddressSanitizer and enable a supported policy such as
   `caching_sha2_password`.
2. Pause a new unauthenticated connection immediately after it obtains the
   initial authentication plugin-name pointer.
3. In an administrative session, change `@@global.authentication_policy` so
   `Policy::update()` replaces `initial_auth_plugin_name` and frees the old
   allocation.
4. Resume the handshake and let it compare or otherwise read the old pointer.

The checked lifetime reduction performs the same borrow/publish/free/use
ordering. Its control prints `21`; the trigger aborts in `strcmp` with:

```text
ERROR: AddressSanitizer: heap-use-after-free
READ of size 1
#0 ... __interceptor_strcmp
```

Actual result

The source-level lifetime sequence produces a reproducible heap-use-after-free.
A bounded official 8.4.11 stress run interleaved 240 policy changes and
authentication operations; all operations succeeded and the server remained
healthy, so that non-deterministic run did not hit the race.

Expected result

Every handshake should own or retain an immutable plugin-name value for its
entire use, independent of concurrent policy changes.