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

Commit ae47117b authored by Corbin Souffrant's avatar Corbin Souffrant
Browse files

Adding fuzzers for libstagefright.



This is a first batch of fuzzers written for libstagefright covering the following classes: MediaClock, MediaMuxer, SkipCutBuffer, StagefrightMediaScanner.
Test: These were all ran on a Pixel3a device for at least 48 hours to ensure that the fuzzers were stable.

Signed-off-by: default avatarCorbin Souffrant <corbin.souffrant@leviathansecurity.com>
Change-Id: I4e559bb57ee76a530fd01d7e3790133c3fb40349
parent 7ec362b7
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
cc_defaults {
    name: "libstagefright_fuzzer_defaults",
    cflags: [
        "-Wno-multichar",
        "-Werror",
        "-Wno-error=deprecated-declarations",
        "-Wall",
    ],
    shared_libs: [
        "libstagefright",
	"libstagefright_codecbase",
        "libutils",
        "libstagefright_foundation",
        "libmedia",
        "libaudioclient",
        "libmedia_omx",
        "libgui",
        "libbinder",
        "libcutils",
    ],
}

cc_fuzz {
    name: "libstagefright_mediaclock_fuzzer",
    srcs: [
        "MediaClockFuzzer.cpp",
    ],
    defaults: ["libstagefright_fuzzer_defaults"],
}

cc_fuzz {
    name: "libstagefright_mediascanner_fuzzer",
    srcs: [
        "StagefrightMediaScannerFuzzer.cpp",
    ],
    defaults: ["libstagefright_fuzzer_defaults"],
}

cc_fuzz {
    name: "libstagefright_skipcutbuffer_fuzzer",
    srcs: [
        "SkipCutBufferFuzzer.cpp",
    ],
    defaults: ["libstagefright_fuzzer_defaults"],
}

cc_fuzz {
    name: "libstagefright_mediamuxer_fuzzer",
    srcs: [
        "MediaMuxerFuzzer.cpp",
    ],
    defaults: ["libstagefright_fuzzer_defaults"],
}
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */
// Authors: corbin.souffrant@leviathansecurity.com
//          dylan.katz@leviathansecurity.com

#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/MediaClock.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
  sp<MediaClock> mClock(new MediaClock);

  bool registered = false;
  while (fdp.remaining_bytes() > 0) {
    switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 5)) {
    case 0: {
      if (registered == false) {
        mClock->init();
        registered = true;
      }
      break;
    }
    case 1: {
      int64_t startingTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
      mClock->setStartingTimeMedia(startingTimeMediaUs);
      break;
    }
    case 2: {
      mClock->clearAnchor();
      break;
    }
    case 3: {
      int64_t anchorTimeRealUs = fdp.ConsumeIntegral<int64_t>();
      int64_t anchorTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
      int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
      mClock->updateAnchor(anchorTimeMediaUs, anchorTimeRealUs, maxTimeMediaUs);
      break;
    }
    case 4: {
      int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
      mClock->updateMaxTimeMedia(maxTimeMediaUs);
      break;
    }
    case 5: {
      wp<AMessage> msg(new AMessage);
      mClock->setNotificationMessage(msg.promote());
    }
    }
  }

  return 0;
}
} // namespace android
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */
// Authors: corbin.souffrant@leviathansecurity.com
//          dylan.katz@leviathansecurity.com

#include <MediaMuxerFuzzer.h>
#include <cutils/ashmem.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/MediaMuxer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {

// Can't seem to get setBuffer or setString working. It always segfaults on a
// null pointer read or memleaks. So that functionality is missing.
void createMessage(AMessage *msg, FuzzedDataProvider *fdp) {
  size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 32);
  while (fdp->remaining_bytes() > 0 && count > 0) {
    uint8_t function_id =
        fdp->ConsumeIntegralInRange<uint8_t>(0, amessage_setvals.size() - 1);
    amessage_setvals[function_id](msg, fdp);
    count--;
  }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);

  size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
  int fd = ashmem_create_region("mediamuxer_fuzz_region", data_size);
  if (fd < 0)
    return 0;

  uint8_t *sh_data = static_cast<uint8_t *>(
      mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
  if (sh_data == MAP_FAILED)
    return 0;

  MediaMuxer::OutputFormat format =
      (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4);
  sp<MediaMuxer> mMuxer(new MediaMuxer(fd, format));

  while (fdp.remaining_bytes() > 1) {
    switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) {
    case 0: {
      // For some reason it only likes mp4s here...
      if (format == 1 || format == 4)
        break;

      sp<AMessage> a_format(new AMessage);
      createMessage(a_format.get(), &fdp);
      mMuxer->addTrack(a_format);
      break;
    }
    case 1: {
      mMuxer->start();
      break;
    }
    case 2: {
      int degrees = fdp.ConsumeIntegral<int>();
      mMuxer->setOrientationHint(degrees);
      break;
    }
    case 3: {
      int latitude = fdp.ConsumeIntegral<int>();
      int longitude = fdp.ConsumeIntegral<int>();
      mMuxer->setLocation(latitude, longitude);
      break;
    }
    case 4: {
      size_t buf_size = fdp.ConsumeIntegralInRange<size_t>(0, data_size);
      sp<ABuffer> a_buffer(new ABuffer(buf_size));

      size_t trackIndex = fdp.ConsumeIntegral<size_t>();
      int64_t timeUs = fdp.ConsumeIntegral<int64_t>();
      uint32_t flags = fdp.ConsumeIntegral<uint32_t>();
      mMuxer->writeSampleData(a_buffer, trackIndex, timeUs, flags);
    }
    }
  }

  if (fdp.ConsumeBool())
    mMuxer->stop();

  munmap(sh_data, data_size);
  close(fd);
  return 0;
}
} // namespace android
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */
// Authors: corbin.souffrant@leviathansecurity.com
//          dylan.katz@leviathansecurity.com

