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

Commit b0d93589 authored by Hamzeh Zawawy's avatar Hamzeh Zawawy Committed by Automerger Merge Worker
Browse files

Merge "Adding Message and Serialization fuzzers to libpdx" am: 533d3688 am:...

Merge "Adding Message and Serialization fuzzers to libpdx" am: 533d3688 am: bd9017b9 am: 4d2885bc am: cfeeece1

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

Change-Id: Id64bd60e7dfdcaafa5194a489601fa4081a60ff2
parents b08dab50 cfeeece1
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
cc_fuzz {
    name: "libpdx_fuzz",
    name: "libpdx_service_dispatcher_fuzzer",
    clang: true,
    srcs: [
        "service_dispatcher_fuzzer.cpp",
@@ -15,6 +15,48 @@ cc_fuzz {
    shared_libs: [
        "libutils",
        "liblog",
	"libcutils",
        "libcutils"
    ],
}

cc_fuzz {
    name: "libpdx_message_fuzzer",
    clang: true,
    srcs: [
        "message_fuzzer.cpp",
    ],
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
    ],
    static_libs: [
        "libpdx",
    ],
    shared_libs: [
        "libutils",
        "liblog",
        "libcutils"
    ],
}

cc_fuzz {
    name: "libpdx_serialization_fuzzer",
    clang: true,
    srcs: [
        "serialization_fuzzer.cpp",
    ],
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
    ],
    static_libs: [
        "libpdx",
    ],
    shared_libs: [
        "libutils",
        "liblog",
        "libcutils"
    ],
}
+175 −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
//          brian.balling@leviathansecurity.com

#include <fuzzer/FuzzedDataProvider.h>
#include <helpers.h>
#include <pdx/client_channel.h>
#include <pdx/service.h>
#include <pdx/service_dispatcher.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/eventfd.h>
#include <thread>

using namespace android::pdx;

// Fuzzer for Message object functions.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);

  FuzzEndpoint* endpoint = new FuzzEndpoint(&fdp);
  std::shared_ptr<Service> service(
      new Service("FuzzService", std::unique_ptr<Endpoint>(endpoint)));
  std::shared_ptr<Channel> channel(nullptr);

  // Generate a random Message object to call functions in.
  MessageInfo info;
  info.pid = fdp.ConsumeIntegral<int>();
  info.tid = fdp.ConsumeIntegral<int>();
  info.cid = fdp.ConsumeIntegral<int>();
  info.mid = fdp.ConsumeIntegral<int>();
  info.euid = fdp.ConsumeIntegral<int>();
  info.egid = fdp.ConsumeIntegral<int>();
  info.op = fdp.ConsumeIntegral<int32_t>();
  info.flags = fdp.ConsumeIntegral<uint32_t>();
  info.service = service.get();
  info.channel = channel.get();
  info.send_len = fdp.ConsumeIntegral<size_t>();
  info.recv_len = fdp.ConsumeIntegral<size_t>();
  info.fd_count = fdp.ConsumeIntegral<size_t>();
  if (fdp.remaining_bytes() >= 32) {
    std::vector<uint8_t> impulse_vec = fdp.ConsumeBytes<uint8_t>(32);
    memcpy(info.impulse, impulse_vec.data(), 32);
  }

  Message message = Message(info);

  // A bunch of getters that probably won't do much, but might as well
  // get coverage, while we are here.
  message.GetProcessId();
  message.GetThreadId();
  message.GetEffectiveUserId();
  message.GetEffectiveGroupId();
  message.GetChannelId();
  message.GetMessageId();
  message.GetOp();
  message.GetFlags();
  message.GetSendLength();
  message.GetReceiveLength();
  message.GetFileDescriptorCount();
  message.ImpulseEnd();
  message.replied();
  message.IsChannelExpired();
  message.IsServiceExpired();
  message.GetState();
  message.GetState();

  // Some misc. functions.
  unsigned int fd = fdp.ConsumeIntegral<unsigned int>();
  int clear_mask = fdp.ConsumeIntegral<int>();
  int set_mask = fdp.ConsumeIntegral<int>();
  Status<void> status = {};
  message.ModifyChannelEvents(clear_mask, set_mask);

  // Fuzz the handle functions.
  LocalHandle l_handle = {};
  BorrowedHandle b_handle = {};
  RemoteHandle r_handle = {};
  LocalChannelHandle lc_handle = {};
  BorrowedChannelHandle bc_handle = {};
  RemoteChannelHandle rc_handle = {};
  FileReference f_ref = fdp.ConsumeIntegral<int32_t>();
  ChannelReference c_ref = fdp.ConsumeIntegral<int32_t>();

  // These don't actually modify any state in the Message or params.
  // They can be called in any order.
  message.PushFileHandle(b_handle);
  message.PushFileHandle(r_handle);
  message.PushChannelHandle(lc_handle);
  message.PushChannelHandle(bc_handle);
  message.PushChannelHandle(rc_handle);
  message.GetFileHandle(f_ref, &l_handle);
  message.GetChannelHandle(c_ref, &lc_handle);

  // Can only reply once, pick at random.
  switch (fdp.ConsumeIntegral<uint8_t>()) {
    case 0:
      message.ReplyFileDescriptor(fd);
      break;
    case 1:
      message.Reply(status);
      break;
    case 2:
      message.Reply(l_handle);
      break;
    case 3:
      message.Reply(b_handle);
      break;
    case 4:
      message.Reply(r_handle);
      break;
    case 5:
      message.Reply(lc_handle);
      break;
    case 6:
      message.Reply(bc_handle);
      break;
    case 7:
      message.Reply(rc_handle);
  }

  // Fuzz the channel functions.
  int flags = fdp.ConsumeIntegral<int>();
  int channel_id = 0;
  message.PushChannel(flags, channel, &channel_id);
  message.CheckChannel(service.get(), c_ref, &channel);
  message.CheckChannel(c_ref, &channel);
  message.PushChannel(service.get(), flags, channel, &channel_id);
  size_t iovec_size = sizeof(iovec);
  struct iovec* iovecs = nullptr;

  // Fuzz the read/write functions. Needs at least one iovec, plus one byte.
  if (fdp.remaining_bytes() >= iovec_size + 1) {
    std::vector<uint8_t> tmp_vec = fdp.ConsumeBytes<uint8_t>(iovec_size);
    struct iovec* vector = reinterpret_cast<struct iovec*>(tmp_vec.data());
    std::vector<uint8_t> tmp_buf =
        fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
    void* buf = reinterpret_cast<void*>(tmp_buf.data());
    size_t buf_size = fdp.ConsumeIntegral<size_t>();

    // Capping num_vecs to 1024 so it doesn't allocate too much memory.
    size_t num_vecs = fdp.ConsumeIntegralInRange<size_t>(0, 1024);

    if (num_vecs > 0)
      iovecs = new struct iovec[num_vecs];
    for (size_t i = 0; i < num_vecs; i++) {
      iovecs[i] = *vector;
    }

    message.ReadAll(vector, buf_size);
    message.WriteAll(buf, buf_size);
    message.ReadVectorAll(vector, num_vecs);
    message.WriteVectorAll(vector, num_vecs);
    message.ReadVector(vector, buf_size);
    message.WriteVector(vector, buf_size);
  }

  if (iovecs != nullptr)
    delete[] iovecs;
  return 0;
}
+111 −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
//          brian.balling@leviathansecurity.com

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <thread>
#include <utility>

