You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
6.4 KiB

/*
* 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<void(hci::EventView)> event_handler) {
return &security_interface_;
}
hci::LeSecurityInterface* FuzzHciLayer::GetLeSecurityInterface(
ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
return &le_security_interface_;
}
hci::AclConnectionInterface* FuzzHciLayer::GetAclConnectionInterface(
ContextualCallback<void(hci::EventView)> event_handler,
ContextualCallback<void(uint16_t, hci::ErrorCode)> 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<void(hci::LeMetaEventView)> event_handler,
ContextualCallback<void(uint16_t, hci::ErrorCode)> 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<void(hci::LeMetaEventView)> event_handler) {
return &le_advertising_interface_;
}
hci::LeScanningInterface* FuzzHciLayer::GetLeScanningInterface(
ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
return &le_scanning_interface_;
}
hci::LeIsoInterface* FuzzHciLayer::GetLeIsoInterface(ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
return &le_iso_interface_;
}
void FuzzHciLayer::Start() {
acl_dev_null_ = new os::fuzz::DevNullQueue<AclBuilder>(acl_queue_.GetDownEnd(), GetHandler());
acl_dev_null_->Start();
acl_inject_ = new os::fuzz::FuzzInjectQueue<AclView>(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<uint8_t> data) {
CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(hci::AclView, 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);
}
void FuzzHciLayer::injectCommandStatus(std::vector<uint8_t> data) {
InvokeIfValid<hci::CommandStatusView>(std::move(on_command_status_), data);
}
void FuzzHciLayer::injectEvent(FuzzedDataProvider& fdp) {
auto handler_pair = event_handlers_.find(static_cast<EventCode>(fdp.ConsumeIntegral<uint8_t>()));
if (handler_pair != event_handlers_.end()) {
InvokeIfValid<EventView>(handler_pair->second, GetArbitraryBytes(&fdp));
}
}
void FuzzHciLayer::injectLeEvent(FuzzedDataProvider& fdp) {
auto handler_pair = le_event_handlers_.find(static_cast<SubeventCode>(fdp.ConsumeIntegral<uint8_t>()));
if (handler_pair != le_event_handlers_.end()) {
InvokeIfValid<LeMetaEventView>(handler_pair->second, GetArbitraryBytes(&fdp));
}
}
void FuzzHciLayer::injectSecurityEvent(std::vector<uint8_t> data) {
InvokeIfValid<EventView>(security_event_handler_, data);
}
void FuzzHciLayer::injectLeSecurityEvent(std::vector<uint8_t> data) {
InvokeIfValid<LeMetaEventView>(le_security_event_handler_, data);
}
void FuzzHciLayer::injectAclEvent(std::vector<uint8_t> data) {
InvokeIfValid<EventView>(acl_event_handler_, data);
}
void FuzzHciLayer::injectAclDisconnect(FuzzedDataProvider& fdp) {
acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral<uint16_t>(),
static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>()));
}
void FuzzHciLayer::injectLeAclEvent(std::vector<uint8_t> data) {
InvokeIfValid<LeMetaEventView>(le_acl_event_handler_, data);
}
void FuzzHciLayer::injectLeAclDisconnect(FuzzedDataProvider& fdp) {
le_acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral<uint16_t>(),
static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>()));
}
void FuzzHciLayer::injectLeAdvertisingEvent(std::vector<uint8_t> data) {
InvokeIfValid<LeMetaEventView>(le_advertising_event_handler_, data);
}
void FuzzHciLayer::injectLeScanningEvent(std::vector<uint8_t> data) {
InvokeIfValid<LeMetaEventView>(le_scanning_event_handler_, data);
}
void FuzzHciLayer::injectLeIsoEvent(std::vector<uint8_t> data) {
InvokeIfValid<LeMetaEventView>(le_iso_event_handler_, data);
}
const ModuleFactory FuzzHciLayer::Factory = ModuleFactory([]() { return new FuzzHciLayer(); });
} // namespace fuzz
} // namespace hci
} // namespace bluetooth