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

Commit 27378ad9 authored by Kris Alder's avatar Kris Alder Committed by Gerrit Code Review
Browse files

Merge "Added fuzzers for libbtcore"

parents 9005389e a22123f8
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.
 */

cc_defaults {
    name: "btcore_fuzz_defaults",
    shared_libs: [
        "libcrypto",
        "libstatslog",
        "libbluetooth",
        "android.hardware.bluetooth@1.0",
        "android.hardware.bluetooth@1.1",
    ],
    static_libs: [
        "libosi",
        "liblog",
        "libbase",
        "libevent",
        "libutils",
        "libbtcore",
        "libchrome",
        "libmodpb64",
        "libhidlbase",
        "libvndksupport",
        "libbt-common",
        "libbluetooth-types",
        "libbluetooth-protos",
        "libprotobuf-cpp-lite",
        "libbluetooth_rust_interop",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/gd/rust/shim",
    ],
    header_libs: [
        "libbluetooth_headers",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}

cc_fuzz {
    name: "btcore_device_class_fuzzer",
    defaults: [
        "btcore_fuzz_defaults",
    ],
    srcs: [
        "btcore_device_class_fuzzer.cpp",
    ],
}

cc_fuzz {
    name: "btcore_property_fuzzer",
    defaults: [
        "btcore_fuzz_defaults",
    ],
    srcs: [
        "btcore_property_fuzzer.cpp",
    ],

}

cc_fuzz {
    name: "btcore_module_fuzzer",
    defaults: [
        "btcore_fuzz_defaults",
    ],
    srcs: [
        "btcore_module_fuzzer.cpp",
    ],
}
+56 −0
Original line number Diff line number Diff line
# Fuzzers for libbtcore

## Plugin Design Considerations
The fuzzer plugins for `libbtcore` are designed based on the understanding of the
source code and tries to achieve the following:

##### Maximize code coverage
The configuration parameters are not hard-coded, but instead selected based on
incoming data. This ensures more code paths are reached by the fuzzers.

Fuzzers assigns values to the following parameters to pass on to libbtcore:
1. Bluetooth Device Type (parameter name: `deviceType`)
2. Bluetooth Adapter Visibility Mode (parameter name: `mode`)
3. Bluetooth Address (parameter name: `btAddress`)
4. Bluetooth Device Class parameter (parameter name: `deviceClassT`)

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
| `deviceType` | 0.`BT_DEVICE_DEVTYPE_BREDR` 1.`BT_DEVICE_DEVTYPE_BLE` 2.`BT_DEVICE_DEVTYPE_DUAL` | Value obtained from FuzzedDataProvider |
| `mode` | 0.`BT_SCAN_MODE_NONE` 1.`BT_SCAN_MODE_CONNECTABLE` 2.`BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE` | Value obtained from FuzzedDataProvider |
| `btAddress` | Values inside array ranges from `0x0` to `0xFF` | Value obtained from FuzzedDataProvider |
| `deviceClassT` | Values inside array ranges from `0x0` to `0xFF` | Value obtained from FuzzedDataProvider |
This also ensures that the plugins are always deterministic for any given input.

##### Maximize utilization of input data
The plugins feed the entire input data to the module.
This ensures that the plugins tolerates any kind of input (empty, huge,
malformed, etc) and doesn't `exit()` on any input and thereby increasing the
chance of identifying vulnerabilities.

## Build

This describes steps to build btcore_device_class_fuzzer, btcore_property_fuzzer and btcore_module_fuzzer binaries.

### Android

#### Steps to build
Build the fuzzer
```
  $ mm -j$(nproc) btcore_device_class_fuzzer
  $ mm -j$(nproc) btcore_property_fuzzer
  $ mm -j$(nproc) btcore_module_fuzzer
```
### Steps to run

To run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/btcore_device_class_fuzzer/btcore_device_class_fuzzer
  $ adb shell /data/fuzz/arm64/btcore_property_fuzzer/btcore_property_fuzzer
  $ adb shell /data/fuzz/arm64/btcore_module_fuzzer/btcore_module_fuzzer
```

## References:
 * http://llvm.org/docs/LibFuzzer.html
 * https://github.com/google/oss-fuzz
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 <fuzzer/FuzzedDataProvider.h>
#include "btcore/include/device_class.h"

class BTCoreDeviceClassFuzzer {
 public:
  void process(const uint8_t* data, size_t size);

 private:
  std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
};

void BTCoreDeviceClassFuzzer::process(const uint8_t* data, size_t size) {
  mFdp = std::make_unique<FuzzedDataProvider>(data, size);
  size_t dcStreamSize = sizeof(bt_device_class_t) * sizeof(uint8_t);

  std::vector<uint8_t> dcStreamSrc(dcStreamSize, 0x0);
  mFdp->ConsumeData(dcStreamSrc.data(), dcStreamSize);

  bt_device_class_t deviceClass;
  device_class_from_stream(&deviceClass, dcStreamSrc.data());

  std::vector<uint8_t> dcStreamDst(dcStreamSize, 0x0);
  (void)device_class_to_stream(&deviceClass, dcStreamDst.data(), dcStreamSize);

  device_class_set_limited(&deviceClass, mFdp->ConsumeBool());
  (void)device_class_get_limited(&deviceClass);

  int val = mFdp->ConsumeIntegral<int>();
  device_class_set_major_device(&deviceClass, val);
  (void)device_class_get_major_device(&deviceClass);

  val = mFdp->ConsumeIntegral<int>();
  device_class_set_minor_device(&deviceClass, val);
  (void)device_class_get_minor_device(&deviceClass);

  device_class_set_information(&deviceClass, mFdp->ConsumeBool());
  (void)device_class_get_information(&deviceClass);

  bt_device_class_t deviceClassCopy;
  (void)device_class_copy(&deviceClassCopy, &deviceClass);
  (void)device_class_equals(&deviceClass, &deviceClassCopy);

  val = mFdp->ConsumeIntegralInRange(1, INT_MAX);
  device_class_from_int(&deviceClass, val);
  (void)device_class_to_int(&deviceClass);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  BTCoreDeviceClassFuzzer btCoreDeviceClassFuzzer;
  btCoreDeviceClassFuzzer.process(data, size);
  return 0;
}
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 "btcore/include/hal_util.h"
#include "btcore/include/module.h"

extern const module_t osi_module;

extern "C" {
struct android_namespace_t* android_get_exported_namespace(const char*) {
  return nullptr;
}
}

class BTCoreModuleFuzzer {
 public:
  void process();
};

void BTCoreModuleFuzzer::process() {
  const bt_interface_t* interface;
  (void)hal_util_load_bt_library(&interface);
  module_management_start();
  module_init(&osi_module);
  (void)module_start_up(&osi_module);
  (void)get_module(osi_module.name);
  module_shut_down(&osi_module);
  module_clean_up(&osi_module);
  module_management_stop();
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t*, size_t) {
  BTCoreModuleFuzzer btCoreModuleFuzzer;
  btCoreModuleFuzzer.process();
  return 0;
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 <fuzzer/FuzzedDataProvider.h>
#include "btcore/include/property.h"

using bluetooth::Uuid;

constexpr int32_t kRandomStringLength = 256;

class BTCorePropertyFuzzer {
 public:
  void process(const uint8_t* data, size_t size);

 private:
  std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
};

void BTCorePropertyFuzzer::process(const uint8_t* data, size_t size) {
  mFdp = std::make_unique<FuzzedDataProvider>(data, size);
  uint8_t addr[RawAddress::kLength];
  mFdp->ConsumeData(addr, sizeof(uint8_t) * RawAddress::kLength);
  RawAddress btAddress = {addr};
  bt_property_t* property = property_new_addr(&btAddress);
  property_as_addr(property);
  property_free(property);

  bt_device_class_t deviceClass = {{mFdp->ConsumeIntegral<uint8_t>(),
                                    mFdp->ConsumeIntegral<uint8_t>(),
                                    mFdp->ConsumeIntegral<uint8_t>()}};
  property = property_new_device_class(&deviceClass);

  const bt_device_class_t* pDeviceClass = property_as_device_class(property);
  (void)device_class_to_int(pDeviceClass);
  property_free(property);

  bt_device_type_t deviceType =
      (bt_device_type_t)(mFdp->ConsumeIntegral<uint32_t>());
  property = property_new_device_type(deviceType);
  (void)property_as_device_type(property);
  property_free(property);

  uint32_t timeout = mFdp->ConsumeIntegral<uint32_t>();
  property = property_new_discovery_timeout(timeout);
  (void)property_as_discovery_timeout(property);
  property_free(property);

  std::string name = mFdp->ConsumeRandomLengthString(kRandomStringLength);
  property = property_new_name(name.c_str());
  (void)property_as_name(property);
  property_free(property);

  int8_t rssi = mFdp->ConsumeIntegral<int8_t>();
  property = property_new_rssi(rssi);
  (void)property_as_rssi(property);
  property_free(property);

  bt_scan_mode_t mode = (bt_scan_mode_t)(mFdp->ConsumeIntegral<uint32_t>());
  property = property_new_scan_mode(mode);
  (void)property_as_scan_mode(property);
  property_free(property);

  size_t uuidSize = sizeof(uint8_t) * bluetooth::Uuid::kNumBytes128;
  uint8_t uuid[bluetooth::Uuid::kNumBytes128];
  mFdp->ConsumeData(uuid, uuidSize);
  Uuid uuidBE = Uuid::From128BitBE(uuid);
  property = property_new_uuids(&uuidBE, 1);
  size_t uuidCount;
  (void)property_as_uuids(property, &uuidCount);
  property_free(property);

  mFdp->ConsumeData(uuid, uuidSize);
  Uuid uuidLE = Uuid::From128BitLE(uuid);
  Uuid uuids[] = {uuidBE, uuidLE};
  bt_property_t* propertySrc = property_new_uuids(uuids, std::size(uuids));
  bt_property_t propertyDest;
  (void)property_copy(&propertyDest, propertySrc);
  property_free(propertySrc);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  BTCorePropertyFuzzer btCorePropertyFuzzer;
  btCorePropertyFuzzer.process(data, size);
  return 0;
}