1 /*
2 * Copyright 2022 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 #include <android-base/stringprintf.h>
17 #include <gui/BufferQueueConsumer.h>
18 #include <gui/BufferQueueCore.h>
19 #include <gui/BufferQueueProducer.h>
20 #include <gui/bufferqueue/2.0/types.h>
21 #include <system/window.h>
22
23 #include <libgui_fuzzer_utils.h>
24
25 using namespace android;
26 using namespace hardware::graphics::bufferqueue;
27 using namespace V1_0::utils;
28 using namespace V2_0::utils;
29
30 constexpr int32_t kMaxBytes = 256;
31
32 constexpr int32_t kError[] = {
33 OK, NO_MEMORY, NO_INIT, BAD_VALUE, DEAD_OBJECT, INVALID_OPERATION,
34 TIMED_OUT, WOULD_BLOCK, UNKNOWN_ERROR, ALREADY_EXISTS,
35 };
36
37 constexpr int32_t kAPIConnection[] = {
38 BufferQueueCore::CURRENTLY_CONNECTED_API,
39 BufferQueueCore::NO_CONNECTED_API,
40 NATIVE_WINDOW_API_EGL,
41 NATIVE_WINDOW_API_CPU,
42 NATIVE_WINDOW_API_MEDIA,
43 NATIVE_WINDOW_API_CAMERA,
44 };
45
46 class BufferQueueFuzzer {
47 public:
BufferQueueFuzzer(const uint8_t * data,size_t size)48 BufferQueueFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
49 void process();
50
51 private:
52 void invokeTypes();
53 void invokeH2BGraphicBufferV1();
54 void invokeH2BGraphicBufferV2();
55 void invokeBufferQueueConsumer();
56 void invokeBufferQueueProducer();
57 void invokeBlastBufferQueue();
58 void invokeQuery(sp<BufferQueueProducer>);
59 void invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer>);
60 void invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer>);
61 void invokeAcquireBuffer(sp<BufferQueueConsumer>);
62 void invokeOccupancyTracker(sp<BufferQueueConsumer>);
63 sp<SurfaceControl> makeSurfaceControl();
64 sp<BLASTBufferQueue> makeBLASTBufferQueue(sp<SurfaceControl>);
65
66 FuzzedDataProvider mFdp;
67 };
68
69 class ManageResourceHandle {
70 public:
ManageResourceHandle(FuzzedDataProvider * fdp)71 ManageResourceHandle(FuzzedDataProvider* fdp) {
72 mNativeHandle = native_handle_create(0 /*numFds*/, 1 /*numInts*/);
73 mShouldOwn = fdp->ConsumeBool();
74 mStream = NativeHandle::create(mNativeHandle, mShouldOwn);
75 }
~ManageResourceHandle()76 ~ManageResourceHandle() {
77 if (!mShouldOwn) {
78 native_handle_close(mNativeHandle);
79 native_handle_delete(mNativeHandle);
80 }
81 }
getStream()82 sp<NativeHandle> getStream() { return mStream; }
83
84 private:
85 bool mShouldOwn;
86 sp<NativeHandle> mStream;
87 native_handle_t* mNativeHandle;
88 };
89
makeSurfaceControl()90 sp<SurfaceControl> BufferQueueFuzzer::makeSurfaceControl() {
91 sp<IBinder> handle;
92 const sp<FakeBnSurfaceComposerClient> testClient(new FakeBnSurfaceComposerClient());
93 sp<SurfaceComposerClient> client = new SurfaceComposerClient(testClient);
94 sp<BnGraphicBufferProducer> producer;
95 uint32_t layerId = mFdp.ConsumeIntegral<uint32_t>();
96 std::string layerName = base::StringPrintf("#%d", layerId);
97 return sp<SurfaceControl>::make(client, handle, layerId, layerName,
98 mFdp.ConsumeIntegral<int32_t>(),
99 mFdp.ConsumeIntegral<uint32_t>(),
100 mFdp.ConsumeIntegral<int32_t>(),
101 mFdp.ConsumeIntegral<uint32_t>(),
102 mFdp.ConsumeIntegral<uint32_t>());
103 }
104
makeBLASTBufferQueue(sp<SurfaceControl> surface)105 sp<BLASTBufferQueue> BufferQueueFuzzer::makeBLASTBufferQueue(sp<SurfaceControl> surface) {
106 return sp<BLASTBufferQueue>::make(mFdp.ConsumeRandomLengthString(kMaxBytes), surface,
107 mFdp.ConsumeIntegral<uint32_t>(),
108 mFdp.ConsumeIntegral<uint32_t>(),
109 mFdp.ConsumeIntegral<int32_t>());
110 }
111
invokeBlastBufferQueue()112 void BufferQueueFuzzer::invokeBlastBufferQueue() {
113 sp<SurfaceControl> surface = makeSurfaceControl();
114 sp<BLASTBufferQueue> queue = makeBLASTBufferQueue(surface);
115
116 BufferItem item;
117 queue->onFrameAvailable(item);
118 queue->onFrameReplaced(item);
119 uint64_t bufferId = mFdp.ConsumeIntegral<uint64_t>();
120 queue->onFrameDequeued(bufferId);
121 queue->onFrameCancelled(bufferId);
122
123 SurfaceComposerClient::Transaction next;
124 uint64_t frameNumber = mFdp.ConsumeIntegral<uint64_t>();
125 queue->mergeWithNextTransaction(&next, frameNumber);
126 queue->applyPendingTransactions(frameNumber);
127
128 queue->update(surface, mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
129 mFdp.ConsumeIntegral<int32_t>());
130 queue->setFrameRate(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeIntegral<int8_t>(),
131 mFdp.ConsumeBool() /*shouldBeSeamless*/);
132 FrameTimelineInfo info;
133 queue->setFrameTimelineInfo(mFdp.ConsumeIntegral<uint64_t>(), info);
134
135 ManageResourceHandle handle(&mFdp);
136 queue->setSidebandStream(handle.getStream());
137
138 queue->getLastTransformHint();
139 queue->getLastAcquiredFrameNum();
140
141 CompositorTiming compTiming;
142 sp<Fence> previousFence = new Fence(memfd_create("pfd", MFD_ALLOW_SEALING));
143 sp<Fence> gpuFence = new Fence(memfd_create("gfd", MFD_ALLOW_SEALING));
144 FrameEventHistoryStats frameStats(frameNumber, gpuFence, compTiming,
145 mFdp.ConsumeIntegral<int64_t>(),
146 mFdp.ConsumeIntegral<int64_t>());
147 std::vector<SurfaceControlStats> stats;
148 sp<Fence> presentFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING));
149 SurfaceControlStats controlStats(surface, mFdp.ConsumeIntegral<int64_t>(),
150 mFdp.ConsumeIntegral<int64_t>(), presentFence, previousFence,
151 mFdp.ConsumeIntegral<uint32_t>(), frameStats,
152 mFdp.ConsumeIntegral<uint32_t>());
153 stats.push_back(controlStats);
154 }
155
invokeQuery(sp<BufferQueueProducer> producer)156 void BufferQueueFuzzer::invokeQuery(sp<BufferQueueProducer> producer) {
157 int32_t value;
158 producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
159 }
160
invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer> producer)161 void BufferQueueFuzzer::invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer> producer) {
162 int32_t value;
163 producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
164 }
165
invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer> producer)166 void BufferQueueFuzzer::invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer> producer) {
167 int32_t value;
168 producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
169 }
170
invokeBufferQueueProducer()171 void BufferQueueFuzzer::invokeBufferQueueProducer() {
172 sp<BufferQueueCore> core(new BufferQueueCore());
173 sp<BufferQueueProducer> producer(new BufferQueueProducer(core));
174 const sp<android::IProducerListener> listener;
175 android::IGraphicBufferProducer::QueueBufferOutput output;
176 uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
177 producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
178
179 sp<GraphicBuffer> buffer;
180 int32_t slot = mFdp.ConsumeIntegral<int32_t>();
181 uint32_t maxBuffers = mFdp.ConsumeIntegral<uint32_t>();
182 producer->requestBuffer(slot, &buffer);
183 producer->setMaxDequeuedBufferCount(maxBuffers);
184 producer->setAsyncMode(mFdp.ConsumeBool() /*async*/);
185
186 android::IGraphicBufferProducer::QueueBufferInput input;
187 producer->attachBuffer(&slot, buffer);
188 producer->queueBuffer(slot, input, &output);
189
190 int32_t format = mFdp.ConsumeIntegral<int32_t>();
191 uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
192 uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
193 uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
194 uint64_t outBufferAge;
195 FrameEventHistoryDelta outTimestamps;
196 sp<android::Fence> fence;
197 producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
198 &outTimestamps);
199 producer->detachBuffer(slot);
200 producer->detachNextBuffer(&buffer, &fence);
201 producer->cancelBuffer(slot, fence);
202
203 invokeQuery(producer);
204
205 ManageResourceHandle handle(&mFdp);
206 producer->setSidebandStream(handle.getStream());
207
208 producer->allocateBuffers(width, height, format, usage);
209 producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
210 producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
211 producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
212 producer->setLegacyBufferDrop(mFdp.ConsumeBool() /*drop*/);
213 producer->setAutoPrerotation(mFdp.ConsumeBool() /*autoPrerotation*/);
214
215 producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
216 producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
217 producer->disconnect(api);
218 }
219
invokeAcquireBuffer(sp<BufferQueueConsumer> consumer)220 void BufferQueueFuzzer::invokeAcquireBuffer(sp<BufferQueueConsumer> consumer) {
221 BufferItem item;
222 consumer->acquireBuffer(&item, mFdp.ConsumeIntegral<uint32_t>(),
223 mFdp.ConsumeIntegral<uint64_t>());
224 }
225
invokeOccupancyTracker(sp<BufferQueueConsumer> consumer)226 void BufferQueueFuzzer::invokeOccupancyTracker(sp<BufferQueueConsumer> consumer) {
227 String8 outResult;
228 String8 prefix((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
229 consumer->dumpState(prefix, &outResult);
230
231 std::vector<OccupancyTracker::Segment> outHistory;
232 consumer->getOccupancyHistory(mFdp.ConsumeBool() /*forceFlush*/, &outHistory);
233 }
234
invokeBufferQueueConsumer()235 void BufferQueueFuzzer::invokeBufferQueueConsumer() {
236 sp<BufferQueueCore> core(new BufferQueueCore());
237 sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
238 sp<android::IConsumerListener> listener;
239 consumer->consumerConnect(listener, mFdp.ConsumeBool() /*controlledByApp*/);
240 invokeAcquireBuffer(consumer);
241
242 int32_t slot = mFdp.ConsumeIntegral<int32_t>();
243 sp<GraphicBuffer> buffer =
244 new GraphicBuffer(mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
245 mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
246 mFdp.ConsumeIntegral<uint64_t>());
247 consumer->attachBuffer(&slot, buffer);
248 consumer->detachBuffer(slot);
249
250 consumer->setDefaultBufferSize(mFdp.ConsumeIntegral<uint32_t>(),
251 mFdp.ConsumeIntegral<uint32_t>());
252 consumer->setMaxBufferCount(mFdp.ConsumeIntegral<int32_t>());
253 consumer->setMaxAcquiredBufferCount(mFdp.ConsumeIntegral<int32_t>());
254
255 String8 name((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
256 consumer->setConsumerName(name);
257 consumer->setDefaultBufferFormat(mFdp.ConsumeIntegral<int32_t>());
258 android_dataspace dataspace =
259 static_cast<android_dataspace>(mFdp.PickValueInArray(kDataspaces));
260 consumer->setDefaultBufferDataSpace(dataspace);
261
262 consumer->setTransformHint(mFdp.ConsumeIntegral<uint32_t>());
263 consumer->setConsumerUsageBits(mFdp.ConsumeIntegral<uint64_t>());
264 consumer->setConsumerIsProtected(mFdp.ConsumeBool() /*isProtected*/);
265 invokeOccupancyTracker(consumer);
266
267 sp<Fence> releaseFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING));
268 consumer->releaseBuffer(mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint64_t>(),
269 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
270 consumer->consumerDisconnect();
271 }
272
invokeTypes()273 void BufferQueueFuzzer::invokeTypes() {
274 HStatus hStatus;
275 int32_t status = mFdp.PickValueInArray(kError);
276 bool bufferNeedsReallocation = mFdp.ConsumeBool();
277 bool releaseAllBuffers = mFdp.ConsumeBool();
278 b2h(status, &hStatus, &bufferNeedsReallocation, &releaseAllBuffers);
279 h2b(hStatus, &status);
280
281 HConnectionType type;
282 int32_t apiConnection = mFdp.PickValueInArray(kAPIConnection);
283 b2h(apiConnection, &type);
284 h2b(type, &apiConnection);
285 }
286
invokeH2BGraphicBufferV1()287 void BufferQueueFuzzer::invokeH2BGraphicBufferV1() {
288 sp<V1_0::utils::H2BGraphicBufferProducer> producer(
289 new V1_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV1()));
290 const sp<android::IProducerListener> listener;
291 android::IGraphicBufferProducer::QueueBufferOutput output;
292 uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
293 producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
294
295 sp<GraphicBuffer> buffer;
296 int32_t slot = mFdp.ConsumeIntegral<int32_t>();
297 producer->requestBuffer(slot, &buffer);
298 producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<int32_t>());
299 producer->setAsyncMode(mFdp.ConsumeBool());
300
301 android::IGraphicBufferProducer::QueueBufferInput input;
302 input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING));
303 producer->attachBuffer(&slot, buffer);
304 producer->queueBuffer(slot, input, &output);
305
306 int32_t format = mFdp.ConsumeIntegral<int32_t>();
307 uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
308 uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
309 uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
310 uint64_t outBufferAge;
311 FrameEventHistoryDelta outTimestamps;
312 sp<android::Fence> fence;
313 producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
314 &outTimestamps);
315 producer->detachBuffer(slot);
316 producer->cancelBuffer(slot, fence);
317
318 invokeQuery(producer);
319
320 ManageResourceHandle handle(&mFdp);
321 producer->setSidebandStream(handle.getStream());
322
323 producer->allocateBuffers(width, height, format, usage);
324 producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
325 producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
326 producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
327
328 producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
329 producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
330 producer->disconnect(api);
331 }
332
invokeH2BGraphicBufferV2()333 void BufferQueueFuzzer::invokeH2BGraphicBufferV2() {
334 sp<V2_0::utils::H2BGraphicBufferProducer> producer(
335 new V2_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV2()));
336 const sp<android::IProducerListener> listener;
337 android::IGraphicBufferProducer::QueueBufferOutput output;
338 uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
339 producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
340
341 sp<GraphicBuffer> buffer;
342 int32_t slot = mFdp.ConsumeIntegral<int32_t>();
343 producer->requestBuffer(slot, &buffer);
344 producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<uint32_t>());
345 producer->setAsyncMode(mFdp.ConsumeBool());
346
347 android::IGraphicBufferProducer::QueueBufferInput input;
348 input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING));
349 producer->attachBuffer(&slot, buffer);
350 producer->queueBuffer(slot, input, &output);
351
352 int32_t format = mFdp.ConsumeIntegral<int32_t>();
353 uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
354 uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
355 uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
356 uint64_t outBufferAge;
357 FrameEventHistoryDelta outTimestamps;
358 sp<android::Fence> fence;
359 producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
360 &outTimestamps);
361 producer->detachBuffer(slot);
362 producer->cancelBuffer(slot, fence);
363
364 invokeQuery(producer);
365
366 ManageResourceHandle handle(&mFdp);
367 producer->setSidebandStream(handle.getStream());
368
369 producer->allocateBuffers(width, height, format, usage);
370 producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
371 producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
372 producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
373
374 producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
375 producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
376 producer->disconnect(api);
377 }
378
process()379 void BufferQueueFuzzer::process() {
380 invokeBlastBufferQueue();
381 invokeH2BGraphicBufferV1();
382 invokeH2BGraphicBufferV2();
383 invokeTypes();
384 invokeBufferQueueConsumer();
385 invokeBufferQueueProducer();
386 }
387
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)388 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
389 BufferQueueFuzzer bufferQueueFuzzer(data, size);
390 bufferQueueFuzzer.process();
391 return 0;
392 }
393