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

Commit 36a8fb38 authored by Kris Alder's avatar Kris Alder Committed by Automerger Merge Worker
Browse files

Merge "Added cmd_fuzzer" am: 9435528c

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1730544

Change-Id: I1800381836b3db050bec1d9312a7a316f7172c55
parents 97f85756 9435528c
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: "cmd_fuzzer",
    srcs: [
        "cmd_fuzzer.cpp",
    ],
    static_libs: [
        "libcmd",
        "libutils",
        "liblog",
        "libselinux",
    ],
    shared_libs: [
        "libbinder",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}
+51 −0
Original line number Diff line number Diff line
# Fuzzer for libcmd_fuzzer

## Plugin Design Considerations
The fuzzer plugin for libcmd 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.

libcmd supports the following parameters:
1. In (parameter name: `in`)
2. Out (parameter name: `out`)
3. Err (parameter name: `err`)
4. Run Mode (parameter name: `runMode`)

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
| `in` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider|
| `out` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider|
| `err` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider|
| `runMode` | 1.`RunMode::kStandalone` 2. `RunMode::kLibrary` | Value chosen from valid values using 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 cmd 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 cmd_fuzzer binary.

### Android

#### Steps to build
Build the fuzzer
```
  $ mm -j$(nproc) cmd_fuzzer
```
#### Steps to run
To run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/${TARGET_ARCH}/cmd_fuzzer/cmd_fuzzer
```

## References:
 * http://llvm.org/docs/LibFuzzer.html
 * https://github.com/google/oss-fuzz
+85 −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 <binder/TextOutput.h>
#include <cmd.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <vector>

#include <fuzzer/FuzzedDataProvider.h>

using namespace std;
using namespace android;

class TestTextOutput : public TextOutput {
public:
    TestTextOutput() {}
    virtual ~TestTextOutput() {}

    virtual status_t print(const char* /*txt*/, size_t /*len*/) { return NO_ERROR; }
    virtual void moveIndent(int /*delta*/) { return; }
    virtual void pushBundle() { return; }
    virtual void popBundle() { return; }
};

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

private:
    FuzzedDataProvider* mFDP = nullptr;
};

void CmdFuzzer::process(const uint8_t* data, size_t size) {
    mFDP = new FuzzedDataProvider(data, size);
    vector<string> arguments;
    if (mFDP->ConsumeBool()) {
        if (mFDP->ConsumeBool()) {
            arguments = {"-w", "media.aaudio"};
        } else {
            arguments = {"-l"};
        }
    } else {
        while (mFDP->remaining_bytes() > 0) {
            size_t sizestr = mFDP->ConsumeIntegralInRange<size_t>(1, mFDP->remaining_bytes());
            string argument = mFDP->ConsumeBytesAsString(sizestr);
            arguments.emplace_back(argument);
        }
    }
    vector<string_view> argSV;
    for (auto& argument : arguments) {
        argSV.emplace_back(argument.c_str());
    }
    int32_t in = open("/dev/null", O_RDWR | O_CREAT);
    int32_t out = open("/dev/null", O_RDWR | O_CREAT);
    int32_t err = open("/dev/null", O_RDWR | O_CREAT);
    TestTextOutput output;
    TestTextOutput error;
    RunMode runMode = mFDP->ConsumeBool() ? RunMode::kStandalone : RunMode::kLibrary;
    cmdMain(argSV, output, error, in, out, err, runMode);
    delete mFDP;
    close(in);
    close(out);
    close(err);
}

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