• 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 "appspawn_modulemgr.h"
17 
18 #include "appspawn_hook.h"
19 #include "appspawn_manager.h"
20 #include "appspawn_utils.h"
21 #include "hookmgr.h"
22 #include "modulemgr.h"
23 
24 typedef struct {
25     const AppSpawnContent *content;
26     const AppSpawnedProcessInfo *appInfo;
27 } AppSpawnAppArg;
28 
29 static struct {
30     MODULE_MGR *moduleMgr;
31     AppSpawnModuleType type;
32     const char *moduleName;
33 } g_moduleMgr[MODULE_MAX] = {
34     {NULL, MODULE_DEFAULT, "appspawn"},
35     {NULL, MODULE_APPSPAWN, "appspawn/appspawn"},
36     {NULL, MODULE_NWEBSPAWN, "appspawn/nwebspawn"},
37     {NULL, MODULE_COMMON, "appspawn/common"},
38 };
39 static HOOK_MGR *g_appspawnHookMgr = NULL;
40 
AppSpawnModuleMgrInstall(const char * moduleName)41 int AppSpawnModuleMgrInstall(const char *moduleName)
42 {
43     if (moduleName == NULL) {
44         return -1;
45     }
46     int type = MODULE_DEFAULT;
47     if (g_moduleMgr[type].moduleMgr == NULL) {
48         g_moduleMgr[type].moduleMgr = ModuleMgrCreate(g_moduleMgr[type].moduleName);
49     }
50     if (g_moduleMgr[type].moduleMgr == NULL) {
51         return -1;
52     }
53 #ifndef APPSPAWN_TEST
54     return ModuleMgrInstall(g_moduleMgr[type].moduleMgr, moduleName, 0, NULL);
55 #else
56     return 0;
57 #endif
58 }
59 
AppSpawnModuleMgrUnInstall(int type)60 void AppSpawnModuleMgrUnInstall(int type)
61 {
62     if (type >= MODULE_MAX) {
63         return;
64     }
65     if (g_moduleMgr[type].moduleMgr == NULL) {
66         return;
67     }
68     ModuleMgrDestroy(g_moduleMgr[type].moduleMgr);
69     g_moduleMgr[type].moduleMgr = NULL;
70 }
71 
AppSpawnLoadAutoRunModules(int type)72 int AppSpawnLoadAutoRunModules(int type)
73 {
74     if (type >= MODULE_MAX) {
75         return -1;
76     }
77     if (g_moduleMgr[type].moduleMgr != NULL) {
78         return 0;
79     }
80     APPSPAWN_LOGI("AppSpawnLoadAutoRunModules: %{public}d moduleName: %{public}s", type, g_moduleMgr[type].moduleName);
81 #ifndef APPSPAWN_TEST
82     g_moduleMgr[type].moduleMgr = ModuleMgrScan(g_moduleMgr[type].moduleName);
83     return g_moduleMgr[type].moduleMgr == NULL ? -1 : 0;
84 #else
85     return 0;
86 #endif
87 }
88 
GetAppSpawnHookMgr(void)89 HOOK_MGR *GetAppSpawnHookMgr(void)
90 {
91     if (g_appspawnHookMgr != NULL) {
92         return g_appspawnHookMgr;
93     }
94     g_appspawnHookMgr = HookMgrCreate("appspawn");
95     return g_appspawnHookMgr;
96 }
97 
DeleteAppSpawnHookMgr(void)98 void DeleteAppSpawnHookMgr(void)
99 {
100     HookMgrDestroy(g_appspawnHookMgr);
101     g_appspawnHookMgr = NULL;
102 }
103 
ServerStageHookRun(const HOOK_INFO * hookInfo,void * executionContext)104 static int ServerStageHookRun(const HOOK_INFO *hookInfo, void *executionContext)
105 {
106     AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
107     ServerStageHook realHook = (ServerStageHook)hookInfo->hookCookie;
108     return realHook((void *)arg->content);
109 }
110 
PreHookExec(const HOOK_INFO * hookInfo,void * executionContext)111 static void PreHookExec(const HOOK_INFO *hookInfo, void *executionContext)
112 {
113     AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
114     AppSpawnMgr *spawnMgr = (AppSpawnMgr *)arg->content;
115     clock_gettime(CLOCK_MONOTONIC, &spawnMgr->perLoadStart);
116     APPSPAWN_LOGI("Hook stage: %{public}d prio: %{public}d start", hookInfo->stage, hookInfo->prio);
117 }
118 
PostHookExec(const HOOK_INFO * hookInfo,void * executionContext,int executionRetVal)119 static void PostHookExec(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal)
120 {
121     AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
122     AppSpawnMgr *spawnMgr = (AppSpawnMgr *)arg->content;
123     clock_gettime(CLOCK_MONOTONIC, &spawnMgr->perLoadEnd);
124     uint64_t diff = DiffTime(&spawnMgr->perLoadStart, &spawnMgr->perLoadEnd);
125     APPSPAWN_LOGI("Hook stage: %{public}d prio: %{public}d end time %{public}" PRId64 " ns result: %{public}d",
126         hookInfo->stage, hookInfo->prio, diff, executionRetVal);
127 }
128 
ServerStageHookExecute(AppSpawnHookStage stage,AppSpawnContent * content)129 int ServerStageHookExecute(AppSpawnHookStage stage, AppSpawnContent *content)
130 {
131     APPSPAWN_CHECK(content != NULL, return APPSPAWN_ARG_INVALID, "Invalid content");
132     APPSPAWN_CHECK((stage >= STAGE_SERVER_PRELOAD) && (stage <= STAGE_SERVER_EXIT),
133         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
134     AppSpawnHookArg arg;
135     arg.content = content;
136     arg.client = NULL;
137     HOOK_EXEC_OPTIONS options;
138     options.flags = TRAVERSE_STOP_WHEN_ERROR;
139     options.preHook = PreHookExec;
140     options.postHook = PostHookExec;
141     int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&arg), &options);
142     APPSPAWN_LOGV("Execute hook [%{public}d] result %{public}d", stage, ret);
143     return ret == ERR_NO_HOOK_STAGE ? 0 : ret;
144 }
145 
AddServerStageHook(AppSpawnHookStage stage,int prio,ServerStageHook hook)146 int AddServerStageHook(AppSpawnHookStage stage, int prio, ServerStageHook hook)
147 {
148     APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
149     APPSPAWN_CHECK((stage >= STAGE_SERVER_PRELOAD) && (stage <= STAGE_SERVER_EXIT),
150         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
151     HOOK_INFO info;
152     info.stage = stage;
153     info.prio = prio;
154     info.hook = ServerStageHookRun;
155     info.hookCookie = (void *)hook;
156     APPSPAWN_LOGI("AddServerStageHook prio: %{public}d", prio);
157     return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
158 }
159 
AppSpawnHookRun(const HOOK_INFO * hookInfo,void * executionContext)160 static int AppSpawnHookRun(const HOOK_INFO *hookInfo, void *executionContext)
161 {
162     AppSpawnForkArg *arg = (AppSpawnForkArg *)executionContext;
163     AppSpawnHook realHook = (AppSpawnHook)hookInfo->hookCookie;
164     return realHook((AppSpawnMgr *)arg->content, (AppSpawningCtx *)arg->client);
165 }
166 
PreAppSpawnHookExec(const HOOK_INFO * hookInfo,void * executionContext)167 static void PreAppSpawnHookExec(const HOOK_INFO *hookInfo, void *executionContext)
168 {
169     AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
170     clock_gettime(CLOCK_MONOTONIC, &arg->tmStart);
171     APPSPAWN_LOGV("Hook stage: %{public}d prio: %{public}d start", hookInfo->stage, hookInfo->prio);
172 }
173 
PostAppSpawnHookExec(const HOOK_INFO * hookInfo,void * executionContext,int executionRetVal)174 static void PostAppSpawnHookExec(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal)
175 {
176     AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
177     clock_gettime(CLOCK_MONOTONIC, &arg->tmEnd);
178     uint64_t diff = DiffTime(&arg->tmStart, &arg->tmEnd);
179     APPSPAWN_LOGV("Hook stage: %{public}d prio: %{public}d end time %{public}" PRId64 " ns result: %{public}d",
180         hookInfo->stage, hookInfo->prio, diff, executionRetVal);
181 }
182 
AppSpawnHookExecute(AppSpawnHookStage stage,uint32_t flags,AppSpawnContent * content,AppSpawnClient * client)183 int AppSpawnHookExecute(AppSpawnHookStage stage, uint32_t flags, AppSpawnContent *content, AppSpawnClient *client)
184 {
185     APPSPAWN_CHECK(content != NULL && client != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg");
186     APPSPAWN_LOGV("Execute hook [%{public}d] for app: %{public}s", stage, GetProcessName((AppSpawningCtx *)client));
187     APPSPAWN_CHECK((stage >= STAGE_PARENT_PRE_FORK) && (stage <= STAGE_CHILD_PRE_RUN),
188         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
189     AppSpawnHookArg forkArg;
190     forkArg.client = client;
191     forkArg.content = content;
192     HOOK_EXEC_OPTIONS options;
193     options.flags = flags;  // TRAVERSE_STOP_WHEN_ERROR : 0;
194     options.preHook = PreAppSpawnHookExec;
195     options.postHook = PostAppSpawnHookExec;
196     int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&forkArg), &options);
197     ret = (ret == ERR_NO_HOOK_STAGE) ? 0 : ret;
198     if (ret != 0) {
199         APPSPAWN_LOGE("Execute hook [%{public}d] result %{public}d", stage, ret);
200     }
201     return ret;
202 }
203 
AppSpawnExecuteClearEnvHook(AppSpawnContent * content,AppSpawnClient * client)204 int AppSpawnExecuteClearEnvHook(AppSpawnContent *content, AppSpawnClient *client)
205 {
206     return AppSpawnHookExecute(STAGE_CHILD_PRE_COLDBOOT, HOOK_STOP_WHEN_ERROR, content, client);
207 }
208 
AppSpawnExecuteSpawningHook(AppSpawnContent * content,AppSpawnClient * client)209 int AppSpawnExecuteSpawningHook(AppSpawnContent *content, AppSpawnClient *client)
210 {
211     return AppSpawnHookExecute(STAGE_CHILD_EXECUTE, HOOK_STOP_WHEN_ERROR, content, client);
212 }
213 
AppSpawnExecutePostReplyHook(AppSpawnContent * content,AppSpawnClient * client)214 int AppSpawnExecutePostReplyHook(AppSpawnContent *content, AppSpawnClient *client)
215 {
216     return AppSpawnHookExecute(STAGE_CHILD_POST_RELY, HOOK_STOP_WHEN_ERROR, content, client);
217 }
218 
AppSpawnExecutePreReplyHook(AppSpawnContent * content,AppSpawnClient * client)219 int AppSpawnExecutePreReplyHook(AppSpawnContent *content, AppSpawnClient *client)
220 {
221     return AppSpawnHookExecute(STAGE_CHILD_PRE_RELY, HOOK_STOP_WHEN_ERROR, content, client);
222 }
223 
AppSpawnEnvClear(AppSpawnContent * content,AppSpawnClient * client)224 void AppSpawnEnvClear(AppSpawnContent *content, AppSpawnClient *client)
225 {
226     (void)AppSpawnHookExecute(STAGE_CHILD_PRE_RUN, 0, content, client);
227 }
228 
AddAppSpawnHook(AppSpawnHookStage stage,int prio,AppSpawnHook hook)229 int AddAppSpawnHook(AppSpawnHookStage stage, int prio, AppSpawnHook hook)
230 {
231     APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
232     APPSPAWN_CHECK((stage >= STAGE_PARENT_PRE_FORK) && (stage <= STAGE_CHILD_PRE_RUN),
233         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
234     HOOK_INFO info;
235     info.stage = stage;
236     info.prio = prio;
237     info.hook = AppSpawnHookRun;
238     info.hookCookie = (void *)hook;
239     APPSPAWN_LOGI("AddAppSpawnHook stage: %{public}d prio: %{public}d", stage, prio);
240     return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
241 }
242 
ProcessMgrHookExecute(AppSpawnHookStage stage,const AppSpawnContent * content,const AppSpawnedProcessInfo * appInfo)243 int ProcessMgrHookExecute(AppSpawnHookStage stage, const AppSpawnContent *content,
244     const AppSpawnedProcessInfo *appInfo)
245 {
246     APPSPAWN_CHECK(content != NULL && appInfo != NULL,
247         return APPSPAWN_ARG_INVALID, "Invalid hook");
248     APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
249         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
250 
251     AppSpawnAppArg arg;
252     arg.appInfo = appInfo;
253     arg.content = content;
254     int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&arg), NULL);
255     return ret == ERR_NO_HOOK_STAGE ? 0 : ret;
256 }
257 
ProcessMgrHookRun(const HOOK_INFO * hookInfo,void * executionContext)258 static int ProcessMgrHookRun(const HOOK_INFO *hookInfo, void *executionContext)
259 {
260     AppSpawnAppArg *arg = (AppSpawnAppArg *)executionContext;
261     ProcessChangeHook realHook = (ProcessChangeHook)hookInfo->hookCookie;
262     return realHook((AppSpawnMgr *)arg->content, arg->appInfo);
263 }
264 
AddProcessMgrHook(AppSpawnHookStage stage,int prio,ProcessChangeHook hook)265 int AddProcessMgrHook(AppSpawnHookStage stage, int prio, ProcessChangeHook hook)
266 {
267     APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
268     APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
269         return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
270     HOOK_INFO info;
271     info.stage = stage;
272     info.prio = prio;
273     info.hook = ProcessMgrHookRun;
274     info.hookCookie = hook;
275     return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
276 }
277 
RegChildLooper(struct AppSpawnContent * content,ChildLoop loop)278 void RegChildLooper(struct AppSpawnContent *content, ChildLoop loop)
279 {
280     APPSPAWN_CHECK(content != NULL && loop != NULL, return, "Invalid content for RegChildLooper");
281     content->runChildProcessor = loop;
282 }
283