• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fcntl.h>
17 #include <stdio.h>
18 #include "appspawn_kickdog.h"
19 
OpenAndWriteToProc(const char * procName,const char * writeStr,size_t writeLen)20 static int OpenAndWriteToProc(const char *procName, const char *writeStr, size_t writeLen)
21 {
22     if (writeStr == NULL) {
23         APPSPAWN_LOGE("Write string is null");
24         return -1;
25     }
26 
27     int procFd = open(procName, O_WRONLY | O_CLOEXEC);
28     if (procFd == -1) {
29         APPSPAWN_LOGE("open %{public}s fail,errno:%{public}d", procName, errno);
30         return procFd;
31     }
32 
33     int writeResult = write(procFd, writeStr, writeLen);
34     if (writeResult != (int)writeLen) {
35         APPSPAWN_LOGE("write %{public}s fail, ret %{public}d, errno %{public}d", writeStr, writeResult, errno);
36     } else {
37         APPSPAWN_LOGV("write %{public}s success", writeStr);
38     }
39 
40     close(procFd);
41     return writeResult;
42 }
43 
GetProcFile(bool isLinux)44 static const char *GetProcFile(bool isLinux)
45 {
46     if (isLinux) {
47         return LINUX_APPSPAWN_WATCHDOG_FILE;
48     }
49     return HM_APPSPAWN_WATCHDOG_FILE;
50 }
51 
GetProcContent(bool isLinux,bool isOpen,int mode)52 static const char *GetProcContent(bool isLinux, bool isOpen, int mode)
53 {
54     if (isOpen) {
55         if (isLinux) {
56             return LINUX_APPSPAWN_WATCHDOG_ON;
57         }
58         if (mode == MODE_FOR_NWEB_SPAWN) {
59             return HM_NWEBSPAWN_WATCHDOG_ON;
60         }
61         return (mode == MODE_FOR_HYBRID_SPAWN) ? HM_HYBRIDSPAWN_WATCHDOG_ON : HM_APPSPAWN_WATCHDOG_ON;
62     }
63 
64     if (isLinux) {
65         return LINUX_APPSPAWN_WATCHDOG_KICK;
66     }
67     if (mode == MODE_FOR_NWEB_SPAWN) {
68         return HM_NWEBSPAWN_WATCHDOG_KICK;
69     }
70     return (mode == MODE_FOR_HYBRID_SPAWN) ? HM_HYBRIDSPAWN_WATCHDOG_KICK : HM_APPSPAWN_WATCHDOG_KICK;
71 }
72 
DealSpawnWatchdog(AppSpawnContent * content,bool isOpen)73 static void DealSpawnWatchdog(AppSpawnContent *content, bool isOpen)
74 {
75     int result = 0;
76     const char *procFile = GetProcFile(content->isLinux);
77     const char *procContent = GetProcContent(content->isLinux, isOpen, content->mode);
78     result = OpenAndWriteToProc(procFile, procContent, strlen(procContent));
79     if (isOpen) {
80         content->wdgOpened = (result != -1);
81     }
82     APPSPAWN_KLOGI("%{public}s %{public}s %{public}d", (content->mode == MODE_FOR_NWEB_SPAWN) ? "Nweb" :
83         ((content->mode == MODE_FOR_HYBRID_SPAWN) ? "Hybrid" : "App"), isOpen ? "enable" : "kick", result);
84 }
85 
ProcessTimerHandle(const TimerHandle taskHandle,void * context)86 static void ProcessTimerHandle(const TimerHandle taskHandle, void *context)
87 {
88     AppSpawnContent *wdgContent = (AppSpawnContent *)context;
89 
90     if (!wdgContent->wdgOpened) {  //first time deal kernel file
91         DealSpawnWatchdog(wdgContent, true);
92         return;
93     }
94 
95     DealSpawnWatchdog(wdgContent, false);
96 }
97 
CreateTimerLoopTask(AppSpawnContent * content)98 static void CreateTimerLoopTask(AppSpawnContent *content)
99 {
100     LoopHandle loop = LE_GetDefaultLoop();
101     TimerHandle timer = NULL;
102     int ret = LE_CreateTimer(loop, &timer, ProcessTimerHandle, (void *)content);
103     APPSPAWN_CHECK(ret == 0, return, "Failed to create timerLoopTask ret %{public}d", ret);
104     // start a timer to write kernel file every 10s
105     ret = LE_StartTimer(loop, timer, APPSPAWN_WATCHDOG_KICKTIME, INT64_MAX);
106     APPSPAWN_CHECK(ret == 0, return, "Failed to start timerLoopTask ret %{public}d", ret);
107 }
108 
CheckKernelType(bool * isLinux)109 static int CheckKernelType(bool *isLinux)
110 {
111     struct utsname uts;
112     if (uname(&uts) == -1) {
113         APPSPAWN_LOGE("Kernel type get failed,errno:%{public}d", errno);
114         return -1;
115     }
116 
117     if (strcmp(uts.sysname, "Linux") == 0) {
118         APPSPAWN_LOGI("Kernel type is linux");
119         *isLinux = true;
120         return 0;
121     }
122 
123     *isLinux = false;
124     return 0;
125 }
126 
SpawnKickDogStart(AppSpawnMgr * mgrContent)127 APPSPAWN_STATIC int SpawnKickDogStart(AppSpawnMgr *mgrContent)
128 {
129     APPSPAWN_CHECK(mgrContent != NULL, return 0, "content is null");
130     APPSPAWN_CHECK((mgrContent->content.mode == MODE_FOR_APP_SPAWN) ||
131         (mgrContent->content.mode == MODE_FOR_NWEB_SPAWN) || (mgrContent->content.mode == MODE_FOR_HYBRID_SPAWN),
132         return 0, "Mode %{public}u no need enable watchdog", mgrContent->content.mode);
133 
134     if (CheckKernelType(&mgrContent->content.isLinux) != 0) {
135         return 0;
136     }
137 
138     DealSpawnWatchdog(&mgrContent->content, true);
139     CreateTimerLoopTask(&mgrContent->content);
140 
141     return 0;
142 }
143 
MODULE_CONSTRUCTOR(void)144 MODULE_CONSTRUCTOR(void)
145 {
146     AddPreloadHook(HOOK_PRIO_COMMON, SpawnKickDogStart);
147 }