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

Commit b6eaa507 authored by Chris Manton's avatar Chris Manton
Browse files

DO NOT MERGE Ensure hci command status event has sufficient packet length

Bug: 141618611
Test: net_test_hci_native

Change-Id: I70a318b05d7781ddf8f82d7922a8ee7afc8d2e9f
(cherry picked from commit 6e25c5d81c4a43c2794a605c9fc8a194f37889af)
parent 728f3045
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -77,3 +77,39 @@ cc_test {
        "libbt-protos-lite",
    ],
}

// HCI native unit tests for target
// ========================================================
cc_test {
    name: "net_test_hci_native",
    test_suites: ["device-tests"],
    defaults: ["fluoride_defaults"],
    host_supported: true,
    local_include_dirs: [
        "include",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs: [
        "test/hci_layer_test.cc",
        "test/other_stack_stub.cc",
    ],
    shared_libs: [
        "libcrypto",
        "liblog",
        "libprotobuf-cpp-lite",
    ],
    static_libs: [
        "libbt-common",
        "libbt-protos-lite",
        "libosi",
        "libosi-AllocationTestHarness",
    ],
    sanitize: {
        address: true,
        cfi: true,
        misc_undefined: ["bounds"],
    },
}
+7 −1
Original line number Diff line number Diff line
@@ -569,11 +569,12 @@ static bool filter_incoming_event(BT_HDR* packet) {
  waiting_command_t* wait_entry = NULL;
  uint8_t* stream = packet->data;
  uint8_t event_code;
  uint8_t length;
  int credits = 0;
  command_opcode_t opcode;

  STREAM_TO_UINT8(event_code, stream);
  STREAM_SKIP_UINT8(stream);  // Skip the parameter total length field
  STREAM_TO_UINT8(length, stream);

  if (event_code == HCI_COMMAND_COMPLETE_EVT) {
    STREAM_TO_UINT8(credits, stream);
@@ -601,6 +602,11 @@ static bool filter_incoming_event(BT_HDR* packet) {

    goto intercepted;
  } else if (event_code == HCI_COMMAND_STATUS_EVT) {
    if (length < (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint16_t))) {
      LOG_WARN(LOG_TAG, "%s Unexpected hci command status event length:%hhd",
               __func__, length);
      goto intercepted;
    }
    uint8_t status;
    STREAM_TO_UINT8(status, stream);
    STREAM_TO_UINT8(credits, stream);
+124 −0
Original line number Diff line number Diff line
/*
 * 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 <base/logging.h>
#include <gtest/gtest.h>
#include <stdint.h>

#include "common/message_loop_thread.h"
#include "hci/src/hci_layer.cc"
#include "hci_internals.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
#include "osi/test/AllocationTestHarness.h"
#include "osi/test/test_stubs.h"
#include "stack/include/bt_types.h"
#include "stack/include/hcidefs.h"

extern void allocation_tracker_uninit(void);

allocator_t buffer_allocator_ = {
    .alloc = osi_malloc,
    .free = osi_free,
};

void monitor_socket(int ctrl_fd, int fd) {
  LOG(INFO) << __func__ << " UNIMPLEMENTED";
}
void hci_initialize() { LOG(INFO) << __func__ << " UNIMPLEMENTED"; }
void hci_close() { LOG(INFO) << __func__ << " UNIMPLEMENTED"; }
void hci_transmit(BT_HDR* packet) { LOG(INFO) << __func__ << " UNIMPLEMENTED"; }
int hci_open_firmware_log_file() { return INVALID_FD; }
void hci_close_firmware_log_file(int fd) {}
void hci_log_firmware_debug_packet(int fd, BT_HDR* packet) {}
const allocator_t* buffer_allocator_get_interface() {
  return &buffer_allocator_;
}

/**
 * Test class to test selected functionality in hci/src/hci_layer.cc
 */
class HciLayerTest : public AllocationTestHarness {
 protected:
  void SetUp() override {
    AllocationTestHarness::SetUp();
    // Disable our allocation tracker to allow ASAN full range
    allocation_tracker_uninit();
    commands_pending_response = list_new(NULL);
    buffer_allocator = &buffer_allocator_;
  }

  void TearDown() override {
    list_free(commands_pending_response);
    AllocationTestHarness::TearDown();
  }

  BT_HDR* AllocateHciEventPacket(size_t packet_length) const {
    return AllocatePacket(packet_length, MSG_HC_TO_STACK_HCI_EVT);
  }

  uint8_t* GetPayloadPointer(BT_HDR* packet) const {
    return static_cast<uint8_t*>(packet->data);
  }

 private:
  BT_HDR* AllocatePacket(size_t packet_length, uint16_t event) const {
    BT_HDR* packet =
        static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
    packet->offset = 0;
    packet->len = packet_length;
    packet->layer_specific = 0;
    packet->event = MSG_HC_TO_STACK_HCI_EVT;
    return packet;
  }
};

TEST_F(HciLayerTest, FilterIncomingEvent) {
  {
    BT_HDR* packet = AllocateHciEventPacket(3);

    auto p = GetPayloadPointer(packet);
    *p++ = HCI_COMMAND_STATUS_EVT;
    *p++ = 0x0;  // length

    CHECK(filter_incoming_event(packet));
  }

  {
    BT_HDR* packet = AllocateHciEventPacket(3);

    auto p = GetPayloadPointer(packet);
    *p++ = HCI_COMMAND_STATUS_EVT;
    *p++ = 0x1;  // length
    *p++ = 0xff;

    CHECK(filter_incoming_event(packet));
  }

  {
    BT_HDR* packet = AllocateHciEventPacket(6);

    auto p = GetPayloadPointer(packet);
    *p++ = HCI_COMMAND_STATUS_EVT;
    *p++ = 0x04;  // length
    *p++ = 0x00;  // status
    *p++ = 0x01;  // credits
    *p++ = 0x34;  // opcode0
    *p++ = 0x12;  // opcode1

    CHECK(filter_incoming_event(packet));
  }
}
+45 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

/**
 * Gabeldorsche related legacy-only-stack-side expansion and support code.
 */
#include "base/bind.h"
#include "btcore/include/module.h"  // base::OnceClosure
#include "hci/include/btsnoop.h"
#include "hci/include/hci_layer.h"

const btsnoop_t* btsnoop_get_interface() { return nullptr; }
const packet_fragmenter_t* packet_fragmenter_get_interface() { return nullptr; }
base::MessageLoop* get_main_message_loop() { return nullptr; }

namespace bluetooth {
namespace bqr {

void DumpLmpLlMessage(uint8_t length, uint8_t* p_lmp_ll_message_event) {}
void DumpBtScheduling(unsigned char, unsigned char*) {}

}  // namespace bqr

namespace shim {

bool is_gd_shim_enabled() { return false; }
bool is_gd_stack_started_up() { return false; }
void Post(base::OnceClosure task) {}
const hci_t* hci_layer_get_interface() { return nullptr; }

}  // namespace shim
}  // namespace bluetooth