summaryrefslogtreecommitdiff
path: root/storage/perfschema
diff options
context:
space:
mode:
authorMarc Alff <marc.alff@oracle.com>2010-09-15 12:20:48 -0600
committerMarc Alff <marc.alff@oracle.com>2010-09-15 12:20:48 -0600
commit2e4717ffcd8a3c7a025be78a7328ec219bed97db (patch)
tree2b52329831e507e99e869b0ed9274a672b8e69ef /storage/perfschema
parent93e7e5f9d94c10f94f5d19ae10ebe9adcf443e78 (diff)
downloadmariadb-git-2e4717ffcd8a3c7a025be78a7328ec219bed97db.tar.gz
Bug#56761 Segfault on CHECKSUM TABLE performance_schema.EVENTS_WAITS_HISTORY EXTENDED
Before this fix, the server could crash inside a memcpy when reading data from the EVENTS_WAITS_CURRENT / HISTORY / HISTORY_LONG tables. The root cause is that the length used in a memcpy could be corrupted, when another thread writes data in the wait record being read. Reading unsafe data is ok, per design choice, and the code does sanitize the data in general, but did not sanitize the length given to memcpy. The fix is to also sanitize the schema name / object name / file name length when extracting the data to produce a row.
Diffstat (limited to 'storage/perfschema')
-rw-r--r--storage/perfschema/table_events_waits.cc20
-rw-r--r--storage/perfschema/table_events_waits.h2
2 files changed, 14 insertions, 8 deletions
diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc
index 5e5972b68f1..d34f6fbe722 100644
--- a/storage/perfschema/table_events_waits.cc
+++ b/storage/perfschema/table_events_waits.cc
@@ -187,7 +187,7 @@ void table_events_waits_common::clear_object_columns()
*/
void table_events_waits_common::make_row(bool thread_own_wait,
PFS_thread *pfs_thread,
- PFS_events_waits *wait)
+ volatile PFS_events_waits *wait)
{
pfs_lock lock;
PFS_thread *safe_thread;
@@ -251,21 +251,27 @@ void table_events_waits_common::make_row(bool thread_own_wait,
case WAIT_CLASS_TABLE:
m_row.m_object_type= "TABLE";
m_row.m_object_type_length= 5;
- memcpy(m_row.m_object_schema, wait->m_schema_name,
- wait->m_schema_name_length);
m_row.m_object_schema_length= wait->m_schema_name_length;
- memcpy(m_row.m_object_name, wait->m_object_name,
- wait->m_object_name_length);
+ if (unlikely((m_row.m_object_schema_length == 0) ||
+ (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))))
+ return;
+ memcpy(m_row.m_object_schema, wait->m_schema_name, m_row.m_object_schema_length);
m_row.m_object_name_length= wait->m_object_name_length;
+ if (unlikely((m_row.m_object_name_length == 0) ||
+ (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+ return;
+ memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
safe_class= &global_table_class;
break;
case WAIT_CLASS_FILE:
m_row.m_object_type= "FILE";
m_row.m_object_type_length= 4;
m_row.m_object_schema_length= 0;
- memcpy(m_row.m_object_name, wait->m_object_name,
- wait->m_object_name_length);
m_row.m_object_name_length= wait->m_object_name_length;
+ if (unlikely((m_row.m_object_name_length == 0) ||
+ (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+ return;
+ memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
safe_class= sanitize_file_class((PFS_file_class*) wait->m_class);
break;
case NO_WAIT_CLASS:
diff --git a/storage/perfschema/table_events_waits.h b/storage/perfschema/table_events_waits.h
index 2aa88b54be4..aa4edb4a368 100644
--- a/storage/perfschema/table_events_waits.h
+++ b/storage/perfschema/table_events_waits.h
@@ -137,7 +137,7 @@ protected:
void clear_object_columns();
void make_row(bool thread_own_wait, PFS_thread *pfs_thread,
- PFS_events_waits *wait);
+ volatile PFS_events_waits *wait);
/** Current row. */
row_events_waits m_row;