SteveMacenski / slam_toolbox

Slam Toolbox for lifelong mapping and localization in potentially massive maps with ROS
GNU Lesser General Public License v2.1
1.67k stars 525 forks source link

UAF bug occurs during `karto::Name::ToString()` #696

Closed GoesM closed 4 months ago

GoesM commented 6 months ago

Required Info:

Steps to reproduce issue

I use slam-toolbox (async) by following command :

#!/bin/bash
export ASAN_OPTIONS=halt_on_error=0:new_delete_type_mismatch=0:detect_leaks=0:log_path=asan
source install/setup.bash
ros2 launch slam_toolbox online_async_launch.py

Running Slam-Toolbox within AddressSanitizer , I always faced to such UAF report during shutdown-period

Expected behavior

No UAF occurs

Actual behavior

we could always face to an ASAN-report about UAF bug as following:

=================================================================
==301204==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b00003e360 at pc 0x570803d9332a bp 0x7fa2ba2e8bb0 sp 0x7fa2ba2e8ba8
READ of size 8 at 0x60b00003e360 thread T20
    #0 0x570803d93329 in karto::Name::ToString[abi:cxx11]() const (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x13e329) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #1 0x570803d92c6d in karto::Name::operator<(karto::Name const&) const (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x13dc6d) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #2 0x7fa2cc1e7c3b in karto::SensorManager::GetSensorByName(karto::Name const&) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x1e7c3b) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #3 0x7fa2c8004947 in karto::Mapper::Process(karto::LocalizedRangeScan*, karto::Matrix3*) (/home/***/slam_toolbox/install/slam_toolbox/lib/libkartoSlamToolbox.so+0x204947) (BuildId: 2dbb35367cda8afe894c24f7258cd868357940f7)
    #4 0x7fa2cc1cd78e in slam_toolbox::SlamToolbox::addScan(karto::LaserRangeFinder*, std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const> const&, karto::Pose2&) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x1cd78e) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #5 0x7fa2cc6f80a8 in slam_toolbox::AsynchronousSlamToolbox::laserCallback(std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const>) (/home/***/slam_toolbox/install/slam_toolbox/lib/libasync_slam_toolbox.so+0x510a8) (BuildId: dfd93fd6d8c439ddd8872d21ec131f9383d9e085)
    #6 0x7fa2cc3b5356 in void std::__invoke_impl<void, void (slam_toolbox::SlamToolbox::*&)(std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const>), slam_toolbox::SlamToolbox*&, std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const> const&>(std::__invoke_memfun_deref, void (slam_toolbox::SlamToolbox::*&)(std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const>), slam_toolbox::SlamToolbox*&, std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const> const&) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x3b5356) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #7 0x7fa2cc3b4b38 in message_filters::CallbackHelper1T<std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > const> const&, sensor_msgs::msg::LaserScan_<std::allocator<void> > >::call(message_filters::MessageEvent<sensor_msgs::msg::LaserScan_<std::allocator<void> > const> const&, bool) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x3b4b38) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #8 0x7fa2cc3ad065 in tf2_ros::MessageFilter<sensor_msgs::msg::LaserScan_<std::allocator<void> >, tf2_ros::Buffer>::transformReadyCallback(tf2_ros::TransformStampedFuture const&, unsigned long) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x3ad065) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #9 0x7fa2cc5fde8d  (/opt/ros/humble/lib/libtf2_ros.so+0x4fe8d) (BuildId: dceacb25e05c8a82678784802b23fb16ba98d172)
    #10 0x7fa2ca76565e in tf2::BufferCore::testTransformableRequests() (/opt/ros/humble/lib/libtf2.so+0x1065e) (BuildId: 5677f8e557cfe0980662adcc0a17f03987f8b7f1)
    #11 0x7fa2ca7683fa in tf2::BufferCore::setTransformImpl(tf2::Transform const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (/opt/ros/humble/lib/libtf2.so+0x133fa) (BuildId: 5677f8e557cfe0980662adcc0a17f03987f8b7f1)
    #12 0x7fa2ca768b29 in tf2::BufferCore::setTransform(geometry_msgs::msg::TransformStamped_<std::allocator<void> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (/opt/ros/humble/lib/libtf2.so+0x13b29) (BuildId: 5677f8e557cfe0980662adcc0a17f03987f8b7f1)
    #13 0x7fa2cc606bb0 in tf2_ros::TransformListener::subscription_callback(std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>, bool) (/opt/ros/humble/lib/libtf2_ros.so+0x58bb0) (BuildId: dceacb25e05c8a82678784802b23fb16ba98d172)
    #14 0x7fa2cbd9e7e9 in std::_Function_handler<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>), std::_Bind<void (tf2_ros::TransformListener::* (tf2_ros::TransformListener*, std::_Placeholder<1>, bool))(std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>, bool)> >::_M_invoke(std::_Any_data const&, std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>&&) (/opt/ros/humble/lib/librviz_default_plugins.so+0x79e7e9) (BuildId: b9e8c9e8368837fa41d968409b5b6b05e426765a)
    #15 0x7fa2cbda95b1 in std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::__detail::__variant::__deduce_visit_result<void> (*)(rclcpp::AnySubscriptionCallback<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::allocator<void> >::dispatch(std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >, rclcpp::MessageInfo const&)::'lambda'(auto&&)&&, std::variant<std::function<void (tf2_msgs::msg::TFMessage_<std::allocator<void> > const&)>, std::function<void (tf2_msgs::msg::TFMessage_<std::allocator<void> > const&, rclcpp::MessageInfo const&)>, std::function<void (rclcpp::SerializedMessage const&)>, std::function<void (rclcpp::SerializedMessage const&, rclcpp::MessageInfo const&)>, std::function<void (std::unique_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::default_delete<tf2_msgs::msg::TFMessage_<std::allocator<void> > > >)>, std::function<void (std::unique_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::default_delete<tf2_msgs::msg::TFMessage_<std::allocator<void> > > >, rclcpp::MessageInfo const&)>, std::function<void (std::unique_ptr<rclcpp::SerializedMessage, std::default_delete<rclcpp::SerializedMessage> >)>, std::function<void (std::unique_ptr<rclcpp::SerializedMessage, std::default_delete<rclcpp::SerializedMessage> >, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const>)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const>, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const> const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const> const&, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const> const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const> const&, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage>)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage>, rclcpp::MessageInfo const&)> >&)>, std::integer_sequence<unsigned long, 8ul> >::__visit_invoke(rclcpp::AnySubscriptionCallback<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::allocator<void> >::dispatch(std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >, rclcpp::MessageInfo const&)::'lambda'(auto&&)&&, std::variant<std::function<void (tf2_msgs::msg::TFMessage_<std::allocator<void> > const&)>, std::function<void (tf2_msgs::msg::TFMessage_<std::allocator<void> > const&, rclcpp::MessageInfo const&)>, std::function<void (rclcpp::SerializedMessage const&)>, std::function<void (rclcpp::SerializedMessage const&, rclcpp::MessageInfo const&)>, std::function<void (std::unique_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::default_delete<tf2_msgs::msg::TFMessage_<std::allocator<void> > > >)>, std::function<void (std::unique_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> >, std::default_delete<tf2_msgs::msg::TFMessage_<std::allocator<void> > > >, rclcpp::MessageInfo const&)>, std::function<void (std::unique_ptr<rclcpp::SerializedMessage, std::default_delete<rclcpp::SerializedMessage> >)>, std::function<void (std::unique_ptr<rclcpp::SerializedMessage, std::default_delete<rclcpp::SerializedMessage> >, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const>, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const>)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const>, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const> const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > const> const&, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const> const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage const> const&, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >)>, std::function<void (std::shared_ptr<tf2_msgs::msg::TFMessage_<std::allocator<void> > >, rclcpp::MessageInfo const&)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage>)>, std::function<void (std::shared_ptr<rclcpp::SerializedMessage>, rclcpp::MessageInfo const&)> >&) (/opt/ros/humble/lib/librviz_default_plugins.so+0x7a95b1) (BuildId: b9e8c9e8368837fa41d968409b5b6b05e426765a)
    #16 0x7fa2cbdaa282  (/opt/ros/humble/lib/librviz_default_plugins.so+0x7aa282) (BuildId: b9e8c9e8368837fa41d968409b5b6b05e426765a)
    #17 0x7fa2c7cf07bb in rclcpp::Executor::execute_subscription(std::shared_ptr<rclcpp::SubscriptionBase>) (/opt/ros/humble/lib/librclcpp.so+0xe77bb) (BuildId: 4cca8a387f3c93d38a0567a8efc7cba9106f5d9a)
    #18 0x7fa2c7cf0fbe in rclcpp::Executor::execute_any_executable(rclcpp::AnyExecutable&) (/opt/ros/humble/lib/librclcpp.so+0xe7fbe) (BuildId: 4cca8a387f3c93d38a0567a8efc7cba9106f5d9a)
    #19 0x7fa2c7cf88af in rclcpp::executors::SingleThreadedExecutor::spin() (/opt/ros/humble/lib/librclcpp.so+0xef8af) (BuildId: 4cca8a387f3c93d38a0567a8efc7cba9106f5d9a)
    #20 0x7fa2c72dc252  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc252) (BuildId: e37fe1a879783838de78cbc8c80621fa685d58a2)
    #21 0x7fa2c6e94ac2 in start_thread nptl/./nptl/pthread_create.c:442:8
    #22 0x7fa2c6f2684f  misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

