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

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

Merge "Added fuzzers for libbt-audio-hal-interface"

parents 506ed817 1364509d
Loading
Loading
Loading
Loading
+135 −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: "libbt_audio_hal_interface_fuzz_defaults",
    header_libs: [
        "avrcp_headers",
        "libbluetooth_headers",
    ],
    shared_libs: [
        "libz",
        "libfmq",
        "libaaudio",
        "libcrypto",
        "libstatslog",
        "libbinder_ndk",
        "libstatssocket",
        "android.hardware.bluetooth@1.0",
        "android.hardware.bluetooth@1.1",
        "android.hardware.bluetooth.a2dp@1.0",
        "android.hardware.bluetooth.audio@2.0",
        "android.hardware.bluetooth.audio@2.1",
        "android.hardware.bluetooth.audio@2.2",
        "android.system.suspend.control-V1-ndk",
    ],
    static_libs: [
        "libbte",
        "liblog",
        "libosi",
        "libbtif",
        "libbase",
        "libutils",
        "libevent",
        "libcutils",
        "libchrome",
        "libbtcore",
        "libbt-bta",
        "libbt-hci",
        "libjsoncpp",
        "libbt-utils",
        "libbtdevice",
        "libcgrouprc",
        "libhidlbase",
        "libbt-stack",
        "libg722codec",
        "libudrv-uipc",
        "libbt-common",
        "liblc3codec",
        "liblc3",
        "libstatslog_bt",
        "libvndksupport",
        "libprocessgroup",
        "libbluetooth_gd",
        "libFraunhoferAAC",
        "libbt-sbc-decoder",
        "libbt-sbc-encoder",
        "libcgrouprc_format",
        "libbluetooth-types",
        "libbluetooth-protos",
        "libbluetooth-dumpsys",
        "libprotobuf-cpp-lite",
        "libbt-audio-hal-interface",
        "libbluetooth_rust_interop",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/gd",
        "packages/modules/Bluetooth/system/btif",
        "packages/modules/Bluetooth/system/gd/rust/shim",
        "packages/modules/Bluetooth/system/stack/include",
        "packages/modules/Bluetooth/system/bta/include",
    ],
    cflags: [
        "-DHAS_NO_BDROID_BUILDCFG",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}

cc_fuzz {
    name: "libbt_audio_hal_a2dp_encoding_fuzzer",
    defaults: [
        "libbt_audio_hal_interface_fuzz_defaults",
    ],
    srcs: [
        "libbt_audio_hal_a2dp_encoding_fuzzer.cpp",
    ],
}

cc_fuzz {
    name: "libbt_audio_hal_le_audio_software_fuzzer",
    defaults: [
        "libbt_audio_hal_interface_fuzz_defaults",
    ],
    srcs: [
        "libbt_audio_hal_le_audio_software_fuzzer.cpp",
    ],
}

cc_fuzz {
    name: "libbt_audio_hal_hearing_aid_software_encoding_fuzzer",
    defaults: [
        "libbt_audio_hal_interface_fuzz_defaults",
    ],
    srcs: [
        "libbt_audio_hal_hearing_aid_software_encoding_fuzzer.cpp",
    ],
}

cc_fuzz {
    name: "libbt_audio_hal_client_interface_fuzzer",
    defaults: [
        "libbt_audio_hal_interface_fuzz_defaults",
    ],
    srcs: [
        "libbt_audio_hal_client_interface_fuzzer.cpp",
    ],
}
+92 −0
Original line number Diff line number Diff line
# Fuzzers for libbt-audio-hal-interface

