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