1 /*
2  * Copyright 2022 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 <bluetooth/log.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 
20 #include <cstdint>
21 #include <functional>
22 #include <vector>
23 
24 #include "osi/include/allocator.h"
25 #include "stack/include/bnep_api.h"
26 #include "test/fake/fake_osi.h"
27 #include "test/mock/mock_btif_config.h"
28 #include "test/mock/mock_stack_acl.h"
29 #include "test/mock/mock_stack_btm_dev.h"
30 #include "test/mock/mock_stack_l2cap_api.h"
31 #include "test/mock/mock_stack_l2cap_ble.h"
32 #include "types/bluetooth/uuid.h"
33 
34 // TODO(b/369381361) Enfore -Wmissing-prototypes
35 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
36 #pragma GCC diagnostic ignored "-Wunused-parameter"
37 
38 using bluetooth::Uuid;
39 
40 namespace {
41 
42 constexpr uint16_t kDummyCid = 0x1234;
43 constexpr uint8_t kDummyId = 0x77;
44 constexpr uint8_t kDummyRemoteAddr[] = {0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC};
45 constexpr uint8_t kDummySrcUuid[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
46                                      0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
47 constexpr uint8_t kDummyDstUuid[] = {0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22,
48                                      0x33, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x59};
49 
50 // Set up default callback structure
51 static tL2CAP_APPL_INFO appl_info;
52 
53 class FakeBtStack {
54 public:
FakeBtStack()55   FakeBtStack() {
56     test::mock::stack_l2cap_api::L2CA_DataWrite.body = [](uint16_t cid, BT_HDR* p_data) {
57       bluetooth::log::assert_that(cid == kDummyCid, "assert failed: cid == kDummyCid");
58       osi_free(p_data);
59       return tL2CAP_DW_RESULT::SUCCESS;
60     };
61     test::mock::stack_l2cap_api::L2CA_DisconnectReq.body = [](uint16_t cid) {
62       bluetooth::log::assert_that(cid == kDummyCid, "assert failed: cid == kDummyCid");
63       return true;
64     };
65     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity.body =
66             [](uint16_t psm, const RawAddress& p_bd_addr, uint16_t sec_level) {
67               bluetooth::log::assert_that(p_bd_addr == kDummyRemoteAddr,
68                                           "assert failed: p_bd_addr == kDummyRemoteAddr");
69               return kDummyCid;
70             };
71     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity.body =
72             [](uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop,
73                tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu,
74                uint16_t sec_level) {
75               appl_info = p_cb_info;
76               return psm;
77             };
78     test::mock::stack_l2cap_api::L2CA_Deregister.body = [](uint16_t psm) {};
79   }
80 
~FakeBtStack()81   ~FakeBtStack() {
82     test::mock::stack_l2cap_api::L2CA_DataWrite = {};
83     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity = {};
84     test::mock::stack_l2cap_api::L2CA_DisconnectReq = {};
85     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity = {};
86     test::mock::stack_l2cap_api::L2CA_Deregister = {};
87   }
88 };
89 
90 class Fakes {
91 public:
92   test::fake::FakeOsi fake_osi;
93   FakeBtStack fake_stack;
94 };
95 
96 }  // namespace
97 
98 // Verify the passed data is readable
ConsumeData(const uint8_t * data,size_t size)99 static void ConsumeData(const uint8_t* data, size_t size) {
100   volatile uint8_t checksum = 0;
101   for (size_t i = 0; i < size; i++) {
102     checksum ^= data[i];
103   }
104 }
105 
Fuzz(const uint8_t * data,size_t size)106 static void Fuzz(const uint8_t* data, size_t size) {
107   tBNEP_REGISTER reg = {
108           .p_conn_ind_cb = [](uint16_t handle, const RawAddress& bd_addr,
109                               const bluetooth::Uuid& remote_uuid, const bluetooth::Uuid& local_uuid,
110                               bool is_role_change) { BNEP_ConnectResp(handle, BNEP_SUCCESS); },
111           .p_conn_state_cb = [](uint16_t handle, const RawAddress& rem_bda, tBNEP_RESULT result,
112                                 bool is_role_change) {},
113           .p_data_ind_cb = [](uint16_t handle, const RawAddress& src, const RawAddress& dst,
114                               uint16_t protocol, uint8_t* p_data, uint16_t len,
115                               bool fw_ext_present) { ConsumeData(p_data, len); },
116           .p_tx_data_flow_cb = [](uint16_t handle, tBNEP_RESULT event) {},
117           .p_filter_ind_cb = [](uint16_t handle, bool indication, tBNEP_RESULT result,
118                                 uint16_t num_filters,
119                                 uint8_t* p_filters) { ConsumeData(p_filters, num_filters); },
120           .p_mfilter_ind_cb = [](uint16_t handle, bool indication, tBNEP_RESULT result,
121                                  uint16_t num_mfilters,
122                                  uint8_t* p_mfilters) { ConsumeData(p_mfilters, num_mfilters); },
123   };
124 
125   BNEP_Init();
126   if (BNEP_SUCCESS != BNEP_Register(&reg)) {
127     return;
128   }
129 
130   FuzzedDataProvider fdp(data, size);
131   bool is_server = fdp.ConsumeBool();
132   if (is_server) {
133     // Simulating an inbound connection event
134     appl_info.pL2CA_ConnectInd_Cb(kDummyRemoteAddr, kDummyCid, 0, kDummyId);
135   } else {
136     // Initiating an outbound connection
137     uint16_t handle;
138     BNEP_Connect(kDummyRemoteAddr, Uuid::From128BitBE(kDummySrcUuid),
139                  Uuid::From128BitBE(kDummyDstUuid), &handle, 0);
140 
141     // Simulating outbound connection confirm event
142     appl_info.pL2CA_ConnectCfm_Cb(kDummyCid, tL2CAP_CONN::L2CAP_CONN_OK);
143   }
144 
145   // Simulating configuration confirmation event
146   tL2CAP_CFG_INFO cfg = {};
147   appl_info.pL2CA_ConfigCfm_Cb(kDummyCid, 0, &cfg);
148 
149   // Feeding input packets
150   constexpr uint16_t kMaxPacketSize = 1024;
151   while (fdp.remaining_bytes() > 0) {
152     auto size = fdp.ConsumeIntegralInRange<uint16_t>(0, kMaxPacketSize);
153     auto bytes = fdp.ConsumeBytes<uint8_t>(size);
154     BT_HDR* hdr = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + bytes.size());
155     hdr->len = bytes.size();
156     std::copy(bytes.cbegin(), bytes.cend(), hdr->data);
157     appl_info.pL2CA_DataInd_Cb(kDummyCid, hdr);
158   }
159 
160   // Simulating disconnecting event
161   appl_info.pL2CA_DisconnectInd_Cb(kDummyCid, false);
162 
163   BNEP_Deregister();
164 }
165 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)166 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
167   auto fakes = std::make_unique<Fakes>();
168   Fuzz(Data, Size);
169   return 0;
170 }
171