eProsima / Fast-DDS

The most complete DDS - Proven: Plenty of success cases. Looking for commercial support? Contact info@eprosima.com
https://eprosima.com
Apache License 2.0
2.15k stars 765 forks source link

SIGABRT while receiving data on specific HistoryQosPolicy depth setting #4365

Closed mirusu400 closed 7 months ago

mirusu400 commented 7 months ago

Is there an already existing issue for this?

Vulnerability Type

DoS

Expected behavior

When setting depth = 0 and kind = KEEP_LAST_HISTORY_QOS for DataReader’s HistoryQosPolicy, handle errors or receive DataWriter’s data properly.

Current behavior

When setting depth = 0 and kind = KEEP_LAST_HISTORY_QOS for DataReader’s HistoryQosPolicy, the program aborts upon receiving DataWriter’s data.

Attack Vectors

To exploit vulnerability, victim must receive data with setting depth = 0 and kind = KEEP_LAST_HISTORY_QOS for DataReader's HistoryQosPolicy.

Steps to reproduce

A quick simple:

// Creating DataReader QoS like this caused error.

DataReaderQos dr_qos = eprosima::fastdds::dds::DATAREADER_QOS_DEFAULT;

dr_qos.history().kind = eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS;
dr_qos.history().depth = 0;
dr_qos.resource_limits().max_samples = 0;

Detailed Example: Fastdds-poc_src.zip

Test:

mkdir build
cd build
cmake ..
make
./Fastdds_poc_src

Cause error like:

Create Topic
Create DataReader
Create DataWriter
Subscription matched    1
Publication matched     1
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
Aborted (core dumped)

GDB backtrace result:

Thread 1 "Fastdds_poc_src" received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737352876288) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) backtrace
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737352876288) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737352876288) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737352876288, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7242476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff72287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff76a2b9e in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff76ae20c in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff76ae277 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x00007ffff76ae4d8 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007ffff76a54cd in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#10 0x00000000008ac81e in std::vector<eprosima::fastrtps::rtps::CacheChange_t*, std::allocator<eprosima::fastrtps::rtps::CacheChange_t*> >::_M_range_check (
    __n=0, this=<optimized out>) at /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_vector.h:1153
--Type <RET> for more, q to quit, c to continue without paging--
#11 std::vector<eprosima::fastrtps::rtps::CacheChange_t*, std::allocator<eprosima::fastrtps::rtps::CacheChange_t*> >::at (__n=0, this=<optimized out>)
    at /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_vector.h:1175
#12 eprosima::fastrtps::ResourceLimitedVector<eprosima::fastrtps::rtps::CacheChange_t*, std::integral_constant<bool, true>, eprosima::fastrtps::ResourceLimitedContainerConfig, std::allocator<eprosima::fastrtps::rtps::CacheChange_t*>, std::vector<eprosima::fastrtps::rtps::CacheChange_t*, std::allocator<eprosima::fastrtps::rtps::CacheChange_t*> > >::at (pos=0, this=<optimized out>)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/include/fastrtps/utils/collections/ResourceLimitedVector.hpp:353
#13 eprosima::fastdds::dds::detail::DataReaderHistory::received_change_keep_last (this=<optimized out>, a_change=<optimized out>, 
    rejection_reason=<optimized out>) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp:276
#14 0x00000000008ad911 in std::function<bool (eprosima::fastrtps::rtps::CacheChange_t*, unsigned long, eprosima::fastdds::dds::SampleRejectedStatusKind&)>::operator()(eprosima::fastrtps::rtps::CacheChange_t*, unsigned long, eprosima::fastdds::dds::SampleRejectedStatusKind&) const (this=0x61e000005cc0, 
    __args=@0x7fffffffa120: eprosima::fastdds::dds::NOT_REJECTED, __args=@0x7fffffffa120: eprosima::fastdds::dds::NOT_REJECTED, 
    __args=@0x7fffffffa120: eprosima::fastdds::dds::NOT_REJECTED)
--Type <RET> for more, q to quit, c to continue without paging--
    at /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:591
#15 eprosima::fastdds::dds::detail::DataReaderHistory::received_change (this=<optimized out>, a_change=<optimized out>, 
    unknown_missing_changes_up_to=<optimized out>, rejection_reason=@0x7fffffffa120: eprosima::fastdds::dds::NOT_REJECTED)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp:207
#16 0x00000000008ad5d5 in eprosima::fastdds::dds::detail::DataReaderHistory::received_change (this=0x61e000005940, change=<optimized out>, 
    unknown_missing_changes_up_to=<optimized out>)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp:186
#17 0x000000000101911b in eprosima::fastrtps::rtps::StatelessReader::change_received (this=0x617000000e80, change=0x611000016200)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/reader/StatelessReader.cpp:297
#18 0x000000000101b381 in eprosima::fastrtps::rtps::StatelessReader::processDataMsg (this=<optimized out>, change=<optimized out>)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/reader/StatelessReader.cpp:557
#19 0x0000000000f57586 in eprosima::fastrtps::rtps::StatefulWriter::intraprocess_delivery (change=0x9f506, reader_proxy=0x617000001200, 
--Type <RET> for more, q to quit, c to continue without paging--
    this=<optimized out>) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/writer/StatefulWriter.cpp:481
