ASAN shows heap-use-after-free while boost::asio calls pure recv on socket

1

I have around 100 open TCP sockets, monitoring some remote devices. It's a pure master-slave communication. Where the server is master (which connects to the devices) and the devices are slave.

Master periodically sends the requests to all the devices and wait some time for the responses to come. Only after the send operation is supposed to be successful (handler handle_send called), the socket will fire async_read_some until the message is complete. When the server receives a good message it will stop launching async_read_some as it is not supposed to receive any message anymore.

Randomly, it happens that ASAN complains about unallocated buffer in recv phase (when the real system call 'recvmsg' is called [see boost 1.66 /usr/include/boost/asio/detail/impl/socket_ops.ipp:784])

We are on a linux machine and the same problem happens when I use boost 1.53

Here goes the stack trace:

==7779==ERROR: AddressSanitizer: heap-use-after-free on address 0x611001478a40 at pc 0x503308 bp 0x7ffdea424a70 sp 0x7ffdea424a40
WRITE of size 53 at 0x611001478a40 thread T0
\#0 0x503307 in __interceptor_recvmsg (/usr/tsp/bin/tspinger+0x503307)
\#1 0x8a62c7 in boost::asio::detail::socket_ops::recv(int, iovec*, unsigned long, int, boost::system::error_code&) /usr/include/boost/asio/detail/impl/socket_ops.ipp:784
\#2 0x8a5457 in boost::asio::detail::socket_ops::non_blocking_recv(int, iovec*, unsigned long, int, bool, boost::system::error_code&, unsigned long&) /usr/include/boost/asio/detail/impl/socket_ops.ipp:877
\#3 0x8a4ac3 in boost::asio::detail::reactive_socket_recv_op_base<boost::asio::mutable_buffers_1>::do_perform(boost::asio::detail::reactor_op*) /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:55
\#4 0x681c4e in boost::asio::detail::reactor_op::perform() /usr/include/boost/asio/detail/reactor_op.hpp:44
\#5 0x6f9a98 in boost::asio::detail::epoll_reactor::descriptor_state::perform_io(unsigned int) /usr/include/boost/asio/detail/impl/epoll_reactor.ipp:743
\#6 0x6f8a30 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/impl/epoll_reactor.ipp:774
\#7 0x603207 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
\#8 0x5fe649 in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/include/boost/asio/detail/impl/scheduler.ipp:401
\#9 0x5fc7d1 in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:154
\#10 0x5e5e85 in boost::asio::io_context::run() /usr/include/boost/asio/impl/io_context.ipp:62
0x611001478a40 is located 0 bytes inside of 209-byte region [0x611001478a40,0x611001478b11)
freed by thread T0 here:
==7779==AddressSanitizer CHECK failed: /builddir/build/BUILD/llvm-3.4.2.src/projects/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cc:184 "((id & (1u << 31))) == ((0))" (0x80000000, 0x0)
\#0 0x52fe0f in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/tsp/bin/tspinger+0x52fe0f)
\#1 0x535671 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/tsp/bin/tspinger+0x535671)
\#2 0x53bb8d in __sanitizer::StackDepotGet(unsigned int, unsigned long*) (/usr/tsp/bin/tspinger+0x53bb8d)
\#3 0x4f0c54 in __asan::AsanChunkView::GetFreeStack(__sanitizer::StackTrace*) (/usr/tsp/bin/tspinger+0x4f0c54)
\#4 0x52d096 in __asan::DescribeHeapAddress(unsigned long, unsigned long) (/usr/tsp/bin/tspinger+0x52d096)
\#5 0x52e211 in __asan_report_error (/usr/tsp/bin/tspinger+0x52e211)
\#6 0x503323 in __interceptor_recvmsg (/usr/tsp/bin/tspinger+0x503323)
\#7 0x8a62c7 in boost::asio::detail::socket_ops::recv(int, iovec*, unsigned long, int, boost::system::error_code&) /usr/include/boost/asio/detail/impl/socket_ops.ipp:784
\#8 0x8a5457 in boost::asio::detail::socket_ops::non_blocking_recv(int, iovec*, unsigned long, int, bool, boost::system::error_code&, unsigned long&) /usr/include/boost/asio/detail/impl/socket_ops.ipp:877
\#9 0x8a4ac3 in boost::asio::detail::reactive_socket_recv_op_base<boost::asio::mutable_buffers_1>::do_perform(boost::asio::detail::reactor_op*) /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:55
\#10 0x681c4e in boost::asio::detail::reactor_op::perform() /usr/include/boost/asio/detail/reactor_op.hpp:44
\#11 0x6f9a98 in boost::asio::detail::epoll_reactor::descriptor_state::perform_io(unsigned int) /usr/include/boost/asio/detail/impl/epoll_reactor.ipp:743
\#12 0x6f8a30 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/impl/epoll_reactor.ipp:774
\#13 0x603207 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
\#14 0x5fe649 in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/include/boost/asio/detail/impl/scheduler.ipp:401
\#15 0x5fc7d1 in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:154
\#16 0x5e5e85 in boost::asio::io_context::run() /usr/include/boost/asio/impl/io_context.ipp:62

Now the RX buffer declared in async_read some is called as

m_invector = vector<byte>(RX_BUFFER_SIZE);
socket_.async_read_some(boost::asio::buffer(m_invector),
                   std::bind(&RemoteObject::handle_read, shared_from_this(),
                      std::placeholders::_1, std::placeholders::_2));

So the buffer is always clean when async_read_some is launched. For completion I add boost recv routine for non Windows systems

signed_size_type recv(socket_type s, buf* bufs, size_t count,
    int flags, boost::system::error_code& ec)
{
  clear_last_error();
  msghdr msg = msghdr();
  msg.msg_iov = bufs;
  msg.msg_iovlen = static_cast<int>(count);
  signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec); //LINE 784
  if (result >= 0)
    ec = boost::system::error_code();
  return result;
}

I cannot get the point: ASAN is showing the same point of memory use and free, that is boost/asio/detail/impl/socket_ops.ipp:784, that is system's recvmsg call.

Have you got any clues?

Thanks.

c++
c++11
boost
address-sanitizer
asked on Stack Overflow Mar 7, 2019 by radice

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0