/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/fuzz/fuzz_hci_layer.h" #include "fuzz/helpers.h" namespace bluetooth { namespace hci { namespace fuzz { using bluetooth::common::ContextualCallback; using bluetooth::fuzz::GetArbitraryBytes; using bluetooth::fuzz::InvokeIfValid; hci::SecurityInterface* FuzzHciLayer::GetSecurityInterface(ContextualCallback event_handler) { return &security_interface_; } hci::LeSecurityInterface* FuzzHciLayer::GetLeSecurityInterface( ContextualCallback event_handler) { return &le_security_interface_; } hci::AclConnectionInterface* FuzzHciLayer::GetAclConnectionInterface( ContextualCallback event_handler, ContextualCallback on_disconnect, ContextualCallback< void(hci::ErrorCode, uint16_t, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version)> on_read_remote_version) { return &acl_connection_interface_; } hci::LeAclConnectionInterface* FuzzHciLayer::GetLeAclConnectionInterface( ContextualCallback event_handler, ContextualCallback on_disconnect, ContextualCallback< void(hci::ErrorCode, uint16_t, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version)> on_read_remote_version) { return &le_acl_connection_interface_; } hci::LeAdvertisingInterface* FuzzHciLayer::GetLeAdvertisingInterface( ContextualCallback event_handler) { return &le_advertising_interface_; } hci::LeScanningInterface* FuzzHciLayer::GetLeScanningInterface( ContextualCallback event_handler) { return &le_scanning_interface_; } hci::LeIsoInterface* FuzzHciLayer::GetLeIsoInterface(ContextualCallback event_handler) { return &le_iso_interface_; } void FuzzHciLayer::Start() { acl_dev_null_ = new os::fuzz::DevNullQueue(acl_queue_.GetDownEnd(), GetHandler()); acl_dev_null_->Start(); acl_inject_ = new os::fuzz::FuzzInjectQueue(acl_queue_.GetDownEnd(), GetHandler()); } void FuzzHciLayer::Stop() { acl_dev_null_->Stop(); delete acl_dev_null_; delete acl_inject_; } void FuzzHciLayer::injectArbitrary(FuzzedDataProvider& fdp) { const uint8_t action = fdp.ConsumeIntegralInRange(0, 13); switch (action) { case 1: injectAclData(GetArbitraryBytes(&fdp)); break; case 2: injectCommandComplete(GetArbitraryBytes(&fdp)); break; case 3: injectCommandStatus(GetArbitraryBytes(&fdp)); break; case 4: injectEvent(fdp); break; case 5: injectLeEvent(fdp); break; case 6: injectSecurityEvent(GetArbitraryBytes(&fdp)); break; case 7: injectLeSecurityEvent(GetArbitraryBytes(&fdp)); break; case 8: injectAclEvent(GetArbitraryBytes(&fdp)); break; case 9: injectAclDisconnect(fdp); break; case 10: injectLeAclEvent(GetArbitraryBytes(&fdp)); break; case 11: injectLeAclDisconnect(fdp); break; case 12: injectLeAdvertisingEvent(GetArbitraryBytes(&fdp)); break; case 13: injectLeScanningEvent(GetArbitraryBytes(&fdp)); break; } } void FuzzHciLayer::injectAclData(std::vector data) { CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(hci::AclView, packet, data); acl_inject_->Inject(std::move(packet)); } void FuzzHciLayer::injectCommandComplete(std::vector data) { InvokeIfValid(std::move(on_command_complete_), data); } void FuzzHciLayer::injectCommandStatus(std::vector data) { InvokeIfValid(std::move(on_command_status_), data); } void FuzzHciLayer::injectEvent(FuzzedDataProvider& fdp) { auto handler_pair = event_handlers_.find(static_cast(fdp.ConsumeIntegral())); if (handler_pair != event_handlers_.end()) { InvokeIfValid(handler_pair->second, GetArbitraryBytes(&fdp)); } } void FuzzHciLayer::injectLeEvent(FuzzedDataProvider& fdp) { auto handler_pair = le_event_handlers_.find(static_cast(fdp.ConsumeIntegral())); if (handler_pair != le_event_handlers_.end()) { InvokeIfValid(handler_pair->second, GetArbitraryBytes(&fdp)); } } void FuzzHciLayer::injectSecurityEvent(std::vector data) { InvokeIfValid(security_event_handler_, data); } void FuzzHciLayer::injectLeSecurityEvent(std::vector data) { InvokeIfValid(le_security_event_handler_, data); } void FuzzHciLayer::injectAclEvent(std::vector data) { InvokeIfValid(acl_event_handler_, data); } void FuzzHciLayer::injectAclDisconnect(FuzzedDataProvider& fdp) { acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral(), static_cast(fdp.ConsumeIntegral())); } void FuzzHciLayer::injectLeAclEvent(std::vector data) { InvokeIfValid(le_acl_event_handler_, data); } void FuzzHciLayer::injectLeAclDisconnect(FuzzedDataProvider& fdp) { le_acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral(), static_cast(fdp.ConsumeIntegral())); } void FuzzHciLayer::injectLeAdvertisingEvent(std::vector data) { InvokeIfValid(le_advertising_event_handler_, data); } void FuzzHciLayer::injectLeScanningEvent(std::vector data) { InvokeIfValid(le_scanning_event_handler_, data); } void FuzzHciLayer::injectLeIsoEvent(std::vector data) { InvokeIfValid(le_iso_event_handler_, data); } const ModuleFactory FuzzHciLayer::Factory = ModuleFactory([]() { return new FuzzHciLayer(); }); } // namespace fuzz } // namespace hci } // namespace bluetooth