Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-29575

Access to innodb_trx, innodb_locks and innodb_lock_waits along with detached XA's can cause SIGSEGV

    XMLWordPrintable

Details

    Description

      trx->mysql_thd can be zeroed-out between thd_get_thread_id() and thd_query_safe() calls in fill_trx_row(). trx_disconnect_prepared() zeroes out trx->mysql_thd. And this can cause null pointer dereferencing in fill_trx_row().

      The bug can be reproduced with the following new sync point:

      diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc
      index 2dc39118d3d..c2cc8c970b0 100644
      --- a/storage/innobase/trx/trx0i_s.cc
      +++ b/storage/innobase/trx/trx0i_s.cc
      @@ -461,6 +461,8 @@ fill_trx_row(
              row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd);
       
              char    query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
      +       ut_d(if (trx->state == TRX_STATE_PREPARED)
      +           DEBUG_SYNC_C("fill_trx_row_before_query_request"));
              if (size_t stmt_len = thd_query_safe(trx->mysql_thd, query,
                                                   sizeof query)) {
                      row->trx_query = static_cast<const char*>(
      diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
      index 3b19d213d5a..92bf9de375a 100644
      --- a/storage/innobase/trx/trx0trx.cc
      +++ b/storage/innobase/trx/trx0trx.cc
      @@ -550,6 +550,7 @@ void trx_disconnect_prepared(trx_t *trx)
         trx->read_view.close();
         trx->is_recovered= true;
         trx->mysql_thd= NULL;
      +  DEBUG_SYNC_C("trx_disconnect_prepared_reset_thd");
         /* todo/fixme: suggest to do it at innodb prepare */
         trx->will_lock= false;
         trx_sys.rw_trx_hash.put_pins(trx);
      

      and the following test case:

      --source include/have_innodb.inc                                                
      --source include/have_debug.inc                                                 
      --source include/have_debug_sync.inc                                            
      --source include/count_sessions.inc                                             
                                                                                      
      --connection default                                                            
      create table t (a int) engine=innodb;                                           
      insert into t values(1);                                                        
                                                                                      
      --connect (con_xa, localhost, root,,)                                           
      SET DEBUG_SYNC="trx_disconnect_prepared_reset_thd SIGNAL thd_reset";            
      xa start '1';                                                                   
      insert into t values(1);                                                        
      xa end '1';                                                                     
      xa prepare '1';                                                                 
                                                                                      
      --connection default                                                            
      SET DEBUG_SYNC="fill_trx_row_before_query_request SIGNAL reached WAIT_FOR fill_row_cont";
      --send select * from information_schema.innodb_trx;                             
                                                                                      
      --connect (con_sync, localhost, root,,)                                         
      SET DEBUG_SYNC="now WAIT_FOR reached";                                          
      --disconnect con_xa                                                             
      SET DEBUG_SYNC="now WAIT_FOR thd_reset";                                        
      SET DEBUG_SYNC="now SIGNAL fill_row_cont";                                      
      --disconnect con_sync                                                           
                                                                                      
      --connection default                                                            
      --disable_result_log                                                            
      # Must crash here with SIGSEGV if not fixed                                     
      --reap;                                                                         
      --enable_result_log                                                             
      xa commit '1';                                                                  
      drop table t;                                                                   
      SET DEBUG_SYNC="RESET";                                                         
      --source include/wait_until_count_sessions.inc      
      

      It does not affect 10.3 as 10.3 does not detach XA on disconnection (compare THD::cleanup() in 10.3 and 10.4+ and see trans_xa_detach() in 10.4+ for details).

      Until MDEV-29368 is fixed the workaround is not to use innodb_trx, innodb_locks and innodb_lock_waits from information_schema along with detached XA's.

      Attachments

        Issue Links

          Activity

            People

              vlad.lesin Vladislav Lesin
              vlad.lesin Vladislav Lesin
              Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.