/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include "btif/include/stack_manager_t.h" #include "common/message_loop_thread.h" #include "hal/snoop_logger.h" #include "hci/controller_interface_mock.h" #include "osi/include/allocator.h" #include "stack/btm/btm_int_types.h" #include "stack/include/bt_psm_types.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_controller_interface.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/l2cap_module.h" #include "stack/include/l2cdefs.h" #include "stack/l2cap/l2c_int.h" #include "test/fake/fake_osi.h" #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_stack_acl.h" #include "test/mock/mock_stack_btm_devctl.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" using bluetooth::Uuid; using testing::Return; using namespace bluetooth; // Verify the passed data is readable static void ConsumeData(const uint8_t* data, size_t size) { volatile uint8_t checksum = 0; for (size_t i = 0; i < size; i++) { checksum ^= data[i]; } } tBTM_CB btm_cb; bt_status_t do_in_main_thread(base::OnceCallback) { // this is not properly mocked, so we use abort to catch if this is used in // any test cases abort(); } bt_status_t do_in_main_thread_delayed(base::OnceCallback, std::chrono::microseconds) { // this is not properly mocked, so we use abort to catch if this is used in // any test cases abort(); } bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } bluetooth::common::PostableContext* get_main() { return nullptr; } namespace bluetooth { namespace os { uint32_t GetSystemPropertyUint32Base(const std::string& /*property*/, uint32_t default_value, int /*base*/) { return default_value; } } // namespace os namespace hal { class SnoopLogger; const std::string SnoopLogger::kBtSnoopLogModeFiltered = "filtered"; std::string SnoopLogger::GetCurrentSnoopMode() { return "filtered"; } void SnoopLogger::AcceptlistL2capChannel(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::AddA2dpMediaChannel(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::AddRfcommL2capChannel(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::ClearL2capAcceptlist(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::RemoveA2dpMediaChannel(uint16_t, uint16_t) {} void SnoopLogger::SetL2capChannelClose(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::SetL2capChannelOpen(uint16_t, uint16_t, uint16_t, uint16_t, bool) {} } // namespace hal } // namespace bluetooth namespace connection_manager { bool create_le_connection(uint8_t /* id */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */) { return true; } } // namespace connection_manager namespace { class FakeBtStack { public: FakeBtStack() { test::mock::stack_acl::acl_send_data_packet_br_edr.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); osi_free(hdr); }; test::mock::stack_acl::acl_send_data_packet_ble.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); osi_free(hdr); }; GetInterfaceToProfiles()->profileSpecific_HACK->GetHearingAidDeviceCount = []() { return 1; }; ON_CALL(controller_, GetLeSuggestedDefaultDataLength).WillByDefault(Return(512)); bluetooth::hci::LeBufferSize iso_size; iso_size.le_data_packet_length_ = 512; iso_size.total_num_le_packets_ = 6; ON_CALL(controller_, GetControllerIsoBufferSize).WillByDefault(Return(iso_size)); bluetooth::hci::LeBufferSize le_size; le_size.le_data_packet_length_ = 512; le_size.total_num_le_packets_ = 6; ON_CALL(controller_, GetLeBufferSize).WillByDefault(Return(le_size)); ON_CALL(controller_, SupportsBle).WillByDefault(Return(true)); ON_CALL(controller_, GetAclPacketLength).WillByDefault(Return(512)); bluetooth::hci::testing::mock_controller_ = &controller_; } ~FakeBtStack() { test::mock::stack_acl::acl_send_data_packet_br_edr = {}; test::mock::stack_acl::acl_send_data_packet_ble = {}; bluetooth::hci::testing::mock_controller_ = nullptr; } bluetooth::hci::testing::MockControllerInterface controller_; }; class Fakes { public: test::fake::FakeOsi fake_osi; FakeBtStack fake_stack; }; } // namespace constexpr uint8_t kAttAddr[] = {0x11, 0x78, 0x78, 0x78, 0x78, 0x78}; constexpr uint16_t kAttHndl = 0x0111; constexpr uint8_t kEattAddr[] = {0x22, 0x78, 0x78, 0x78, 0x78, 0x78}; constexpr uint8_t kSmpBrAddr[] = {0x33, 0x78, 0x78, 0x78, 0x78, 0x78}; constexpr uint16_t kSmpBrHndl = 0x0222; constexpr uint16_t kNumClassicAclBuffer = 100; constexpr uint16_t kNumLeAclBuffer = 100; static void Fuzz(const uint8_t* data, size_t size) { memset(&btm_cb, 0, sizeof(btm_cb)); l2c_init(); l2c_link_init(kNumClassicAclBuffer); l2c_link_process_ble_num_bufs(kNumLeAclBuffer); tL2CAP_FIXED_CHNL_REG reg = { .pL2CA_FixedConn_Cb = [](uint16_t, const RawAddress&, bool, uint16_t, tBT_TRANSPORT) {}, .pL2CA_FixedData_Cb = [](uint16_t, const RawAddress&, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); }, .pL2CA_FixedCong_Cb = [](const RawAddress&, bool) {}, .default_idle_tout = 1000, }; tL2CAP_APPL_INFO appl_info = { .pL2CA_ConnectInd_Cb = [](const RawAddress&, uint16_t, uint16_t, uint8_t) {}, .pL2CA_ConnectCfm_Cb = [](uint16_t, tL2CAP_CONN) {}, .pL2CA_ConfigInd_Cb = [](uint16_t, tL2CAP_CFG_INFO*) {}, .pL2CA_ConfigCfm_Cb = [](uint16_t, uint16_t, tL2CAP_CFG_INFO*) {}, .pL2CA_DisconnectInd_Cb = [](uint16_t, bool) {}, .pL2CA_DisconnectCfm_Cb = [](uint16_t, uint16_t) {}, .pL2CA_DataInd_Cb = [](uint16_t, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); }, .pL2CA_CongestionStatus_Cb = [](uint16_t, bool) {}, .pL2CA_TxComplete_Cb = [](uint16_t, uint16_t) {}, .pL2CA_Error_Cb = [](uint16_t, uint16_t) {}, .pL2CA_CreditBasedConnectInd_Cb = [](const RawAddress&, std::vector&, uint16_t, uint16_t, uint8_t) {}, .pL2CA_CreditBasedConnectCfm_Cb = [](const RawAddress&, uint16_t, uint16_t, tL2CAP_LE_RESULT_CODE) {}, .pL2CA_CreditBasedReconfigCompleted_Cb = [](const RawAddress&, uint16_t, bool, tL2CAP_LE_CFG_INFO*) {}, .pL2CA_CreditBasedCollisionInd_Cb = [](const RawAddress&) {}, }; log::assert_that(stack::l2cap::get_interface().L2CA_RegisterWithSecurity( BT_PSM_ATT, appl_info, false, nullptr, L2CAP_MTU_SIZE, 0, BTM_SEC_NONE), "assert failed: L2CA_RegisterWithSecurity(BT_PSM_ATT, appl_info, " "false, nullptr, L2CAP_MTU_SIZE, 0, BTM_SEC_NONE)"); log::assert_that(stack::l2cap::get_interface().L2CA_RegisterLECoc(BT_PSM_EATT, appl_info, BTM_SEC_NONE, {}), "assert failed: L2CA_RegisterLECoc(BT_PSM_EATT, appl_info, " "BTM_SEC_NONE, {{}})"); log::assert_that(stack::l2cap::get_interface().L2CA_RegisterFixedChannel(L2CAP_ATT_CID, ®), "assert failed: L2CA_RegisterFixedChannel(L2CAP_ATT_CID, ®)"); log::assert_that(stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_ATT_CID, kAttAddr), "assert failed: L2CA_ConnectFixedChnl(L2CAP_ATT_CID, kAttAddr)"); log::assert_that( l2cble_conn_comp(kAttHndl, HCI_ROLE_CENTRAL, kAttAddr, BLE_ADDR_PUBLIC, 100, 100, 100), "assert failed: l2cble_conn_comp(kAttHndl, HCI_ROLE_CENTRAL, kAttAddr, " "BLE_ADDR_PUBLIC, 100, 100, 100)"); log::assert_that(stack::l2cap::get_interface().L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, ®), "assert failed: L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, ®)"); log::assert_that( stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr), "assert failed: L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr)"); l2c_link_hci_conn_comp(HCI_SUCCESS, kSmpBrHndl, kSmpBrAddr); auto att_cid = stack::l2cap::get_interface().L2CA_ConnectReq(BT_PSM_ATT, kAttAddr); log::assert_that(att_cid != 0, "assert failed: att_cid != 0"); tL2CAP_LE_CFG_INFO cfg; auto eatt_cid = stack::l2cap::get_interface().L2CA_ConnectLECocReq(BT_PSM_EATT, kEattAddr, &cfg, 0); log::assert_that(eatt_cid != 0, "assert failed: eatt_cid != 0"); FuzzedDataProvider fdp(data, size); // Feeding input packets constexpr uint16_t kMinPacketSize = 4 + L2CAP_PKT_OVERHEAD; constexpr uint16_t kMaxPacketSize = 1024; for (;;) { auto size = fdp.ConsumeIntegralInRange(kMinPacketSize, kMaxPacketSize); auto bytes = fdp.ConsumeBytes(size); if (bytes.size() < kMinPacketSize) { break; } BT_HDR* hdr = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + bytes.size()); hdr->len = bytes.size(); std::copy(bytes.cbegin(), bytes.cend(), hdr->data); l2c_rcv_acl_data(hdr); } (void)stack::l2cap::get_interface().L2CA_DisconnectReq(att_cid); (void)stack::l2cap::get_interface().L2CA_DisconnectLECocReq(eatt_cid); (void)stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr); l2c_link_hci_disc_comp(kSmpBrHndl, HCI_SUCCESS); (void)stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_ATT_CID, kAttAddr); l2c_link_hci_disc_comp(kAttHndl, HCI_SUCCESS); l2cu_device_reset(); l2c_free(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { auto fakes = std::make_unique(); Fuzz(Data, Size); return 0; }