## Plugin Design Considerations
The fuzzer plugins for `libbt-audio-hal-interface` 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 libbt-audio-hal-interface:
1. A2DP Control Ack Status (parameter name: `status`)
2. A2DP supported codecs (parameter name: `index`)
3. Session Type  (parameter name: `sessionType`)
4. Session Type V2_1 (parameter name: `sessionType_2_1`)
5. Sample Rates (parameter name: `param.sampleRate`)
6. Sample Rates V2_1 (parameter name: `param.sampleRate`)
7. BTAV Sample Rates (parameter name: `a2dpCodecConfig.sample_rate`)
8. Bits per Sample (parameter name: `param.bitsPerSample`)
9. BTAV A2DP Codec Bits per Sample (parameter name: `a2dpCodecConfig.bits_per_sample`)
10. Channel Mode (parameter name: `param.channelMode`)
11. A2DP Codec Channel Mode (parameter name: `a2dpCodecConfig.channel_mode`)
12. Sbc Subbands (parameter name: `sbc.numSubbands`)
13. Sbc alloc methods (parameter name: `sbc.allocMethod `)
14. Sbc Channel mode (parameter name: `sbc.channelMode `)
15. Sbc Block Length (parameter name: `sbc.blockLength `)
16. Aac Object Type  (parameter name: `aac.objectType`)
17. Aac Variable Bit Rate (parameter name: `aac.variableBitRateEnabled`)
18. Ldac Quality Index (parameter name: `ldac.qualityIndex`)
19. Ldac Channel Mode (parameter name: `ldac.channelMode`)
20. Codec Type (parameter name: `codecConfig.codecType`)

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
| `status` | 0.`A2DP_CTRL_ACK_SUCCESS` 1.`A2DP_CTRL_ACK_FAILURE` 2.`A2DP_CTRL_ACK_INCALL_FAILURE` 3.`A2DP_CTRL_ACK_UNSUPPORTED` 4.`A2DP_CTRL_ACK_PENDING` 5.`A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS` | Value obtained from FuzzedDataProvider |
| `index` | 0.`BTAV_A2DP_CODEC_INDEX_SOURCE_SBC` 1.`BTAV_A2DP_CODEC_INDEX_SOURCE_AAC` 2.`BTAV_A2DP_CODEC_INDEX_SOURCE_APTX` 3.`BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD` 4.`BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC` 5.`BTAV_A2DP_CODEC_INDEX_SINK_SBC` 6.`BTAV_A2DP_CODEC_INDEX_SINK_AAC` 7.`BTAV_A2DP_CODEC_INDEX_SINK_LDAC` | Value obtained from FuzzedDataProvider |
| `sessionType` | 0.`SessionType::UNKNOWN` 1.`SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH` 2.`SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH` 3.`SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH` | Value obtained from FuzzedDataProvider |
| `sessionType_2_1` | 0.`SessionType_2_1::UNKNOWN` 1.`SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH` 2.`SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH` 3.`SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH` 4.`SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH` 5.`SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH` 6.`SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH` 7.`SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH` | Value obtained from FuzzedDataProvider |
| `param.sampleRate` | 0.`SampleRate::RATE_UNKNOWN` 1.`SampleRate::RATE_8000` 2.`SampleRate::RATE_16000` 3.`SampleRate::RATE_24000` 4.`SampleRate::RATE_32000` 5.`SampleRate::RATE_44100` 6.`SampleRate::RATE_48000` | Value obtained from FuzzedDataProvider |
| `param.sampleRate (V2_1)` | 0.`SampleRate_2_1::RATE_UNKNOWN` 1.`SampleRate_2_1::RATE_8000` 2.`SampleRate_2_1::RATE_16000` 3.`SampleRate_2_1::RATE_24000` 4.`SampleRate_2_1::RATE_32000` 5.`SampleRate_2_1::RATE_44100` 6.`SampleRate_2_1::RATE_48000` | Value obtained from FuzzedDataProvider |
| `a2dpCodecConfig.sample_rate` | 0.`BTAV_A2DP_CODEC_SAMPLE_RATE_NONE` 1.`BTAV_A2DP_CODEC_SAMPLE_RATE_44100` 2.`BTAV_A2DP_CODEC_SAMPLE_RATE_48000` 3.`BTAV_A2DP_CODEC_SAMPLE_RATE_88200` 4.`BTAV_A2DP_CODEC_SAMPLE_RATE_96000` 5.`BTAV_A2DP_CODEC_SAMPLE_RATE_176400` 6.`BTAV_A2DP_CODEC_SAMPLE_RATE_192000` 7.`BTAV_A2DP_CODEC_SAMPLE_RATE_16000` 8.`BTAV_A2DP_CODEC_SAMPLE_RATE_24000` | Value obtained from FuzzedDataProvider |
| `param.bitsPerSample` | 0.`BitsPerSample::BITS_UNKNOWN` 1.`BitsPerSample::BITS_16` 2.`BitsPerSample::BITS_24` 3.`BitsPerSample::BITS_32` | Value obtained from FuzzedDataProvider |
| `a2dpCodecConfig.bits_per_sample` | 0.`BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE` 1.`BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16` 2.`BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24` 3.`BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32` | Value obtained from FuzzedDataProvider |
| `param.channelMode` | 0.`ChannelMode::UNKNOWN` 1.`ChannelMode::MONO` 2.`ChannelMode::STEREO`  | Value obtained from FuzzedDataProvider |
| `a2dpCodecConfig.channel_mode` | 0.`BTAV_A2DP_CODEC_CHANNEL_MODE_NONE` 1.`BTAV_A2DP_CODEC_CHANNEL_MODE_MONO` 2.`BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO`  | Value obtained from FuzzedDataProvider |
| `param.peerMtu` | 0.`660` 1.`663` 2.`883` 3.`1005` 4.`1500`  | Value obtained from FuzzedDataProvider |
| `sbc.numSubbands` | 0.`SbcNumSubbands::SUBBAND_4` 1.`SbcNumSubbands::SUBBAND_8` | Value obtained from FuzzedDataProvider |
| `sbc.allocMethod` | 0.`SbcAllocMethod::ALLOC_MD_S` 1.`SbcAllocMethod::ALLOC_MD_L` | Value obtained from FuzzedDataProvider |
| `sbc.channelMode ` | 0.`SbcChannelMode::UNKNOWN` 1.`SbcChannelMode::JOINT_STEREO` 2.`SbcChannelMode::STEREO` 3.`SbcChannelMode::DUAL` 4.`SbcChannelMode::MONO`  | Value obtained from FuzzedDataProvider |
| `sbc.blockLength ` | 0.`SbcBlockLength::BLOCKS_4` 1.`SbcBlockLength::BLOCKS_8` 2.`SbcBlockLength::BLOCKS_12` 3.`SbcBlockLength::BLOCKS_16` | Value obtained from FuzzedDataProvider |
| `aac.objectType` | 0.`AacObjectType::MPEG2_LC` 1.`AacObjectType::MPEG4_LC` 2.`AacObjectType::MPEG4_LTP` 3.`AacObjectType::MPEG4_SCALABLE` | Value obtained from FuzzedDataProvider |
| `aac.variableBitRateEnabled` | 0.`AacVariableBitRate::DISABLED` 1.`AacVariableBitRate::ENABLED` | Value obtained from FuzzedDataProvider |
| `ldac.qualityIndex` | 0.`LdacQualityIndex::QUALITY_HIGH` 1.`LdacQualityIndex::QUALITY_MID` 2.`LdacQualityIndex::QUALITY_LOW` 3.`LdacQualityIndex::QUALITY_ABR` | Value obtained from FuzzedDataProvider |
| `ldac.channelMode ` | 0.`LdacChannelMode::UNKNOWN` 1.`LdacChannelMode::STEREO` 2.`LdacChannelMode::DUAL` 3.`LdacChannelMode::MONO` | Value obtained from FuzzedDataProvider |
| `codecConfig.codecType` | 0.`CodecType::APTX` 1.`CodecType::APTX_HD` | 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 libbt_audio_hal_a2dp_encoding_fuzzer, libbt_audio_hal_le_audio_software_fuzzer, libbt_audio_hal_hearing_aid_software_encoding_fuzzer and libbt_audio_hal_client_interface_fuzzer binaries.

