Loading system/gd/common/contextual_callback.h +20 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,16 @@ class ContextualOnceCallback<R(Args...)> { context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); } void InvokeIfNotEmpty(Args... args) { if (context_ != nullptr) { context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); } } bool IsEmpty() { return context_ == nullptr; } private: common::OnceCallback<R(Args...)> callback_; IPostableContext* context_; Loading @@ -75,6 +85,16 @@ class ContextualCallback<R(Args...)> { context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); } void InvokeIfNotEmpty(Args... args) { if (context_ != nullptr) { context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); } } bool IsEmpty() { return context_ == nullptr; } private: common::Callback<R(Args...)> callback_; IPostableContext* context_; Loading system/gd/fuzz/helpers.h +15 −0 Original line number Diff line number Diff line Loading @@ -30,5 +30,20 @@ std::vector<std::vector<uint8_t>> SplitInput(const uint8_t* data, size_t size, c std::vector<uint8_t> GetArbitraryBytes(FuzzedDataProvider* fdp); #define CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(T, name, data) \ auto name = std::make_unique<T>(T::FromBytes(data)); \ if (!name->IsValid()) { \ return; \ } template <typename TView> void InvokeIfValid(common::ContextualOnceCallback<void(TView)> callback, std::vector<uint8_t> data) { auto packet = TView::FromBytes(data); if (!packet.IsValid()) { return; } callback.InvokeIfNotEmpty(packet); } } // namespace fuzz } // namespace bluetooth system/gd/hci/fuzz/acl_manager_fuzz_test.cc +2 −0 Original line number Diff line number Diff line Loading @@ -40,7 +40,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static FuzzTestModuleRegistry moduleRegistry = FuzzTestModuleRegistry(); FuzzHciLayer* fuzzHci = moduleRegistry.Inject<FuzzHciLayer>(&HciLayer::Factory); fuzzHci->TurnOnAutoReply(&dataProvider); moduleRegistry.Start<AclManager>(); fuzzHci->TurnOffAutoReply(); while (dataProvider.remaining_bytes() > 0) { const uint8_t action = dataProvider.ConsumeIntegralInRange(0, 2); Loading system/gd/hci/fuzz/fuzz_hci_layer.cc +17 −10 Original line number Diff line number Diff line Loading @@ -23,10 +23,7 @@ namespace fuzz { using bluetooth::common::ContextualCallback; using bluetooth::fuzz::GetArbitraryBytes; common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* FuzzHciLayer::GetAclQueueEnd() { return acl_queue_.GetUpEnd(); } using bluetooth::fuzz::InvokeIfValid; hci::SecurityInterface* FuzzHciLayer::GetSecurityInterface( ContextualCallback<void(hci::EventPacketView)> event_handler) { Loading Loading @@ -73,21 +70,31 @@ void FuzzHciLayer::Stop() { } void FuzzHciLayer::injectArbitrary(FuzzedDataProvider& fdp) { const uint8_t action = fdp.ConsumeIntegralInRange(0, 1); const uint8_t action = fdp.ConsumeIntegralInRange(0, 3); switch (action) { case 1: injectAclData(GetArbitraryBytes(&fdp)); break; case 2: injectCommandComplete(GetArbitraryBytes(&fdp)); break; case 3: injectCommandStatus(GetArbitraryBytes(&fdp)); break; } } void FuzzHciLayer::injectAclData(std::vector<uint8_t> data) { hci::AclPacketView aclPacket = hci::AclPacketView::FromBytes(data); if (!aclPacket.IsValid()) { return; CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(hci::AclPacketView, packet, data); acl_inject_->Inject(std::move(packet)); } void FuzzHciLayer::injectCommandComplete(std::vector<uint8_t> data) { InvokeIfValid<hci::CommandCompleteView>(std::move(on_command_complete), data); } acl_inject_->Inject(std::make_unique<AclPacketView>(aclPacket)); void FuzzHciLayer::injectCommandStatus(std::vector<uint8_t> data) { InvokeIfValid<hci::CommandStatusView>(std::move(on_command_status), data); } const ModuleFactory FuzzHciLayer::Factory = ModuleFactory([]() { return new FuzzHciLayer(); }); Loading system/gd/hci/fuzz/fuzz_hci_layer.h +32 −3 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ #include "hci/hci_layer.h" #include "os/fuzz/dev_null_queue.h" #include "os/fuzz/fuzz_inject_queue.h" #include "os/log.h" #include <fuzzer/FuzzedDataProvider.h> #include "fuzz/helpers.h" namespace bluetooth { namespace hci { Loading @@ -39,13 +41,33 @@ class FuzzCommandInterface : public CommandInterface<T> { class FuzzHciLayer : public HciLayer { public: void TurnOnAutoReply(FuzzedDataProvider* fdp) { auto_reply_fdp = fdp; } void TurnOffAutoReply() { auto_reply_fdp = nullptr; } void EnqueueCommand(std::unique_ptr<hci::CommandPacketBuilder> command, common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override {} common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override { on_command_complete = std::move(on_complete); if (auto_reply_fdp != nullptr) { injectCommandComplete(bluetooth::fuzz::GetArbitraryBytes(auto_reply_fdp)); } } void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command, common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override {} common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override { on_command_status = std::move(on_status); if (auto_reply_fdp != nullptr) { injectCommandStatus(bluetooth::fuzz::GetArbitraryBytes(auto_reply_fdp)); } } common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* GetAclQueueEnd() override; common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* GetAclQueueEnd() override { return acl_queue_.GetUpEnd(); } void RegisterEventHandler(hci::EventCode event_code, common::ContextualCallback<void(hci::EventPacketView)> event_handler) override {} Loading Loading @@ -92,6 +114,10 @@ class FuzzHciLayer : public HciLayer { private: void injectAclData(std::vector<uint8_t> data); void injectCommandComplete(std::vector<uint8_t> data); void injectCommandStatus(std::vector<uint8_t> data); FuzzedDataProvider* auto_reply_fdp; common::BidiQueue<hci::AclPacketView, hci::AclPacketBuilder> acl_queue_{3}; os::fuzz::DevNullQueue<AclPacketBuilder>* acl_dev_null_; Loading @@ -103,6 +129,9 @@ class FuzzHciLayer : public HciLayer { FuzzCommandInterface<LeSecurityCommandBuilder> le_security_interface_{}; FuzzCommandInterface<LeAdvertisingCommandBuilder> le_advertising_interface_{}; FuzzCommandInterface<LeScanningCommandBuilder> le_scanning_interface_{}; common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_command_complete; common::ContextualOnceCallback<void(hci::CommandStatusView)> on_command_status; }; } // namespace fuzz Loading Loading
system/gd/common/contextual_callback.h +20 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,16 @@ class ContextualOnceCallback<R(Args...)> { context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); } void InvokeIfNotEmpty(Args... args) { if (context_ != nullptr) { context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); } } bool IsEmpty() { return context_ == nullptr; } private: common::OnceCallback<R(Args...)> callback_; IPostableContext* context_; Loading @@ -75,6 +85,16 @@ class ContextualCallback<R(Args...)> { context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); } void InvokeIfNotEmpty(Args... args) { if (context_ != nullptr) { context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); } } bool IsEmpty() { return context_ == nullptr; } private: common::Callback<R(Args...)> callback_; IPostableContext* context_; Loading
system/gd/fuzz/helpers.h +15 −0 Original line number Diff line number Diff line Loading @@ -30,5 +30,20 @@ std::vector<std::vector<uint8_t>> SplitInput(const uint8_t* data, size_t size, c std::vector<uint8_t> GetArbitraryBytes(FuzzedDataProvider* fdp); #define CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(T, name, data) \ auto name = std::make_unique<T>(T::FromBytes(data)); \ if (!name->IsValid()) { \ return; \ } template <typename TView> void InvokeIfValid(common::ContextualOnceCallback<void(TView)> callback, std::vector<uint8_t> data) { auto packet = TView::FromBytes(data); if (!packet.IsValid()) { return; } callback.InvokeIfNotEmpty(packet); } } // namespace fuzz } // namespace bluetooth
system/gd/hci/fuzz/acl_manager_fuzz_test.cc +2 −0 Original line number Diff line number Diff line Loading @@ -40,7 +40,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static FuzzTestModuleRegistry moduleRegistry = FuzzTestModuleRegistry(); FuzzHciLayer* fuzzHci = moduleRegistry.Inject<FuzzHciLayer>(&HciLayer::Factory); fuzzHci->TurnOnAutoReply(&dataProvider); moduleRegistry.Start<AclManager>(); fuzzHci->TurnOffAutoReply(); while (dataProvider.remaining_bytes() > 0) { const uint8_t action = dataProvider.ConsumeIntegralInRange(0, 2); Loading
system/gd/hci/fuzz/fuzz_hci_layer.cc +17 −10 Original line number Diff line number Diff line Loading @@ -23,10 +23,7 @@ namespace fuzz { using bluetooth::common::ContextualCallback; using bluetooth::fuzz::GetArbitraryBytes; common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* FuzzHciLayer::GetAclQueueEnd() { return acl_queue_.GetUpEnd(); } using bluetooth::fuzz::InvokeIfValid; hci::SecurityInterface* FuzzHciLayer::GetSecurityInterface( ContextualCallback<void(hci::EventPacketView)> event_handler) { Loading Loading @@ -73,21 +70,31 @@ void FuzzHciLayer::Stop() { } void FuzzHciLayer::injectArbitrary(FuzzedDataProvider& fdp) { const uint8_t action = fdp.ConsumeIntegralInRange(0, 1); const uint8_t action = fdp.ConsumeIntegralInRange(0, 3); switch (action) { case 1: injectAclData(GetArbitraryBytes(&fdp)); break; case 2: injectCommandComplete(GetArbitraryBytes(&fdp)); break; case 3: injectCommandStatus(GetArbitraryBytes(&fdp)); break; } } void FuzzHciLayer::injectAclData(std::vector<uint8_t> data) { hci::AclPacketView aclPacket = hci::AclPacketView::FromBytes(data); if (!aclPacket.IsValid()) { return; CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(hci::AclPacketView, packet, data); acl_inject_->Inject(std::move(packet)); } void FuzzHciLayer::injectCommandComplete(std::vector<uint8_t> data) { InvokeIfValid<hci::CommandCompleteView>(std::move(on_command_complete), data); } acl_inject_->Inject(std::make_unique<AclPacketView>(aclPacket)); void FuzzHciLayer::injectCommandStatus(std::vector<uint8_t> data) { InvokeIfValid<hci::CommandStatusView>(std::move(on_command_status), data); } const ModuleFactory FuzzHciLayer::Factory = ModuleFactory([]() { return new FuzzHciLayer(); }); Loading
system/gd/hci/fuzz/fuzz_hci_layer.h +32 −3 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ #include "hci/hci_layer.h" #include "os/fuzz/dev_null_queue.h" #include "os/fuzz/fuzz_inject_queue.h" #include "os/log.h" #include <fuzzer/FuzzedDataProvider.h> #include "fuzz/helpers.h" namespace bluetooth { namespace hci { Loading @@ -39,13 +41,33 @@ class FuzzCommandInterface : public CommandInterface<T> { class FuzzHciLayer : public HciLayer { public: void TurnOnAutoReply(FuzzedDataProvider* fdp) { auto_reply_fdp = fdp; } void TurnOffAutoReply() { auto_reply_fdp = nullptr; } void EnqueueCommand(std::unique_ptr<hci::CommandPacketBuilder> command, common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override {} common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override { on_command_complete = std::move(on_complete); if (auto_reply_fdp != nullptr) { injectCommandComplete(bluetooth::fuzz::GetArbitraryBytes(auto_reply_fdp)); } } void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command, common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override {} common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override { on_command_status = std::move(on_status); if (auto_reply_fdp != nullptr) { injectCommandStatus(bluetooth::fuzz::GetArbitraryBytes(auto_reply_fdp)); } } common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* GetAclQueueEnd() override; common::BidiQueueEnd<hci::AclPacketBuilder, hci::AclPacketView>* GetAclQueueEnd() override { return acl_queue_.GetUpEnd(); } void RegisterEventHandler(hci::EventCode event_code, common::ContextualCallback<void(hci::EventPacketView)> event_handler) override {} Loading Loading @@ -92,6 +114,10 @@ class FuzzHciLayer : public HciLayer { private: void injectAclData(std::vector<uint8_t> data); void injectCommandComplete(std::vector<uint8_t> data); void injectCommandStatus(std::vector<uint8_t> data); FuzzedDataProvider* auto_reply_fdp; common::BidiQueue<hci::AclPacketView, hci::AclPacketBuilder> acl_queue_{3}; os::fuzz::DevNullQueue<AclPacketBuilder>* acl_dev_null_; Loading @@ -103,6 +129,9 @@ class FuzzHciLayer : public HciLayer { FuzzCommandInterface<LeSecurityCommandBuilder> le_security_interface_{}; FuzzCommandInterface<LeAdvertisingCommandBuilder> le_advertising_interface_{}; FuzzCommandInterface<LeScanningCommandBuilder> le_scanning_interface_{}; common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_command_complete; common::ContextualOnceCallback<void(hci::CommandStatusView)> on_command_status; }; } // namespace fuzz Loading