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 <base/functional/bind.h>
18 #include <bluetooth/log.h>
19 #include <fuzzer/FuzzedDataProvider.h>
20 
21 #include <cstdint>
22 #include <functional>
23 #include <vector>
24 
25 #include "osi/include/allocator.h"
26 #include "stack/include/avct_api.h"
27 #include "stack/include/avrc_api.h"
28 #include "stack/include/bt_psm_types.h"
29 #include "test/fake/fake_osi.h"
30 #include "test/mock/mock_btif_config.h"
31 #include "test/mock/mock_stack_acl.h"
32 #include "test/mock/mock_stack_btm_dev.h"
33 #include "test/mock/mock_stack_l2cap_api.h"
34 #include "types/bluetooth/uuid.h"
35 
36 // TODO(b/369381361) Enfore -Wmissing-prototypes
37 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
38 #pragma GCC diagnostic ignored "-Wunused-parameter"
39 
40 using bluetooth::Uuid;
41 using namespace bluetooth;
42 
43 // Verify the passed data is readable
ConsumeData(const uint8_t * data,size_t size)44 static void ConsumeData(const uint8_t* data, size_t size) {
45   volatile uint8_t checksum = 0;
46   for (size_t i = 0; i < size; i++) {
47     checksum ^= data[i];
48   }
49 }
50 
51 namespace {
52 
53 constexpr uint16_t kDummyCid = 0x1234;
54 constexpr uint8_t kDummyId = 0x77;
55 constexpr uint8_t kDummyRemoteAddr[] = {0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC};
56 
57 // Set up default callback structure
58 static tL2CAP_APPL_INFO avct_appl, avct_br_appl;
59 
60 class FakeBtStack {
61 public:
FakeBtStack()62   FakeBtStack() {
63     test::mock::stack_l2cap_api::L2CA_DataWrite.body = [](uint16_t cid, BT_HDR* hdr) {
64       log::assert_that(cid == kDummyCid, "assert failed: cid == kDummyCid");
65       ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len);
66       osi_free(hdr);
67       return tL2CAP_DW_RESULT::SUCCESS;
68     };
69     test::mock::stack_l2cap_api::L2CA_DisconnectReq.body = [](uint16_t cid) {
70       log::assert_that(cid == kDummyCid, "assert failed: cid == kDummyCid");
71       return true;
72     };
73     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity.body =
74             [](uint16_t psm, const RawAddress& p_bd_addr, uint16_t sec_level) {
75               log::assert_that(p_bd_addr == kDummyRemoteAddr,
76                                "assert failed: p_bd_addr == kDummyRemoteAddr");
77               return kDummyCid;
78             };
79     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity.body =
80             [](uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop,
81                tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu,
82                uint16_t sec_level) {
83               log::assert_that(psm == BT_PSM_AVCTP || psm == BT_PSM_AVCTP_BROWSE,
84                                "assert failed: psm == BT_PSM_AVCTP || psm == BT_PSM_AVCTP_BROWSE");
85               if (psm == BT_PSM_AVDTP) {
86                 avct_appl = p_cb_info;
87               } else if (psm == BT_PSM_AVCTP_BROWSE) {
88                 avct_br_appl = p_cb_info;
89               }
90               return psm;
91             };
92     test::mock::stack_l2cap_api::L2CA_Deregister.body = [](uint16_t psm) {};
93   }
94 
~FakeBtStack()95   ~FakeBtStack() {
96     test::mock::stack_l2cap_api::L2CA_DataWrite = {};
97     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity = {};
98     test::mock::stack_l2cap_api::L2CA_DisconnectReq = {};
99     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity = {};
100     test::mock::stack_l2cap_api::L2CA_Deregister = {};
101   }
102 };
103 
104 class Fakes {
105 public:
106   test::fake::FakeOsi fake_osi;
107   FakeBtStack fake_stack;
108 };
109 
110 }  // namespace
111 
112 #ifdef __ANDROID__
113 namespace android {
114 namespace sysprop {
115 namespace bluetooth {
116 namespace Avrcp {
absolute_volume()117 std::optional<bool> absolute_volume() { return true; }
118 }  // namespace Avrcp
119 
120 namespace Bta {
disable_delay()121 std::optional<std::int32_t> disable_delay() { return 200; }
122 }  // namespace Bta
123 
124 namespace Pan {
nap()125 std::optional<bool> nap() { return false; }
126 }  // namespace Pan
127 }  // namespace bluetooth
128 }  // namespace sysprop
129 }  // namespace android
130 #endif
131 
ctrl_cb(uint8_t handle,uint8_t event,uint16_t result,const RawAddress * peer_addr)132 static void ctrl_cb(uint8_t handle, uint8_t event, uint16_t result, const RawAddress* peer_addr) {}
133 
msg_cb(uint8_t handle,uint8_t label,uint8_t opcode,tAVRC_MSG * p_msg)134 static void msg_cb(uint8_t handle, uint8_t label, uint8_t opcode, tAVRC_MSG* p_msg) {
135   uint8_t scratch_buf[512];
136   tAVRC_STS status;
137 
138   if (p_msg->hdr.ctype == AVCT_CMD) {
139     tAVRC_COMMAND cmd = {0};
140     memset(scratch_buf, 0, sizeof(scratch_buf));
141     status = AVRC_ParsCommand(p_msg, &cmd, scratch_buf, sizeof(scratch_buf));
142     if (status == AVRC_STS_NO_ERROR) {
143       BT_HDR* p_pkt = (BT_HDR*)nullptr;
144       status = AVRC_BldCommand(&cmd, &p_pkt);
145       if (status == AVRC_STS_NO_ERROR && p_pkt) {
146         osi_free(p_pkt);
147       }
148     }
149   } else if (p_msg->hdr.ctype == AVCT_RSP) {
150     tAVRC_RESPONSE rsp = {0};
151     memset(scratch_buf, 0, sizeof(scratch_buf));
152     status = AVRC_ParsResponse(p_msg, &rsp, scratch_buf, sizeof(scratch_buf));
153     if (status == AVRC_STS_NO_ERROR) {
154       BT_HDR* p_pkt = (BT_HDR*)nullptr;
155       status = AVRC_BldResponse(handle, &rsp, &p_pkt);
156       if (status == AVRC_STS_NO_ERROR && p_pkt) {
157         osi_free(p_pkt);
158       }
159     }
160 
161     uint16_t buf_len = sizeof(scratch_buf);
162     memset(scratch_buf, 0, sizeof(scratch_buf));
163     status = AVRC_Ctrl_ParsResponse(p_msg, &rsp, scratch_buf, &buf_len);
164     if (status == AVRC_STS_NO_ERROR) {
165       BT_HDR* p_pkt = (BT_HDR*)nullptr;
166       status = AVRC_BldResponse(handle, &rsp, &p_pkt);
167       if (status == AVRC_STS_NO_ERROR && p_pkt) {
168         osi_free(p_pkt);
169       }
170     }
171   }
172 }
173 
Fuzz(const uint8_t * data,size_t size)174 static void Fuzz(const uint8_t* data, size_t size) {
175   FuzzedDataProvider fdp(data, size);
176   bool is_initiator = fdp.ConsumeBool();
177   bool is_controller = fdp.ConsumeBool();
178   bool is_br = fdp.ConsumeBool();
179 
180   AVCT_Register();
181   AVRC_Init();
182 
183   tL2CAP_APPL_INFO* appl_info = is_br ? &avct_br_appl : &avct_appl;
184 
185   tAVRC_CONN_CB ccb = {
186           .ctrl_cback = base::Bind(ctrl_cb),
187           .msg_cback = base::Bind(msg_cb),
188           .conn = (is_initiator ? AVCT_ROLE_INITIATOR : AVCT_ROLE_ACCEPTOR),
189           .control = (uint8_t)(is_controller ? AVCT_CONTROL : AVCT_TARGET),
190   };
191 
192   appl_info->pL2CA_ConnectInd_Cb(kDummyRemoteAddr, kDummyCid, 0, kDummyId);
193 
194   uint8_t handle;
195   if (AVCT_SUCCESS != AVRC_Open(&handle, &ccb, kDummyRemoteAddr)) {
196     return;
197   }
198 
199   tL2CAP_CFG_INFO cfg;
200   appl_info->pL2CA_ConfigCfm_Cb(kDummyCid, is_initiator, &cfg);
201 
202   // Feeding input packets
203   constexpr uint16_t kMaxPacketSize = 1024;
204   while (fdp.remaining_bytes() > 0) {
205     auto size = fdp.ConsumeIntegralInRange<uint16_t>(0, kMaxPacketSize);
206     auto bytes = fdp.ConsumeBytes<uint8_t>(size);
207     BT_HDR* hdr = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + bytes.size());
208     hdr->len = bytes.size();
209     std::copy(bytes.cbegin(), bytes.cend(), hdr->data);
210     appl_info->pL2CA_DataInd_Cb(kDummyCid, hdr);
211   }
212 
213   AVRC_Close(handle);
214 
215   // Simulating disconnecting event
216   appl_info->pL2CA_DisconnectInd_Cb(kDummyCid, false);
217 
218   AVCT_Deregister();
219 }
220 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)221 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
222   auto fakes = std::make_unique<Fakes>();
223   Fuzz(Data, Size);
224   return 0;
225 }
226