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

Commit c4f1261f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add fuzzing for rest of interfaces on hci_layer"

parents dbedfc1f 03fb5108
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -30,12 +30,10 @@ constexpr EventCode AclConnectionEvents[] = {
    EventCode::CONNECTION_COMPLETE,
    EventCode::DISCONNECTION_COMPLETE,
    EventCode::CONNECTION_REQUEST,
    EventCode::CONNECTION_PACKET_TYPE_CHANGED,
    EventCode::AUTHENTICATION_COMPLETE,
    EventCode::READ_CLOCK_OFFSET_COMPLETE,
    EventCode::MODE_CHANGE,
    EventCode::QOS_SETUP_COMPLETE,
    EventCode::ROLE_CHANGE,
    EventCode::FLOW_SPECIFICATION_COMPLETE,
    EventCode::FLUSH_OCCURRED,
    EventCode::READ_REMOTE_SUPPORTED_FEATURES_COMPLETE,
+35 −0
Original line number Diff line number Diff line
@@ -29,6 +29,16 @@ void DevNullHci::Start() {
  aclDevNull_ = new os::fuzz::DevNullQueue<AclPacketView>(hci_->GetAclQueueEnd(), GetHandler());
  aclDevNull_->Start();
  aclInject_ = new os::fuzz::FuzzInjectQueue<AclPacketBuilder>(hci_->GetAclQueueEnd(), GetHandler());

  // Can't do security right now, due to the Encryption Change conflict between ACL manager & security
  // security_interface_ = hci_->GetSecurityInterface(common::Bind([](EventPacketView){}), GetHandler());
  le_security_interface_ = hci_->GetLeSecurityInterface(common::Bind([](LeMetaEventView) {}), GetHandler());
  acl_connection_interface_ = hci_->GetAclConnectionInterface(
      common::Bind([](EventPacketView) {}), common::Bind([](uint16_t, hci::ErrorCode) {}), GetHandler());
  le_acl_connection_interface_ = hci_->GetLeAclConnectionInterface(
      common::Bind([](LeMetaEventView) {}), common::Bind([](uint16_t, hci::ErrorCode) {}), GetHandler());
  le_advertising_interface_ = hci_->GetLeAdvertisingInterface(common::Bind([](LeMetaEventView) {}), GetHandler());
  le_scanning_interface_ = hci_->GetLeScanningInterface(common::Bind([](LeMetaEventView) {}), GetHandler());
}

void DevNullHci::Stop() {
@@ -51,6 +61,31 @@ void DevNullHci::injectHciCommand(std::vector<uint8_t> data) {
  inject_command<CommandPacketView, CommandPacketBuilder>(data, hci_);
}

void DevNullHci::injectSecurityCommand(std::vector<uint8_t> data) {
  inject_command<SecurityCommandView, SecurityCommandBuilder>(data, security_interface_);
}

void DevNullHci::injectLeSecurityCommand(std::vector<uint8_t> data) {
  inject_command<LeSecurityCommandView, LeSecurityCommandBuilder>(data, le_security_interface_);
}

void DevNullHci::injectAclConnectionCommand(std::vector<uint8_t> data) {
  inject_command<ConnectionManagementCommandView, ConnectionManagementCommandBuilder>(data, acl_connection_interface_);
}

void DevNullHci::injectLeAclConnectionCommand(std::vector<uint8_t> data) {
  inject_command<LeConnectionManagementCommandView, LeConnectionManagementCommandBuilder>(data,
                                                                                          le_acl_connection_interface_);
}

void DevNullHci::injectLeAdvertisingCommand(std::vector<uint8_t> data) {
  inject_command<LeAdvertisingCommandView, LeAdvertisingCommandBuilder>(data, le_advertising_interface_);
}

void DevNullHci::injectLeScanningCommand(std::vector<uint8_t> data) {
  inject_command<LeScanningCommandView, LeScanningCommandBuilder>(data, le_scanning_interface_);
}

}  // namespace fuzz
}  // namespace hci
}  // namespace bluetooth
+14 −3
Original line number Diff line number Diff line
@@ -37,8 +37,13 @@ class DevNullHci : public Module {
  void Stop() override;

  void injectAclData(std::vector<uint8_t> data);

  void injectHciCommand(std::vector<uint8_t> data);
  void injectSecurityCommand(std::vector<uint8_t> data);
  void injectLeSecurityCommand(std::vector<uint8_t> data);
  void injectAclConnectionCommand(std::vector<uint8_t> data);
  void injectLeAclConnectionCommand(std::vector<uint8_t> data);
  void injectLeAdvertisingCommand(std::vector<uint8_t> data);
  void injectLeScanningCommand(std::vector<uint8_t> data);

  void ListDependencies(ModuleList* list) override {
    list->add<hci::HciLayer>();
@@ -53,8 +58,7 @@ class DevNullHci : public Module {
 private:
  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);
    TVIEW commandPacket = TVIEW::FromBytes(data);
    if (!commandPacket.IsValid()) {
      return;
    }
@@ -71,6 +75,13 @@ class DevNullHci : public Module {
  hci::HciLayer* hci_ = nullptr;
  os::fuzz::DevNullQueue<AclPacketView>* aclDevNull_;
  os::fuzz::FuzzInjectQueue<AclPacketBuilder>* aclInject_;

  SecurityInterface* security_interface_;
  LeSecurityInterface* le_security_interface_;
  AclConnectionInterface* acl_connection_interface_;
  LeAclConnectionInterface* le_acl_connection_interface_;
  LeAdvertisingInterface* le_advertising_interface_;
  LeScanningInterface* le_scanning_interface_;
};

}  // namespace fuzz
+28 −6
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ using bluetooth::hci::fuzz::DevNullHci;
using bluetooth::os::fuzz::fake_timerfd_advance;
using bluetooth::os::fuzz::fake_timerfd_reset;

static std::vector<uint8_t> GetArbitraryBytes(FuzzedDataProvider* fdp) {
  return fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegral<size_t>());
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  FuzzedDataProvider dataProvider(data, size);

@@ -43,25 +47,43 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  DevNullHci* devNullHci = moduleRegistry.GetModuleUnderTest<DevNullHci>();

  while (dataProvider.remaining_bytes() > 0) {
    const uint8_t action = dataProvider.ConsumeIntegralInRange(0, 6);
    const uint8_t action = dataProvider.ConsumeIntegralInRange(0, 12);
    switch (action) {
      case 1:
        fake_timerfd_advance(dataProvider.ConsumeIntegral<uint64_t>());
        break;
      case 2:
        fuzzHal->injectAclData(dataProvider.ConsumeBytes<uint8_t>(dataProvider.ConsumeIntegral<size_t>()));
        fuzzHal->injectAclData(GetArbitraryBytes(&dataProvider));
        break;
      case 3:
        fuzzHal->injectHciEvent(dataProvider.ConsumeBytes<uint8_t>(dataProvider.ConsumeIntegral<size_t>()));
        fuzzHal->injectHciEvent(GetArbitraryBytes(&dataProvider));
        break;
      case 4:
        fuzzHal->injectScoData(dataProvider.ConsumeBytes<uint8_t>(dataProvider.ConsumeIntegral<size_t>()));
        fuzzHal->injectScoData(GetArbitraryBytes(&dataProvider));
        break;
      case 5:
        devNullHci->injectAclData(dataProvider.ConsumeBytes<uint8_t>(dataProvider.ConsumeIntegral<size_t>()));
        devNullHci->injectAclData(GetArbitraryBytes(&dataProvider));
        break;
      case 6:
        devNullHci->injectHciCommand(dataProvider.ConsumeBytes<uint8_t>(dataProvider.ConsumeIntegral<size_t>()));
        devNullHci->injectHciCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 7:
        // TODO: devNullHci->injectSecurityCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 8:
        devNullHci->injectLeSecurityCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 9:
        devNullHci->injectAclConnectionCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 10:
        devNullHci->injectLeAclConnectionCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 11:
        devNullHci->injectLeAdvertisingCommand(GetArbitraryBytes(&dataProvider));
        break;
      case 12:
        devNullHci->injectLeScanningCommand(GetArbitraryBytes(&dataProvider));
        break;
    }
  }
+29 −29
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ void PacketDef::GenParserDefinition(std::ostream& s) const {
    s << "{ return " << name_ << "View(packet); }";
  }

  GenTestingParserFromBytes(s);

  std::set<std::string> fixed_types = {
      FixedScalarField::kFieldType,
      FixedEnumField::kFieldType,
@@ -88,6 +90,29 @@ void PacketDef::GenParserDefinition(std::ostream& s) const {
  s << "};\n";
}

void PacketDef::GenTestingParserFromBytes(std::ostream& s) const {
  s << "\n#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)\n";

  s << "static " << name_ << "View FromBytes(std::vector<uint8_t> bytes) {";
  s << "auto vec = std::make_shared<std::vector<uint8_t>>(bytes);";
  s << "return " << name_ << "View::Create(";
  auto ancestor_ptr = parent_;
  size_t parent_parens = 0;
  while (ancestor_ptr != nullptr) {
    s << ancestor_ptr->name_ << "View::Create(";
    parent_parens++;
    ancestor_ptr = ancestor_ptr->parent_;
  }
  s << "vec";
  for (size_t i = 0; i < parent_parens; i++) {
    s << ")";
  }
  s << ");";
  s << "}";

  s << "\n#endif\n";
}

void PacketDef::GenParserDefinitionPybind11(std::ostream& s) const {
  s << "py::class_<" << name_ << "View";
  if (parent_ != nullptr) {
@@ -412,20 +437,7 @@ void PacketDef::GenTestDefine(std::ostream& s) const {
  s << "class " << name_ << "ReflectionTest : public testing::TestWithParam<std::vector<uint8_t>> { ";
  s << "public: ";
  s << "void CompareBytes(std::vector<uint8_t> captured_packet) {";
  s << "auto vec = std::make_shared<std::vector<uint8_t>>(captured_packet.begin(), captured_packet.end());";
  s << name_ << "View view = " << name_ << "View::Create(";
  auto ancestor_ptr = parent_;
  size_t parent_parens = 0;
  while (ancestor_ptr != nullptr) {
    s << ancestor_ptr->name_ << "View::Create(";
    parent_parens++;
    ancestor_ptr = ancestor_ptr->parent_;
  }
  s << "vec";
  for (size_t i = 0; i < parent_parens; i++) {
    s << ")";
  }
  s << ");";
  s << name_ << "View view = " << name_ << "View::FromBytes(captured_packet);";
  s << "if (!view.IsValid()) { LOG_INFO(\"Invalid Packet Bytes (size = %zu)\", view.size());";
  s << "for (size_t i = 0; i < view.size(); i++) { LOG_DEBUG(\"%5zd:%02X\", i, *(view.begin() + i)); }}";
  s << "ASSERT_TRUE(view.IsValid());";
@@ -434,7 +446,7 @@ void PacketDef::GenTestDefine(std::ostream& s) const {
  s << "packet_bytes->reserve(packet->size());";
  s << "BitInserter it(*packet_bytes);";
  s << "packet->Serialize(it);";
  s << "ASSERT_EQ(*packet_bytes, *vec);";
  s << "ASSERT_EQ(*packet_bytes, captured_packet);";
  s << "}";
  s << "};";
  s << "TEST_P(" << name_ << "ReflectionTest, generatedReflectionTest) {";
@@ -449,20 +461,8 @@ void PacketDef::GenFuzzTestDefine(std::ostream& s) const {
  s << "#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING)\n";
  s << "#define DEFINE_" << name_ << "ReflectionFuzzTest() ";
  s << "void Run" << name_ << "ReflectionFuzzTest(const uint8_t* data, size_t size) {";
  s << "auto vec = std::make_shared<std::vector<uint8_t>>(data, data + size);";
  s << name_ << "View view = " << name_ << "View::Create(";
  auto ancestor_ptr = parent_;
  size_t parent_parens = 0;
  while (ancestor_ptr != nullptr) {
    s << ancestor_ptr->name_ << "View::Create(";
    parent_parens++;
    ancestor_ptr = ancestor_ptr->parent_;
  }
  s << "vec";
  for (size_t i = 0; i < parent_parens; i++) {
    s << ")";
  }
  s << ");";
  s << "auto vec = std::vector<uint8_t>(data, data + size);";
  s << name_ << "View view = " << name_ << "View::FromBytes(vec);";
  s << "if (!view.IsValid()) { return; }";
  s << "auto packet = " << name_ << "Builder::FromView(view);";
  s << "std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();";
Loading