#include <fuzzer/FuzzedDataProvider.h>
#include <pdx/rpc/argument_encoder.h>
#include <pdx/rpc/array_wrapper.h>
#include <pdx/rpc/default_initialization_allocator.h>
#include <pdx/rpc/payload.h>
#include <pdx/rpc/serializable.h>
#include <pdx/rpc/serialization.h>
#include <pdx/rpc/string_wrapper.h>
#include <pdx/utility.h>

using namespace android::pdx;
using namespace android::pdx::rpc;

struct FuzzType {
  int a;
  float b;
  std::string c;

  FuzzType() {}
  FuzzType(int a, float b, const std::string& c) : a(a), b(b), c(c) {}

 private:
  PDX_SERIALIZABLE_MEMBERS(FuzzType, a, b, c);
};

// Fuzzer for Serialization operations, this is mostly just lifted from the
// existing test cases to use fuzzed values as inputs.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
  Payload result;

  // Currently, only fuzzing subset of types. In the future, may want
  // to add more difficult to generate types like array, map, enum, etc...
  bool b_val = fdp.ConsumeBool();
  uint8_t u8_val = fdp.ConsumeIntegral<uint8_t>();
  uint16_t u16_val = fdp.ConsumeIntegral<uint16_t>();
  uint32_t u32_val = fdp.ConsumeIntegral<uint32_t>();
  uint64_t u64_val = fdp.ConsumeIntegral<uint64_t>();
  int8_t i8_val = fdp.ConsumeIntegral<int8_t>();
  int16_t i16_val = fdp.ConsumeIntegral<uint16_t>();
  int32_t i32_val = fdp.ConsumeIntegral<uint32_t>();
  int64_t i64_val = fdp.ConsumeIntegral<uint64_t>();
  float f_val = fdp.ConsumeFloatingPoint<float>();
  double d_val = fdp.ConsumeFloatingPoint<double>();
  std::string s_val = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
  std::vector<uint8_t> vec_val =
      fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
  FuzzType t1_val{reinterpret_cast<int>(i32_val), f_val, s_val};

  // Types need to be individually fuzzed because code path changes depending
  // on which type is being serialized/deserialized.
  Serialize(b_val, &result);
  Deserialize(&b_val, &result);
  Serialize(u8_val, &result);
  Deserialize(&u8_val, &result);
  Serialize(u16_val, &result);
  Deserialize(&u16_val, &result);
  Serialize(u32_val, &result);
  Deserialize(&u32_val, &result);
  Serialize(u64_val, &result);
  Deserialize(&u64_val, &result);
  Serialize(i8_val, &result);
  Deserialize(&i8_val, &result);
  Serialize(i16_val, &result);
  Deserialize(&i16_val, &result);
  Serialize(i32_val, &result);
  Deserialize(&i32_val, &result);
  Serialize(i64_val, &result);
  Deserialize(&i64_val, &result);
  Serialize(f_val, &result);
  Deserialize(&f_val, &result);
  Serialize(d_val, &result);
  Deserialize(&d_val, &result);
  Serialize(s_val, &result);
  Deserialize(&s_val, &result);
  Serialize(WrapString(s_val), &result);
  Deserialize(&s_val, &result);
  Serialize(vec_val, &result);
  Deserialize(&vec_val, &result);
  Serialize(t1_val, &result);
  Deserialize(&t1_val, &result);

  return 0;
}