1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <base/location.h>
18 #include <bluetooth/log.h>
19 #include <fuzzer/FuzzedDataProvider.h>
20 #include <gmock/gmock.h>
21 
22 #include <cstdint>
23 #include <iostream>
24 #include <string>
25 
26 #include "common/time_util.h"
27 #include "hal/snoop_logger.h"
28 #include "osi/include/allocator.h"
29 #include "stack/include/port_api.h"
30 #include "stack/include/rfcdefs.h"
31 #include "stack/test/common/stack_test_packet_utils.h"
32 #include "test/fake/fake_osi.h"
33 #include "test/mock/mock_btif_config.h"
34 #include "test/mock/mock_main_shim_entry.h"
35 #include "test/mock/mock_stack_acl.h"
36 #include "test/mock/mock_stack_btm_dev.h"
37 #include "test/mock/mock_stack_l2cap_api.h"
38 #include "test/mock/mock_stack_l2cap_ble.h"
39 #include "test/mock/mock_stack_l2cap_interface.h"
40 #include "test/rfcomm/stack_rfcomm_test_utils.h"
41 
42 // TODO(b/369381361) Enfore -Wmissing-prototypes
43 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
44 #pragma GCC diagnostic ignored "-Wunused-parameter"
45 
46 using ::testing::_;
47 using ::testing::NiceMock;
48 using ::testing::Return;
49 using ::testing::Unused;
50 
51 namespace bluetooth {
52 namespace hal {
53 class SnoopLogger;
54 
AcceptlistRfcommDlci(uint16_t,uint16_t,uint8_t)55 void SnoopLogger::AcceptlistRfcommDlci(uint16_t, uint16_t, uint8_t) {}
SetRfcommPortOpen(uint16_t,uint16_t,uint8_t,uint16_t,bool)56 void SnoopLogger::SetRfcommPortOpen(uint16_t, uint16_t, uint8_t, uint16_t, bool) {}
SetRfcommPortClose(uint16_t,uint16_t,uint8_t,uint16_t)57 void SnoopLogger::SetRfcommPortClose(uint16_t, uint16_t, uint8_t, uint16_t) {}
58 }  // namespace hal
59 
60 namespace common {
time_get_os_boottime_ms()61 uint64_t time_get_os_boottime_ms() { return 0; }
62 }  // namespace common
63 }  // namespace bluetooth
64 
65 namespace {
66 
67 tL2CAP_APPL_INFO appl_info;
68 bluetooth::rfcomm::MockRfcommCallback* rfcomm_callback = nullptr;
69 tBTM_SEC_CALLBACK* security_callback = nullptr;
70 
71 constexpr uint8_t kDummyId = 0x77;
72 constexpr uint8_t kDummyRemoteAddr[] = {0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC};
73 constexpr uint16_t kDummyCID = 0x1234;
74 constexpr uint8_t kDummyAddr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
75 
port_mgmt_cback(const tPORT_RESULT code,uint16_t port_handle)76 void port_mgmt_cback(const tPORT_RESULT code, uint16_t port_handle) {
77   rfcomm_callback->PortManagementCallback(code, port_handle, 0);
78 }
port_event_cback(uint32_t code,uint16_t port_handle)79 void port_event_cback(uint32_t code, uint16_t port_handle) {
80   rfcomm_callback->PortEventCallback(code, port_handle, 0);
81 }
82 
83 class FakeBtStack {
84   NiceMock<bluetooth::testing::stack::l2cap::Mock> mock_l2cap_interface;
85 public:
86   NiceMock<bluetooth::rfcomm::MockRfcommCallback> mock_rfcomm_callback;
87 
FakeBtStack()88   FakeBtStack() {
89     ON_CALL(mock_l2cap_interface, L2CA_DataWrite)
90         .WillByDefault([](Unused, BT_HDR* hdr) {
91           osi_free(hdr);
92           return tL2CAP_DW_RESULT::SUCCESS;
93         });
94     ON_CALL(mock_l2cap_interface, L2CA_ConnectReq)
95         .WillByDefault([](Unused, Unused) { return kDummyCID; });
96     ON_CALL(mock_l2cap_interface, L2CA_DisconnectReq)
97         .WillByDefault([](Unused) { return true; });
98     ON_CALL(mock_l2cap_interface, L2CA_Register)
99       .WillByDefault([](uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, Unused, Unused,
100           Unused, Unused, Unused) {
101         appl_info = p_cb_info;
102         return psm;
103       });
104     bluetooth::testing::stack::l2cap::set_interface(&mock_l2cap_interface);
105 
106     rfcomm_callback = &mock_rfcomm_callback;
107   }
108 
~FakeBtStack()109   ~FakeBtStack() {
110     rfcomm_callback = nullptr;
111     bluetooth::testing::stack::l2cap::reset_interface();
112   }
113 };
114 
115 class Fakes {
116 public:
117   test::fake::FakeOsi fake_osi;
118   FakeBtStack fake_stack;
119 };
120 
121 }  // namespace
122 
Cleanup(uint16_t * server_handle)123 static int Cleanup(uint16_t* server_handle) { return RFCOMM_RemoveServer(*server_handle); }
124 
ServerInit(FuzzedDataProvider * fdp,uint16_t * server_handle)125 static int ServerInit(FuzzedDataProvider* fdp, uint16_t* server_handle) {
126   RFCOMM_Init();
127 
128   auto mtu = fdp->ConsumeIntegral<uint16_t>();
129   auto scn = fdp->ConsumeIntegral<uint8_t>();
130   auto uuid = fdp->ConsumeIntegral<uint16_t>();
131 
132   int status = RFCOMM_CreateConnectionWithSecurity(uuid, scn, true, mtu, kDummyAddr, server_handle,
133                                                    port_mgmt_cback, 0);
134   if (status != PORT_SUCCESS) {
135     return status;
136   }
137   status = PORT_SetEventMaskAndCallback(*server_handle, PORT_EV_RXCHAR, port_event_cback);
138   return status;
139 }
140 
FuzzAsServer(FuzzedDataProvider * fdp)141 static void FuzzAsServer(FuzzedDataProvider* fdp) {
142   auto server_handle = fdp->ConsumeIntegralInRange<uint16_t>(1, MAX_RFC_PORTS);
143   if (ServerInit(fdp, &server_handle) != PORT_SUCCESS) {
144     return;
145   }
146 
147   appl_info.pL2CA_ConnectInd_Cb(kDummyRemoteAddr, kDummyCID, 0, kDummyId);
148 
149   // Simulating configuration confirmation event
150   tL2CAP_CFG_INFO cfg = {};
151   appl_info.pL2CA_ConfigCfm_Cb(kDummyCID, 0, &cfg);
152 
153   // Feeding input packets
154   constexpr uint16_t kMaxPacketSize = 1024;
155   while (fdp->remaining_bytes() > 0) {
156     auto size = fdp->ConsumeIntegralInRange<uint16_t>(0, kMaxPacketSize);
157     auto bytes = fdp->ConsumeBytes<uint8_t>(size);
158     BT_HDR* hdr = reinterpret_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + bytes.size()));
159     hdr->len = bytes.size();
160     std::copy(bytes.cbegin(), bytes.cend(), hdr->data);
161     appl_info.pL2CA_DataInd_Cb(kDummyCID, hdr);
162   }
163 
164   // Simulating disconnecting event
165   appl_info.pL2CA_DisconnectInd_Cb(kDummyCID, false);
166 
167   Cleanup(&server_handle);
168 }
169 
ClientInit(FuzzedDataProvider * fdp,uint16_t * client_handle)170 static int ClientInit(FuzzedDataProvider* fdp, uint16_t* client_handle) {
171   RFCOMM_Init();
172 
173   auto mtu = fdp->ConsumeIntegral<uint16_t>();
174   auto scn = fdp->ConsumeIntegral<uint8_t>();
175   auto uuid = fdp->ConsumeIntegral<uint16_t>();
176 
177   int status = RFCOMM_CreateConnectionWithSecurity(uuid, scn, false, mtu, kDummyAddr, client_handle,
178                                                    port_mgmt_cback, 0);
179   if (status != PORT_SUCCESS) {
180     return status;
181   }
182   status = PORT_SetEventMaskAndCallback(*client_handle, PORT_EV_RXCHAR, port_event_cback);
183   return status;
184 }
185 
FuzzAsClient(FuzzedDataProvider * fdp)186 static void FuzzAsClient(FuzzedDataProvider* fdp) {
187   auto client_handle = fdp->ConsumeIntegralInRange<uint16_t>(1, MAX_RFC_PORTS);
188 
189   if (ClientInit(fdp, &client_handle) != PORT_SUCCESS) {
190     return;
191   }
192 
193   // Simulating outbound connection confirm event
194   appl_info.pL2CA_ConnectCfm_Cb(kDummyCID, tL2CAP_CONN::L2CAP_CONN_OK);
195 
196   // Simulating configuration confirmation event
197   tL2CAP_CFG_INFO cfg = {};
198   appl_info.pL2CA_ConfigCfm_Cb(kDummyCID, 0, &cfg);
199 
200   // Feeding input packets
201   constexpr uint16_t kMaxPacketSize = 1024;
202   while (fdp->remaining_bytes() > 0) {
203     auto size = fdp->ConsumeIntegralInRange<uint16_t>(0, kMaxPacketSize);
204     auto bytes = fdp->ConsumeBytes<uint8_t>(size);
205     BT_HDR* hdr = reinterpret_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + bytes.size()));
206     hdr->len = bytes.size();
207     std::copy(bytes.cbegin(), bytes.cend(), hdr->data);
208     appl_info.pL2CA_DataInd_Cb(kDummyCID, hdr);
209   }
210 
211   Cleanup(&client_handle);
212 }
213 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)214 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
215   auto fakes = std::make_unique<Fakes>();
216 
217   FuzzedDataProvider fdp(data, size);
218 
219   if (fdp.ConsumeBool()) {
220     FuzzAsServer(&fdp);
221   } else {
222     FuzzAsClient(&fdp);
223   }
224 
225   return 0;
226 }
227