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