### Android

#### Steps to build
Build the fuzzer
```
  $ mm -j$(nproc) libbt_audio_hal_a2dp_encoding_fuzzer
  $ mm -j$(nproc) libbt_audio_hal_le_audio_software_fuzzer
  $ mm -j$(nproc) libbt_audio_hal_hearing_aid_software_encoding_fuzzer
  $ mm -j$(nproc) libbt_audio_hal_client_interface_fuzzer
```
### Steps to run

To run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/libbt_audio_hal_a2dp_encoding_fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer
  $ adb shell /data/fuzz/arm64/libbt_audio_hal_le_audio_software_fuzzer/libbt_audio_hal_le_audio_software_fuzzer
  $ adb shell /data/fuzz/arm64/libbt_audio_hal_hearing_aid_software_encoding_fuzzer/libbt_audio_hal_hearing_aid_software_encoding_fuzzer
  $ adb shell /data/fuzz/arm64/libbt_audio_hal_client_interface_fuzzer/libbt_audio_hal_client_interface_fuzzer
```

## References:
 * http://llvm.org/docs/LibFuzzer.html
 * https://github.com/google/oss-fuzz
+116 −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 "audio_hal_interface/a2dp_encoding.h"
#include "include/btif_av.h"
#include "include/btif_av_co.h"
#include "osi/include/properties.h"

using ::bluetooth::audio::a2dp::update_codec_offloading_capabilities;

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

constexpr tA2DP_CTRL_ACK kCtrlAckStatus[] = {
    A2DP_CTRL_ACK_SUCCESS,        A2DP_CTRL_ACK_FAILURE,
    A2DP_CTRL_ACK_INCALL_FAILURE, A2DP_CTRL_ACK_UNSUPPORTED,
    A2DP_CTRL_ACK_PENDING,        A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS};

constexpr int32_t kRandomStringLength = 256;

static void source_init_delayed(void) {}

constexpr btav_a2dp_codec_index_t kCodecIndices[] = {
    BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,  BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
    BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
    BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, BTAV_A2DP_CODEC_INDEX_SINK_SBC,
    BTAV_A2DP_CODEC_INDEX_SINK_AAC,    BTAV_A2DP_CODEC_INDEX_SINK_LDAC};

std::vector<std::vector<btav_a2dp_codec_config_t>>
CodecOffloadingPreferenceGenerator() {
  std::vector<std::vector<btav_a2dp_codec_config_t>> offloadingPreferences = {
      std::vector<btav_a2dp_codec_config_t>(0)};
  btav_a2dp_codec_config_t btavCodecConfig = {};
  for (btav_a2dp_codec_index_t i : kCodecIndices) {
    btavCodecConfig.codec_type = i;
    auto duplicated_preferences = offloadingPreferences;
    for (auto iter = duplicated_preferences.begin();
         iter != duplicated_preferences.end(); ++iter) {
      iter->push_back(btavCodecConfig);
    }
    offloadingPreferences.insert(offloadingPreferences.end(),
                                 duplicated_preferences.begin(),
                                 duplicated_preferences.end());
  }
  return offloadingPreferences;
}

class A2dpEncodingFuzzer {
 public:
  ~A2dpEncodingFuzzer() {
    delete (mCodec);
    mCodec = nullptr;
  }
  void process(const uint8_t* data, size_t size);
  static A2dpCodecConfig* mCodec;
};

A2dpCodecConfig* A2dpEncodingFuzzer::mCodec{nullptr};

void A2dpEncodingFuzzer::process(const uint8_t* data, size_t size) {
  FuzzedDataProvider fdp(data, size);
  if (!mCodec) {
    mCodec = A2dpCodecConfig::createCodec(fdp.PickValueInArray(kCodecIndices));
  }

  osi_property_set("persist.bluetooth.a2dp_offload.disabled",
                   fdp.PickValueInArray({"true", "false"}));

  std::string name = fdp.ConsumeRandomLengthString(kRandomStringLength);
  bluetooth::common::MessageLoopThread messageLoopThread(name);
  messageLoopThread.StartUp();
  messageLoopThread.DoInThread(FROM_HERE, base::Bind(&source_init_delayed));

  uint16_t delayReport = fdp.ConsumeIntegral<uint16_t>();
  bluetooth::audio::a2dp::set_remote_delay(delayReport);

  (void)bluetooth::audio::a2dp::init(&messageLoopThread);
  (void)bluetooth::audio::a2dp::setup_codec();
  bluetooth::audio::a2dp::start_session();

  tA2DP_CTRL_ACK status = fdp.PickValueInArray(kCtrlAckStatus);
  bluetooth::audio::a2dp::ack_stream_started(status);

  for (auto offloadingPreference : CodecOffloadingPreferenceGenerator()) {
    update_codec_offloading_capabilities(offloadingPreference);
  }
  status = fdp.PickValueInArray(kCtrlAckStatus);
  bluetooth::audio::a2dp::ack_stream_suspended(status);
  bluetooth::audio::a2dp::cleanup();
  messageLoopThread.ShutDown();
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  A2dpEncodingFuzzer a2dpEncodingFuzzer;
  a2dpEncodingFuzzer.process(data, size);
  return 0;
}
+471 −0

File added.

Preview size limit exceeded, changes collapsed.

+47 −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 "audio_hal_interface/hearing_aid_software_encoding.h"
#include "osi/include/properties.h"

constexpr int32_t kRandomStringLength = 256;

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

static void source_init_delayed(void) {}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  FuzzedDataProvider fdp(data, size);
  osi_property_set("persist.bluetooth.a2dp_offload.disabled",
                   fdp.PickValueInArray({"true", "false"}));
  std::string name = fdp.ConsumeRandomLengthString(kRandomStringLength);
  bluetooth::common::MessageLoopThread messageLoopThread(name);
  messageLoopThread.StartUp();
  messageLoopThread.DoInThread(FROM_HERE, base::Bind(&source_init_delayed));

  uint16_t delay = fdp.ConsumeIntegral<uint16_t>();
  bluetooth::audio::hearing_aid::set_remote_delay(delay);

  messageLoopThread.ShutDown();
  return 0;
}
Loading