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

Commit fc449cb3 authored by Aditya Wazir's avatar Aditya Wazir
Browse files

Added codecserviceregistrant_fuzzer

Test: ./codecserviceregistrant_fuzzer
Bug: 189053747

Change-Id: I7f6d361d3b32243d722e1fab4d7f75f72d822950
parent 5322090d
Loading
Loading
Loading
Loading
+37 −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_fuzz {
    name: "codecServiceRegistrant_fuzzer",
    srcs: [
        "codecServiceRegistrant_fuzzer.cpp",
    ],
    static_libs: [
        "libmedia_codecserviceregistrant",
    ],
    header_libs: [
        "libmedia_headers",
    ],
    defaults: [
        "libcodec2-hidl-defaults",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}
+56 −0
Original line number Diff line number Diff line
# Fuzzer for libmedia_codecserviceregistrant

## Plugin Design Considerations
The fuzzer plugin for libmedia_codecserviceregistrant is designed based on the understanding of the library and tries to achieve the following:

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

libmedia_codecserviceregistrant supports the following parameters:
1. C2String (parameter name: `c2String`)
2. Width (parameter name: `width`)
3. Height (parameter name: `height`)
4. SamplingRate (parameter name: `samplingRate`)
5. Channels (parameter name: `channels`)
6. Stream (parameter name: `stream`)

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
| `c2String` |`String` | Value obtained from FuzzedDataProvider|
| `width` |`UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
| `height` |`UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
| `samplingRate` |`UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
| `channels` |`UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
| `stream` |`UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|

This also ensures that the plugin is always deterministic for any given input.

##### Maximize utilization of input data
The plugin feeds the entire input data to the libmedia_codecserviceregistrant module.
This ensures that the plugin tolerates any kind of input (empty, huge,
malformed, etc) and doesnt `exit()` on any input and thereby increasing the
chance of identifying vulnerabilities.

## Build

This describes steps to build codecServiceRegistrant_fuzzer binary.

### Android

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

To run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/${TARGET_ARCH}/codecServiceRegistrant_fuzzer/codecServiceRegistrant_fuzzer
```

## References:
 * http://llvm.org/docs/LibFuzzer.html
 * https://github.com/google/oss-fuzz
+155 −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 "../CodecServiceRegistrant.cpp"
#include "fuzzer/FuzzedDataProvider.h"
#include <C2Config.h>
#include <C2Param.h>

using namespace std;

constexpr char kServiceName[] = "software";

class CodecServiceRegistrantFuzzer {
public:
  void process(const uint8_t *data, size_t size);
  ~CodecServiceRegistrantFuzzer() {
    delete mH2C2;
    if (mInputSize) {
      delete mInputSize;
    }
    if (mSampleRateInfo) {
      delete mSampleRateInfo;
    }
    if (mChannelCountInfo) {
      delete mChannelCountInfo;
    }
  }

private:
  void initH2C2ComponentStore();
  void invokeH2C2ComponentStore();
  void invokeConfigSM();
  void invokeQuerySM();
  H2C2ComponentStore *mH2C2 = nullptr;
  C2StreamPictureSizeInfo::input *mInputSize = nullptr;
  C2StreamSampleRateInfo::output *mSampleRateInfo = nullptr;
  C2StreamChannelCountInfo::output *mChannelCountInfo = nullptr;
  C2Param::Index mIndex = C2StreamProfileLevelInfo::output::PARAM_TYPE;
  C2StreamFrameRateInfo::output mFrameRate;
  FuzzedDataProvider *mFDP = nullptr;
};

void CodecServiceRegistrantFuzzer::initH2C2ComponentStore() {
  using namespace ::android::hardware::media::c2;
  shared_ptr<C2ComponentStore> store =
      android::GetCodec2PlatformComponentStore();
  if (!store) {
    return;
  }
  android::sp<V1_1::IComponentStore> storeV1_1 =
      new V1_1::utils::ComponentStore(store);
  if (storeV1_1->registerAsService(string(kServiceName)) != android::OK) {
    return;
  }
  string const preferredStoreName = string(kServiceName);
  sp<IComponentStore> preferredStore =
      IComponentStore::getService(preferredStoreName.c_str());
  mH2C2 = new H2C2ComponentStore(preferredStore);
}

void CodecServiceRegistrantFuzzer::invokeConfigSM() {
  vector<C2Param *> configParams;
  uint32_t width = mFDP->ConsumeIntegral<uint32_t>();
  uint32_t height = mFDP->ConsumeIntegral<uint32_t>();
  uint32_t samplingRate = mFDP->ConsumeIntegral<uint32_t>();
  uint32_t channels = mFDP->ConsumeIntegral<uint32_t>();
  if (mFDP->ConsumeBool()) {
    mInputSize = new C2StreamPictureSizeInfo::input(0u, width, height);
    configParams.push_back(mInputSize);
  } else {
    if (mFDP->ConsumeBool()) {
      mSampleRateInfo = new C2StreamSampleRateInfo::output(0u, samplingRate);
      configParams.push_back(mSampleRateInfo);
    }
    if (mFDP->ConsumeBool()) {
      mChannelCountInfo = new C2StreamChannelCountInfo::output(0u, channels);
      configParams.push_back(mChannelCountInfo);
    }
  }
  vector<unique_ptr<C2SettingResult>> failures;
  mH2C2->config_sm(configParams, &failures);
}

void CodecServiceRegistrantFuzzer::invokeQuerySM() {
  vector<C2Param *> stackParams;
  vector<C2Param::Index> heapParamIndices;
  if (mFDP->ConsumeBool()) {
    stackParams = {};
    heapParamIndices = {};
  } else {
    uint32_t stream = mFDP->ConsumeIntegral<uint32_t>();
    mFrameRate.setStream(stream);
    stackParams.push_back(&mFrameRate);
    heapParamIndices.push_back(mIndex);
  }
  vector<unique_ptr<C2Param>> heapParams;
  mH2C2->query_sm(stackParams, heapParamIndices, &heapParams);
}

void CodecServiceRegistrantFuzzer::invokeH2C2ComponentStore() {
  initH2C2ComponentStore();
  shared_ptr<C2Component> component;
  shared_ptr<C2ComponentInterface> interface;
  string c2String = mFDP->ConsumeRandomLengthString();
  mH2C2->createComponent(c2String, &component);
  mH2C2->createInterface(c2String, &interface);
  invokeConfigSM();
  invokeQuerySM();

  vector<shared_ptr<C2ParamDescriptor>> params;
  mH2C2->querySupportedParams_nb(&params);

  C2StoreIonUsageInfo usageInfo;
  std::vector<C2FieldSupportedValuesQuery> query = {
      C2FieldSupportedValuesQuery::Possible(
          C2ParamField::Make(usageInfo, usageInfo.usage)),
      C2FieldSupportedValuesQuery::Possible(
          C2ParamField::Make(usageInfo, usageInfo.capacity)),
  };
  mH2C2->querySupportedValues_sm(query);

  mH2C2->getName();
  mH2C2->getParamReflector();
  mH2C2->listComponents();
  shared_ptr<C2GraphicBuffer> src;
  shared_ptr<C2GraphicBuffer> dst;
  mH2C2->copyBuffer(src, dst);
}

void CodecServiceRegistrantFuzzer::process(const uint8_t *data, size_t size) {
  mFDP = new FuzzedDataProvider(data, size);
  invokeH2C2ComponentStore();
  /** RegisterCodecServices is called here to improve code coverage */
  /** as currently it is not called by codecServiceRegistrant       */
  RegisterCodecServices();
  delete mFDP;
}

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