Fix a crash due to weird refcount messup during stack unwinding
ClosedPublic

Authored by dvratil on May 28 2019, 10:48 AM.

Details

Summary

My Akonadi Server has been crashing repeatadly whenever an exception was
thrown inside a handler. The crash was due to memory corruption when
stack unwinding caused the refcount of the "cmd" shared pointer to get
messed up which lead to double-free corruption.

The problem seems to be in the capture-by-value of the shared pointer in the
lambda, but I do not exactly understand what causes the problem, neither
was I able to produce a minimal reproducer case.

We can safely capture the shared pointer by reference, we don't keep a
reference to the functor anywhere.

Diff Detail

Repository
R165 Akonadi
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
dvratil created this revision.May 28 2019, 10:48 AM
Restricted Application added a project: KDE PIM. · View Herald TranscriptMay 28 2019, 10:48 AM
Restricted Application added a subscriber: kde-pim. · View Herald Transcript
dvratil requested review of this revision.May 28 2019, 10:48 AM

The ASAN report, if anyone can make anything out of it:

72: =================================================================                                                                                                                                                                                                                                                          
72: ==10589==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b000073c64 at pc 0x0000003bdb1c bp 0x7f913caa6270 sp 0x7f913caa6268                                                                                                                                                                                   
72: WRITE of size 4 at 0x60b000073c64 thread T11 (0x61000001c940-)                                                                                                                                                                                                                                                             
72:     #0 0x3bdb1b in std::__atomic_base<int>::operator--() /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/atomic_base.h:327:16                                                                                                                                                                     
72:     #1 0x3bdaa4 in bool QAtomicOps<int>::deref<int>(std::atomic<int>&) /usr/include/qt5/QtCore/qatomic_cxx11.h:271:16                                                                                                                                                                                                      
72:     #2 0x3bda84 in QBasicAtomicInteger<int>::deref() /usr/include/qt5/QtCore/qbasicatomic.h:115:42                                                                                                                                                                                                                         
72:     #3 0x3cfdfb in QSharedPointer<Akonadi::Protocol::Command>::deref(QtSharedPointer::ExternalRefCountData*) /usr/include/qt5/QtCore/qsharedpointer_impl.h:464:28                                                                                                                                                          
72:     #4 0x3cfdc0 in QSharedPointer<Akonadi::Protocol::Command>::deref() /usr/include/qt5/QtCore/qsharedpointer_impl.h:460:7                                                                                                                                                                                                 
72:     #5 0x3cfd74 in QSharedPointer<Akonadi::Protocol::Command>::~QSharedPointer() /usr/include/qt5/QtCore/qsharedpointer_impl.h:315:25                                                                                                                                                                                      
72:     #6 0x4027e5 in Akonadi::Server::Connection::handleIncomingData() /data/KDE/src/kde/pim/akonadi/src/server/connection.cpp:346:9                                                                                                                                                                                         
72:     #7 0x40da76 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (Akonadi::Server::Connection::*)()>::call(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:152:13                                               
72:     #8 0x40d7c5 in void QtPrivate::FunctionPointer<void (Akonadi::Server::Connection::*)()>::call<QtPrivate::List<>, void>(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:185:13                                                                
72:     #9 0x40d3db in QtPrivate::QSlotObject<void (Akonadi::Server::Connection::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:414:17                                                                                             
72:     #10 0x7f9157aafdc5  (/lib64/libQt5Core.so.5+0x29adc5)                                                                                                                                                                                                                                                                  
72:     #11 0x7f9157aa43c4 in QObject::event(QEvent*) (/lib64/libQt5Core.so.5+0x28f3c4)                                                                                                                                                                                                                                        
72:     #12 0x7f9157a79254  (/lib64/libQt5Core.so.5+0x264254)                                                                                                                                                                                                                                                                  
72:     #13 0x7f9157a792e7 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (/lib64/libQt5Core.so.5+0x2642e7)                                                                                                                                                                                                           
72:     #14 0x7f9157acd6b2 in QTimerInfoList::activateTimers() (/lib64/libQt5Core.so.5+0x2b86b2)                                                                                                                                                                                                                               
72:     #15 0x7f9157acdf6b  (/lib64/libQt5Core.so.5+0x2b8f6b)                                                                                                                                                                                                                                                                  
72:     #16 0x7f9155c74fcf in g_main_dispatch ../glib/gmain.c:3189:28                                                                                                                                                                                                                                                          
72:     #17 0x7f9155c74fcf in g_main_context_dispatch ../glib/gmain.c:3854:7                                                                                                                                                                                                                                                   
72:     #18 0x7f9155c75367 in g_main_context_iterate ../glib/gmain.c:3927:5                                                                                                                                                                                                                                                    
72:     #19 0x7f9155c75412 in g_main_context_iteration ../glib/gmain.c:3988:12                                                                                                                                                                                                                                                 
72:     #20 0x7f9157ace3f4 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (/lib64/libQt5Core.so.5+0x2b93f4)                                                                                                                                                                                     
72:     #21 0x7f9157a782ba in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (/lib64/libQt5Core.so.5+0x2632ba)                                                                                                                                                                                                        
72:     #22 0x7f91578d1674 in QThread::exec() (/lib64/libQt5Core.so.5+0xbc674)                                                                                                                                                                                                                                                 
72:     #23 0x7f91578d27c5  (/lib64/libQt5Core.so.5+0xbd7c5)                                                                                                                                                                                                                                                                   
72:     #24 0x7f91574c45a1 in start_thread /usr/src/debug/glibc-2.29-18-g52b7cd6e9a/nptl/pthread_create.c:486:8                                                                                                                                                                                                                
72:     #25 0x7f91575e8162 in __GI___clone /usr/src/debug/glibc-2.29-18-g52b7cd6e9a/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95                                                                                                                                                                                          
72:                                                                                                                                                                                                                                                                                                                            
72: 0x60b000073c64 is located 4 bytes inside of 104-byte region [0x60b000073c60,0x60b000073cc8)                                                                                                                                                                                                                                
72: freed by thread T11 (0x61000001c940-) here:                                                                                                                                                                                                                                                                                
72:     #0 0x7f91586e1d7f in operator delete(void*) (/usr/lib64/clang/8.0.0/lib/libclang_rt.asan-x86_64.so+0x13cd7f)                                                                                                                                                                                                           
72:     #1 0x3cff64 in QtSharedPointer::ExternalRefCountData::operator delete(void*) /usr/include/qt5/QtCore/qsharedpointer_impl.h:167:50                                                                                                                                                                                      
72:     #2 0x3cfe4b in QSharedPointer<Akonadi::Protocol::Command>::deref(QtSharedPointer::ExternalRefCountData*) /usr/include/qt5/QtCore/qsharedpointer_impl.h:468:13                                                                                                                                                          
72:     #3 0x3cfdc0 in QSharedPointer<Akonadi::Protocol::Command>::deref() /usr/include/qt5/QtCore/qsharedpointer_impl.h:460:7                                                                                                                                                                                                 
72:     #4 0x3cfd74 in QSharedPointer<Akonadi::Protocol::Command>::~QSharedPointer() /usr/include/qt5/QtCore/qsharedpointer_impl.h:315:25                                                                                                                                                                                      
72:     #5 0x42fb29 in Akonadi::Server::Handler::~Handler() /data/KDE/src/kde/pim/akonadi/src/server/handler.h:52:32                                                                                                                                                                                                           
72:     #6 0x4eacd4 in Akonadi::Server::ItemFetchHandler::~ItemFetchHandler() /data/KDE/src/kde/pim/akonadi/src/server/handler/itemfetchhandler.h:38:42                                                                                                                                                                        
72:     #7 0x4eacf8 in Akonadi::Server::ItemFetchHandler::~ItemFetchHandler() /data/KDE/src/kde/pim/akonadi/src/server/handler/itemfetchhandler.h:38:42                                                                                                                                                                        
72:     #8 0x40cbbc in std::default_delete<Akonadi::Server::Handler>::operator()(Akonadi::Server::Handler*) const /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/unique_ptr.h:81:2                                                                                                                   
72:     #9 0x40b4a7 in std::unique_ptr<Akonadi::Server::Handler, std::default_delete<Akonadi::Server::Handler> >::reset(Akonadi::Server::Handler*) /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/unique_ptr.h:399:4                                                                                 
72:     #10 0x40269b in Akonadi::Server::Connection::handleIncomingData() /data/KDE/src/kde/pim/akonadi/src/server/connection.cpp:336:30                                                                                                                                                                                       
72:     #11 0x40da76 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (Akonadi::Server::Connection::*)()>::call(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:152:13                                              
72:     #12 0x40d7c5 in void QtPrivate::FunctionPointer<void (Akonadi::Server::Connection::*)()>::call<QtPrivate::List<>, void>(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:185:13                                                               
72:     #13 0x40d3db in QtPrivate::QSlotObject<void (Akonadi::Server::Connection::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:414:17                                                                                            
72:     #14 0x7f9157aafdc5  (/lib64/libQt5Core.so.5+0x29adc5)                                                                                                                                                                                                                                                                  
72:                                                                                                                                                                                                                                                                                                                            
72: previously allocated by thread T11 (0x61000001c940-) here:                                                                                                                                                                                                                                                                 
72:     #0 0x7f91586e0f5f in operator new(unsigned long) (/usr/lib64/clang/8.0.0/lib/libclang_rt.asan-x86_64.so+0x13bf5f)                                                                                                                                                                                                      
72:     #1 0x7f915821d749 in QtSharedPointer::ExternalRefCountWithContiguousData<Akonadi::Protocol::FetchItemsCommand>::create(Akonadi::Protocol::FetchItemsCommand**, void (*)(QtSharedPointer::ExternalRefCountData*)) /usr/include/qt5/QtCore/qsharedpointer_impl.h:269:67                                                  
72:     #2 0x7f915821d291 in QSharedPointer<Akonadi::Protocol::FetchItemsCommand> QSharedPointer<Akonadi::Protocol::FetchItemsCommand>::create<>() /usr/include/qt5/QtCore/qsharedpointer_impl.h:442:20                                                                                                                        
72:     #3 0x7f915821cf7d in QSharedPointer<Akonadi::Protocol::Command> Akonadi::Protocol::FactoryPrivate::commandFactoryFunc<Akonadi::Protocol::FetchItemsCommand>() /data/KDE/src/kde/pim/akonadi/src/private/protocol.cpp:463:16                                                                                            
72:     #4 0x7f915815f69a in Akonadi::Protocol::Factory::command(Akonadi::Protocol::Command::Type) /data/KDE/src/kde/pim/akonadi/src/private/protocol.cpp:487:12                                                                                                                                                               
72:     #5 0x7f915817426a in Akonadi::Protocol::deserialize(QIODevice*) /data/KDE/build/kde/pim/akonadi/src/private/protocol_gen.cpp:244:15                                                                                                                                                                                    
72:     #6 0x3fff95 in Akonadi::Server::Connection::handleIncomingData() /data/KDE/src/kde/pim/akonadi/src/server/connection.cpp:243:23                                                                                                                                                                                        
72:     #7 0x40da76 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (Akonadi::Server::Connection::*)()>::call(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:152:13                                               
72:     #8 0x40d7c5 in void QtPrivate::FunctionPointer<void (Akonadi::Server::Connection::*)()>::call<QtPrivate::List<>, void>(void (Akonadi::Server::Connection::*)(), Akonadi::Server::Connection*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:185:13                                                                
72:     #9 0x40d3db in QtPrivate::QSlotObject<void (Akonadi::Server::Connection::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:414:17                                                                                             
72:     #10 0x7f9157aafdc5  (/lib64/libQt5Core.so.5+0x29adc5)
vkrause accepted this revision.May 28 2019, 6:17 PM
This revision is now accepted and ready to land.May 28 2019, 6:17 PM
This revision was automatically updated to reflect the committed changes.