1 /******************************************************************************
2 *
3 * Copyright (C) 2020 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <fuzzer/FuzzedDataProvider.h>
21 #include <stdio.h>
22
23 #include <AAudioService.h>
24 #include <aaudio/AAudio.h>
25 #include "aaudio/BnAAudioClient.h"
26 #include <android/content/AttributionSourceState.h>
27
28 #define UNUSED_PARAM __attribute__((unused))
29
30 using namespace android;
31 using namespace aaudio;
32
33 aaudio_format_t kAAudioFormats[] = {
34 AAUDIO_FORMAT_UNSPECIFIED,
35 AAUDIO_FORMAT_PCM_I16,
36 AAUDIO_FORMAT_PCM_FLOAT,
37 };
38
39 aaudio_usage_t kAAudioUsages[] = {
40 AAUDIO_USAGE_MEDIA,
41 AAUDIO_USAGE_VOICE_COMMUNICATION,
42 AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
43 AAUDIO_USAGE_ALARM,
44 AAUDIO_USAGE_NOTIFICATION,
45 AAUDIO_USAGE_NOTIFICATION_RINGTONE,
46 AAUDIO_USAGE_NOTIFICATION_EVENT,
47 AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
48 AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
49 AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
50 AAUDIO_USAGE_GAME,
51 AAUDIO_USAGE_ASSISTANT,
52 AAUDIO_SYSTEM_USAGE_EMERGENCY,
53 AAUDIO_SYSTEM_USAGE_SAFETY,
54 AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
55 AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
56 };
57
58 aaudio_content_type_t kAAudioContentTypes[] = {
59 AAUDIO_CONTENT_TYPE_SPEECH,
60 AAUDIO_CONTENT_TYPE_MUSIC,
61 AAUDIO_CONTENT_TYPE_MOVIE,
62 AAUDIO_CONTENT_TYPE_SONIFICATION,
63 };
64
65 aaudio_input_preset_t kAAudioInputPresets[] = {
66 AAUDIO_INPUT_PRESET_GENERIC, AAUDIO_INPUT_PRESET_CAMCORDER,
67 AAUDIO_INPUT_PRESET_VOICE_RECOGNITION, AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
68 AAUDIO_INPUT_PRESET_UNPROCESSED, AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
69 };
70
71 aaudio_channel_mask_t kAAudioChannelMasks[] = {
72 AAUDIO_UNSPECIFIED,
73 AAUDIO_CHANNEL_INDEX_MASK_1,
74 AAUDIO_CHANNEL_INDEX_MASK_2,
75 AAUDIO_CHANNEL_INDEX_MASK_3,
76 AAUDIO_CHANNEL_INDEX_MASK_4,
77 AAUDIO_CHANNEL_INDEX_MASK_5,
78 AAUDIO_CHANNEL_INDEX_MASK_6,
79 AAUDIO_CHANNEL_INDEX_MASK_7,
80 AAUDIO_CHANNEL_INDEX_MASK_8,
81 AAUDIO_CHANNEL_INDEX_MASK_9,
82 AAUDIO_CHANNEL_INDEX_MASK_10,
83 AAUDIO_CHANNEL_INDEX_MASK_11,
84 AAUDIO_CHANNEL_INDEX_MASK_12,
85 AAUDIO_CHANNEL_INDEX_MASK_13,
86 AAUDIO_CHANNEL_INDEX_MASK_14,
87 AAUDIO_CHANNEL_INDEX_MASK_15,
88 AAUDIO_CHANNEL_INDEX_MASK_16,
89 AAUDIO_CHANNEL_INDEX_MASK_17,
90 AAUDIO_CHANNEL_INDEX_MASK_18,
91 AAUDIO_CHANNEL_INDEX_MASK_19,
92 AAUDIO_CHANNEL_INDEX_MASK_20,
93 AAUDIO_CHANNEL_INDEX_MASK_21,
94 AAUDIO_CHANNEL_INDEX_MASK_22,
95 AAUDIO_CHANNEL_INDEX_MASK_23,
96 AAUDIO_CHANNEL_INDEX_MASK_24,
97 AAUDIO_CHANNEL_MONO,
98 AAUDIO_CHANNEL_STEREO,
99 AAUDIO_CHANNEL_FRONT_BACK,
100 AAUDIO_CHANNEL_2POINT0POINT2,
101 AAUDIO_CHANNEL_2POINT1POINT2,
102 AAUDIO_CHANNEL_3POINT0POINT2,
103 AAUDIO_CHANNEL_3POINT1POINT2,
104 AAUDIO_CHANNEL_5POINT1,
105 AAUDIO_CHANNEL_MONO,
106 AAUDIO_CHANNEL_STEREO,
107 AAUDIO_CHANNEL_2POINT1,
108 AAUDIO_CHANNEL_TRI,
109 AAUDIO_CHANNEL_TRI_BACK,
110 AAUDIO_CHANNEL_3POINT1,
111 AAUDIO_CHANNEL_2POINT0POINT2,
112 AAUDIO_CHANNEL_2POINT1POINT2,
113 AAUDIO_CHANNEL_3POINT0POINT2,
114 AAUDIO_CHANNEL_3POINT1POINT2,
115 AAUDIO_CHANNEL_QUAD,
116 AAUDIO_CHANNEL_QUAD_SIDE,
117 AAUDIO_CHANNEL_SURROUND,
118 AAUDIO_CHANNEL_PENTA,
119 AAUDIO_CHANNEL_5POINT1,
120 AAUDIO_CHANNEL_5POINT1_SIDE,
121 AAUDIO_CHANNEL_5POINT1POINT2,
122 AAUDIO_CHANNEL_5POINT1POINT4,
123 AAUDIO_CHANNEL_6POINT1,
124 AAUDIO_CHANNEL_7POINT1,
125 AAUDIO_CHANNEL_7POINT1POINT2,
126 AAUDIO_CHANNEL_7POINT1POINT4,
127 AAUDIO_CHANNEL_9POINT1POINT4,
128 AAUDIO_CHANNEL_9POINT1POINT6,
129 };
130
131 const size_t kNumAAudioFormats = std::size(kAAudioFormats);
132 const size_t kNumAAudioUsages = std::size(kAAudioUsages);
133 const size_t kNumAAudioContentTypes = std::size(kAAudioContentTypes);
134 const size_t kNumAAudioInputPresets = std::size(kAAudioInputPresets);
135 const size_t kNumAAudioChannelMasks = std::size(kAAudioChannelMasks);
136
137 class FuzzAAudioClient : public virtual RefBase, public AAudioServiceInterface {
138 public:
139 FuzzAAudioClient(sp<AAudioService> service);
140
141 virtual ~FuzzAAudioClient();
142
143 AAudioServiceInterface *getAAudioService();
144
145 void dropAAudioService();
146
registerClient(const sp<IAAudioClient> & client UNUSED_PARAM)147 void registerClient(const sp<IAAudioClient> &client UNUSED_PARAM) override {}
148
149 aaudio_handle_t openStream(const AAudioStreamRequest &request,
150 AAudioStreamConfiguration &configurationOutput) override;
151
152 aaudio_result_t closeStream(aaudio_handle_t streamHandle) override;
153
154 aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
155 AudioEndpointParcelable &parcelable) override;
156
157 aaudio_result_t startStream(aaudio_handle_t streamHandle) override;
158
159 aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override;
160
161 aaudio_result_t stopStream(aaudio_handle_t streamHandle) override;
162
163 aaudio_result_t flushStream(aaudio_handle_t streamHandle) override;
164
165 aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId,
166 int64_t periodNanoseconds) override;
167
168 aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
169 pid_t clientThreadId) override;
170
startClient(aaudio_handle_t streamHandle UNUSED_PARAM,const AudioClient & client UNUSED_PARAM,const audio_attributes_t * attr UNUSED_PARAM,audio_port_handle_t * clientHandle UNUSED_PARAM)171 aaudio_result_t startClient(aaudio_handle_t streamHandle UNUSED_PARAM,
172 const AudioClient &client UNUSED_PARAM,
173 const audio_attributes_t *attr UNUSED_PARAM,
174 audio_port_handle_t *clientHandle UNUSED_PARAM) override {
175 return AAUDIO_ERROR_UNAVAILABLE;
176 }
177
stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,audio_port_handle_t clientHandle UNUSED_PARAM)178 aaudio_result_t stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,
179 audio_port_handle_t clientHandle UNUSED_PARAM) override {
180 return AAUDIO_ERROR_UNAVAILABLE;
181 }
182
exitStandby(aaudio_handle_t streamHandle UNUSED_PARAM,AudioEndpointParcelable & parcelable UNUSED_PARAM)183 aaudio_result_t exitStandby(aaudio_handle_t streamHandle UNUSED_PARAM,
184 AudioEndpointParcelable &parcelable UNUSED_PARAM) override {
185 return AAUDIO_ERROR_UNAVAILABLE;
186 }
187
onStreamChange(aaudio_handle_t handle,int32_t opcode,int32_t value)188 void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {}
189
getDeathCount()190 int getDeathCount() { return mDeathCount; }
191
incDeathCount()192 void incDeathCount() { ++mDeathCount; }
193
194 class AAudioClient : public IBinder::DeathRecipient, public BnAAudioClient {
195 public:
AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient)196 AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient) : mBinderClient(fuzzAAudioClient) {}
197
binderDied(const wp<IBinder> & who UNUSED_PARAM)198 virtual void binderDied(const wp<IBinder> &who UNUSED_PARAM) {
199 sp<FuzzAAudioClient> client = mBinderClient.promote();
200 if (client.get()) {
201 client->dropAAudioService();
202 client->incDeathCount();
203 }
204 }
205
onStreamChange(int32_t handle,int32_t opcode,int32_t value)206 android::binder::Status onStreamChange(int32_t handle, int32_t opcode, int32_t value) {
207 static_assert(std::is_same_v<aaudio_handle_t, int32_t>);
208 android::sp<FuzzAAudioClient> client = mBinderClient.promote();
209 if (client.get() != nullptr) {
210 client->onStreamChange(handle, opcode, value);
211 }
212 return android::binder::Status::ok();
213 }
214
215 private:
216 wp<FuzzAAudioClient> mBinderClient;
217 };
218
219 private:
220 sp<AAudioService> mAAudioService;
221 sp<AAudioClient> mAAudioClient;
222 AAudioServiceInterface *mAAudioServiceInterface;
223 int mDeathCount;
224 };
225
FuzzAAudioClient(sp<AAudioService> service)226 FuzzAAudioClient::FuzzAAudioClient(sp<AAudioService> service) : AAudioServiceInterface() {
227 mAAudioService = service;
228 mAAudioServiceInterface = &service->asAAudioServiceInterface();
229 mAAudioClient = new AAudioClient(this);
230 mDeathCount = 0;
231 if (mAAudioClient.get() && mAAudioService.get()) {
232 mAAudioService->linkToDeath(mAAudioClient);
233 mAAudioService->registerClient(mAAudioClient);
234 }
235 }
236
~FuzzAAudioClient()237 FuzzAAudioClient::~FuzzAAudioClient() { dropAAudioService(); }
238
getAAudioService()239 AAudioServiceInterface *FuzzAAudioClient::getAAudioService() {
240 if (!mAAudioServiceInterface && mAAudioService.get()) {
241 mAAudioServiceInterface = &mAAudioService->asAAudioServiceInterface();
242 }
243 return mAAudioServiceInterface;
244 }
245
dropAAudioService()246 void FuzzAAudioClient::dropAAudioService() {
247 mAAudioService.clear();
248 }
249
openStream(const AAudioStreamRequest & request,AAudioStreamConfiguration & configurationOutput)250 aaudio_handle_t FuzzAAudioClient::openStream(const AAudioStreamRequest &request,
251 AAudioStreamConfiguration &configurationOutput) {
252 aaudio_handle_t stream;
253 for (int i = 0; i < 2; ++i) {
254 AAudioServiceInterface *service = getAAudioService();
255 if (!service) {
256 return AAUDIO_ERROR_NO_SERVICE;
257 }
258
259 stream = service->openStream(request, configurationOutput);
260
261 if (stream == AAUDIO_ERROR_NO_SERVICE) {
262 dropAAudioService();
263 } else {
264 break;
265 }
266 }
267 return stream;
268 }
269
closeStream(aaudio_handle_t streamHandle)270 aaudio_result_t FuzzAAudioClient::closeStream(aaudio_handle_t streamHandle) {
271 AAudioServiceInterface *service = getAAudioService();
272 if (!service) {
273 return AAUDIO_ERROR_NO_SERVICE;
274 }
275 return service->closeStream(streamHandle);
276 }
277
getStreamDescription(aaudio_handle_t streamHandle,AudioEndpointParcelable & parcelable)278 aaudio_result_t FuzzAAudioClient::getStreamDescription(aaudio_handle_t streamHandle,
279 AudioEndpointParcelable &parcelable) {
280 AAudioServiceInterface *service = getAAudioService();
281 if (!service) {
282 return AAUDIO_ERROR_NO_SERVICE;
283 }
284 return service->getStreamDescription(streamHandle, parcelable);
285 }
286
startStream(aaudio_handle_t streamHandle)287 aaudio_result_t FuzzAAudioClient::startStream(aaudio_handle_t streamHandle) {
288 AAudioServiceInterface *service = getAAudioService();
289 if (!service) {
290 return AAUDIO_ERROR_NO_SERVICE;
291 }
292 return service->startStream(streamHandle);
293 }
294
pauseStream(aaudio_handle_t streamHandle)295 aaudio_result_t FuzzAAudioClient::pauseStream(aaudio_handle_t streamHandle) {
296 AAudioServiceInterface *service = getAAudioService();
297 if (!service) {
298 return AAUDIO_ERROR_NO_SERVICE;
299 }
300 return service->pauseStream(streamHandle);
301 }
302
stopStream(aaudio_handle_t streamHandle)303 aaudio_result_t FuzzAAudioClient::stopStream(aaudio_handle_t streamHandle) {
304 AAudioServiceInterface *service = getAAudioService();
305 if (!service) {
306 return AAUDIO_ERROR_NO_SERVICE;
307 }
308 return service->stopStream(streamHandle);
309 }
310
flushStream(aaudio_handle_t streamHandle)311 aaudio_result_t FuzzAAudioClient::flushStream(aaudio_handle_t streamHandle) {
312 AAudioServiceInterface *service = getAAudioService();
313 if (!service) {
314 return AAUDIO_ERROR_NO_SERVICE;
315 }
316 return service->flushStream(streamHandle);
317 }
318
registerAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId,int64_t periodNanoseconds)319 aaudio_result_t FuzzAAudioClient::registerAudioThread(aaudio_handle_t streamHandle,
320 pid_t clientThreadId,
321 int64_t periodNanoseconds) {
322 AAudioServiceInterface *service = getAAudioService();
323 if (!service) {
324 return AAUDIO_ERROR_NO_SERVICE;
325 }
326 return service->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds);
327 }
328
unregisterAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId)329 aaudio_result_t FuzzAAudioClient::unregisterAudioThread(aaudio_handle_t streamHandle,
330 pid_t clientThreadId) {
331 AAudioServiceInterface *service = getAAudioService();
332 if (!service) {
333 return AAUDIO_ERROR_NO_SERVICE;
334 }
335 return service->unregisterAudioThread(streamHandle, clientThreadId);
336 }
337
338 class OboeserviceFuzzer {
339 public:
340 OboeserviceFuzzer();
341 ~OboeserviceFuzzer() = default;
342 void process(const uint8_t *data, size_t size);
343
344 private:
345 sp<FuzzAAudioClient> mClient;
346 };
347
OboeserviceFuzzer()348 OboeserviceFuzzer::OboeserviceFuzzer() {
349 sp<AAudioService> service = new AAudioService();
350 mClient = new FuzzAAudioClient(service);
351 }
352
process(const uint8_t * data,size_t size)353 void OboeserviceFuzzer::process(const uint8_t *data, size_t size) {
354 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
355 AAudioStreamRequest request;
356 AAudioStreamConfiguration configurationOutput;
357
358 // Initialize stream request
359 request.getConfiguration().setFormat((audio_format_t)(
360 fdp.ConsumeBool()
361 ? fdp.ConsumeIntegral<int32_t>()
362 : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
363
364 // TODO b/182392769: use attribution source util
365 android::content::AttributionSourceState attributionSource;
366 attributionSource.uid = getuid();
367 attributionSource.pid = getpid();
368 attributionSource.token = sp<BBinder>::make();
369 request.setAttributionSource(attributionSource);
370 request.setInService(fdp.ConsumeBool());
371
372 request.getConfiguration().setDeviceId(fdp.ConsumeIntegral<int32_t>());
373 request.getConfiguration().setSampleRate(fdp.ConsumeIntegral<int32_t>());
374 request.getConfiguration().setChannelMask((aaudio_channel_mask_t)(
375 fdp.ConsumeBool()
376 ? fdp.ConsumeIntegral<int32_t>()
377 : kAAudioChannelMasks[fdp.ConsumeIntegralInRange<int32_t>(
378 0, kNumAAudioChannelMasks - 1)]));
379 request.getConfiguration().setDirection(
380 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
381 : (fdp.ConsumeBool() ? AAUDIO_DIRECTION_OUTPUT : AAUDIO_DIRECTION_INPUT));
382 request.getConfiguration().setSharingMode(
383 fdp.ConsumeBool()
384 ? fdp.ConsumeIntegral<int32_t>()
385 : (fdp.ConsumeBool() ? AAUDIO_SHARING_MODE_EXCLUSIVE : AAUDIO_SHARING_MODE_SHARED));
386
387 request.getConfiguration().setUsage(
388 fdp.ConsumeBool()
389 ? fdp.ConsumeIntegral<int32_t>()
390 : kAAudioUsages[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioUsages - 1)]);
391 request.getConfiguration().setContentType(
392 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
393 : kAAudioContentTypes[fdp.ConsumeIntegralInRange<int32_t>(
394 0, kNumAAudioContentTypes - 1)]);
395 request.getConfiguration().setInputPreset(
396 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
397 : kAAudioInputPresets[fdp.ConsumeIntegralInRange<int32_t>(
398 0, kNumAAudioInputPresets - 1)]);
399 request.getConfiguration().setPrivacySensitive(fdp.ConsumeBool());
400
401 request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
402
403 aaudio_handle_t stream = mClient->openStream(request, configurationOutput);
404 if (stream < 0) {
405 // invalid request, stream not opened.
406 return;
407 }
408 while (fdp.remaining_bytes()) {
409 AudioEndpointParcelable audioEndpointParcelable;
410 int action = fdp.ConsumeIntegralInRange<int32_t>(0, 4);
411 switch (action) {
412 case 0:
413 mClient->getStreamDescription(stream, audioEndpointParcelable);
414 break;
415 case 1:
416 mClient->startStream(stream);
417 break;
418 case 2:
419 mClient->pauseStream(stream);
420 break;
421 case 3:
422 mClient->stopStream(stream);
423 break;
424 case 4:
425 mClient->flushStream(stream);
426 break;
427 }
428 }
429 mClient->closeStream(stream);
430 assert(mClient->getDeathCount() == 0);
431 }
432
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)433 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
434 if (size < 1) {
435 return 0;
436 }
437 OboeserviceFuzzer oboeserviceFuzzer;
438 oboeserviceFuzzer.process(data, size);
439 return 0;
440 }
441