1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ressched_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <cstdlib>
21 #include <securec.h>
22 #include <vector>
23 
24 #include "iremote_stub.h"
25 #include "ires_sched_service.h"
26 #include "iservice_registry.h"
27 #include "oobe_datashare_utils.h"
28 #include "oobe_manager.h"
29 #include "ioobe_task.h"
30 #include "plugin_mgr.h"
31 #include "res_sched_service.h"
32 #include "singleton.h"
33 #include "system_ability_definition.h"
34 #include "res_sched_client.h"
35 #include "res_sched_service_stub.h"
36 #include "res_sched_systemload_notifier_client.h"
37 #include "res_sched_systemload_notifier_proxy.h"
38 #include "notifier_mgr.h"
39 
40 #define private public
41 #define protected public
42 
43 #ifndef errno_t
44 typedef int errno_t;
45 #endif
46 
47 #ifndef EOK
48 #define EOK 0
49 #endif
50 
51 namespace OHOS {
52 namespace ResourceSchedule {
53 namespace {
54     static const int32_t TWO_PARAMETERS = 2;
55 }
56 
57     constexpr int32_t MAX_CODE = 5;
58     constexpr int32_t MIN_LEN = 4;
59     std::mutex mutexLock;
60     sptr<IRemoteObject> remoteObj;
61     const uint8_t* DATA = nullptr;
62     size_t g_size = 0;
63     size_t g_pos;
64 
65     /**
66      * describe: get data from outside untrusted data(DATA) which size is according to sizeof(T)
67      * tips: only support basic type
68      */
69     template<class T>
GetData()70     T GetData()
71     {
72         T object {};
73         size_t objectSize = sizeof(object);
74         if (DATA == nullptr || objectSize > g_size - g_pos) {
75             return object;
76         }
77         errno_t ret = memcpy_s(&object, objectSize, DATA + g_pos, objectSize);
78         if (ret != EOK) {
79             return {};
80         }
81         g_pos += objectSize;
82         return object;
83     }
84 
GetStringFromData(int strlen)85     std::string GetStringFromData(int strlen)
86     {
87         if (strlen <= 0) {
88             return "";
89         }
90         char cstr[strlen];
91         cstr[strlen - 1] = '\0';
92         for (int i = 0; i < strlen - 1; i++) {
93             char tmp = GetData<char>();
94             if (tmp == '\0') {
95                 tmp = '1';
96             }
97             cstr[i] = tmp;
98         }
99         std::string str(cstr);
100         return str;
101     }
102 
DoInit()103     bool DoInit()
104     {
105         std::lock_guard<std::mutex> lock(mutexLock);
106         if (remoteObj) {
107             return true;
108         }
109         auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
110         if (!samgr) {
111             return false;
112         }
113         remoteObj = samgr->GetSystemAbility(RES_SCHED_SYS_ABILITY_ID);
114         if (!remoteObj) {
115             return false;
116         }
117         return true;
118     }
119 
onRemoteRequest(uint32_t code,MessageParcel & data)120     int32_t onRemoteRequest(uint32_t code, MessageParcel& data)
121     {
122         if (!DoInit()) {
123             return -1;
124         }
125         MessageParcel reply;
126         MessageOption option;
127         return remoteObj->SendRequest(code, data, reply, option);
128     }
129 
DoSomethingInterestingWithMyAPI(const uint8_t * data,size_t size)130     bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
131     {
132         if (size <= MIN_LEN) {
133             return false;
134         }
135 
136         MessageParcel dataMessageParcel;
137         if (!dataMessageParcel.WriteInterfaceToken(IRemoteStub<IResSchedService>::GetDescriptor())) {
138             return false;
139         }
140 
141         uint32_t code = *(reinterpret_cast<const uint32_t*>(data));
142         size -= sizeof(uint32_t);
143 
144         dataMessageParcel.WriteBuffer(data + sizeof(uint32_t), size);
145         dataMessageParcel.RewindRead(0);
146 
147         onRemoteRequest(code, dataMessageParcel);
148         return true;
149     }
150 
OnRemoteRequest(const uint8_t * data,size_t size)151     bool OnRemoteRequest(const uint8_t* data, size_t size)
152     {
153         if (data == nullptr) {
154             return false;
155         }
156 
157         if (size <= MIN_LEN) {
158             return false;
159         }
160 
161         // initialize
162         DATA = data;
163         g_size = size;
164         g_pos = 0;
165 
166         // getdata
167         uint32_t fuzzCode = GetData<uint32_t>();
168         MessageParcel fuzzData;
169         fuzzData.WriteInterfaceToken(ResSchedServiceStub::GetDescriptor());
170         fuzzData.WriteBuffer(DATA + g_pos, g_size - g_pos);
171         fuzzData.RewindRead(0);
172         MessageParcel fuzzReply;
173         MessageOption fuzzOption;
174         DelayedSingleton<ResSchedService>::GetInstance()->OnRemoteRequest(fuzzCode % MAX_CODE,
175             fuzzData, fuzzReply, fuzzOption);
176         return true;
177     }
178 
SyncEventFuzzTest(const uint8_t * data,size_t size)179     bool SyncEventFuzzTest(const uint8_t* data, size_t size)
180     {
181         if (data == nullptr) {
182             return false;
183         }
184 
185         if (size <= MIN_LEN) {
186             return false;
187         }
188 
189         // initialize
190         DATA = data;
191         g_size = size;
192         g_pos = 0;
193 
194         // getdata
195         MessageParcel fuzzData;
196         fuzzData.WriteInterfaceToken(ResSchedServiceStub::GetDescriptor());
197         fuzzData.WriteBuffer(DATA + g_pos, g_size - g_pos);
198         fuzzData.RewindRead(0);
199         MessageParcel fuzzReply;
200         DelayedSingleton<ResSchedService>::GetInstance()->ReportSyncEventInner(fuzzData, fuzzReply);
201         return true;
202     }
203 
ResSchedClientFuzzTest(const uint8_t * data,size_t size)204     bool ResSchedClientFuzzTest(const uint8_t* data, size_t size)
205     {
206         if (data == nullptr) {
207             return false;
208         }
209 
210         if (size <= sizeof(uint32_t) + sizeof(int64_t) + TWO_PARAMETERS * sizeof(std::string)) {
211             return false;
212         }
213 
214         // initialize
215         DATA = data;
216         g_size = size;
217         g_pos = 0;
218 
219         uint32_t resType = GetData<uint32_t>();
220         int64_t value = GetData<int64_t>();
221         std::unordered_map<std::string, std::string> mapPayload;
222         mapPayload["pid"] = GetStringFromData(int(size) - sizeof(uint32_t) - sizeof(int64_t));
223         mapPayload["processName"] = GetStringFromData(int(size) - sizeof(std::string) -
224         sizeof(uint32_t) - sizeof(int64_t));
225 
226         ResSchedClient::GetInstance().ReportData(resType, value, mapPayload);
227         ResSchedClient::GetInstance().KillProcess(mapPayload);
228         ResSchedClient::GetInstance().StopRemoteObject();
229 
230         sptr<ResSchedSystemloadNotifierClient> callbackObj;
231         ResSchedClient::GetInstance().RegisterSystemloadNotifier(callbackObj);
232         ResSchedClient::GetInstance().UnRegisterSystemloadNotifier(callbackObj);
233         ResSchedClient::GetInstance().GetSystemloadLevel();
234         return true;
235     }
236 
OnSystemloadLevelFuzzTest(const uint8_t * data,size_t size)237     bool OnSystemloadLevelFuzzTest(const uint8_t* data, size_t size)
238     {
239         if (data == nullptr) {
240             return false;
241         }
242 
243         // initialize
244         DATA = data;
245         g_size = size;
246         g_pos = 0;
247 
248         int32_t level = GetData<int32_t>();
249         if (!DoInit()) {
250             return false;
251         }
252         auto resSchedSystemloadNotifierProxy = std::make_unique<ResSchedSystemloadNotifierProxy>(remoteObj);
253         resSchedSystemloadNotifierProxy->OnSystemloadLevel(level);
254         return true;
255     }
256 
NotifierMgrFuzzTest(const uint8_t * data,size_t size)257     bool NotifierMgrFuzzTest(const uint8_t* data, size_t size)
258     {
259         if (data == nullptr) {
260             return false;
261         }
262 
263         // initialize
264         DATA = data;
265         g_size = size;
266         g_pos = 0;
267 
268         int32_t pid = GetData<int32_t>();
269         int32_t type = GetData<int32_t>();
270         int32_t level = GetData<int32_t>();
271         int32_t state = GetData<int32_t>();
272         if (!DoInit()) {
273             return false;
274         }
275 
276         NotifierMgr::GetInstance().Init();
277         NotifierMgr::GetInstance().RegisterNotifier(pid, remoteObj);
278         NotifierMgr::GetInstance().UnRegisterNotifier(pid);
279         NotifierMgr::GetInstance().OnRemoteNotifierDied(remoteObj);
280         NotifierMgr::GetInstance().OnDeviceLevelChanged(type, level);
281         NotifierMgr::GetInstance().OnApplicationStateChange(state, level);
282         NotifierMgr::GetInstance().GetSystemloadLevel();
283         NotifierMgr::GetInstance().DumpRegisterInfo();
284         NotifierMgr::GetInstance().Deinit();
285         return true;
286     }
287 
OOBEManagerFuzzTest(const uint8_t * data,size_t size)288     bool OOBEManagerFuzzTest(const uint8_t* data, size_t size)
289     {
290         if (data == nullptr) {
291             return false;
292         }
293 
294         if (size <= sizeof(std::string)) {
295             return false;
296         }
297 
298         std::string key = GetStringFromData(int(size));
299         OOBEManager::ResDataAbilityObserver::UpdateFunc updateFunc = [&]() {};
300         if (!DoInit()) {
301             return false;
302         }
303 
304         OOBEManager::GetInstance().GetOOBValue();
305         OOBEManager::GetInstance().RegisterObserver(key, updateFunc);
306         OOBEManager::GetInstance().UnregisterObserver();
307         sptr<OOBEManager::ResDataAbilityObserver> oobeObserver = new OOBEManager::ResDataAbilityObserver();
308         oobeObserver->OnChange();
309         oobeObserver->SetUpdateFunc(updateFunc);
310         OOBEManager::GetInstance().Initialize();
311         OOBEManager::GetInstance().StartListen();
312         return true;
313     }
314 
OOBEDatashareUtilsFuzzTest(const uint8_t * data,size_t size)315     bool OOBEDatashareUtilsFuzzTest(const uint8_t* data, size_t size)
316     {
317         if (data == nullptr) {
318             return false;
319         }
320 
321         if (size <= TWO_PARAMETERS * sizeof(std::string)) {
322             return false;
323         }
324 
325         std::string key = GetStringFromData(int(size));
326         std::string value = GetStringFromData(int(size));
327         if (!DoInit()) {
328             return false;
329         }
330 
331         DataShareUtils::GetInstance().GetValue(key, value);
332         DataShareUtils::GetInstance().GetStringValue(key, value);
333         std::shared_ptr<DataShare::DataShareHelper> helper = DataShareUtils::GetInstance().CreateDataShareHelper();
334         DataShareUtils::GetInstance().ReleaseDataShareHelper(helper);
335         DataShareUtils::GetInstance().InitSystemAbilityManager();
336         DataShareUtils::GetInstance().AssembleUri(key);
337         DataShareUtils::GetInstance().GetDataShareReadyFlag();
338         DataShareUtils::GetInstance().SetDataShareReadyFlag(true);
339         return true;
340     }
341 } // namespace ResourceSchedule
342 } // namespace OHOS
343 
344 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)345 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
346 {
347     /* Run your code on data */
348     OHOS::ResourceSchedule::DoSomethingInterestingWithMyAPI(data, size);
349     OHOS::ResourceSchedule::OnRemoteRequest(data, size);
350     OHOS::ResourceSchedule::SyncEventFuzzTest(data, size);
351     OHOS::ResourceSchedule::ResSchedClientFuzzTest(data, size);
352     OHOS::ResourceSchedule::OnSystemloadLevelFuzzTest(data, size);
353     OHOS::ResourceSchedule::NotifierMgrFuzzTest(data, size);
354     OHOS::ResourceSchedule::OOBEManagerFuzzTest(data, size);
355     OHOS::ResourceSchedule::OOBEDatashareUtilsFuzzTest(data, size);
356     return 0;
357 }
358