diff options
Diffstat (limited to 'libs/vr/libpdx/fuzz/helpers.h')
-rw-r--r-- | libs/vr/libpdx/fuzz/helpers.h | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/libs/vr/libpdx/fuzz/helpers.h b/libs/vr/libpdx/fuzz/helpers.h new file mode 100644 index 0000000000..83ec4096f6 --- /dev/null +++ b/libs/vr/libpdx/fuzz/helpers.h @@ -0,0 +1,294 @@ +/* + * 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 + +#ifndef LEV_FUZZERS_LIBPDX_HELPERS_H_ +#define LEV_FUZZERS_LIBPDX_HELPERS_H_ + +#define UNUSED(expr) \ + do { \ + (void)(expr); \ + } while (0) + +#include <fuzzer/FuzzedDataProvider.h> +#include <pdx/client.h> +#include <pdx/service.h> +#include <pdx/service_dispatcher.h> +#include <pdx/service_endpoint.h> +#include <sys/eventfd.h> +#include <memory> +#include <vector> + +using namespace android::pdx; + +// Vector of operations we can call in the dispatcher. +static const std::vector<std::function<void( + const std::unique_ptr<ServiceDispatcher>&, FuzzedDataProvider*)>> + dispatcher_operations = { + [](const std::unique_ptr<ServiceDispatcher>& dispatcher, + FuzzedDataProvider*) -> void { dispatcher->EnterDispatchLoop(); }, + [](const std::unique_ptr<ServiceDispatcher>& dispatcher, + FuzzedDataProvider*) -> void { dispatcher->ReceiveAndDispatch(); }, + [](const std::unique_ptr<ServiceDispatcher>& dispatcher, + FuzzedDataProvider* fdp) -> void { + dispatcher->ReceiveAndDispatch(fdp->ConsumeIntegral<int>()); + }}; + +// Most of the fuzzing occurs within the endpoint, which is derived from an +// abstract class. So we are returning garbage data for most functions besides +// the ones we added or need to actually use. +class FuzzEndpoint : public Endpoint { + public: + explicit FuzzEndpoint(FuzzedDataProvider* fdp) { + _fdp = fdp; + _epoll_fd = eventfd(0, 0); + } + + ~FuzzEndpoint() { close(_epoll_fd); } + + // Returns an fd that can be used with epoll() to wait for incoming messages + // from this endpoint. + int epoll_fd() const { return _epoll_fd; } + + // Associates a Service instance with an endpoint by setting the service + // context pointer to the address of the Service. Only one Service may be + // associated with a given endpoint. + Status<void> SetService(Service* service) { + _service = service; + return Status<void>(0); + } + + // Set the channel context for the given channel. + Status<void> SetChannel(int channel_id, Channel* channel) { + UNUSED(channel_id); + _channel = std::shared_ptr<Channel>(channel); + return Status<void>(0); + } + + // Receives a message on the given endpoint file descriptor. + // This is called by the dispatcher to determine what operations + // to make, so we are fuzzing the response. + Status<void> MessageReceive(Message* message) { + // Create a randomized MessageInfo struct. + MessageInfo info; + eventfd_t wakeup_val = 0; + 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; + 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(info); + eventfd_read(_epoll_fd, &wakeup_val); + + return Status<void>(); + } + + // Returns a tag that uniquely identifies a specific underlying IPC + // transport. + uint32_t GetIpcTag() const { return 0; } + + // Close a channel, signaling the client file object and freeing the channel + // id. Once closed, the client side of the channel always returns the error + // ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE. + Status<void> CloseChannel(int channel_id) { + UNUSED(channel_id); + return Status<void>(); + } + + // Update the event bits for the given channel (given by id), using the + // given clear and set masks. + Status<void> ModifyChannelEvents(int channel_id, int clear_mask, + int set_mask) { + UNUSED(channel_id); + UNUSED(clear_mask); + UNUSED(set_mask); + return Status<void>(); + } + + // Create a new channel and push it as a file descriptor to the process + // sending the |message|. |flags| may be set to O_NONBLOCK and/or + // O_CLOEXEC to control the initial behavior of the new file descriptor (the + // sending process may change these later using fcntl()). The internal + // Channel instance associated with this channel is set to |channel|, + // which may be nullptr. The new channel id allocated for this channel is + // returned in |channel_id|, which may also be nullptr if not needed. + Status<RemoteChannelHandle> PushChannel(Message* message, int flags, + Channel* channel, int* channel_id) { + UNUSED(message); + UNUSED(flags); + UNUSED(channel); + UNUSED(channel_id); + return Status<RemoteChannelHandle>(); + } + + // Check whether the |ref| is a reference to a channel to the service + // represented by the |endpoint|. If the channel reference in question is + // valid, the Channel object is returned in |channel| when non-nullptr and + // the channel ID is returned through the Status object. + Status<int> CheckChannel(const Message* message, ChannelReference ref, + Channel** channel) { + UNUSED(message); + UNUSED(ref); + UNUSED(channel); + return Status<int>(); + } + + // Replies to the message with a return code. + Status<void> MessageReply(Message* message, int return_code) { + UNUSED(message); + UNUSED(return_code); + return Status<void>(); + } + + // Replies to the message with a file descriptor. + Status<void> MessageReplyFd(Message* message, unsigned int push_fd) { + UNUSED(message); + UNUSED(push_fd); + return Status<void>(); + } + + // Replies to the message with a local channel handle. + Status<void> MessageReplyChannelHandle(Message* message, + const LocalChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<void>(); + } + + // Replies to the message with a borrowed local channel handle. + Status<void> MessageReplyChannelHandle(Message* message, + const BorrowedChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<void>(); + } + + // Replies to the message with a remote channel handle. + Status<void> MessageReplyChannelHandle(Message* message, + const RemoteChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<void>(); + } + + // Reads message data into an array of memory buffers. + Status<size_t> ReadMessageData(Message* message, const iovec* vector, + size_t vector_length) { + UNUSED(message); + UNUSED(vector); + UNUSED(vector_length); + return Status<size_t>(); + } + + // Sends reply data for message. + Status<size_t> WriteMessageData(Message* message, const iovec* vector, + size_t vector_length) { + UNUSED(message); + UNUSED(vector); + UNUSED(vector_length); + return Status<size_t>(); + } + + // Records a file descriptor into the message buffer and returns the + // remapped reference to be sent to the remote process. + Status<FileReference> PushFileHandle(Message* message, + const LocalHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<FileReference>(); + } + + Status<FileReference> PushFileHandle(Message* message, + const BorrowedHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<FileReference>(); + } + + Status<FileReference> PushFileHandle(Message* message, + const RemoteHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<FileReference>(); + } + + Status<ChannelReference> PushChannelHandle(Message* message, + const LocalChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<ChannelReference>(); + } + + Status<ChannelReference> PushChannelHandle( + Message* message, const BorrowedChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<ChannelReference>(); + } + + Status<ChannelReference> PushChannelHandle( + Message* message, const RemoteChannelHandle& handle) { + UNUSED(message); + UNUSED(handle); + return Status<ChannelReference>(); + } + + // Obtains a file descriptor/channel handle from a message for the given + // reference. + LocalHandle GetFileHandle(Message* message, FileReference ref) const { + UNUSED(message); + UNUSED(ref); + return LocalHandle(); + } + + LocalChannelHandle GetChannelHandle(Message* message, + ChannelReference ref) const { + UNUSED(message); + UNUSED(ref); + return LocalChannelHandle(); + } + + // Transport-specific message state management. + void* AllocateMessageState() { return nullptr; } + + void FreeMessageState(void* state) { UNUSED(state); } + + // Cancels the endpoint, unblocking any receiver threads waiting for a + // message. + Status<void> Cancel() { return Status<void>(); } + + private: + FuzzedDataProvider* _fdp; + std::shared_ptr<Channel> _channel; + Service* _service; + int _epoll_fd; +}; + +#endif // LEV_FUZZERS_LIBPDX_HELPERS_H_ |