1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include <fuzzer/FuzzedDataProvider.h>
16 #include <pw_async/fake_dispatcher.h>
17 #include <pw_random/fuzzer.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
20 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_dynamic_channel.h"
22 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_signaling_channel.h"
23 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel.h"
24 
25 constexpr static bt::hci_spec::ConnectionHandle kTestHandle = 0x0001;
26 
ConsumeChannelParameters(FuzzedDataProvider & provider)27 bt::l2cap::ChannelParameters ConsumeChannelParameters(
28     FuzzedDataProvider& provider) {
29   bt::l2cap::ChannelParameters params;
30 
31   bool use_defaults = provider.ConsumeBool();
32   if (use_defaults) {
33     return params;
34   }
35 
36   params.mode = provider.ConsumeBool()
37                     ? bt::l2cap::RetransmissionAndFlowControlMode::kBasic
38                     : bt::l2cap::RetransmissionAndFlowControlMode::
39                           kEnhancedRetransmission;
40   params.max_rx_sdu_size = provider.ConsumeIntegral<uint16_t>();
41   return params;
42 }
43 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)44 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
45   FuzzedDataProvider provider(data, size);
46   pw::random::FuzzerRandomGenerator rng(&provider);
47   bt::set_random_generator(&rng);
48 
49   // Dispatcher needed for signaling channel response timeout.
50   pw::async::test::FakeDispatcher dispatcher;
51 
52   auto fake_chan = std::make_unique<bt::l2cap::testing::FakeChannel>(
53       bt::l2cap::kSignalingChannelId,
54       bt::l2cap::kSignalingChannelId,
55       kTestHandle,
56       bt::LinkType::kACL);
57 
58   bt::l2cap::internal::BrEdrSignalingChannel sig_chan(
59       fake_chan->GetWeakPtr(),
60       pw::bluetooth::emboss::ConnectionRole::CENTRAL,
61       dispatcher);
62 
63   auto open_cb = [](auto chan) {};
64   auto close_cb = [](auto chan) {};
65   auto service_chan_cb = [](auto chan) {};
66 
67   auto service_cb = [&](auto psm) {
68     // Reject some PSMs.
69     if (provider.ConsumeBool()) {
70       return std::optional<
71           bt::l2cap::internal::DynamicChannelRegistry::ServiceInfo>();
72     }
73 
74     auto params = ConsumeChannelParameters(provider);
75     return std::optional(
76         bt::l2cap::internal::DynamicChannelRegistry::ServiceInfo(
77             params, service_chan_cb));
78   };
79   bt::l2cap::internal::BrEdrDynamicChannelRegistry registry(
80       &sig_chan,
81       close_cb,
82       service_cb,
83       /*random_channel_ids=*/true);
84 
85   while (provider.remaining_bytes() > 0) {
86     // Receive an l2cap packet.
87     uint16_t data_size = provider.ConsumeIntegral<uint16_t>();
88     auto packet = provider.ConsumeBytes<uint8_t>(data_size);
89     fake_chan->Receive(bt::BufferView(packet.data(), packet.size()));
90 
91     if (provider.ConsumeBool()) {
92       registry.OpenOutbound(
93           bt::l2cap::kAVDTP, ConsumeChannelParameters(provider), open_cb);
94     }
95 
96     if (provider.ConsumeBool()) {
97       dispatcher.RunFor(std::chrono::seconds(1));
98     }
99   }
100 
101   bt::set_random_generator(nullptr);
102   return 0;
103 }
104