blob: 83ec4096f6c16577edb71d47f2310526aafc3a66 [file] [log] [blame]
Corbin Souffrantd3c76842020-06-05 18:54:11 -07001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16// Authors: corbin.souffrant@leviathansecurity.com
17// brian.balling@leviathansecurity.com
18
19#ifndef LEV_FUZZERS_LIBPDX_HELPERS_H_
20#define LEV_FUZZERS_LIBPDX_HELPERS_H_
21
22#define UNUSED(expr) \
23 do { \
24 (void)(expr); \
25 } while (0)
26
27#include <fuzzer/FuzzedDataProvider.h>
28#include <pdx/client.h>
29#include <pdx/service.h>
30#include <pdx/service_dispatcher.h>
31#include <pdx/service_endpoint.h>
32#include <sys/eventfd.h>
33#include <memory>
34#include <vector>
35
36using namespace android::pdx;
37
38// Vector of operations we can call in the dispatcher.
39static const std::vector<std::function<void(
40 const std::unique_ptr<ServiceDispatcher>&, FuzzedDataProvider*)>>
41 dispatcher_operations = {
42 [](const std::unique_ptr<ServiceDispatcher>& dispatcher,
43 FuzzedDataProvider*) -> void { dispatcher->EnterDispatchLoop(); },
44 [](const std::unique_ptr<ServiceDispatcher>& dispatcher,
45 FuzzedDataProvider*) -> void { dispatcher->ReceiveAndDispatch(); },
46 [](const std::unique_ptr<ServiceDispatcher>& dispatcher,
47 FuzzedDataProvider* fdp) -> void {
48 dispatcher->ReceiveAndDispatch(fdp->ConsumeIntegral<int>());
49 }};
50
51// Most of the fuzzing occurs within the endpoint, which is derived from an
52// abstract class. So we are returning garbage data for most functions besides
53// the ones we added or need to actually use.
54class FuzzEndpoint : public Endpoint {
55 public:
56 explicit FuzzEndpoint(FuzzedDataProvider* fdp) {
57 _fdp = fdp;
58 _epoll_fd = eventfd(0, 0);
59 }
60
61 ~FuzzEndpoint() { close(_epoll_fd); }
62
63 // Returns an fd that can be used with epoll() to wait for incoming messages
64 // from this endpoint.
65 int epoll_fd() const { return _epoll_fd; }
66
67 // Associates a Service instance with an endpoint by setting the service
68 // context pointer to the address of the Service. Only one Service may be
69 // associated with a given endpoint.
70 Status<void> SetService(Service* service) {
71 _service = service;
72 return Status<void>(0);
73 }
74
75 // Set the channel context for the given channel.
76 Status<void> SetChannel(int channel_id, Channel* channel) {
77 UNUSED(channel_id);
78 _channel = std::shared_ptr<Channel>(channel);
79 return Status<void>(0);
80 }
81
82 // Receives a message on the given endpoint file descriptor.
83 // This is called by the dispatcher to determine what operations
84 // to make, so we are fuzzing the response.
85 Status<void> MessageReceive(Message* message) {
86 // Create a randomized MessageInfo struct.
87 MessageInfo info;
88 eventfd_t wakeup_val = 0;
89 info.pid = _fdp->ConsumeIntegral<int>();
90 info.tid = _fdp->ConsumeIntegral<int>();
91 info.cid = _fdp->ConsumeIntegral<int>();
92 info.mid = _fdp->ConsumeIntegral<int>();
93 info.euid = _fdp->ConsumeIntegral<int>();
94 info.egid = _fdp->ConsumeIntegral<int>();
95 info.op = _fdp->ConsumeIntegral<int32_t>();
96 info.flags = _fdp->ConsumeIntegral<uint32_t>();
97 info.service = _service;
98 info.channel = _channel.get();
99 info.send_len = _fdp->ConsumeIntegral<size_t>();
100 info.recv_len = _fdp->ConsumeIntegral<size_t>();
101 info.fd_count = _fdp->ConsumeIntegral<size_t>();
102 if (_fdp->remaining_bytes() >= 32) {
103 std::vector<uint8_t> impulse_vec = _fdp->ConsumeBytes<uint8_t>(32);
104 memcpy(info.impulse, impulse_vec.data(), 32);
105 }
106
107 *message = Message(info);
108 eventfd_read(_epoll_fd, &wakeup_val);
109
110 return Status<void>();
111 }
112
113 // Returns a tag that uniquely identifies a specific underlying IPC
114 // transport.
115 uint32_t GetIpcTag() const { return 0; }
116
117 // Close a channel, signaling the client file object and freeing the channel
118 // id. Once closed, the client side of the channel always returns the error
119 // ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE.
120 Status<void> CloseChannel(int channel_id) {
121 UNUSED(channel_id);
122 return Status<void>();
123 }
124
125 // Update the event bits for the given channel (given by id), using the
126 // given clear and set masks.
127 Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
128 int set_mask) {
129 UNUSED(channel_id);
130 UNUSED(clear_mask);
131 UNUSED(set_mask);
132 return Status<void>();
133 }
134
135 // Create a new channel and push it as a file descriptor to the process
136 // sending the |message|. |flags| may be set to O_NONBLOCK and/or
137 // O_CLOEXEC to control the initial behavior of the new file descriptor (the
138 // sending process may change these later using fcntl()). The internal
139 // Channel instance associated with this channel is set to |channel|,
140 // which may be nullptr. The new channel id allocated for this channel is
141 // returned in |channel_id|, which may also be nullptr if not needed.
142 Status<RemoteChannelHandle> PushChannel(Message* message, int flags,
143 Channel* channel, int* channel_id) {
144 UNUSED(message);
145 UNUSED(flags);
146 UNUSED(channel);
147 UNUSED(channel_id);
148 return Status<RemoteChannelHandle>();
149 }
150
151 // Check whether the |ref| is a reference to a channel to the service
152 // represented by the |endpoint|. If the channel reference in question is
153 // valid, the Channel object is returned in |channel| when non-nullptr and
154 // the channel ID is returned through the Status object.
155 Status<int> CheckChannel(const Message* message, ChannelReference ref,
156 Channel** channel) {
157 UNUSED(message);
158 UNUSED(ref);
159 UNUSED(channel);
160 return Status<int>();
161 }
162
163 // Replies to the message with a return code.
164 Status<void> MessageReply(Message* message, int return_code) {
165 UNUSED(message);
166 UNUSED(return_code);
167 return Status<void>();
168 }
169
170 // Replies to the message with a file descriptor.
171 Status<void> MessageReplyFd(Message* message, unsigned int push_fd) {
172 UNUSED(message);
173 UNUSED(push_fd);
174 return Status<void>();
175 }
176
177 // Replies to the message with a local channel handle.
178 Status<void> MessageReplyChannelHandle(Message* message,
179 const LocalChannelHandle& handle) {
180 UNUSED(message);
181 UNUSED(handle);
182 return Status<void>();
183 }
184
185 // Replies to the message with a borrowed local channel handle.
186 Status<void> MessageReplyChannelHandle(Message* message,
187 const BorrowedChannelHandle& handle) {
188 UNUSED(message);
189 UNUSED(handle);
190 return Status<void>();
191 }
192
193 // Replies to the message with a remote channel handle.
194 Status<void> MessageReplyChannelHandle(Message* message,
195 const RemoteChannelHandle& handle) {
196 UNUSED(message);
197 UNUSED(handle);
198 return Status<void>();
199 }
200
201 // Reads message data into an array of memory buffers.
202 Status<size_t> ReadMessageData(Message* message, const iovec* vector,
203 size_t vector_length) {
204 UNUSED(message);
205 UNUSED(vector);
206 UNUSED(vector_length);
207 return Status<size_t>();
208 }
209
210 // Sends reply data for message.
211 Status<size_t> WriteMessageData(Message* message, const iovec* vector,
212 size_t vector_length) {
213 UNUSED(message);
214 UNUSED(vector);
215 UNUSED(vector_length);
216 return Status<size_t>();
217 }
218
219 // Records a file descriptor into the message buffer and returns the
220 // remapped reference to be sent to the remote process.
221 Status<FileReference> PushFileHandle(Message* message,
222 const LocalHandle& handle) {
223 UNUSED(message);
224 UNUSED(handle);
225 return Status<FileReference>();
226 }
227
228 Status<FileReference> PushFileHandle(Message* message,
229 const BorrowedHandle& handle) {
230 UNUSED(message);
231 UNUSED(handle);
232 return Status<FileReference>();
233 }
234
235 Status<FileReference> PushFileHandle(Message* message,
236 const RemoteHandle& handle) {
237 UNUSED(message);
238 UNUSED(handle);
239 return Status<FileReference>();
240 }
241
242 Status<ChannelReference> PushChannelHandle(Message* message,
243 const LocalChannelHandle& handle) {
244 UNUSED(message);
245 UNUSED(handle);
246 return Status<ChannelReference>();
247 }
248
249 Status<ChannelReference> PushChannelHandle(
250 Message* message, const BorrowedChannelHandle& handle) {
251 UNUSED(message);
252 UNUSED(handle);
253 return Status<ChannelReference>();
254 }
255
256 Status<ChannelReference> PushChannelHandle(
257 Message* message, const RemoteChannelHandle& handle) {
258 UNUSED(message);
259 UNUSED(handle);
260 return Status<ChannelReference>();
261 }
262
263 // Obtains a file descriptor/channel handle from a message for the given
264 // reference.
265 LocalHandle GetFileHandle(Message* message, FileReference ref) const {
266 UNUSED(message);
267 UNUSED(ref);
268 return LocalHandle();
269 }
270
271 LocalChannelHandle GetChannelHandle(Message* message,
272 ChannelReference ref) const {
273 UNUSED(message);
274 UNUSED(ref);
275 return LocalChannelHandle();
276 }
277
278 // Transport-specific message state management.
279 void* AllocateMessageState() { return nullptr; }
280
281 void FreeMessageState(void* state) { UNUSED(state); }
282
283 // Cancels the endpoint, unblocking any receiver threads waiting for a
284 // message.
285 Status<void> Cancel() { return Status<void>(); }
286
287 private:
288 FuzzedDataProvider* _fdp;
289 std::shared_ptr<Channel> _channel;
290 Service* _service;
291 int _epoll_fd;
292};
293
294#endif // LEV_FUZZERS_LIBPDX_HELPERS_H_