1 /*
2  * Copyright (c) 2024 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 "devicemanager_fuzzer.h"
17 
18 #include "devicestatus_define.h"
19 
20 #undef LOG_TAG
21 #define LOG_TAG "DeviceManagerFuzzTest"
22 namespace OHOS {
23 namespace Msdp {
24 namespace DeviceStatus {
25 namespace {
26 struct DeviceStatusEpollEvent {
27     int32_t fd { -1 };
28     EpollEventType eventType { EPOLL_EVENT_BEGIN };
29 };
30 
31 const uint8_t *g_baseFuzzData = nullptr;
32 size_t g_baseFuzzSize = 0;
33 size_t g_baseFuzzPos = 0;
34 constexpr size_t STR_LEN = 255;
35 ContextService *g_instance = nullptr;
36 constexpr int32_t DEFAULT_WAIT_TIME_MS { 1000 };
37 constexpr int32_t WAIT_FOR_ONCE { 1 };
38 constexpr int32_t MAX_N_RETRIES { 100 };
39 } // namespace
40 
ContextService()41 ContextService::ContextService()
42 {
43     OnStart();
44 }
45 
~ContextService()46 ContextService::~ContextService()
47 {
48     OnStop();
49 }
50 
GetDelegateTasks()51 IDelegateTasks& ContextService::GetDelegateTasks()
52 {
53     return delegateTasks_;
54 }
55 
GetDeviceManager()56 IDeviceManager& ContextService::GetDeviceManager()
57 {
58     return devMgr_;
59 }
60 
GetTimerManager()61 ITimerManager& ContextService::GetTimerManager()
62 {
63     return timerMgr_;
64 }
65 
GetDragManager()66 IDragManager& ContextService::GetDragManager()
67 {
68     return dragMgr_;
69 }
70 
GetInstance()71 ContextService* ContextService::GetInstance()
72 {
73     static std::once_flag flag;
74     std::call_once(flag, [&]() {
75         ContextService *cooContext = new (std::nothrow) ContextService();
76         CHKPL(cooContext);
77         g_instance = cooContext;
78     });
79     return g_instance;
80 }
81 
GetSocketSessionManager()82 ISocketSessionManager& ContextService::GetSocketSessionManager()
83 {
84     return socketSessionMgr_;
85 }
86 
GetPluginManager()87 IPluginManager& ContextService::GetPluginManager()
88 {
89     return *pluginMgr_;
90 }
91 
GetInput()92 IInputAdapter& ContextService::GetInput()
93 {
94     return *input_;
95 }
96 
GetDSoftbus()97 IDSoftbusAdapter& ContextService::GetDSoftbus()
98 {
99     return *dsoftbusAda_;
100 }
101 
Init()102 bool ContextService::Init()
103 {
104     CALL_DEBUG_ENTER;
105     if (EpollCreate() != RET_OK) {
106         FI_HILOGE("Create epoll failed");
107         return false;
108     }
109     if (InitDelegateTasks() != RET_OK) {
110         FI_HILOGE("Delegate tasks init failed");
111         goto INIT_FAIL;
112     }
113     if (InitTimerMgr() != RET_OK) {
114         FI_HILOGE("TimerMgr init failed");
115         goto INIT_FAIL;
116     }
117     if (InitDevMgr() != RET_OK) {
118         FI_HILOGE("DevMgr init failed");
119         goto INIT_FAIL;
120     }
121 
122     return true;
123 
124 INIT_FAIL:
125     EpollClose();
126     return false;
127 }
InitDevMgr()128 int32_t ContextService::InitDevMgr()
129 {
130     CALL_DEBUG_ENTER;
131     int32_t ret = devMgr_.Init(this);
132     if (ret != RET_OK) {
133         FI_HILOGE("DevMgr init failed");
134         return ret;
135     }
136     return ret;
137 }
138 
InitTimerMgr()139 int32_t ContextService::InitTimerMgr()
140 {
141     CALL_DEBUG_ENTER;
142     int32_t ret = timerMgr_.Init(this);
143     if (ret != RET_OK) {
144         FI_HILOGE("TimerMgr init failed");
145         return ret;
146     }
147 
148     ret = AddEpoll(EPOLL_EVENT_TIMER, timerMgr_.GetTimerFd());
149     if (ret != RET_OK) {
150         FI_HILOGE("AddEpoll for timer failed");
151     }
152     return ret;
153 }
154 
InitDelegateTasks()155 int32_t ContextService::InitDelegateTasks()
156 {
157     CALL_DEBUG_ENTER;
158     if (!delegateTasks_.Init()) {
159         FI_HILOGE("The delegate task init failed");
160         return RET_ERR;
161     }
162     int32_t ret = AddEpoll(EPOLL_EVENT_ETASK, delegateTasks_.GetReadFd());
163     if (ret != RET_OK) {
164         FI_HILOGE("AddEpoll error ret:%{public}d", ret);
165     }
166     FI_HILOGI("AddEpoll, epollfd:%{public}d, fd:%{public}d", epollFd_, delegateTasks_.GetReadFd());
167     return ret;
168 }
169 
EpollCreate()170 int32_t ContextService::EpollCreate()
171 {
172     CALL_DEBUG_ENTER;
173     epollFd_ = ::epoll_create1(EPOLL_CLOEXEC);
174     if (epollFd_ < 0) {
175         FI_HILOGE("epoll_create1 failed:%{public}s", ::strerror(errno));
176         return RET_ERR;
177     }
178     return RET_OK;
179 }
180 
AddEpoll(EpollEventType type,int32_t fd)181 int32_t ContextService::AddEpoll(EpollEventType type, int32_t fd)
182 {
183     CALL_DEBUG_ENTER;
184     if (!(type >= EPOLL_EVENT_BEGIN && type < EPOLL_EVENT_END)) {
185         FI_HILOGE("Invalid type:%{public}d", type);
186         return RET_ERR;
187     }
188     if (fd < 0) {
189         FI_HILOGE("Invalid fd:%{public}d", fd);
190         return RET_ERR;
191     }
192     auto eventData = static_cast<DeviceStatusEpollEvent*>(malloc(sizeof(DeviceStatusEpollEvent)));
193     if (!eventData) {
194         FI_HILOGE("Malloc failed");
195         return RET_ERR;
196     }
197     eventData->fd = fd;
198     eventData->eventType = type;
199     FI_HILOGD("EventData:[fd:%{public}d, type:%{public}d]", eventData->fd, eventData->eventType);
200 
201     struct epoll_event ev {};
202     ev.events = EPOLLIN;
203     ev.data.ptr = eventData;
204     if (EpollCtl(fd, EPOLL_CTL_ADD, ev) != RET_OK) {
205         free(eventData);
206         eventData = nullptr;
207         ev.data.ptr = nullptr;
208         FI_HILOGE("EpollCtl failed");
209         return RET_ERR;
210     }
211     return RET_OK;
212 }
213 
DelEpoll(EpollEventType type,int32_t fd)214 int32_t ContextService::DelEpoll(EpollEventType type, int32_t fd)
215 {
216     CALL_DEBUG_ENTER;
217     if (!(type >= EPOLL_EVENT_BEGIN && type < EPOLL_EVENT_END)) {
218         FI_HILOGE("Invalid type:%{public}d", type);
219         return RET_ERR;
220     }
221     if (fd < 0) {
222         FI_HILOGE("Invalid fd:%{public}d", fd);
223         return RET_ERR;
224     }
225     struct epoll_event ev {};
226     if (EpollCtl(fd, EPOLL_CTL_DEL, ev) != RET_OK) {
227         FI_HILOGE("DelEpoll failed");
228         return RET_ERR;
229     }
230     return RET_OK;
231 }
232 
EpollClose()233 void ContextService::EpollClose()
234 {
235     CALL_DEBUG_ENTER;
236     if (epollFd_ >= 0) {
237         if (close(epollFd_) < 0) {
238             FI_HILOGE("Close epoll fd failed, error:%{public}s, epollFd_:%{public}d", strerror(errno), epollFd_);
239         }
240         epollFd_ = -1;
241     }
242 }
243 
EpollCtl(int32_t fd,int32_t op,struct epoll_event & event)244 int32_t ContextService::EpollCtl(int32_t fd, int32_t op, struct epoll_event &event)
245 {
246     CALL_DEBUG_ENTER;
247     if (fd < 0) {
248         FI_HILOGE("Invalid fd:%{public}d", fd);
249         return RET_ERR;
250     }
251     if (epollFd_ < 0) {
252         FI_HILOGE("Invalid epollFd:%{public}d", epollFd_);
253         return RET_ERR;
254     }
255     if (::epoll_ctl(epollFd_, op, fd, &event) != 0) {
256         FI_HILOGE("epoll_ctl(%{public}d,%{public}d,%{public}d) failed:%{public}s", epollFd_, op, fd, ::strerror(errno));
257         return RET_ERR;
258     }
259     return RET_OK;
260 }
261 
EpollWait(int32_t maxevents,int32_t timeout,struct epoll_event & events)262 int32_t ContextService::EpollWait(int32_t maxevents, int32_t timeout, struct epoll_event &events)
263 {
264     if (epollFd_ < 0) {
265         FI_HILOGE("Invalid epollFd:%{public}d", epollFd_);
266         return RET_ERR;
267     }
268     return epoll_wait(epollFd_, &events, maxevents, timeout);
269 }
270 
OnTimeout(const struct epoll_event & ev)271 void ContextService::OnTimeout(const struct epoll_event &ev)
272 {
273     CALL_DEBUG_ENTER;
274     if ((ev.events & EPOLLIN) == EPOLLIN) {
275         uint64_t expiration {};
276         ssize_t ret = read(timerMgr_.GetTimerFd(), &expiration, sizeof(expiration));
277         if (ret < 0) {
278             FI_HILOGE("Read expiration failed:%{public}s", strerror(errno));
279         }
280         timerMgr_.ProcessTimers();
281     } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
282         FI_HILOGE("Epoll hangup:%{public}s", strerror(errno));
283     }
284 }
285 
OnDeviceMgr(const struct epoll_event & ev)286 void ContextService::OnDeviceMgr(const struct epoll_event &ev)
287 {
288     CALL_DEBUG_ENTER;
289     if ((ev.events & EPOLLIN) == EPOLLIN) {
290         devMgr_.Dispatch(ev);
291     } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
292         FI_HILOGE("Epoll hangup:%{public}s", strerror(errno));
293     }
294 }
295 
EnableDevMgr(int32_t nRetries)296 int32_t ContextService::EnableDevMgr(int32_t nRetries)
297 {
298     CALL_INFO_TRACE;
299     static int32_t timerId { -1 };
300     int32_t ret = devMgr_.Enable();
301     if (ret != RET_OK) {
302         FI_HILOGE("Failed to enable device manager");
303         if (nRetries > 0) {
304             timerId = timerMgr_.AddTimer(DEFAULT_WAIT_TIME_MS, WAIT_FOR_ONCE,
305                 [this, nRetries] { return this->EnableDevMgr(nRetries - 1); });
306             if (timerId < 0) {
307                 FI_HILOGE("AddTimer failed, Failed to enable device manager");
308             }
309         } else {
310             FI_HILOGE("Maximum number of retries exceeded, Failed to enable device manager");
311         }
312         return ret;
313     }
314     AddEpoll(EPOLL_EVENT_DEVICE_MGR, devMgr_.GetFd());
315     if (timerId >= 0) {
316         timerMgr_.RemoveTimer(timerId);
317         timerId = -1;
318     }
319     return RET_OK;
320 }
321 
DisableDevMgr()322 void ContextService::DisableDevMgr()
323 {
324     DelEpoll(EPOLL_EVENT_DEVICE_MGR, devMgr_.GetFd());
325     devMgr_.Disable();
326 }
327 
OnStart()328 void ContextService::OnStart()
329 {
330     CALL_DEBUG_ENTER;
331     uint64_t tid = GetThisThreadId();
332     delegateTasks_.SetWorkerThreadId(tid);
333 
334     if (!Init()) {
335         FI_HILOGE("On start call init failed");
336         return;
337     }
338     state_ = ServiceRunningState::STATE_RUNNING;
339     ready_ = true;
340 
341     worker_ = std::thread(std::bind(&ContextService::OnThread, this));
342 }
343 
OnStop()344 void ContextService::OnStop()
345 {
346     CALL_DEBUG_ENTER;
347     if (timerMgr_.GetTimerFd() >= 0) {
348         if (close(timerMgr_.GetTimerFd()) < 0) {
349             FI_HILOGE("Close timer fd failed, error:%{public}s", strerror(errno));
350         }
351     }
352     if (!ready_) {
353         FI_HILOGI("ready state is false");
354         return;
355     }
356     ready_ = false;
357     state_ = ServiceRunningState::STATE_EXIT;
358 
359     delegateTasks_.PostAsyncTask([]() -> int32_t {
360         FI_HILOGD("No asynchronous operations");
361         return RET_OK;
362     });
363     if (worker_.joinable()) {
364         worker_.join();
365     }
366     DisableDevMgr();
367     EpollClose();
368     FI_HILOGI("OnStop leave");
369 }
370 
OnThread()371 void ContextService::OnThread()
372 {
373     CALL_DEBUG_ENTER;
374     SetThreadName(std::string("os_ds_service"));
375     uint64_t tid = GetThisThreadId();
376     delegateTasks_.SetWorkerThreadId(tid);
377     EnableDevMgr(MAX_N_RETRIES);
378     FI_HILOGD("Main worker thread start, tid:%{public}" PRId64 "", tid);
379 
380     while (state_ == ServiceRunningState::STATE_RUNNING) {
381         struct epoll_event ev[MAX_EVENT_SIZE] {};
382         int32_t count = EpollWait(MAX_EVENT_SIZE, -1, ev[0]);
383         for (int32_t i = 0; i < count && state_ == ServiceRunningState::STATE_RUNNING; i++) {
384             auto epollEvent = reinterpret_cast<DeviceStatusEpollEvent*>(ev[i].data.ptr);
385             CHKPC(epollEvent);
386             if (epollEvent->eventType == EPOLL_EVENT_TIMER) {
387                 OnTimeout(ev[i]);
388             } else if (epollEvent->eventType == EPOLL_EVENT_ETASK) {
389                 OnDelegateTask(ev[i]);
390             } else if (epollEvent->eventType == EPOLL_EVENT_DEVICE_MGR) {
391                 OnDeviceMgr(ev[i]);
392             } else {
393                 FI_HILOGW("Unknown epoll event type:%{public}d", epollEvent->eventType);
394             }
395         }
396     }
397     FI_HILOGD("Main worker thread stop, tid:%{public}" PRId64 "", tid);
398 }
399 
OnDelegateTask(const struct epoll_event & ev)400 void ContextService::OnDelegateTask(const struct epoll_event &ev)
401 {
402     if ((ev.events & EPOLLIN) == 0) {
403         FI_HILOGW("Not epollin");
404         return;
405     }
406     DelegateTasks::TaskData data {};
407     ssize_t res = read(delegateTasks_.GetReadFd(), &data, sizeof(data));
408     if (res == -1) {
409         FI_HILOGW("Read failed erron:%{public}d", errno);
410     }
411     FI_HILOGD("RemoteRequest notify td:%{public}" PRId64 ", std:%{public}" PRId64 ""
412         ", taskId:%{public}d", GetThisThreadId(), data.tid, data.taskId);
413     delegateTasks_.ProcessTasks();
414 }
415 
GetData()416 template <class T> T GetData()
417 {
418     T objetct{};
419     size_t objetctSize = sizeof(objetct);
420     if (g_baseFuzzData == nullptr || objetctSize > g_baseFuzzSize - g_baseFuzzPos) {
421         return objetct;
422     }
423     errno_t ret = memcpy_s(&objetct, objetctSize, g_baseFuzzData + g_baseFuzzPos, objetctSize);
424     if (ret != EOK) {
425         return {};
426     }
427     g_baseFuzzPos += objetctSize;
428     return objetct;
429 }
430 
SetGlobalFuzzData(const uint8_t * data,size_t size)431 void SetGlobalFuzzData(const uint8_t *data, size_t size)
432 {
433     g_baseFuzzData = data;
434     g_baseFuzzSize = size;
435     g_baseFuzzPos = 0;
436 }
437 
GetStringFromData(int strlen)438 std::string GetStringFromData(int strlen)
439 {
440     if (strlen < 1) {
441         return "";
442     }
443 
444     char cstr[strlen];
445     cstr[strlen - 1] = '\0';
446     for (int i = 0; i < strlen - 1; i++) {
447         cstr[i] = GetData<char>();
448     }
449     std::string str(cstr);
450     return str;
451 }
452 
DeviceManagerFuzzTest(const uint8_t * data,size_t size)453 bool DeviceManagerFuzzTest(const uint8_t* data, size_t size)
454 {
455     if ((data == nullptr) || (size < 1)) {
456         return false;
457     }
458     SetGlobalFuzzData(data, size);
459 
460     std::string devStr = GetStringFromData(STR_LEN);
461     int32_t id = GetData<int32_t>();
462 
463     struct epoll_event ev {};
464     std::weak_ptr<IDeviceObserver> weakObserver = std::weak_ptr<IDeviceObserver>();
465     auto env = ContextService::GetInstance();
466 
467     env->devMgr_.AddDevice(devStr);
468     env->devMgr_.FindDevice(devStr);
469     env->devMgr_.Dispatch(ev);
470     env->GetDeviceManager().GetDevice(id);
471     env->GetDeviceManager().RetriggerHotplug(weakObserver);
472     env->GetDeviceManager().AddDeviceObserver(weakObserver);
473     env->GetDeviceManager().RemoveDeviceObserver(weakObserver);
474     env->devMgr_.HasLocalPointerDevice();
475     env->devMgr_.HasLocalKeyboardDevice();
476     env->devMgr_.HasKeyboard();
477     env->devMgr_.GetKeyboard();
478     env->devMgr_.RemoveDevice(devStr);
479     return true;
480 }
481 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)482 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
483 {
484     /* Run your code on data */
485     if (data == nullptr) {
486         return 0;
487     }
488 
489     OHOS::Msdp::DeviceStatus::DeviceManagerFuzzTest(data, size);
490 
491     return 0;
492 }
493 } // namespace DeviceStatus
494 } // namespace Msdp
495 } // namespace OHOS