diff options
author | Hamzeh Zawawy <hamzeh@google.com> | 2020-07-14 16:59:15 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-07-14 16:59:15 +0000 |
commit | 533d3688082fb7e18fc5122ff1b64725d4dc959a (patch) | |
tree | 88036404520230a0d596b21a0ee791a3608eb59f | |
parent | 6091a2d60282f9db3f11907902a63343ab974562 (diff) | |
parent | c9b03bd09db82f5d63771f0270d775c8dce9873e (diff) | |
download | native-533d3688082fb7e18fc5122ff1b64725d4dc959a.tar.gz |
Merge "Adding Message and Serialization fuzzers to libpdx"android-r-beta-3android-r-beta-2
-rw-r--r-- | libs/vr/libpdx/fuzz/Android.bp | 46 | ||||
-rw-r--r-- | libs/vr/libpdx/fuzz/message_fuzzer.cpp | 175 | ||||
-rw-r--r-- | libs/vr/libpdx/fuzz/serialization_fuzzer.cpp | 111 |
3 files changed, 330 insertions, 2 deletions
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp index 8ab09f3c32..b36e0deea0 100644 --- a/libs/vr/libpdx/fuzz/Android.bp +++ b/libs/vr/libpdx/fuzz/Android.bp @@ -1,5 +1,5 @@ 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" ], } diff --git a/libs/vr/libpdx/fuzz/message_fuzzer.cpp b/libs/vr/libpdx/fuzz/message_fuzzer.cpp new file mode 100644 index 0000000000..b627045ab6 --- /dev/null +++ b/libs/vr/libpdx/fuzz/message_fuzzer.cpp @@ -0,0 +1,175 @@ +/* + * 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; +} diff --git a/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp b/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp new file mode 100644 index 0000000000..afde5f7f32 --- /dev/null +++ b/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp @@ -0,0 +1,111 @@ +/* + * 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; +} |