/* * 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 #include #include #include #include #include #include #include #include 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( new Service("FuzzService", std::unique_ptr(endpoint))); std::shared_ptr channel(nullptr); // Generate a random Message object to call functions in. MessageInfo info; info.pid = fdp.ConsumeIntegral(); info.tid = fdp.ConsumeIntegral(); info.cid = fdp.ConsumeIntegral(); info.mid = fdp.ConsumeIntegral(); info.euid = fdp.ConsumeIntegral(); info.egid = fdp.ConsumeIntegral(); info.op = fdp.ConsumeIntegral(); info.flags = fdp.ConsumeIntegral(); info.service = service.get(); info.channel = channel.get(); info.send_len = fdp.ConsumeIntegral(); info.recv_len = fdp.ConsumeIntegral(); info.fd_count = fdp.ConsumeIntegral(); if (fdp.remaining_bytes() >= 32) { std::vector impulse_vec = fdp.ConsumeBytes(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(); int clear_mask = fdp.ConsumeIntegral(); int set_mask = fdp.ConsumeIntegral(); Status 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(); ChannelReference c_ref = fdp.ConsumeIntegral(); // 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()) { 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 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 tmp_vec = fdp.ConsumeBytes(iovec_size); struct iovec* vector = reinterpret_cast(tmp_vec.data()); std::vector tmp_buf = fdp.ConsumeBytes(fdp.remaining_bytes()); void* buf = reinterpret_cast(tmp_buf.data()); size_t buf_size = fdp.ConsumeIntegral(); // Capping num_vecs to 1024 so it doesn't allocate too much memory. size_t num_vecs = fdp.ConsumeIntegralInRange(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; }