From: Marc Alff Date: November 11 2010 11:34am Subject: bzr commit into mysql-5.5-bugteam branch (marc.alff:3120) Bug#58003 List-Archive: http://lists.mysql.com/commits/123590 X-Bug: 58003 Message-Id: <201011111136.oABA7pke023907@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============5480038061927080263==" --===============5480038061927080263== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/malff/BZR_TREE/mysql-5.5-bugteam-58003/ based on revid:svoj@stripped 3120 Marc Alff 2010-11-11 Bug#58003 Segfault on CHECKSUM TABLE performance_schema.EVENTS_WAITS_HISTORY_LONG EXTENDED This fix is a follow up on the fix for similar issue 56761. When sanitizing data read from the events_waits_history_long table, the code needs also to sanitize the schema_name / object_name / file_name pointers, because such pointers could also hold invalid values. Checking the string length alone was required but not sufficient. This fix verifies that: - the table schema and table name used in table io events - the file name used in file io events are valid pointers before dereferencing these pointers. modified: storage/perfschema/pfs_global.h storage/perfschema/pfs_instr.cc storage/perfschema/pfs_instr.h storage/perfschema/pfs_instr_class.cc storage/perfschema/pfs_instr_class.h storage/perfschema/table_events_waits.cc === modified file 'storage/perfschema/pfs_global.h' --- a/storage/perfschema/pfs_global.h 2010-07-16 01:03:08 +0000 +++ b/storage/perfschema/pfs_global.h 2010-11-11 11:34:46 +0000 @@ -79,5 +79,21 @@ inline uint randomized_index(const void void pfs_print_error(const char *format, ...); +/** + Given an array defined as T ARRAY[MAX], + check that an UNSAFE pointer actually points to an element + within the array. +*/ +#define SANITIZE_ARRAY_BODY(T, ARRAY, MAX, UNSAFE) \ + intptr offset; \ + if ((&ARRAY[0] <= UNSAFE) && \ + (UNSAFE < &ARRAY[MAX])) \ + { \ + offset= ((intptr) UNSAFE - (intptr) ARRAY) % sizeof(T); \ + if (offset == 0) \ + return UNSAFE; \ + } \ + return NULL + #endif === modified file 'storage/perfschema/pfs_instr.cc' --- a/storage/perfschema/pfs_instr.cc 2010-07-16 01:25:03 +0000 +++ b/storage/perfschema/pfs_instr.cc 2010-11-11 11:34:46 +0000 @@ -758,9 +758,26 @@ PFS_thread* create_thread(PFS_thread_cla */ PFS_thread *sanitize_thread(PFS_thread *unsafe) { - if ((&thread_array[0] <= unsafe) && - (unsafe < &thread_array[thread_max])) - return unsafe; + SANITIZE_ARRAY_BODY(PFS_thread, thread_array, thread_max, unsafe); +} + +const char *sanitize_file_name(const char *unsafe) +{ + intptr ptr= (intptr) unsafe; + intptr first= (intptr) &file_array[0]; + intptr last= (intptr) &file_array[file_max]; + + /* Check if unsafe points inside file_array[] */ + if (likely((first <= ptr) && (ptr < last))) + { + /* Check if unsafe points to PFS_file::m_filename */ + intptr offset= (ptr - first) % sizeof(PFS_file); + intptr valid_offset= my_offsetof(PFS_file, m_filename[0]); + if (likely(offset == valid_offset)) + { + return unsafe; + } + } return NULL; } === modified file 'storage/perfschema/pfs_instr.h' --- a/storage/perfschema/pfs_instr.h 2010-07-16 01:03:08 +0000 +++ b/storage/perfschema/pfs_instr.h 2010-11-11 11:34:46 +0000 @@ -227,6 +227,7 @@ struct PFS_thread }; PFS_thread *sanitize_thread(PFS_thread *unsafe); +const char *sanitize_file_name(const char *unsafe); PFS_single_stat_chain* find_per_thread_mutex_class_wait_stat(PFS_thread *thread, === modified file 'storage/perfschema/pfs_instr_class.cc' --- a/storage/perfschema/pfs_instr_class.cc 2010-07-15 23:44:45 +0000 +++ b/storage/perfschema/pfs_instr_class.cc 2010-11-11 11:34:46 +0000 @@ -543,15 +543,9 @@ PFS_mutex_class *find_mutex_class(PFS_sy FIND_CLASS_BODY(key, mutex_class_allocated_count, mutex_class_array); } -#define SANITIZE_ARRAY_BODY(ARRAY, MAX, UNSAFE) \ - if ((&ARRAY[0] <= UNSAFE) && \ - (UNSAFE < &ARRAY[MAX])) \ - return UNSAFE; \ - return NULL - PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe) { - SANITIZE_ARRAY_BODY(mutex_class_array, mutex_class_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_mutex_class, mutex_class_array, mutex_class_max, unsafe); } /** @@ -566,7 +560,7 @@ PFS_rwlock_class *find_rwlock_class(PFS_ PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe) { - SANITIZE_ARRAY_BODY(rwlock_class_array, rwlock_class_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_rwlock_class, rwlock_class_array, rwlock_class_max, unsafe); } /** @@ -581,7 +575,7 @@ PFS_cond_class *find_cond_class(PFS_sync PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe) { - SANITIZE_ARRAY_BODY(cond_class_array, cond_class_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_cond_class, cond_class_array, cond_class_max, unsafe); } /** @@ -636,7 +630,7 @@ PFS_thread_class *find_thread_class(PFS_ PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe) { - SANITIZE_ARRAY_BODY(thread_class_array, thread_class_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_thread_class, thread_class_array, thread_class_max, unsafe); } /** @@ -687,7 +681,7 @@ PFS_file_class *find_file_class(PFS_file PFS_file_class *sanitize_file_class(PFS_file_class *unsafe) { - SANITIZE_ARRAY_BODY(file_class_array, file_class_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_file_class, file_class_array, file_class_max, unsafe); } /** @@ -820,7 +814,59 @@ search: PFS_table_share *sanitize_table_share(PFS_table_share *unsafe) { - SANITIZE_ARRAY_BODY(table_share_array, table_share_max, unsafe); + SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe); +} + +const char *sanitize_table_schema_name(const char *unsafe) +{ + intptr ptr= (intptr) unsafe; + intptr first= (intptr) &table_share_array[0]; + intptr last= (intptr) &table_share_array[table_share_max]; + + PFS_table_share dummy; + + /* Check if unsafe points inside table_share_array[] */ + if (likely((first <= ptr) && (ptr < last))) + { + intptr offset= (ptr - first) % sizeof(PFS_table_share); + intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key); + intptr len= sizeof(dummy.m_key.m_hash_key); + /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */ + if (likely((from <= offset) && (offset < from + len))) + { + PFS_table_share *base= (PFS_table_share*) (ptr - offset); + /* Check if unsafe really is the schema name */ + if (likely(base->m_schema_name == unsafe)) + return unsafe; + } + } + return NULL; +} + +const char *sanitize_table_object_name(const char *unsafe) +{ + intptr ptr= (intptr) unsafe; + intptr first= (intptr) &table_share_array[0]; + intptr last= (intptr) &table_share_array[table_share_max]; + + PFS_table_share dummy; + + /* Check if unsafe points inside table_share_array[] */ + if (likely((first <= ptr) && (ptr < last))) + { + intptr offset= (ptr - first) % sizeof(PFS_table_share); + intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key); + intptr len= sizeof(dummy.m_key.m_hash_key); + /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */ + if (likely((from <= offset) && (offset < from + len))) + { + PFS_table_share *base= (PFS_table_share*) (ptr - offset); + /* Check if unsafe really is the table name */ + if (likely(base->m_table_name == unsafe)) + return unsafe; + } + } + return NULL; } static void reset_mutex_class_waits(void) === modified file 'storage/perfschema/pfs_instr_class.h' --- a/storage/perfschema/pfs_instr_class.h 2010-07-15 23:44:45 +0000 +++ b/storage/perfschema/pfs_instr_class.h 2010-11-11 11:34:46 +0000 @@ -222,6 +222,8 @@ PFS_thread_class *find_thread_class(PSI_ PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe); PFS_file_class *find_file_class(PSI_file_key key); PFS_file_class *sanitize_file_class(PFS_file_class *unsafe); +const char *sanitize_table_schema_name(const char *unsafe); +const char *sanitize_table_object_name(const char *unsafe); PFS_table_share *find_or_create_table_share(PFS_thread *thread, const char *schema_name, === modified file 'storage/perfschema/table_events_waits.cc' --- a/storage/perfschema/table_events_waits.cc 2010-11-03 15:42:33 +0000 +++ b/storage/perfschema/table_events_waits.cc 2010-11-11 11:34:46 +0000 @@ -194,6 +194,9 @@ void table_events_waits_common::make_row PFS_instr_class *safe_class; const char *base; const char *safe_source_file; + const char *safe_table_schema_name; + const char *safe_table_object_name; + const char *safe_file_name; m_row_exists= false; safe_thread= sanitize_thread(pfs_thread); @@ -252,15 +255,19 @@ void table_events_waits_common::make_row m_row.m_object_type= "TABLE"; m_row.m_object_type_length= 5; m_row.m_object_schema_length= wait->m_schema_name_length; + safe_table_schema_name= sanitize_table_schema_name(wait->m_schema_name); if (unlikely((m_row.m_object_schema_length == 0) || - (m_row.m_object_schema_length > sizeof(m_row.m_object_schema)))) + (m_row.m_object_schema_length > sizeof(m_row.m_object_schema)) || + (safe_table_schema_name == NULL))) return; - memcpy(m_row.m_object_schema, wait->m_schema_name, m_row.m_object_schema_length); + memcpy(m_row.m_object_schema, safe_table_schema_name, m_row.m_object_schema_length); m_row.m_object_name_length= wait->m_object_name_length; + safe_table_object_name= sanitize_table_object_name(wait->m_object_name); if (unlikely((m_row.m_object_name_length == 0) || - (m_row.m_object_name_length > sizeof(m_row.m_object_name)))) + (m_row.m_object_name_length > sizeof(m_row.m_object_name)) || + (safe_table_object_name == NULL))) return; - memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length); + memcpy(m_row.m_object_name, safe_table_object_name, m_row.m_object_name_length); safe_class= &global_table_class; break; case WAIT_CLASS_FILE: @@ -268,10 +275,12 @@ void table_events_waits_common::make_row m_row.m_object_type_length= 4; m_row.m_object_schema_length= 0; m_row.m_object_name_length= wait->m_object_name_length; + safe_file_name= sanitize_file_name(wait->m_object_name); if (unlikely((m_row.m_object_name_length == 0) || - (m_row.m_object_name_length > sizeof(m_row.m_object_name)))) + (m_row.m_object_name_length > sizeof(m_row.m_object_name)) || + (safe_file_name == NULL))) return; - memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length); + memcpy(m_row.m_object_name, safe_file_name, m_row.m_object_name_length); safe_class= sanitize_file_class((PFS_file_class*) wait->m_class); break; case NO_WAIT_CLASS: --===============5480038061927080263== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-5.5-bugteam-58003/ # testament_sha1: e8f4f287ff166ab8f38a6a0e46e0ef30a78667fb # timestamp: 2010-11-11 12:34:58 +0100 # base_revision_id: svoj@stripped # # Begin bundle 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 9SYSiWR/4u5IpwoSFKjRzQA= --===============5480038061927080263==--