#pragma once

#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {

// Mappings vectors are the list of attributes that the MediaMuxer
// class looks for in the message.
static std::vector<const char *> floatMappings{
    "capture-rate",
    "time-lapse-fps",
    "frame-rate",
};

static std::vector<const char *> int64Mappings{
    "exif-offset",    "exif-size", "target-time",
    "thumbnail-time", "timeUs",    "durationUs",
};

static std::vector<const char *> int32Mappings{"loop",
                                               "time-scale",
                                               "crypto-mode",
                                               "crypto-default-iv-size",
                                               "crypto-encrypted-byte-block",
                                               "crypto-skip-byte-block",
                                               "frame-count",
                                               "max-bitrate",
                                               "pcm-big-endian",
                                               "temporal-layer-count",
                                               "temporal-layer-id",
                                               "thumbnail-width",
                                               "thumbnail-height",
                                               "track-id",
                                               "valid-samples",
                                               "color-format",
                                               "ca-system-id",
                                               "is-sync-frame",
                                               "bitrate",
                                               "max-bitrate",
                                               "width",
                                               "height",
                                               "sar-width",
                                               "sar-height",
                                               "display-width",
                                               "display-height",
                                               "is-default",
                                               "tile-width",
                                               "tile-height",
                                               "grid-rows",
                                               "grid-cols",
                                               "rotation-degrees",
                                               "channel-count",
                                               "sample-rate",
                                               "bits-per-sample",
                                               "channel-mask",
                                               "encoder-delay",
                                               "encoder-padding",
                                               "is-adts",
                                               "frame-rate",
                                               "max-height",
                                               "max-width",
                                               "max-input-size",
                                               "haptic-channel-count",
                                               "pcm-encoding",
                                               "aac-profile"};

static const std::vector<std::function<void(AMessage *, FuzzedDataProvider *)>>
    amessage_setvals = {
        [](AMessage *msg, FuzzedDataProvider *fdp) -> void {
          msg->setRect("crop", fdp->ConsumeIntegral<int32_t>(),
                       fdp->ConsumeIntegral<int32_t>(),
                       fdp->ConsumeIntegral<int32_t>(),
                       fdp->ConsumeIntegral<int32_t>());
        },
        [](AMessage *msg, FuzzedDataProvider *fdp) -> void {
          msg->setFloat(floatMappings[fdp->ConsumeIntegralInRange<size_t>(
                            0, floatMappings.size() - 1)],
                        fdp->ConsumeFloatingPoint<float>());
        },
        [](AMessage *msg, FuzzedDataProvider *fdp) -> void {
          msg->setInt64(int64Mappings[fdp->ConsumeIntegralInRange<size_t>(
                            0, int64Mappings.size() - 1)],
                        fdp->ConsumeIntegral<int64_t>());
        },
        [](AMessage *msg, FuzzedDataProvider *fdp) -> void {
          msg->setInt32(int32Mappings[fdp->ConsumeIntegralInRange<size_t>(
                            0, int32Mappings.size() - 1)],
                        fdp->ConsumeIntegral<int32_t>());
        }};
} // namespace android
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */
// Authors: corbin.souffrant@leviathansecurity.com
//          dylan.katz@leviathansecurity.com

#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/SkipCutBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
  size_t skip = fdp.ConsumeIntegral<size_t>();
  size_t cut = fdp.ConsumeIntegral<size_t>();
  size_t num16Channels = fdp.ConsumeIntegral<size_t>();
  sp<SkipCutBuffer> sBuffer(new SkipCutBuffer(skip, cut, num16Channels));

  while (fdp.remaining_bytes() > 0) {
    // Cap size to 1024 to limit max amount allocated.
    size_t buf_size = fdp.ConsumeIntegralInRange<size_t>(0, 1024);
    size_t range = fdp.ConsumeIntegralInRange<size_t>(0, buf_size);
    size_t length = fdp.ConsumeIntegralInRange<size_t>(0, buf_size - range);

    switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) {
    case 0: {
      sp<ABuffer> a_buffer(new ABuffer(buf_size));
      sp<AMessage> format(new AMessage);
      sp<MediaCodecBuffer> s_buffer(new MediaCodecBuffer(format, a_buffer));
      s_buffer->setRange(range, length);
      sBuffer->submit(s_buffer);
      break;
    }
    case 1: {
      std::unique_ptr<MediaBufferBase> m_buffer(new MediaBuffer(buf_size));
      m_buffer->set_range(range, length);
      sBuffer->submit(reinterpret_cast<MediaBuffer *>(m_buffer.get()));
      break;
    }
    case 2: {
      sp<ABuffer> a_buffer(new ABuffer(buf_size));
      sp<AMessage> format(new AMessage);
      sp<MediaCodecBuffer> s_buffer(new MediaCodecBuffer(format, a_buffer));
      a_buffer->setRange(range, length);
      sBuffer->submit(a_buffer);
      break;
    }
    case 3: {
      sBuffer->clear();
      break;
    }
    case 4: {
      sBuffer->size();
    }
    }
  }
  return 0;
}
} // namespace android
Loading