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

Commit 6a82af9d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Ic4584b2d,I6c18ae05 into main

* changes:
  Add rtsp_connection_fuzzer
  Add packet_source_fuzzer
parents e6588b4e fa329a32
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -62,3 +62,28 @@ cc_fuzz {
        "libcutils",
    ],
}

cc_fuzz {
    name: "packet_source_fuzzer",
    srcs: [
        "packet_source_fuzzer.cpp",
    ],
    defaults: [
        "libstagefright_rtsp_fuzzer_defaults",
    ],
}

cc_fuzz {
    name: "rtsp_connection_fuzzer",
    srcs: [
        "rtsp_connection_fuzzer.cpp",
    ],
    shared_libs: [
        "libcrypto",
        "libcutils",
        "libnetd_client",
    ],
    defaults: [
        "libstagefright_rtsp_fuzzer_defaults",
    ],
}
+53 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
## Table of contents
+ [sdploader_fuzzer](#SDPLoader)
+ [rtp_writer_fuzzer](#ARTPWriter)
+ [packet_source_fuzzer](#packetSource)
+ [rtsp_connection_fuzzer](#ARTSPConnection)

# <a name="SDPLoader"></a> Fuzzer for SDPLoader

@@ -62,3 +64,54 @@ ARTPWriter supports the following parameters:
  $ adb sync data
  $ adb shell /data/fuzz/arm64/rtp_writer_fuzzer/rtp_writer_fuzzer
```

# <a name="packetSource"></a> Fuzzer for  PacketSource

 PacketSource supports the following parameters:
1. Codec (parameter name: "kCodecs")
2. Format (parameter name: "kFmtp")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`kCodecs`| 0. `opus`<br/>1. `ISAC`<br/>2. `VP8`<br/>3. `google-data`<br/>4. `G722`<br/>5. `PCMU`<br/>6. `PCMA`<br/>7. `CN`<br/>8. `telephone-event`<br/>9. `VP9`<br/>10. `red`<br/>11. `ulpfec`<br/>12. `rtx`<br/>13. `H264`<br/>14. `iLBC`<br/>15. `H261`<br/>16. `MPV`<br/>17. `H263`<br/>18. `AMR`<br/>19. `AC3`<br/>20. `G723`<br/>21. `G729A`<br/>22. `MP4V-ES`<br/>23. `H265`<br/>24. `H263-2000`<br/>25. `H263-1998`<br/>26. `AMR-WB`<br/>27. `MP4A-LATM`<br/>28. `MP2T`<br/>29. `mpeg4-generic` |Value obtained from FuzzedDataProvider|
|`kFmtp`| <br/>0. `br=`<br/>1. `bw=`<br/>2. `ch-aw-recv=`<br/>3. `mode-change-capability=`<br/>4. `max-red =`<br/>5. `octet-align=`<br/>6. `mode-change-capability=`<br/>7. `profile-level-id=`<br/>8. `packetization-mode=`<br/>9. `profile=`<br/>10. `level=` <br/>11. `apt=`<br/>12. `annexb=`<br/>13. `protocol=`<br/>14. `config=`<br/>15. `streamtype=`<br/>16. `mode=`<br/>17. `sizelength=`<br/>18. `indexlength=`<br/>19. `indexdeltalength=`<br/>20. `minptime=`<br/>21. `useinbandfec=`<br/>22. `maxplaybackrate=`<br/>23. `stereo=`<br/>24. `level-asymmetry-allowed=`<br/>25. `max-fs=`<br/>26. `max-fr=`|Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) packet_source_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/packet_source_fuzzer/packet_source_fuzzer
```

# <a name="ARTSPConnection"></a> Fuzzer for ARTSPConnection

## Design Considerations
This fuzzer aims at covering ARTSPConnection.cpp. A server is implemented in the fuzzer. After accepting a connect request, the server accepts the connections and handles them in a seperate thread. The threads are maintained in a ThreadPool which limits the maximum number of threads alive at a time. When the fuzzer process ends, all the threads in the ThreadPool are joined to the main thread.
The inputs to the server are generated using FuzzedDataProvider and stored in a variable 'mFuzzData'. As this variable is shared among multiple threads, mutex is used to ensure synchronization.
### Fuzzer Inputs:
The inputs generated in the fuzzer using FuzzzedDataProvider have been randomized as much as possible. Due to the constraints in the module source code, the inputs have to be limited and arranged in some specific format.

ARTSPConnection supports the following parameters:
1. Authentication Type (parameter name: "kAuthType")
2. FuzzData (parameter name: "mFuzzData")
3. RequestData (parameter name: "mFuzzRequestData")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`kAuthType`| 0.`Basic`<br/>1.`Digest`|Value obtained from FuzzedDataProvider|
|`mFuzzData`| `String` |Value obtained from FuzzedDataProvider|
|`mFuzzRequestData`| `String` |Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) rtsp_connection_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/rtsp_connection_fuzzer/rtsp_connection_fuzzer
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/rtsp/APacketSource.h>
#include <media/stagefright/rtsp/ASessionDescription.h>

using namespace android;

static constexpr int32_t kMinValue = 0;
static constexpr int32_t kMaxIPAddress = 255;
static constexpr int32_t kMaxFmt = 255;
static constexpr int32_t kMinAPICase = 0;
static constexpr int32_t kMaxPacketSourceAPI = 5;
static constexpr size_t kMinIndex = 1;
static constexpr size_t kMaxCodecConfigs = 4;

std::string kCodecs[] = {"opus",        "ISAC",         "VP8",
                         "google-data", "G722",         "PCMU",
                         "PCMA",        "CN",           "telephone-event",
                         "VP9",         "red",          "ulpfec",
                         "rtx",         "H264",         "iLBC",
                         "H261",        "MPV",          "H263",
                         "AMR",         "AC3",          "G723",
                         "G729A",       "H264",         "MP4V-ES",
                         "H265",        "H263-2000",    "H263-1998",
                         "AMR",         "AMR-WB",       "MP4A-LATM",
                         "MP2T",        "mpeg4-generic"};

std::string kFmtp[] = {"br=",
                       "bw=",
                       "ch-aw-recv=",
                       "mode-change-capability=",
                       "max-red =",
                       "octet-align=",
                       "mode-change-capability=",
                       "max-red=",
                       "profile-level-id=",
                       "packetization-mode=",
                       "profile=",
                       "level=",
                       "apt=",
                       "annexb=",
                       "protocol=",
                       "streamtype=",
                       "mode=",
                       "sizelength=",
                       "indexlength=",
                       "indexdeltalength=",
                       "minptime=",
                       "useinbandfec=",
                       "maxplaybackrate=",
                       "stereo=",
                       "level-asymmetry-allowed=",
                       "max-fs=",
                       "max-fr="};

std::string kCodecConfigString[kMaxCodecConfigs][2] = {{"H264", "profile-level-id="},
                                                       {"MP4A-LATM", "config="},
                                                       {"MP4V-ES", "config="},
                                                       {"mpeg4-generic", "mode="}};

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

  private:
    FuzzedDataProvider mFdp;
};

bool checkFormatSupport(const std::string& codec, const std::string& format) {
    for (int i = 0; i < kMaxCodecConfigs; ++i) {
        if (codec == kCodecConfigString[i][0]) {
            if (format == kCodecConfigString[i][1]) {
                return true;
            } else {
                return false;
            }
        }
    }
    return true;
}

void ASessionPacketFuzzer::process() {
    AString inputString;
    const sp<ASessionDescription> sessionPacket = sp<ASessionDescription>::make();
    std::string codec = mFdp.PickValueInArray(kCodecs);
    std::string ipAddress =
            std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." +
            std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." +
            std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." + "0";
    std::string format = mFdp.PickValueInArray(kFmtp);
    std::string fmptStr = format + std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxFmt)) +
                          ";" + mFdp.PickValueInArray(kFmtp) +
                          std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxFmt));
    sessionPacket->SDPStringFactory(
            inputString, ipAddress.c_str() /* ip */, mFdp.ConsumeBool() /* isAudio */,
            mFdp.ConsumeIntegral<unsigned int>() /* port */,
            mFdp.ConsumeIntegral<unsigned int>() /* payloadType */,
            mFdp.ConsumeIntegral<unsigned int>() /* as */, codec.c_str(), /* codec */
            fmptStr.c_str() /* fmtp */, mFdp.ConsumeIntegral<int32_t>() /* width */,
            mFdp.ConsumeIntegral<int32_t>() /* height */,
            mFdp.ConsumeIntegral<int32_t>() /* cvoExtMap */);
    sessionPacket->setTo(inputString.c_str(), inputString.size());
    size_t trackSize = sessionPacket->countTracks();
    AString desc = nullptr;
    while (mFdp.remaining_bytes()) {
        int32_t packetSourceAPI =
                mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxPacketSourceAPI);
        switch (packetSourceAPI) {
            case 0: {
                unsigned long payload = 0;
                AString params = nullptr;
                sessionPacket->getFormatType(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
                                             &payload, &desc, &params);
                break;
            }
            case 1: {
                int32_t width, height;
                unsigned long payload = mFdp.ConsumeIntegral<unsigned long>();
                sessionPacket->getDimensions(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
                                             payload, &width, &height);
                break;
            }
            case 2: {
                int32_t cvoExtMap = mFdp.ConsumeIntegral<int32_t>();
                sessionPacket->getCvoExtMap(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
                                            &cvoExtMap);
                break;
            }
            case 3: {
                int64_t durationUs = mFdp.ConsumeIntegral<int64_t>();
                sessionPacket->getDurationUs(&durationUs);
                break;
            }
            case 4: {
                int32_t timeScale, numChannels;
                if (desc != nullptr) {
                    sessionPacket->ParseFormatDesc(desc.c_str(), &timeScale, &numChannels);
                }
                break;
            }
            case 5: {
                if (checkFormatSupport(codec, format)) {
                    sp<APacketSource> packetSource = sp<APacketSource>::make(
                            sessionPacket, mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1));
                }
                break;
            }
        }
    }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    ASessionPacketFuzzer packetSourceFuzzer(data, size);
    packetSourceFuzzer.process();
    return 0;
}
+397 −0

File added.

Preview size limit exceeded, changes collapsed.