diff options
author | Vlad Lesin <vlad_lesin@mail.ru> | 2019-05-24 13:09:13 +0300 |
---|---|---|
committer | Vlad Lesin <vlad_lesin@mail.ru> | 2019-05-31 10:03:17 +0300 |
commit | c9b49a4be723c18a8fad2bf4fd549079d45a33a5 (patch) | |
tree | d15770dc77c976ff77e2cd6209b8aee84872b9e7 /storage/maria | |
parent | 9d142a895c4ac9e34f839222df70b967dfb840e3 (diff) | |
download | mariadb-git-c9b49a4be723c18a8fad2bf4fd549079d45a33a5.tar.gz |
MDEV-18207: ASAN heap-use-after-free in _ma_get_status upon concurrent operations with sequence
The issue is that two MARIA_HA instances shares the same MARIA_STATUS_INFO
object during UNION execution, so the second MARIA_HA instance state pointer
MARIA_HA::state points to the MARIA_HA::state_save of the first MARIA instance.
This happens in
thr_multi_lock(...) {
...
for (first_lock=data, pos= data+1 ; pos < end ; pos++)
{
...
if (pos[0]->lock == pos[-1]->lock && pos[0]->lock->copy_status)
(pos[0]->lock->copy_status)((*pos)->status_param,
(*first_lock)->status_param);
...
}
...
}
Usually the state is restored from ha_maria::external_lock(...):
\#0 _ma_update_status (param=0x6290000e6270) at ./storage/maria/ma_state.c:309
\#1 0x00005555577ccb15 in _ma_update_status_with_lock (info=0x6290000e6270) at ./storage/maria/ma_state.c:361
\#2 0x00005555577c7dcc in maria_lock_database (info=0x6290000e6270, lock_type=2) at ./storage/maria/ma_locking.c:66
\#3 0x0000555557802ccd in ha_maria::external_lock (this=0x61d0001b1308, thd=0x62a000048270, lock_type=2) at ./storage/maria/ha_maria.cc:2727
But _ma_update_status() does not take into account the case when
MARIA_HA::status points to the MARIA_HA::state_save of the other MARIA_HA
instance.
The fix is to restore MARIA_HA::state in ha_maria::external_lock() after
maria_lock_database() call for transactional tables.
Diffstat (limited to 'storage/maria')
-rw-r--r-- | storage/maria/ha_maria.cc | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 5a371a07fc3..f64ea4b1edb 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2798,9 +2798,12 @@ int ha_maria::external_lock(THD *thd, int lock_type) } } } /* if transactional table */ - DBUG_RETURN(maria_lock_database(file, !table->s->tmp_table ? + int result = maria_lock_database(file, !table->s->tmp_table ? lock_type : ((lock_type == F_UNLCK) ? - F_UNLCK : F_EXTRA_LCK))); + F_UNLCK : F_EXTRA_LCK)); + if (!file->s->base.born_transactional) + file->state= &file->s->state.state; // Restore state if clone + DBUG_RETURN(result); } int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type) |