#20 eprosima::fastrtps::rtps::StatefulWriter::deliver_sample_to_intraprocesses (this=0x61c000006080, change=<optimized out>)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/writer/StatefulWriter.cpp:633
#21 0x0000000000f681c6 in eprosima::fastrtps::rtps::StatefulWriter::deliver_sample_nts (this=0x61c000006080, cache_change=0x6120000154c0, group=..., 
    locator_selector=..., max_blocking_time=...) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/writer/StatefulWriter.cpp:2100
#22 0x000000000121f939 in eprosima::fastdds::rtps::FlowControllerImpl<eprosima::fastdds::rtps::FlowControllerSyncPublishMode, eprosima::fastdds::rtps::FlowControllerFifoSchedule>::add_new_sample_impl<eprosima::fastdds::rtps::FlowControllerSyncPublishMode> (this=<optimized out>, writer=<optimized out>, 
    change=<optimized out>, max_blocking_time=...) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/flowcontrol/FlowControllerImpl.hpp:1151
#23 0x0000000000f51d46 in eprosima::fastrtps::rtps::StatefulWriter::unsent_change_added_to_history (this=<optimized out>, change=0x6, max_blocking_time=...)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/rtps/writer/StatefulWriter.cpp:453
#24 0x0000000000819de9 in eprosima::fastrtps::rtps::WriterHistory::add_change_with_commit_hook<eprosima::fastdds::dds::DataWriterImpl::perform_create_new_change(eprosima::fastrtps::rtps::ChangeKind_t, void*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastrtps::rtps::InstanceHandle_t const&)::$_11>(eprosima--Type <RET> for more, q to quit, c to continue without paging--
::fastrtps::rtps::CacheChange_t*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastdds::dds::DataWriterImpl::perform_create_new_change(eprosima::fastrtps::rtps::ChangeKind_t, void*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastrtps::rtps::InstanceHandle_t const&)::$_11, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) (this=0x9f506, a_change=0x6120000154c0, wparams=..., 
    pre_commit=..., max_blocking_time=...) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/include/fastdds/rtps/history/WriterHistory.h:183
#25 eprosima::fastdds::dds::DataWriterHistory::add_pub_change_with_commit_hook<eprosima::fastdds::dds::DataWriterImpl::perform_create_new_change(eprosima::fastrtps::rtps::ChangeKind_t, void*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastrtps::rtps::InstanceHandle_t const&)::$_11>(eprosima::fastrtps::rtps::CacheChange_t*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastdds::dds::DataWriterImpl::perform_create_new_change(eprosima::fastrtps::rtps::ChangeKind_t, void*, eprosima::fastrtps::rtps::WriteParams&, eprosima::fastrtps::rtps::InstanceHandle_t const&)::$_11, std::unique_lock<std::recursive_timed_mutex>&, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > > const&) (this=0x9f506, 
    change=0x6120000154c0, wparams=..., pre_commit=..., lock=..., max_blocking_time=...)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/publisher/DataWriterHistory.hpp:141
#26 eprosima::fastdds::dds::DataWriterImpl::perform_create_new_change (this=0x627000000100, change_kind=<optimized out>, data=<optimized out>, wparams=..., 
--Type <RET> for more, q to quit, c to continue without paging--
    handle=...) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/publisher/DataWriterImpl.cpp:963
#27 0x0000000000812943 in eprosima::fastdds::dds::DataWriterImpl::create_new_change_with_params (this=0x9f506, changeKind=eprosima::fastrtps::rtps::ALIVE, 
    data=0x6, wparams=...) at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/publisher/DataWriterImpl.cpp:1037
#28 eprosima::fastdds::dds::DataWriterImpl::create_new_change (this=0x9f506, changeKind=eprosima::fastrtps::rtps::ALIVE, data=0x6)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/publisher/DataWriterImpl.cpp:884
#29 eprosima::fastdds::dds::DataWriterImpl::write (this=0x9f506, data=<optimized out>)
    at /mnt/EAE2CD0AE2CCDBC7/Fast-dds-2112/Fast-DDS/src/cpp/fastdds/publisher/DataWriterImpl.cpp:564
#30 0x00000000007b96bc in main () at /mnt/EAE2CD0AE2CCDBC7/DDS-FUZZ/detector/Fastdds-poc_src/Fastdds_poc.cpp:127

Fast DDS version/commit

Platform/Architecture

Ubuntu Focal 20.04 amd64

Transport layer

Default configuration, UDPv4 & SHM

Additional context

No response

XML configuration file

No response

Relevant log output

No response

Network traffic capture

No response

JesusPoderoso commented 7 months ago

Hi @mirusu400, thanks for using Fast DDS. As you have described in the expected behavior, setting the HistoryQoS kind as KEEP_LAST and the depth = 0 is inconsistent and Fast DDS should address it by handling the error. The PRs including that error handling plus improving the documentation are attached to this issue, and once they are merged, this issue will be closed automatically. Please feel free to re-open it if necessary. Thanks for your report!