You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug#27471510 PERFORMANCE_SCHEMA STATUS AND VARIABLE BY THREAD ARE NOT SAFE
Patch for 8.0.
Before this fix, executing:
SELECT * FROM performance_schema.status_by_thread
SELECT * FROM performance_schema.variables_by_thread
under heavy load was unsafe.
Root cause 1
============
SELECT * from performance_schema.status_by_thread
inspects the status variables of running sessions.
For sessions using SSL, SSL status variables are inspected.
For example, the status variable "Ssl_cipher_list" is evaluated
by executing function show_ssl_get_cipher_list()
This function is implemented as follows:
show_ssl_get_cipher_list()
{
if (thd->get_protocol()->get_ssl()) // (a)
{
...
SSL_get_cipher(thd->get_protocol()->get_ssl())); // (b)
...
}
}
The problem is that evaluating
thd->get_protocol()->get_ssl()
to access the underlying SSL structure is unsafe,
and subject to race conditions.
The value returned in (a) can change by the time (b)
is evaluated, for example when using prepared statements,
because the thd->get_protocol() pointer will change
during execution of PREPARE and EXECUTE.
Fix 1
=====
thd->get_protocol()->get_ssl()
is not a proper way to access SSL data for the session.
Instead, THD::m_SSL now keeps the SSL data attached to the
THD session.
THD::m_SSL is set after the SSL connection is established,
is reset upon disconnect,
and is immutable during the session execution.
Inspecting this attribute is safe when LOCK_thd_data is held,
which make table performance_schema.status_by_thread safe.
Root cause 2
============
SELECT * from performance_schema.variables_by_thread
inspects the variables of running sessions.
In particular, variable "session_track_system_variables"
is inspected.
This variable value is stored in THD::variables.track_sysvars_ptr
On the session connection,
THD::variables.track_sysvars_ptr
is duplicated and points to allocated memory,
in this call:
thd->session_sysvar_res_mgr.init(&thd->variables.track_sysvars_ptr,
thd->charset());
This is because Session_sysvar_resource_manager::init()
modifies the THD::variables.track_sysvars_ptr pointer itself.
On session disconnect,
Session_sysvar_resource_manager::deinit()
free the allocated memory,
which leaves the THD::variables.track_sysvars_ptr pointer
invalid, referencing freed memory.
As soon as cleanup_variables() unlocks LOCK_thd_data,
a race condition is possible,
when using the now invalid THD::variables.track_sysvars_ptr pointer.
Fix 2
=====
In cleanup_variables(),
clear the offending pointer before freeing the underlying memory
with the call to session_sysvar_res_mgr.deinit()
This makes table performance_schema.variables_by_thread safe.
0 commit comments