From 0951e4b5b3711f044cdc23396bd3c37c841a6205 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 May 2021 10:38:49 +0800 Subject: [PATCH] mds: place the journaler pointer under the mds_lock When the _recovery_thread is trying to reformat the journal, it will delete the old journal pointer and assign with a new one, during this the mds_lock is unlocked. That means in other threads, such as when 'flush journal', who are using the MDSLog::journaler pointer will potentially hit use-after-free bug. Fixes: https://tracker.ceph.com/issues/50807 Signed-off-by: Xiubo Li (cherry picked from commit 0c143922f8a7bad0f19a0a2c97121a470b8fcba5) --- src/mds/MDLog.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mds/MDLog.cc b/src/mds/MDLog.cc index ee2d08cebba47..2ee4c70b1790f 100644 --- a/src/mds/MDLog.cc +++ b/src/mds/MDLog.cc @@ -1088,9 +1088,9 @@ void MDLog::_recovery_thread(MDSContext *completion) * tolerate replaying old journals until we have to go active. Use front_journal as * our journaler attribute and complete */ dout(4) << "Recovered journal " << jp.front << " in format " << front_journal->get_stream_format() << dendl; - journaler->set_write_error_handler(new C_MDL_WriteError(this)); { std::lock_guard l(mds->mds_lock); + journaler->set_write_error_handler(new C_MDL_WriteError(this)); if (mds->is_daemon_stopping()) { return; } @@ -1273,17 +1273,14 @@ void MDLog::_reformat_journal(JournalPointer const &jp_in, Journaler *old_journa ceph_assert(journaler == old_journal); journaler = NULL; delete old_journal; - } - /* Update the pointer to reflect we're back in clean single journal state. */ - jp.back = 0; - write_result = jp.save(mds->objecter); - ceph_assert(write_result == 0); + /* Update the pointer to reflect we're back in clean single journal state. */ + jp.back = 0; + write_result = jp.save(mds->objecter); + ceph_assert(write_result == 0); - /* Reset the Journaler object to its default state */ - dout(1) << "Journal rewrite complete, continuing with normal startup" << dendl; - { - std::lock_guard l(mds->mds_lock); + /* Reset the Journaler object to its default state */ + dout(1) << "Journal rewrite complete, continuing with normal startup" << dendl; if (mds->is_daemon_stopping()) { delete new_journal; return; @@ -1291,11 +1288,8 @@ void MDLog::_reformat_journal(JournalPointer const &jp_in, Journaler *old_journa journaler = new_journal; journaler->set_readonly(); journaler->set_write_error_handler(new C_MDL_WriteError(this)); - } - /* Trigger completion */ - { - std::lock_guard l(mds->mds_lock); + /* Trigger completion */ if (mds->is_daemon_stopping()) { return; } -- 2.39.5