0x60b00003e360 is located 80 bytes inside of 112-byte region [0x60b00003e310,0x60b00003e380)
freed by thread T0 here:
    #0 0x570803d779cd in operator delete(void*) (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x1229cd) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #1 0x570803d84117 in std::_Rb_tree<karto::Name, std::pair<karto::Name const, karto::Sensor*>, std::_Select1st<std::pair<karto::Name const, karto::Sensor*> >, std::less<karto::Name>, std::allocator<std::pair<karto::Name const, karto::Sensor*> > >::_M_erase(std::_Rb_tree_node<std::pair<karto::Name const, karto::Sensor*> >*) (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x12f117) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)

previously allocated by thread T0 here:
    #0 0x570803d7716d in operator new(unsigned long) (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x12216d) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #1 0x7fa2cc1e4559 in std::_Rb_tree_iterator<std::pair<karto::Name const, karto::Sensor*> > std::_Rb_tree<karto::Name, std::pair<karto::Name const, karto::Sensor*>, std::_Select1st<std::pair<karto::Name const, karto::Sensor*> >, std::less<karto::Name>, std::allocator<std::pair<karto::Name const, karto::Sensor*> > >::_M_emplace_hint_unique<std::piecewise_construct_t const&, std::tuple<karto::Name const&>, std::tuple<> >(std::_Rb_tree_const_iterator<std::pair<karto::Name const, karto::Sensor*> >, std::piecewise_construct_t const&, std::tuple<karto::Name const&>&&, std::tuple<>&&) (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x1e4559) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)

