Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[application] Fix a race condition on CApplicationPlayerCallback::m_i…
…temCurrentFile * There's a possibility of a race codition on CApplicationPlayerCallback::m_itemCurrentFile leading to heap-use-after-free reported by the address sanitizer [1]. * The crash happens when GUI_MSG_UPDATE_ITEM is being handled. CApplicationPlayerCallback::m_itemCurrentFile can be accessed concurrently by the main thread in CApplication::OnMessage and CApplicationPlayerCallback::OnPlayBackStarted in the video thread. Sometimes CApplicationPlayerCallback::OnPlayBackStarted is called first, resets the m_itemCurrentFile (and deallocates the object). Then CApplication::OnMessage tries to read it - this is where heap-use-after-free occurs. * In order to mitigate the issue introduce additional messages GUI_MSG_PLAYBACK_PAUSED, GUI_MSG_PLAYBACK_RESUMED, GUI_MSG_PLAYBACK_PAUSED and GUI_MSG_PLAYBACK_SPEED_CHANGED. Those messages are sent from the GUI thread to the main thread. That way the access to CApplicationPlayerCallback::m_itemCurrentFile is serialized (it will be accessed only from the main thread). * Fixes xbmc#23247. [1]: ================================================================= ==34632==ERROR: AddressSanitizer: heap-use-after-free on address 0x6070000ea040 at pc 0x7ff0eba5f427 bp 0x7ffc508e6f90 sp 0x7ffc508e6738 WRITE of size 65 at 0x6070000ea040 thread T0 #0 0x7ff0eba5f426 in __interceptor_memcpy /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 #1 0x7ff0ea8b1135 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/usr/lib/libtinyxml.so.0+0xf135) #2 0x7ff0e914c49d in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1571 #3 0x7ff0e914c49d in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:805 #4 0x55bf362b423b in CFileItem::SetDynPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/dobo/kodi/xbmc/xbmc/FileItem.cpp:2021 #5 0x55bf362af7bb in CFileItem::UpdateInfo(CFileItem const&, bool) /home/dobo/kodi/xbmc/xbmc/FileItem.cpp:1741 #6 0x55bf35d56d30 in CApplication::OnMessage(CGUIMessage&) /home/dobo/kodi/xbmc/xbmc/application/Application.cpp:2727 #7 0x55bf35b590ba in CGUIWindowManager::SendMessage(CGUIMessage&) /home/dobo/kodi/xbmc/xbmc/guilib/GUIWindowManager.cpp:499 #8 0x55bf35b65e30 in CGUIWindowManager::DispatchThreadMessages() /home/dobo/kodi/xbmc/xbmc/guilib/GUIWindowManager.cpp:1561 #9 0x55bf35d5bfe2 in CApplication::Process() /home/dobo/kodi/xbmc/xbmc/application/Application.cpp:3100 #10 0x55bf35d4c2e0 in CApplication::Run() /home/dobo/kodi/xbmc/xbmc/application/Application.cpp:1907 #11 0x55bf356ae727 in XBMC_Run /home/dobo/kodi/xbmc/xbmc/platform/xbmc.cpp:61 #12 0x55bf34321830 in main /home/dobo/kodi/xbmc/xbmc/platform/posix/main.cpp:71 #13 0x7ff0e9c9a78f (/usr/lib/libc.so.6+0x2378f) #14 0x7ff0e9c9a849 in __libc_start_main (/usr/lib/libc.so.6+0x23849) #15 0x55bf343213d4 in _start (/usr/lib/kodi/kodi.bin+0x2c263d4) 0x6070000ea040 is located 0 bytes inside of 66-byte region [0x6070000ea040,0x6070000ea082) freed by thread T62 here: #0 0x7ff0ebac11fa in operator delete(void*) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:152 #1 0x55bf3629cc1b in CFileItem::~CFileItem() /home/dobo/kodi/xbmc/xbmc/FileItem.cpp:439 #2 0x55bf3629ccbb in CFileItem::~CFileItem() /home/dobo/kodi/xbmc/xbmc/FileItem.cpp:439 #3 0x55bf3440220d in std::_Sp_counted_ptr<CFileItem*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/12.2.1/bits/shared_ptr_base.h:428 #4 0x55bf34321add in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/12.2.1/bits/shared_ptr_base.h:346 #5 0x55bf34321e57 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/12.2.1/bits/shared_ptr_base.h:1071 #6 0x55bf343f1309 in std::__shared_ptr<CFileItem, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/12.2.1/bits/shared_ptr_base.h:1524 #7 0x55bf343f65f6 in std::enable_if<std::__sp_is_constructible<CFileItem, CFileItem>::value, void>::type std::__shared_ptr<CFileItem, (__gnu_cxx::_Lock_policy)2>::reset<CFileItem>(CFileItem*) (/usr/lib/kodi/kodi.bin+0x2cfb5f6) #8 0x55bf35da0e50 in CApplicationPlayerCallback::OnPlayBackStarted(CFileItem const&) /home/dobo/kodi/xbmc/xbmc/application/ApplicationPlayerCallback.cpp:84 #9 0x55bf34dbd001 in operator() /home/dobo/kodi/xbmc/xbmc/cores/VideoPlayer/VideoPlayer.cpp:2631 #10 0x55bf34de836b in DoWork /home/dobo/kodi/xbmc/xbmc/utils/JobManager.h:39 #11 0x55bf35422489 in CJobWorker::Process() /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:55 #12 0x55bf35608346 in CThread::Action() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:267 #13 0x55bf35606c3c in operator() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:138 #14 0x55bf35608dd0 in __invoke_impl<void, CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:61 #15 0x55bf35608c89 in __invoke<CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:96 #16 0x55bf35608bbc in _M_invoke<0, 1, 2> /usr/include/c++/12.2.1/bits/std_thread.h:258 #17 0x55bf35608b59 in operator() /usr/include/c++/12.2.1/bits/std_thread.h:265 #18 0x55bf35608b3d in _M_run /usr/include/c++/12.2.1/bits/std_thread.h:210 #19 0x7ff0e90d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82 previously allocated by thread T62 here: #0 0x7ff0ebac0672 in operator new(unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:95 #1 0x7ff0ea8b10fb in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/usr/lib/libtinyxml.so.0+0xf0fb) Thread T62 created by T46 here: #0 0x7ff0eba64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207 #1 0x7ff0e90d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 #2 0x7ff0e90d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147 #3 0x55bf356077d6 in CThread::Create(bool) /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:159 #4 0x55bf354221c2 in CJobWorker::CJobWorker(CJobManager*) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:32 #5 0x55bf354261d2 in CJobManager::StartWorkers(CJob::PRIORITY) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:288 #6 0x55bf35425693 in CJobManager::AddJob(CJob*, IJobCallback*, CJob::PRIORITY) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:247 #7 0x55bf3542406d in CJobQueue::QueueNextJob() /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:147 #8 0x55bf354239ed in CJobQueue::AddJob(CJob*) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:124 #9 0x55bf368a363b in void CJobQueue::Submit<CEventSource<PVR::PVREvent>::Publish<PVR::PVREvent>(PVR::PVREvent)::{lambda()#1}>(CEventSource<PVR::PVREvent>::Publish<PVR::PVREvent>(PVR::PVREvent)::{lambda()#1}&&) (/usr/lib/kodi/kodi.bin+0x51a863b) #10 0x55bf368a0d18 in void CEventSource<PVR::PVREvent>::Publish<PVR::PVREvent>(PVR::PVREvent) /home/dobo/kodi/xbmc/xbmc/utils/EventStream.h:80 #11 0x55bf3689b4db in PVR::CPVREpgContainer::UpdateEPG(bool) /home/dobo/kodi/xbmc/xbmc/pvr/epg/EpgContainer.cpp:805 #12 0x55bf36894d13 in PVR::CPVREpgContainer::Process() /home/dobo/kodi/xbmc/xbmc/pvr/epg/EpgContainer.cpp:346 #13 0x55bf35608346 in CThread::Action() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:267 #14 0x55bf35606c3c in operator() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:138 #15 0x55bf35608dd0 in __invoke_impl<void, CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:61 #16 0x55bf35608c89 in __invoke<CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:96 #17 0x55bf35608bbc in _M_invoke<0, 1, 2> /usr/include/c++/12.2.1/bits/std_thread.h:258 #18 0x55bf35608b59 in operator() /usr/include/c++/12.2.1/bits/std_thread.h:265 #19 0x55bf35608b3d in _M_run /usr/include/c++/12.2.1/bits/std_thread.h:210 #20 0x7ff0e90d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82 Thread T46 created by T43 here: #0 0x7ff0eba64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207 #1 0x7ff0e90d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 #2 0x7ff0e90d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147 #3 0x55bf356077d6 in CThread::Create(bool) /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:159 #4 0x55bf36892a8a in PVR::CPVREpgContainer::Start() /home/dobo/kodi/xbmc/xbmc/pvr/epg/EpgContainer.cpp:153 #5 0x55bf36b1ae80 in PVR::CPVRManager::Process() /home/dobo/kodi/xbmc/xbmc/pvr/PVRManager.cpp:513 #6 0x55bf35608346 in CThread::Action() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:267 #7 0x55bf35606c3c in operator() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:138 #8 0x55bf35608dd0 in __invoke_impl<void, CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:61 #9 0x55bf35608c89 in __invoke<CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:96 #10 0x55bf35608bbc in _M_invoke<0, 1, 2> /usr/include/c++/12.2.1/bits/std_thread.h:258 #11 0x55bf35608b59 in operator() /usr/include/c++/12.2.1/bits/std_thread.h:265 #12 0x55bf35608b3d in _M_run /usr/include/c++/12.2.1/bits/std_thread.h:210 #13 0x7ff0e90d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82 Thread T43 created by T24 here: #0 0x7ff0eba64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207 #1 0x7ff0e90d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 #2 0x7ff0e90d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147 #3 0x55bf356077d6 in CThread::Create(bool) /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:159 #4 0x55bf36b1a1f6 in PVR::CPVRManager::Start() /home/dobo/kodi/xbmc/xbmc/pvr/PVRManager.cpp:388 #5 0x55bf36a80919 in PVR::CPVRClients::UpdateClients(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) /home/dobo/kodi/xbmc/xbmc/pvr/addons/PVRClients.cpp:212 #6 0x55bf36a7e4e8 in PVR::CPVRClients::Start() /home/dobo/kodi/xbmc/xbmc/pvr/addons/PVRClients.cpp:59 #7 0x55bf36b19e06 in operator() /home/dobo/kodi/xbmc/xbmc/pvr/PVRManager.cpp:362 #8 0x55bf36b2c143 in DoWork /home/dobo/kodi/xbmc/xbmc/utils/JobManager.h:39 #9 0x55bf35422489 in CJobWorker::Process() /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:55 #10 0x55bf35608346 in CThread::Action() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:267 #11 0x55bf35606c3c in operator() /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:138 #12 0x55bf35608dd0 in __invoke_impl<void, CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:61 #13 0x55bf35608c89 in __invoke<CThread::Create(bool)::<lambda(CThread*, std::promise<bool>)>, CThread*, std::promise<bool> > /usr/include/c++/12.2.1/bits/invoke.h:96 #14 0x55bf35608bbc in _M_invoke<0, 1, 2> /usr/include/c++/12.2.1/bits/std_thread.h:258 #15 0x55bf35608b59 in operator() /usr/include/c++/12.2.1/bits/std_thread.h:265 #16 0x55bf35608b3d in _M_run /usr/include/c++/12.2.1/bits/std_thread.h:210 #17 0x7ff0e90d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82 Thread T24 created by T0 here: #0 0x7ff0eba64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207 #1 0x7ff0e90d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 #2 0x7ff0e90d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147 #3 0x55bf356077d6 in CThread::Create(bool) /home/dobo/kodi/xbmc/xbmc/threads/Thread.cpp:159 #4 0x55bf354221c2 in CJobWorker::CJobWorker(CJobManager*) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:32 #5 0x55bf354261d2 in CJobManager::StartWorkers(CJob::PRIORITY) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:288 #6 0x55bf35425693 in CJobManager::AddJob(CJob*, IJobCallback*, CJob::PRIORITY) /home/dobo/kodi/xbmc/xbmc/utils/JobManager.cpp:247 #7 0x55bf35d64c96 in Submit<CApplication::Initialize()::<lambda()> > /home/dobo/kodi/xbmc/xbmc/utils/JobManager.h:261 #8 0x55bf35d3f094 in CApplication::Initialize() /home/dobo/kodi/xbmc/xbmc/application/Application.cpp:655 #9 0x55bf356ae6b8 in XBMC_Run /home/dobo/kodi/xbmc/xbmc/platform/xbmc.cpp:43 #10 0x55bf34321830 in main /home/dobo/kodi/xbmc/xbmc/platform/posix/main.cpp:71 #11 0x7ff0e9c9a78f (/usr/lib/libc.so.6+0x2378f) SUMMARY: AddressSanitizer: heap-use-after-free /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy Shadow bytes around the buggy address: 0x0c0e800153b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e800153c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e800153d0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa 0x0c0e800153e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e800153f0: fa fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd =>0x0c0e80015400: fd fd fd fa fa fa fa fa[fd]fd fd fd fd fd fd fd 0x0c0e80015410: fd fa fa fa fa fa fd fd fd fd fd fd fd fd fd fa 0x0c0e80015420: fa fa fa fa 00 00 00 00 00 00 00 00 00 fa fa fa 0x0c0e80015430: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa 0x0c0e80015440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 00 00 0x0c0e80015450: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==34632==ABORTING
- Loading branch information