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 #include <unordered_set>
24 #include <random>
25
26 #include "iremote_stub.h"
27 #include "ires_sched_service.h"
28 #include "iservice_registry.h"
29 #include "oobe_datashare_utils.h"
30 #include "oobe_manager.h"
31 #include "ioobe_task.h"
32 #include "plugin_mgr.h"
33 #include "res_sched_service.h"
34 #include "singleton.h"
35 #include "system_ability_definition.h"
36 #include "slide_recognizer.h"
37 #include "ffrt_inner.h"
38 #include "res_sched_client.h"
39 #include "res_sched_service_stub.h"
40 #include "res_sched_systemload_notifier_client.h"
41 #include "res_sched_systemload_notifier_proxy.h"
42 #include "notifier_mgr.h"
43 #include "res_type.h"
44 #include "accesstoken_kit.h"
45 #include "token_setproc.h"
46
47 #define private public
48 #define protected public
49
50 #ifndef errno_t
51 typedef int errno_t;
52 #endif
53
54 #ifndef EOK
55 #define EOK 0
56 #endif
57
58 namespace OHOS {
59 namespace ResourceSchedule {
60 namespace {
61 static const int32_t TWO_PARAMETERS = 2;
62
63 static const std::unordered_set<uint32_t> THIRDPARTY_RES = {
64 ResType::RES_TYPE_CLICK_RECOGNIZE,
65 ResType::RES_TYPE_PUSH_PAGE,
66 ResType::RES_TYPE_SLIDE_RECOGNIZE,
67 ResType::RES_TYPE_POP_PAGE,
68 ResType::RES_TYPE_LOAD_PAGE,
69 ResType::RES_TYPE_WEB_GESTURE,
70 ResType::RES_TYPE_REPORT_KEY_THREAD,
71 ResType::RES_TYPE_REPORT_WINDOW_STATE,
72 ResType::RES_TYPE_REPORT_SCENE_SCHED,
73 ResType::RES_TYPE_WEB_GESTURE_MOVE,
74 ResType::RES_TYPE_WEB_SLIDE_NORMAL,
75 ResType::RES_TYPE_LOAD_URL,
76 ResType::RES_TYPE_MOUSEWHEEL,
77 ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE,
78 ResType::RES_TYPE_REPORT_RENDER_THREAD,
79 ResType::RES_TYPE_LONG_FRAME,
80 ResType::RES_TYPE_AUDIO_SILENT_PLAYBACK,
81 ResType::RES_TYPE_REPORT_DISTRIBUTE_TID,
82 ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE,
83 ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE,
84 ResType::RES_TYPE_BT_SERVICE_EVENT
85 };
86
87 static const std::unordered_map<uint32_t, std::vector<std::string>> RESTYPE_TO_PARAMS = {
88 {ResType::RES_TYPE_CLICK_RECOGNIZE, {"clientPid", "name"}},
89 {ResType::RES_TYPE_PUSH_PAGE, {"pageUrl"}},
90 {ResType::RES_TYPE_SLIDE_RECOGNIZE, {"clientPid"}},
91 {ResType::RES_TYPE_POP_PAGE, {}},
92 {ResType::RES_TYPE_LOAD_PAGE, {}},
93 {ResType::RES_TYPE_WEB_GESTURE, {}},
94 {ResType::RES_TYPE_REPORT_KEY_THREAD, {"uid", "pid", "tid", "role"}},
95 {ResType::RES_TYPE_REPORT_WINDOW_STATE, {"uid", "pid", "windowId", "serialNum", "state"}},
96 {ResType::RES_TYPE_REPORT_SCENE_SCHED, {"uid", "sceneId"}},
97 {ResType::RES_TYPE_WEB_GESTURE_MOVE, {}},
98 {ResType::RES_TYPE_WEB_SLIDE_NORMAL, {}},
99 {ResType::RES_TYPE_LOAD_URL, {}},
100 {ResType::RES_TYPE_MOUSEWHEEL, {}},
101 {ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE, {"uid", "pid", "tid"}},
102 {ResType::RES_TYPE_REPORT_RENDER_THREAD, {"uid", "pid"}},
103 {ResType::RES_TYPE_LONG_FRAME, {"pid", "uid", "bundleName", "abilityName"}},
104 {ResType::RES_TYPE_AUDIO_SILENT_PLAYBACK, {"uid"}},
105 {ResType::RES_TYPE_REPORT_DISTRIBUTE_TID, {"uid", "pid"}},
106 {ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE, {"uid", "pid"}},
107 {ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE, {"uid", "pid"}},
108 {ResType::RES_TYPE_BT_SERVICE_EVENT, {"ADDRESS", "STATE", "ROLE", "CONNECTIF", "STATUS"}}
109 };
110
111 static const int32_t DEFAULT_API_VERSION = 11;
112 static const int32_t PAYLOAD_MAX_SIZE = 3500;
113
114 Security::AccessToken::PermissionStateFull HapState = {
115 .permissionName = "",
116 .isGeneral = true,
117 .resDeviceID = {"local"},
118 .grantStatus = {Security::AccessToken::PermissionState::PERMISSION_GRANTED},
119 .grantFlags = {1}
120 };
121
122 Security::AccessToken::HapPolicyParams HapPolicyParams = {
123 .apl = Security::AccessToken::APL_SYSTEM_BASIC,
124 .domain = "test.domain.ressched",
125 .permList = {},
126 .permStateList = {HapState}
127 };
128
129 Security::AccessToken::HapInfoParams info = {
130 .userID = 100,
131 .bundleName = "com.hos.ressched",
132 .instIndex = 0,
133 .appIDDesc = "thirdParty",
134 .apiVersion = DEFAULT_API_VERSION,
135 .isSystemApp = false
136 };
137 }
138
139 constexpr int32_t MAX_CODE = 5;
140 constexpr int32_t MIN_LEN = 4;
141 std::mutex mutexLock;
142 sptr<IRemoteObject> remoteObj;
143 const uint8_t* g_data = nullptr;
144 size_t g_size = 0;
145 size_t g_pos;
146
147 /**
148 * describe: get data from outside untrusted data(g_data) which size is according to sizeof(T)
149 * tips: only support basic type
150 */
151 template<class T>
GetData()152 T GetData()
153 {
154 T object {};
155 size_t objectSize = sizeof(object);
156 if (g_data == nullptr || objectSize > g_size - g_pos) {
157 return object;
158 }
159 errno_t ret = memcpy_s(&object, objectSize, g_data + g_pos, objectSize);
160 if (ret != EOK) {
161 return {};
162 }
163 g_pos += objectSize;
164 return object;
165 }
166
GetStringFromData(int strlen)167 std::string GetStringFromData(int strlen)
168 {
169 if (strlen <= 0) {
170 return "";
171 }
172 char cstr[strlen];
173 cstr[strlen - 1] = '\0';
174 for (int i = 0; i < strlen - 1; i++) {
175 char tmp = GetData<char>();
176 if (tmp == '\0') {
177 tmp = '1';
178 }
179 cstr[i] = tmp;
180 }
181 std::string str(cstr);
182 return str;
183 }
184
DoInit()185 bool DoInit()
186 {
187 std::lock_guard<std::mutex> lock(mutexLock);
188 if (remoteObj) {
189 return true;
190 }
191 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
192 if (!samgr) {
193 return false;
194 }
195 remoteObj = samgr->GetSystemAbility(RES_SCHED_SYS_ABILITY_ID);
196 if (!remoteObj) {
197 return false;
198 }
199 return true;
200 }
201
onRemoteRequest(uint32_t code, MessageParcel& data)202 int32_t onRemoteRequest(uint32_t code, MessageParcel& data)
203 {
204 if (!DoInit()) {
205 return -1;
206 }
207 MessageParcel reply;
208 MessageOption option;
209 return remoteObj->SendRequest(code, data, reply, option);
210 }
211
DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)212 bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
213 {
214 if (size <= MIN_LEN) {
215 return false;
216 }
217
218 MessageParcel dataMessageParcel;
219 if (!dataMessageParcel.WriteInterfaceToken(IRemoteStub<IResSchedService>::GetDescriptor())) {
220 return false;
221 }
222
223 uint32_t code = *(reinterpret_cast<const uint32_t*>(data));
224 size -= sizeof(uint32_t);
225
226 dataMessageParcel.WriteBuffer(data + sizeof(uint32_t), size);
227 dataMessageParcel.RewindRead(0);
228
229 onRemoteRequest(code, dataMessageParcel);
230 return true;
231 }
232
OnRemoteRequest(const uint8_t* data, size_t size)233 bool OnRemoteRequest(const uint8_t* data, size_t size)
234 {
235 if (data == nullptr) {
236 return false;
237 }
238
239 if (size <= MIN_LEN) {
240 return false;
241 }
242
243 // initialize
244 g_data = data;
245 g_size = size;
246 g_pos = 0;
247
248 // getdata
249 uint32_t fuzzCode = GetData<uint32_t>();
250 MessageParcel fuzzData;
251 fuzzData.WriteInterfaceToken(ResSchedServiceStub::GetDescriptor());
252 fuzzData.WriteBuffer(g_data + g_pos, g_size - g_pos);
253 fuzzData.RewindRead(0);
254 MessageParcel fuzzReply;
255 MessageOption fuzzOption;
256 DelayedSingleton<ResSchedService>::GetInstance()->OnRemoteRequest(fuzzCode % MAX_CODE,
257 fuzzData, fuzzReply, fuzzOption);
258 return true;
259 }
260
SyncEventFuzzTest(const uint8_t* data, size_t size)261 bool SyncEventFuzzTest(const uint8_t* data, size_t size)
262 {
263 if (data == nullptr) {
264 return false;
265 }
266
267 if (size <= MIN_LEN) {
268 return false;
269 }
270
271 // initialize
272 g_data = data;
273 g_size = size;
274 g_pos = 0;
275
276 // getdata
277 MessageParcel fuzzData;
278 fuzzData.WriteInterfaceToken(ResSchedServiceStub::GetDescriptor());
279 fuzzData.WriteBuffer(g_data + g_pos, g_size - g_pos);
280 fuzzData.RewindRead(0);
281 MessageParcel fuzzReply;
282 DelayedSingleton<ResSchedService>::GetInstance()->ReportSyncEventInner(fuzzData, fuzzReply);
283 return true;
284 }
285
ResSchedClientFuzzTest(const uint8_t* data, size_t size)286 bool ResSchedClientFuzzTest(const uint8_t* data, size_t size)
287 {
288 if (data == nullptr) {
289 return false;
290 }
291
292 if (size <= sizeof(uint32_t) + sizeof(int64_t) + TWO_PARAMETERS * sizeof(std::string)) {
293 return false;
294 }
295
296 // initialize
297 g_data = data;
298 g_size = size;
299 g_pos = 0;
300
301 uint32_t resType = GetData<uint32_t>();
302 int64_t value = GetData<int64_t>();
303 std::unordered_map<std::string, std::string> mapPayload;
304 mapPayload["pid"] = GetStringFromData(int(size) - sizeof(uint32_t) - sizeof(int64_t));
305 mapPayload["processName"] = GetStringFromData(int(size) - sizeof(std::string) -
306 sizeof(uint32_t) - sizeof(int64_t));
307
308 ResSchedClient::GetInstance().ReportData(resType, value, mapPayload);
309 ResSchedClient::GetInstance().KillProcess(mapPayload);
310 ResSchedClient::GetInstance().StopRemoteObject();
311
312 sptr<ResSchedSystemloadNotifierClient> callbackObj;
313 ResSchedClient::GetInstance().RegisterSystemloadNotifier(callbackObj);
314 ResSchedClient::GetInstance().UnRegisterSystemloadNotifier(callbackObj);
315 ResSchedClient::GetInstance().GetSystemloadLevel();
316 return true;
317 }
318
OnSystemloadLevelFuzzTest(const uint8_t* data, size_t size)319 bool OnSystemloadLevelFuzzTest(const uint8_t* data, size_t size)
320 {
321 if (data == nullptr) {
322 return false;
323 }
324
325 // initialize
326 g_data = data;
327 g_size = size;
328 g_pos = 0;
329
330 int32_t level = GetData<int32_t>();
331 if (!DoInit()) {
332 return false;
333 }
334 auto resSchedSystemloadNotifierProxy = std::make_unique<ResSchedSystemloadNotifierProxy>(remoteObj);
335 resSchedSystemloadNotifierProxy->OnSystemloadLevel(level);
336 return true;
337 }
338
NotifierMgrFuzzTest(const uint8_t* data, size_t size)339 bool NotifierMgrFuzzTest(const uint8_t* data, size_t size)
340 {
341 if (data == nullptr) {
342 return false;
343 }
344
345 // initialize
346 g_data = data;
347 g_size = size;
348 g_pos = 0;
349
350 int32_t pid = GetData<int32_t>();
351 int32_t type = GetData<int32_t>();
352 int32_t level = GetData<int32_t>();
353 int32_t state = GetData<int32_t>();
354 if (!DoInit()) {
355 return false;
356 }
357
358 NotifierMgr::GetInstance().Init();
359 NotifierMgr::GetInstance().RegisterNotifier(pid, remoteObj);
360 NotifierMgr::GetInstance().UnRegisterNotifier(pid);
361 NotifierMgr::GetInstance().OnRemoteNotifierDied(remoteObj);
362 NotifierMgr::GetInstance().OnDeviceLevelChanged(type, level);
363 NotifierMgr::GetInstance().OnApplicationStateChange(state, level);
364 NotifierMgr::GetInstance().GetSystemloadLevel();
365 NotifierMgr::GetInstance().DumpRegisterInfo();
366 NotifierMgr::GetInstance().Deinit();
367 return true;
368 }
369
SlideRecognizerFuzzTest(const uint8_t* data, size_t size)370 bool SlideRecognizerFuzzTest(const uint8_t* data, size_t size)
371 {
372 if (data == nullptr) {
373 return false;
374 }
375
376 if (size <= sizeof(uint32_t) + sizeof(int64_t)) {
377 return false;
378 }
379
380 uint32_t resType = GetData<uint32_t>();
381 int64_t value = GetData<int64_t>();
382 nlohmann::json payload;
383 auto slideRecognizer = std::make_shared<SlideRecognizer>();
384 slideRecognizer->SetListFlingTimeoutTime(0);
385 slideRecognizer->SetListFlingEndTime(0);
386 slideRecognizer->OnDispatchResource(resType, value, payload);
387 slideRecognizer->HandleSlideDetecting(payload);
388 slideRecognizer->HandleSlideEvent(value, payload);
389 slideRecognizer->HandleListFlingStart(payload);
390 slideRecognizer->HandleSendFrameEvent(payload);
391 slideRecognizer->HandleClickEvent(value, payload);
392 slideRecognizer->HandleSlideOFFEvent();
393 if (slideRecognizer->listFlingEndTask_) {
394 ffrt::skip(slideRecognizer->listFlingEndTask_);
395 }
396 if (slideRecognizer->listFlingTimeOutTask_) {
397 ffrt::skip(slideRecognizer->listFlingTimeOutTask_);
398 }
399 return true;
400 }
401
OOBEManagerFuzzTest(const uint8_t* data, size_t size)402 bool OOBEManagerFuzzTest(const uint8_t* data, size_t size)
403 {
404 if (data == nullptr) {
405 return false;
406 }
407
408 if (size <= sizeof(std::string)) {
409 return false;
410 }
411
412 std::string key = GetStringFromData(int(size));
413 OOBEManager::ResDataAbilityObserver::UpdateFunc updateFunc = [&]() {};
414 if (!DoInit()) {
415 return false;
416 }
417
418 OOBEManager::GetInstance().GetOOBValue();
419 OOBEManager::GetInstance().RegisterObserver(key, updateFunc);
420 OOBEManager::GetInstance().UnregisterObserver();
421 sptr<OOBEManager::ResDataAbilityObserver> oobeObserver = new OOBEManager::ResDataAbilityObserver();
422 oobeObserver->OnChange();
423 oobeObserver->SetUpdateFunc(updateFunc);
424 OOBEManager::GetInstance().Initialize();
425 OOBEManager::GetInstance().StartListen();
426 return true;
427 }
428
OOBEDatashareUtilsFuzzTest(const uint8_t* data, size_t size)429 bool OOBEDatashareUtilsFuzzTest(const uint8_t* data, size_t size)
430 {
431 if (data == nullptr) {
432 return false;
433 }
434
435 if (size <= TWO_PARAMETERS * sizeof(std::string)) {
436 return false;
437 }
438
439 std::string key = GetStringFromData(int(size));
440 std::string value = GetStringFromData(int(size));
441 if (!DoInit()) {
442 return false;
443 }
444
445 DataShareUtils::GetInstance().GetValue(key, value);
446 DataShareUtils::GetInstance().GetStringValue(key, value);
447 std::shared_ptr<DataShare::DataShareHelper> helper = DataShareUtils::GetInstance().CreateDataShareHelper();
448 DataShareUtils::GetInstance().ReleaseDataShareHelper(helper);
449 DataShareUtils::GetInstance().InitSystemAbilityManager();
450 DataShareUtils::GetInstance().AssembleUri(key);
451 DataShareUtils::GetInstance().GetDataShareReadyFlag();
452 DataShareUtils::GetInstance().SetDataShareReadyFlag(true);
453 return true;
454 }
455
SetHapToken()456 void SetHapToken()
457 {
458 Security::AccessToken::AccessTokenIDEx tokenIdEx = {0};
459 tokenIdEx = Security::AccessToken::AccessTokenKit::AllocHapToken(info, HapPolicyParams);
460 SetSelfTokenID(tokenIdEx.tokenIDEx);
461 }
462
DeleteHapToken()463 void DeleteHapToken()
464 {
465 Security::AccessToken::AccessTokenID tokenId =
466 Security::AccessToken::AccessTokenKit::GetHapTokenID(info.userID, info.bundleName, info.instIndex);
467 Security::AccessToken::AccessTokenKit::DeleteToken(tokenId);
468 }
469
GetPayload(uint32_t resType)470 std::unordered_map<std::string, std::string> GetPayload(uint32_t resType)
471 {
472 std::unordered_map<std::string, std::string> payload;
473 const auto ¶ms = RESTYPE_TO_PARAMS.at(resType);
474 size_t paramSize = params.size();
475 if (paramSize == 0) {
476 return payload;
477 }
478 size_t maxLen = PAYLOAD_MAX_SIZE / paramSize;
479 size_t minLen = sizeof(int32_t);
480 if (minLen > maxLen) {
481 minLen = maxLen;
482 }
483 std::mt19937_64 gen(std::random_device{}());
484 std::uniform_int_distribution<size_t> dis(minLen, maxLen);
485 for (const auto ¶m : params) {
486 payload[param] = GetStringFromData(dis(gen));
487 }
488 return payload;
489 }
490
ResSchedThirdPartyFuzzTest(const uint8_t* data, size_t size)491 bool ResSchedThirdPartyFuzzTest(const uint8_t* data, size_t size)
492 {
493 if (data == nullptr || size < sizeof(uint32_t)) {
494 return false;
495 }
496 uint32_t selfToken = GetSelfTokenID();
497 SetHapToken();
498 g_data = data;
499 g_size = size;
500 g_pos = 0;
501
502 uint32_t resType = GetData<uint32_t>() % ResType::RES_TYPE_LAST;
503 if (THIRDPARTY_RES.find(resType) == THIRDPARTY_RES.end()) {
504 return false;
505 }
506
507 int64_t value = GetData<int64_t>();
508 auto mapPayload = GetPayload(resType);
509 ResSchedClient::GetInstance().ReportData(resType, value, mapPayload);
510
511 DeleteHapToken();
512 SetSelfTokenID(selfToken);
513 return true;
514 }
515 } // namespace ResourceSchedule
516 } // namespace OHOS
517
518 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)519 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
520 {
521 /* Run your code on data */
522 OHOS::ResourceSchedule::DoSomethingInterestingWithMyAPI(data, size);
523 OHOS::ResourceSchedule::OnRemoteRequest(data, size);
524 OHOS::ResourceSchedule::SyncEventFuzzTest(data, size);
525 OHOS::ResourceSchedule::ResSchedClientFuzzTest(data, size);
526 OHOS::ResourceSchedule::ResSchedThirdPartyFuzzTest(data, size);
527 OHOS::ResourceSchedule::OnSystemloadLevelFuzzTest(data, size);
528 OHOS::ResourceSchedule::NotifierMgrFuzzTest(data, size);
529 OHOS::ResourceSchedule::OOBEManagerFuzzTest(data, size);
530 OHOS::ResourceSchedule::OOBEDatashareUtilsFuzzTest(data, size);
531 OHOS::ResourceSchedule::SlideRecognizerFuzzTest(data, size);
532 return 0;
533 }
534