Thread T20 created by T0 here:
    #0 0x570803d2581c in __interceptor_pthread_create (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0xd081c) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #1 0x7fa2c72dc328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328) (BuildId: e37fe1a879783838de78cbc8c80621fa685d58a2)
    #2 0x7fa2cc1a8700 in slam_toolbox::SlamToolbox::setROSInterfaces() (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x1a8700) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #3 0x7fa2cc19e0cc in slam_toolbox::SlamToolbox::configure() (/home/***/slam_toolbox/install/slam_toolbox/lib/libtoolbox_common.so+0x19e0cc) (BuildId: e9b06ded44457cd29634e461aae28bcce716a4ce)
    #4 0x570803d7a79c in main (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x12579c) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0)
    #5 0x7fa2c6e29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-use-after-free (/home/***/slam_toolbox/install/slam_toolbox/lib/slam_toolbox/async_slam_toolbox_node+0x13e329) (BuildId: 924645fe03080352703e9ddaaf3b488138509ed0) in karto::Name::ToString[abi:cxx11]() const
Shadow bytes around the buggy address:
  0x0c167ffffc10: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
  0x0c167ffffc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa
  0x0c167ffffc30: fa fa fa fa fa fa 00 00 00 00 00 00 00 00 00 00
  0x0c167ffffc40: 00 00 00 fa fa fa fa fa fa fa fa fa 00 00 00 00
  0x0c167ffffc50: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa
=>0x0c167ffffc60: fa fa fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd
  0x0c167ffffc70: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c167ffffc80: 00 00 00 00 00 fa fa fa fa fa fa fa fa fa 00 00
  0x0c167ffffc90: 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c167ffffca0: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c167ffffcb0: 00 00 fa fa fa fa fa fa fa fa 00 00 00 00 00 00
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
==301204==ABORTING

Additional information

This bug should be caused because: During the shutdown-period, the excutor (which the function `) is not stop before the destruction of theslam-toolbox node`.

the function is bind to the callback-excutor here:

https://github.com/SteveMacenski/slam_toolbox/blob/94cec982a7f850818187c81295d1212f145efe37/src/slam_toolbox_common.cpp#L233-L241

BUT no excutor about freed during on_cleanup() and the destructor

https://github.com/SteveMacenski/slam_toolbox/blob/94cec982a7f850818187c81295d1212f145efe37/src/slam_toolbox_common.cpp#L86-L101

So that, the callback-function might be still working after the node is destructed and cause the UAF bug as a result.

SteveMacenski commented 6 months ago

Got it - so we just need to add the appropriate reset?

GoesM commented 4 months ago

Sure, it's similar to #694, just issue about humble while seems to be fixed in iron and main

SteveMacenski commented 4 months ago

Got it, just backport and I'll merge! Continue conversation in #694!