heap-use-after-free and crash when disconnecting network
Issue generated from Tuleap's migration script. Originally submitted by: Hugo Lefeuvre (hle)
Whenever the network is disconnected, the Ring Daemon crashes.
* Environment:
latest master, Ubuntu 16.04.4 LTS
* Reproduce steps:
- Build dring with ASAN.
$ export CFLAGS="-fsanitize=address -g -O0"
$ export LDFLAGS="-fsanitize=address"
$ export CXXFLAGS="$(CFLAGS)"
$ ./autogen.sh
$ ./configure
$ make - Start freshly built daemon
$ ./bin/dring -pcd - Dirty-disconnect network (in my case: unplug Ethernet cable)
- Dring crashes with following ASAN stacktrace (heap-use-after-free)
=================================================================
==15382==ERROR: AddressSanitizer: heap-use-after-free on address 0x60f00003e6b8 at pc 0x7f9d82f75b50 bp 0x7ffff45aec20 sp 0x7ffff45aec10
WRITE of size 4 at 0x60f00003e6b8 thread T0
#0 0x7f9d82f75b4f in __exchange_and_add /usr/include/c++/5/ext/atomicity.h:49
#1 0x7f9d82f75c9e in __exchange_and_add_dispatch /usr/include/c++/5/ext/atomicity.h:82
#2 0x7f9d82f78946 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/5/bits/shared_ptr_base.h:147
#3 0x7f9d8358ca09 in dht::Dht::searchSynchedNodeListen(std::shared_ptr<dht::Dht::Search> const&, dht::Dht::SearchNode&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf6ea09)
#4 0x7f9d835a22ec in dht::Dht::searchStep(std::shared_ptr<dht::Dht::Search>) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf842ec)
#5 0x7f9d835a926e in std::_Function_handler<void (), std::_Bind<std::_Mem_fn<void (dht::Dht::*)(std::shared_ptr<dht::Dht::Search>)> (dht::Dht*, std::shared_ptr<dht::Dht::Search>)> >::_M_invoke(std::_Any_data const&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf8b26e)
#6 0x7f9d83587573 in dht::Dht::periodic(unsigned char const*, unsigned long, dht::SockAddr const&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf69573)
#7 0x7f9d835a98f1 in dht::Dht::periodic(unsigned char const*, unsigned long, sockaddr const*, unsigned int) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf8b8f1)
#8 0x7f9d8355e9c0 in dht::DhtRunner::loop_() (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf409c0)
#9 0x7f9d832b1f7e in dht::DhtRunner::loop() /home/hlefeuvre/Development/ring-daemon/contrib/x86_64-linux-gnu/include/opendht/dhtrunner.h:364
#10 0x7f9d832728ef in ring::RingAccount::handleEvents() /home/hlefeuvre/Development/ring-daemon/src/ringdht/ringaccount.cpp:1618
#11 0x7f9d83279437 in ring::RingAccount::doRegister_()::{lambda()#8}::operator()() const (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xc5b437)
#12 0x7f9d8329bfe1 in _M_invoke /usr/include/c++/5/functional:1871
#13 0x7f9d82fca457 in std::function<void ()>::operator()() const /usr/include/c++/5/functional:2267
#14 0x7f9d82fb09e8 in ring::Manager::pollEvents() /home/hlefeuvre/Development/ring-daemon/src/manager.cpp:1721
#15 0x7f9d83052de5 in DRing::pollEvents() /home/hlefeuvre/Development/ring-daemon/src/ring_api.cpp:85
#16 0x4b01cf in std::_Function_handler<void (), void (*)()>::_M_invoke(std::_Any_data const&) (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x4b01cf)
#17 0x49ccfd in std::function<void ()>::operator()() const /usr/include/c++/5/functional:2267
#18 0x49b3bf in EventCallback::call(DBus::DefaultTimeout&) const (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x49b3bf)
#19 0x5388d4 in DBus::Slot<void, DBus::DefaultTimeout&>::operator()(DBus::DefaultTimeout&) const (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x5388d4)
#20 0x537eab in DBus::DefaultMainLoop::dispatch() (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x537eab)
#21 0x539c7d in DBus::BusDispatcher::do_iteration() (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x539c7d)
#22 0x53990f in DBus::BusDispatcher::enter() (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x53990f)
#23 0x4930fc in DBusClient::event_loop() /home/hlefeuvre/Development/ring-daemon/bin/dbus/dbusclient.cpp:250
#24 0x48d0d0 in main /home/hlefeuvre/Development/ring-daemon/bin/main.cpp:236
#25 0x7f9d81abf82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#26 0x48c718 in _start (/home/hlefeuvre/Development/ring-daemon/bin/.libs/lt-dring+0x48c718)
0x60f00003e6b8 is located 8 bytes inside of 168-byte region [0x60f00003e6b0,0x60f00003e758)
freed by thread T0 here:
#0 0x7f9d84c5db2a in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99b2a)
#1 0x7f9d82f78a23 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/5/bits/shared_ptr_base.h:167
#2 0x7f9d8358c94d in dht::Dht::searchSynchedNodeListen(std::shared_ptr<dht::Dht::Search> const&, dht::Dht::SearchNode&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf6e94d)
#3 0x7f9d835a22ec in dht::Dht::searchStep(std::shared_ptr<dht::Dht::Search>) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf842ec)
previously allocated by thread T0 here:
#0 0x7f9d84c5d532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
#1 0x7f9d835ca5cf in dht::net::NetworkEngine::sendListen(std::shared_ptr<dht::Node>, dht::Hash<20ul> const&, dht::Query const&, std::vector<unsigned char, std::allocator<unsigned char> > const&, std::shared_ptr<dht::net::Request>, std::function<void (dht::net::Request const&, dht::net::RequestAnswer&&)>&&, std::function<void (dht::net::Request const&, bool)>&&, std::function<void (std::shared_ptr<dht::Node> const&, dht::net::RequestAnswer&&)>&&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xfac5cf)
#2 0x7f9d8358c8cc in dht::Dht::searchSynchedNodeListen(std::shared_ptr<dht::Dht::Search> const&, dht::Dht::SearchNode&) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf6e8cc)
#3 0x7f9d835a22ec in dht::Dht::searchStep(std::shared_ptr<dht::Dht::Search>) (/home/hlefeuvre/Development/ring-daemon/src/.libs/libring.so.0+0xf842ec)
SUMMARY: AddressSanitizer: heap-use-after-free /usr/include/c++/5/ext/atomicity.h:49 __exchange_and_add
Shadow bytes around the buggy address:
0x0c1e7ffffc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c1e7ffffc90: 00 fa fa fa fa fa fa fa fa fa 00 00 00 00 00 00
0x0c1e7ffffca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c1e7ffffcb0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c1e7ffffcc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa
=>0x0c1e7ffffcd0: fa fa fa fa fa fa fd[fd]fd fd fd fd fd fd fd fd
0x0c1e7ffffce0: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x0c1e7ffffcf0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
0x0c1e7ffffd00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
0x0c1e7ffffd10: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c1e7ffffd20: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
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
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
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
==15382==ABORTING
* Expected result:
Obviously, dring should not crash when network is disconnected.
Please, note: This bug may *very well* be located in opendht.
I have marked the bug as affecting GNU/Linux only, but it may very well affect other platforms.