1 /*
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 #include <fuzzer/FuzzedDataProvider.h>
20 #include <helpers.h>
21 #include <pdx/client_channel.h>
22 #include <pdx/service.h>
23 #include <pdx/service_dispatcher.h>
24 #include <stddef.h>
25 #include <stdint.h>
26 #include <sys/eventfd.h>
27 #include <thread>
28 
29 using namespace android::pdx;
30 
31 // Fuzzer for Message object functions.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)32 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
33   FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
34 
35   FuzzEndpoint* endpoint = new FuzzEndpoint(&fdp);
36   std::shared_ptr<Service> service(
37       new Service("FuzzService", std::unique_ptr<Endpoint>(endpoint)));
38   std::shared_ptr<Channel> channel(nullptr);
39 
40   // Generate a random Message object to call functions in.
41   MessageInfo info;
42   info.pid = fdp.ConsumeIntegral<int>();
43   info.tid = fdp.ConsumeIntegral<int>();
44   info.cid = fdp.ConsumeIntegral<int>();
45   info.mid = fdp.ConsumeIntegral<int>();
46   info.euid = fdp.ConsumeIntegral<int>();
47   info.egid = fdp.ConsumeIntegral<int>();
48   info.op = fdp.ConsumeIntegral<int32_t>();
49   info.flags = fdp.ConsumeIntegral<uint32_t>();
50   info.service = service.get();
51   info.channel = channel.get();
52   info.send_len = fdp.ConsumeIntegral<size_t>();
53   info.recv_len = fdp.ConsumeIntegral<size_t>();
54   info.fd_count = fdp.ConsumeIntegral<size_t>();
55   if (fdp.remaining_bytes() >= 32) {
56     std::vector<uint8_t> impulse_vec = fdp.ConsumeBytes<uint8_t>(32);
57     memcpy(info.impulse, impulse_vec.data(), 32);
58   }
59 
60   Message message = Message(info);
61 
62   // A bunch of getters that probably won't do much, but might as well
63   // get coverage, while we are here.
64   message.GetProcessId();
65   message.GetThreadId();
66   message.GetEffectiveUserId();
67   message.GetEffectiveGroupId();
68   message.GetChannelId();
69   message.GetMessageId();
70   message.GetOp();
71   message.GetFlags();
72   message.GetSendLength();
73   message.GetReceiveLength();
74   message.GetFileDescriptorCount();
75   message.ImpulseEnd();
76   message.replied();
77   message.IsChannelExpired();
78   message.IsServiceExpired();
79   message.GetState();
80   message.GetState();
81 
82   // Some misc. functions.
83   unsigned int fd = fdp.ConsumeIntegral<unsigned int>();
84   int clear_mask = fdp.ConsumeIntegral<int>();
85   int set_mask = fdp.ConsumeIntegral<int>();
86   Status<void> status = {};
87   message.ModifyChannelEvents(clear_mask, set_mask);
88 
89   // Fuzz the handle functions.
90   LocalHandle l_handle = {};
91   BorrowedHandle b_handle = {};
92   RemoteHandle r_handle = {};
93   LocalChannelHandle lc_handle = {};
94   BorrowedChannelHandle bc_handle = {};
95   RemoteChannelHandle rc_handle = {};
96   FileReference f_ref = fdp.ConsumeIntegral<int32_t>();
97   ChannelReference c_ref = fdp.ConsumeIntegral<int32_t>();
98 
99   // These don't actually modify any state in the Message or params.
100   // They can be called in any order.
101   message.PushFileHandle(b_handle);
102   message.PushFileHandle(r_handle);
103   message.PushChannelHandle(lc_handle);
104   message.PushChannelHandle(bc_handle);
105   message.PushChannelHandle(rc_handle);
106   message.GetFileHandle(f_ref, &l_handle);
107   message.GetChannelHandle(c_ref, &lc_handle);
108 
109   // Can only reply once, pick at random.
110   switch (fdp.ConsumeIntegral<uint8_t>()) {
111     case 0:
112       message.ReplyFileDescriptor(fd);
113       break;
114     case 1:
115       message.Reply(status);
116       break;
117     case 2:
118       message.Reply(l_handle);
119       break;
120     case 3:
121       message.Reply(b_handle);
122       break;
123     case 4:
124       message.Reply(r_handle);
125       break;
126     case 5:
127       message.Reply(lc_handle);
128       break;
129     case 6:
130       message.Reply(bc_handle);
131       break;
132     case 7:
133       message.Reply(rc_handle);
134   }
135 
136   // Fuzz the channel functions.
137   int flags = fdp.ConsumeIntegral<int>();
138   int channel_id = 0;
139   message.PushChannel(flags, channel, &channel_id);
140   message.CheckChannel(service.get(), c_ref, &channel);
141   message.CheckChannel(c_ref, &channel);
142   message.PushChannel(service.get(), flags, channel, &channel_id);
143   size_t iovec_size = sizeof(iovec);
144   struct iovec* iovecs = nullptr;
145 
146   // Fuzz the read/write functions. Needs at least one iovec, plus one byte.
147   if (fdp.remaining_bytes() >= iovec_size + 1) {
148     std::vector<uint8_t> tmp_vec = fdp.ConsumeBytes<uint8_t>(iovec_size);
149     struct iovec* vector = reinterpret_cast<struct iovec*>(tmp_vec.data());
150     std::vector<uint8_t> tmp_buf =
151         fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
152     void* buf = reinterpret_cast<void*>(tmp_buf.data());
153     size_t buf_size = fdp.ConsumeIntegral<size_t>();
154 
155     // Capping num_vecs to 1024 so it doesn't allocate too much memory.
156     size_t num_vecs = fdp.ConsumeIntegralInRange<size_t>(0, 1024);
157 
158     if (num_vecs > 0)
159       iovecs = new struct iovec[num_vecs];
160     for (size_t i = 0; i < num_vecs; i++) {
161       iovecs[i] = *vector;
162     }
163 
164     message.ReadAll(vector, buf_size);
165     message.WriteAll(buf, buf_size);
166     message.ReadVectorAll(vector, num_vecs);
167     message.WriteVectorAll(vector, num_vecs);
168     message.ReadVector(vector, buf_size);
169     message.WriteVector(vector, buf_size);
170   }
171 
172   if (iovecs != nullptr)
173     delete[] iovecs;
174   return 0;
175 }
176