• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 const size_t kNumAAudioFormats = std::size(kAAudioFormats);
72 const size_t kNumAAudioUsages = std::size(kAAudioUsages);
73 const size_t kNumAAudioContentTypes = std::size(kAAudioContentTypes);
74 const size_t kNumAAudioInputPresets = std::size(kAAudioInputPresets);
75 
76 class FuzzAAudioClient : public virtual RefBase, public AAudioServiceInterface {
77    public:
78     FuzzAAudioClient(sp<AAudioService> service);
79 
80     virtual ~FuzzAAudioClient();
81 
82     AAudioServiceInterface *getAAudioService();
83 
84     void dropAAudioService();
85 
registerClient(const sp<IAAudioClient> & client UNUSED_PARAM)86     void registerClient(const sp<IAAudioClient> &client UNUSED_PARAM) override {}
87 
88     aaudio_handle_t openStream(const AAudioStreamRequest &request,
89                                AAudioStreamConfiguration &configurationOutput) override;
90 
91     aaudio_result_t closeStream(aaudio_handle_t streamHandle) override;
92 
93     aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
94                                          AudioEndpointParcelable &parcelable) override;
95 
96     aaudio_result_t startStream(aaudio_handle_t streamHandle) override;
97 
98     aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override;
99 
100     aaudio_result_t stopStream(aaudio_handle_t streamHandle) override;
101 
102     aaudio_result_t flushStream(aaudio_handle_t streamHandle) override;
103 
104     aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId,
105                                         int64_t periodNanoseconds) override;
106 
107     aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
108                                           pid_t clientThreadId) override;
109 
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)110     aaudio_result_t startClient(aaudio_handle_t streamHandle UNUSED_PARAM,
111                                 const AudioClient &client UNUSED_PARAM,
112                                 const audio_attributes_t *attr UNUSED_PARAM,
113                                 audio_port_handle_t *clientHandle UNUSED_PARAM) override {
114         return AAUDIO_ERROR_UNAVAILABLE;
115     }
116 
stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,audio_port_handle_t clientHandle UNUSED_PARAM)117     aaudio_result_t stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,
118                                audio_port_handle_t clientHandle UNUSED_PARAM) override {
119         return AAUDIO_ERROR_UNAVAILABLE;
120     }
121 
onStreamChange(aaudio_handle_t handle,int32_t opcode,int32_t value)122     void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {}
123 
getDeathCount()124     int getDeathCount() { return mDeathCount; }
125 
incDeathCount()126     void incDeathCount() { ++mDeathCount; }
127 
128     class AAudioClient : public IBinder::DeathRecipient, public BnAAudioClient {
129        public:
AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient)130         AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient) : mBinderClient(fuzzAAudioClient) {}
131 
binderDied(const wp<IBinder> & who UNUSED_PARAM)132         virtual void binderDied(const wp<IBinder> &who UNUSED_PARAM) {
133             sp<FuzzAAudioClient> client = mBinderClient.promote();
134             if (client.get()) {
135                 client->dropAAudioService();
136                 client->incDeathCount();
137             }
138         }
139 
onStreamChange(int32_t handle,int32_t opcode,int32_t value)140         android::binder::Status onStreamChange(int32_t handle, int32_t opcode, int32_t value) {
141             static_assert(std::is_same_v<aaudio_handle_t, int32_t>);
142             android::sp<FuzzAAudioClient> client = mBinderClient.promote();
143             if (client.get() != nullptr) {
144                 client->onStreamChange(handle, opcode, value);
145             }
146             return android::binder::Status::ok();
147         }
148 
149        private:
150         wp<FuzzAAudioClient> mBinderClient;
151     };
152 
153    private:
154     sp<AAudioService> mAAudioService;
155     sp<AAudioClient> mAAudioClient;
156     AAudioServiceInterface *mAAudioServiceInterface;
157     int mDeathCount;
158 };
159 
FuzzAAudioClient(sp<AAudioService> service)160 FuzzAAudioClient::FuzzAAudioClient(sp<AAudioService> service) : AAudioServiceInterface() {
161     mAAudioService = service;
162     mAAudioServiceInterface = &service->asAAudioServiceInterface();
163     mAAudioClient = new AAudioClient(this);
164     mDeathCount = 0;
165     if (mAAudioClient.get() && mAAudioService.get()) {
166         mAAudioService->linkToDeath(mAAudioClient);
167         mAAudioService->registerClient(mAAudioClient);
168     }
169 }
170 
~FuzzAAudioClient()171 FuzzAAudioClient::~FuzzAAudioClient() { dropAAudioService(); }
172 
getAAudioService()173 AAudioServiceInterface *FuzzAAudioClient::getAAudioService() {
174     if (!mAAudioServiceInterface && mAAudioService.get()) {
175         mAAudioServiceInterface = &mAAudioService->asAAudioServiceInterface();
176     }
177     return mAAudioServiceInterface;
178 }
179 
dropAAudioService()180 void FuzzAAudioClient::dropAAudioService() {
181     mAAudioService.clear();
182 }
183 
openStream(const AAudioStreamRequest & request,AAudioStreamConfiguration & configurationOutput)184 aaudio_handle_t FuzzAAudioClient::openStream(const AAudioStreamRequest &request,
185                                              AAudioStreamConfiguration &configurationOutput) {
186     aaudio_handle_t stream;
187     for (int i = 0; i < 2; ++i) {
188         AAudioServiceInterface *service = getAAudioService();
189         if (!service) {
190             return AAUDIO_ERROR_NO_SERVICE;
191         }
192 
193         stream = service->openStream(request, configurationOutput);
194 
195         if (stream == AAUDIO_ERROR_NO_SERVICE) {
196             dropAAudioService();
197         } else {
198             break;
199         }
200     }
201     return stream;
202 }
203 
closeStream(aaudio_handle_t streamHandle)204 aaudio_result_t FuzzAAudioClient::closeStream(aaudio_handle_t streamHandle) {
205     AAudioServiceInterface *service = getAAudioService();
206     if (!service) {
207         return AAUDIO_ERROR_NO_SERVICE;
208     }
209     return service->closeStream(streamHandle);
210 }
211 
getStreamDescription(aaudio_handle_t streamHandle,AudioEndpointParcelable & parcelable)212 aaudio_result_t FuzzAAudioClient::getStreamDescription(aaudio_handle_t streamHandle,
213                                                        AudioEndpointParcelable &parcelable) {
214     AAudioServiceInterface *service = getAAudioService();
215     if (!service) {
216         return AAUDIO_ERROR_NO_SERVICE;
217     }
218     return service->getStreamDescription(streamHandle, parcelable);
219 }
220 
startStream(aaudio_handle_t streamHandle)221 aaudio_result_t FuzzAAudioClient::startStream(aaudio_handle_t streamHandle) {
222     AAudioServiceInterface *service = getAAudioService();
223     if (!service) {
224         return AAUDIO_ERROR_NO_SERVICE;
225     }
226     return service->startStream(streamHandle);
227 }
228 
pauseStream(aaudio_handle_t streamHandle)229 aaudio_result_t FuzzAAudioClient::pauseStream(aaudio_handle_t streamHandle) {
230     AAudioServiceInterface *service = getAAudioService();
231     if (!service) {
232         return AAUDIO_ERROR_NO_SERVICE;
233     }
234     return service->pauseStream(streamHandle);
235 }
236 
stopStream(aaudio_handle_t streamHandle)237 aaudio_result_t FuzzAAudioClient::stopStream(aaudio_handle_t streamHandle) {
238     AAudioServiceInterface *service = getAAudioService();
239     if (!service) {
240         return AAUDIO_ERROR_NO_SERVICE;
241     }
242     return service->stopStream(streamHandle);
243 }
244 
flushStream(aaudio_handle_t streamHandle)245 aaudio_result_t FuzzAAudioClient::flushStream(aaudio_handle_t streamHandle) {
246     AAudioServiceInterface *service = getAAudioService();
247     if (!service) {
248         return AAUDIO_ERROR_NO_SERVICE;
249     }
250     return service->flushStream(streamHandle);
251 }
252 
registerAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId,int64_t periodNanoseconds)253 aaudio_result_t FuzzAAudioClient::registerAudioThread(aaudio_handle_t streamHandle,
254                                                       pid_t clientThreadId,
255                                                       int64_t periodNanoseconds) {
256     AAudioServiceInterface *service = getAAudioService();
257     if (!service) {
258         return AAUDIO_ERROR_NO_SERVICE;
259     }
260     return service->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds);
261 }
262 
unregisterAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId)263 aaudio_result_t FuzzAAudioClient::unregisterAudioThread(aaudio_handle_t streamHandle,
264                                                         pid_t clientThreadId) {
265     AAudioServiceInterface *service = getAAudioService();
266     if (!service) {
267         return AAUDIO_ERROR_NO_SERVICE;
268     }
269     return service->unregisterAudioThread(streamHandle, clientThreadId);
270 }
271 
272 class OboeserviceFuzzer {
273    public:
274     OboeserviceFuzzer();
275     ~OboeserviceFuzzer() = default;
276     void process(const uint8_t *data, size_t size);
277 
278    private:
279     sp<FuzzAAudioClient> mClient;
280 };
281 
OboeserviceFuzzer()282 OboeserviceFuzzer::OboeserviceFuzzer() {
283     sp<AAudioService> service = new AAudioService();
284     mClient = new FuzzAAudioClient(service);
285 }
286 
process(const uint8_t * data,size_t size)287 void OboeserviceFuzzer::process(const uint8_t *data, size_t size) {
288     FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
289     AAudioStreamRequest request;
290     AAudioStreamConfiguration configurationOutput;
291 
292     // Initialize stream request
293     request.getConfiguration().setFormat((audio_format_t)(
294         fdp.ConsumeBool()
295             ? fdp.ConsumeIntegral<int32_t>()
296             : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
297 
298     // TODO b/182392769: use attribution source util
299     android::content::AttributionSourceState attributionSource;
300     attributionSource.uid = getuid();
301     attributionSource.pid = getpid();
302     attributionSource.token = sp<BBinder>::make();
303     request.setAttributionSource(attributionSource);
304     request.setInService(fdp.ConsumeBool());
305 
306     request.getConfiguration().setDeviceId(fdp.ConsumeIntegral<int32_t>());
307     request.getConfiguration().setSampleRate(fdp.ConsumeIntegral<int32_t>());
308     request.getConfiguration().setSamplesPerFrame(fdp.ConsumeIntegral<int32_t>());
309     request.getConfiguration().setDirection(
310         fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
311                           : (fdp.ConsumeBool() ? AAUDIO_DIRECTION_OUTPUT : AAUDIO_DIRECTION_INPUT));
312     request.getConfiguration().setSharingMode(
313         fdp.ConsumeBool()
314             ? fdp.ConsumeIntegral<int32_t>()
315             : (fdp.ConsumeBool() ? AAUDIO_SHARING_MODE_EXCLUSIVE : AAUDIO_SHARING_MODE_SHARED));
316 
317     request.getConfiguration().setUsage(
318         fdp.ConsumeBool()
319             ? fdp.ConsumeIntegral<int32_t>()
320             : kAAudioUsages[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioUsages - 1)]);
321     request.getConfiguration().setContentType(
322         fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
323                           : kAAudioContentTypes[fdp.ConsumeIntegralInRange<int32_t>(
324                                 0, kNumAAudioContentTypes - 1)]);
325     request.getConfiguration().setInputPreset(
326         fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
327                           : kAAudioInputPresets[fdp.ConsumeIntegralInRange<int32_t>(
328                                 0, kNumAAudioInputPresets - 1)]);
329     request.getConfiguration().setPrivacySensitive(fdp.ConsumeBool());
330 
331     request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
332 
333     aaudio_handle_t stream = mClient->openStream(request, configurationOutput);
334     if (stream < 0) {
335         // invalid request, stream not opened.
336         return;
337     }
338     while (fdp.remaining_bytes()) {
339         AudioEndpointParcelable audioEndpointParcelable;
340         int action = fdp.ConsumeIntegralInRange<int32_t>(0, 4);
341         switch (action) {
342             case 0:
343                 mClient->getStreamDescription(stream, audioEndpointParcelable);
344                 break;
345             case 1:
346                 mClient->startStream(stream);
347                 break;
348             case 2:
349                 mClient->pauseStream(stream);
350                 break;
351             case 3:
352                 mClient->stopStream(stream);
353                 break;
354             case 4:
355                 mClient->flushStream(stream);
356                 break;
357         }
358     }
359     mClient->closeStream(stream);
360     assert(mClient->getDeathCount() == 0);
361 }
362 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)363 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
364     if (size < 1) {
365         return 0;
366     }
367     OboeserviceFuzzer oboeserviceFuzzer;
368     oboeserviceFuzzer.process(data, size);
369     return 0;
370 }
371