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
17 #include <fcntl.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 #include "osi/include/alarm.h"
20 #include "osi/include/semaphore.h"
21
22 #include "common/message_loop_thread.h"
23
24 using base::Closure;
25 using base::TimeDelta;
26 using bluetooth::common::MessageLoopThread;
27
28 #define MAX_CONCURRENT_ALARMS 25
29 #define MAX_BUFFER_LEN 4096
30 #define MAX_ALARM_DURATION 25
31
32 static semaphore_t* semaphore;
33 static int cb_counter;
34 static base::MessageLoop* message_loop_;
35
get_main_message_loop()36 base::MessageLoop* get_main_message_loop() { return message_loop_; }
37
cb(void * data)38 static void cb(void* data) {
39 ++cb_counter;
40 semaphore_post(semaphore);
41 }
42
setup()43 void setup() {
44 cb_counter = 0;
45 semaphore = semaphore_new(0);
46 }
teardown()47 void teardown() { semaphore_free(semaphore); }
48
fuzz_init_alarm(FuzzedDataProvider * dataProvider)49 alarm_t* fuzz_init_alarm(FuzzedDataProvider* dataProvider) {
50 size_t name_len =
51 dataProvider->ConsumeIntegralInRange<size_t>(0, MAX_BUFFER_LEN);
52 std::vector<char> alarm_name_vect =
53 dataProvider->ConsumeBytesWithTerminator<char>(name_len, '\0');
54 char* alarm_name = alarm_name_vect.data();
55
56 // Determine if our alarm will be periodic
57 if (dataProvider->ConsumeBool()) {
58 return alarm_new_periodic(alarm_name);
59 } else {
60 return alarm_new(alarm_name);
61 }
62 }
63
fuzz_set_alarm(alarm_t * alarm,uint64_t interval,alarm_callback_t cb,FuzzedDataProvider * dataProvider)64 bool fuzz_set_alarm(alarm_t* alarm, uint64_t interval, alarm_callback_t cb,
65 FuzzedDataProvider* dataProvider) {
66 // Generate a random buffer (or null)
67 void* data_buffer = nullptr;
68 size_t buff_len =
69 dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_LEN);
70 if (buff_len == 0) {
71 return false;
72 }
73
74 // allocate our space
75 std::vector<uint8_t> data_vector =
76 dataProvider->ConsumeBytes<uint8_t>(buff_len);
77 data_buffer = data_vector.data();
78
79 // Make sure alarm is non-null
80 if (alarm) {
81 // Should this alarm be regular or on mloop?
82 if (dataProvider->ConsumeBool()) {
83 alarm_set_on_mloop(alarm, interval, cb, data_buffer);
84 } else {
85 alarm_set(alarm, interval, cb, data_buffer);
86 }
87 }
88
89 return true;
90 }
91
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)92 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
93 // Init our wrapper
94 FuzzedDataProvider dataProvider(Data, Size);
95
96 // Perform setup
97 setup();
98
99 alarm_t* alarm = nullptr;
100 // Should our alarm be valid or null?
101 if (dataProvider.ConsumeBool()) {
102 // Init our alarm
103 alarm = fuzz_init_alarm(&dataProvider);
104 }
105
106 // Set up the alarm & cancel
107 // Alarm must be non-null, or set() will trigger assert
108 if (alarm) {
109 if (!fuzz_set_alarm(alarm, MAX_ALARM_DURATION, cb, &dataProvider)) {
110 return 0;
111 }
112 alarm_cancel(alarm);
113 }
114
115 // Check if scheduled
116 alarm_is_scheduled(alarm);
117
118 if (alarm) {
119 // Set up another set of alarms & let these ones run
120 int num_alarms =
121 dataProvider.ConsumeIntegralInRange<uint8_t>(0, MAX_CONCURRENT_ALARMS);
122 for (int i = 0; i < num_alarms; i++) {
123 uint64_t interval =
124 dataProvider.ConsumeIntegralInRange<uint64_t>(0, MAX_ALARM_DURATION);
125 if (fuzz_set_alarm(alarm, interval, cb, &dataProvider)) {
126 return 0;
127 }
128 alarm_get_remaining_ms(alarm);
129 }
130
131 // Wait for them to complete
132 for (int i = 1; i <= num_alarms; i++) {
133 semaphore_wait(semaphore);
134 }
135 }
136
137 // Free the alarm object
138 alarm_free(alarm);
139
140 // dump debug data to /dev/null
141 int debug_fd = open("/dev/null", O_RDWR);
142 alarm_debug_dump(debug_fd);
143
144 // Cleanup
145 alarm_cleanup();
146
147 // Perform teardown
148 teardown();
149
150 return 0;
151 }
152