Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c6ba623 authored by Zach Johnson's avatar Zach Johnson
Browse files

Add ability to inject hci commands for fuzzing

Also, create a method to determine if a command is requires
a status or complete response.

Test: fuzz/run --host bluetooth_gd_hci_fuzz_test
Change-Id: Ia47cf8472da389e219649013558bb6a26509cf29
parent d8a529b1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -317,6 +317,7 @@ cc_defaults {
    defaults: ["gd_defaults"],
    srcs: [
        ":BluetoothFuzzHelperSources",
        ":BluetoothHciFuzzHelperSources",
    ],
    static_libs: [
        "libbluetooth_gd_fuzzing",
+2 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "hal/fuzz/fuzz_hci_hal.h"
#include "fuzz/helpers.h"
#include "hci/fuzz/status_vs_complete_commands.h"

namespace bluetooth {
namespace hal {
@@ -37,8 +38,7 @@ void FuzzHciHal::sendHciCommand(HciPacket packet) {
  }

  waiting_opcode_ = command.GetOpCode();
  // TODO: expand list or find better way to associate opcodes needing status vs complete
  waiting_for_status_ = waiting_opcode_ == hci::OpCode::RESET;
  waiting_for_status_ = hci::fuzz::uses_command_status(waiting_opcode_);
}

void FuzzHciHal::injectHciEvent(std::vector<uint8_t> data) {
+9 −0
Original line number Diff line number Diff line
@@ -52,3 +52,12 @@ filegroup {
        "hci_packets_fuzz_test.cc",
    ],
}

filegroup {
    name: "BluetoothHciFuzzHelperSources",
    srcs: [
        "fuzz/status_vs_complete_commands.cc",
        "fuzz/dev_null_hci.cc",
    ],
}
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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/dev_null_hci.h"

using bluetooth::hci::AclPacketView;

namespace bluetooth {
namespace hci {
namespace fuzz {

const ModuleFactory DevNullHci::Factory = ModuleFactory([]() { return new DevNullHci(); });

void DevNullHci::Start() {
  hci_ = GetDependency<hci::HciLayer>();
  aclDevNull_ = new os::fuzz::DevNullQueue<AclPacketView>(hci_->GetAclQueueEnd(), GetHandler());
  aclDevNull_->Start();
  aclInject_ = new os::fuzz::FuzzInjectQueue<AclPacketBuilder>(hci_->GetAclQueueEnd(), GetHandler());
}

void DevNullHci::Stop() {
  aclDevNull_->Stop();
  delete aclDevNull_;
  delete aclInject_;
}

void DevNullHci::injectAclData(std::vector<uint8_t> data) {
  auto packet = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(data));
  hci::AclPacketView aclPacket = hci::AclPacketView::Create(packet);
  if (!aclPacket.IsValid()) {
    return;
  }

  aclInject_->Inject(AclPacketBuilder::FromView(aclPacket));
}

void DevNullHci::injectHciCommand(std::vector<uint8_t> data) {
  inject_command<CommandPacketView, CommandPacketBuilder>(data, hci_);
}

}  // namespace fuzz
}  // namespace hci
}  // namespace bluetooth
+28 −31
Original line number Diff line number Diff line
@@ -14,19 +14,17 @@
 * limitations under the License.
 */

#pragma once

#include <stddef.h>
#include <stdint.h>
#include "hci/fuzz/status_vs_complete_commands.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "os/fuzz/dev_null_queue.h"
#include "os/fuzz/fuzz_inject_queue.h"

using bluetooth::hci::AclPacketView;
using bluetooth::hci::HciLayer;
using bluetooth::os::fuzz::DevNullQueue;
using bluetooth::os::fuzz::FuzzInjectQueue;

namespace bluetooth {
namespace hci {
namespace fuzz {
@@ -35,31 +33,15 @@ class DevNullHci : public Module {
 public:
  DevNullHci() : Module() {}

  void Start() override {
    hci_ = GetDependency<HciLayer>();
    aclDevNull_ = new DevNullQueue<AclPacketView>(hci_->GetAclQueueEnd(), GetHandler());
    aclDevNull_->Start();
    aclInject_ = new FuzzInjectQueue<AclPacketBuilder>(hci_->GetAclQueueEnd(), GetHandler());
  }
  void Start() override;
  void Stop() override;

  void Stop() override {
    aclDevNull_->Stop();
    delete aclDevNull_;
    delete aclInject_;
  }
  void injectAclData(std::vector<uint8_t> data);

  void injectAclData(std::vector<uint8_t> data) {
    auto packet = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(data));
    hci::AclPacketView aclPacket = hci::AclPacketView::Create(packet);
    if (!aclPacket.IsValid()) {
      return;
    }

    aclInject_->Inject(AclPacketBuilder::FromView(aclPacket));
  }
  void injectHciCommand(std::vector<uint8_t> data);

  void ListDependencies(ModuleList* list) override {
    list->add<HciLayer>();
    list->add<hci::HciLayer>();
  }

  static const ModuleFactory Factory;
@@ -69,12 +51,27 @@ class DevNullHci : public Module {
  }

 private:
  HciLayer* hci_ = nullptr;
  DevNullQueue<AclPacketView>* aclDevNull_;
  FuzzInjectQueue<AclPacketBuilder>* aclInject_;
};
  template <typename TVIEW, typename TBUILDER>
  void inject_command(std::vector<uint8_t> data, CommandInterface<TBUILDER>* interface) {
    auto packet = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(data));
    TVIEW commandPacket = TVIEW::Create(packet);
    if (!commandPacket.IsValid()) {
      return;
    }

const ModuleFactory DevNullHci::Factory = ModuleFactory([]() { return new DevNullHci(); });
    if (uses_command_status(commandPacket.GetOpCode())) {
      interface->EnqueueCommand(TBUILDER::FromView(commandPacket), common::BindOnce([](CommandStatusView status) {}),
                                GetHandler());
    } else {
      interface->EnqueueCommand(TBUILDER::FromView(commandPacket), common::BindOnce([](CommandCompleteView status) {}),
                                GetHandler());
    }
  }

  hci::HciLayer* hci_ = nullptr;
  os::fuzz::DevNullQueue<AclPacketView>* aclDevNull_;
  os::fuzz::FuzzInjectQueue<AclPacketBuilder>* aclInject_;
};

}  // namespace fuzz
}  // namespace hci
Loading