• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_server.h"
17 
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #undef _GNU_SOURCE
24 #define _GNU_SOURCE
25 #include <sched.h>
26 #ifdef OHOS_DEBUG
27 #include <time.h>
28 #endif // OHOS_DEBUG
29 
30 #define DEFAULT_UMASK 0002
31 
32 #ifndef APPSPAWN_TEST
33 #ifndef OHOS_LITE
34 void DisallowInternet(void);
35 #endif
36 #endif
37 
38 #define SANDBOX_STACK_SIZE (1024 * 1024 * 8)
39 
SetInternetPermission(const AppSpawnClient * client)40 static void SetInternetPermission(const AppSpawnClient *client)
41 {
42 #ifndef APPSPAWN_TEST
43 #ifndef OHOS_LITE
44     if (client == NULL) {
45         return;
46     }
47 
48     APPSPAWN_LOGI("SetInternetPermission id %d setAllowInternet %hhu allowInternet %hhu", client->id,
49                   client->setAllowInternet, client->allowInternet);
50     if (client->setAllowInternet == 1 && client->allowInternet == 0) {
51         DisallowInternet();
52     }
53 #endif
54 #endif
55 }
56 
NotifyResToParent(struct AppSpawnContent_ * content,AppSpawnClient * client,int result)57 static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result)
58 {
59     if (content->notifyResToParent != NULL) {
60         content->notifyResToParent(content, client, result);
61     }
62 }
63 
ProcessExit(void)64 static void ProcessExit(void)
65 {
66     APPSPAWN_LOGI("App exit %d.", getpid());
67 #ifndef APPSPAWN_TEST
68 #ifdef OHOS_LITE
69     _exit(0x7f); // 0x7f user exit
70 #else
71     quick_exit(0);
72 #endif
73 #endif
74 }
75 
DoStartApp(struct AppSpawnContent_ * content,AppSpawnClient * client,char * longProcName,uint32_t longProcNameLen)76 int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen)
77 {
78     SetInternetPermission(client);
79 
80     APPSPAWN_LOGI("DoStartApp id %d longProcNameLen %u", client->id, longProcNameLen);
81     int32_t ret = 0;
82 
83     if ((client->cloneFlags & CLONE_NEWNS) && (content->setAppSandbox)) {
84         ret = content->setAppSandbox(content, client);
85         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
86             return ret, "Failed to set app sandbox");
87     }
88 
89     (void)umask(DEFAULT_UMASK);
90     if (content->setKeepCapabilities) {
91         ret = content->setKeepCapabilities(content, client);
92         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
93             return ret, "Failed to set KeepCapabilities");
94     }
95 
96     if (content->setProcessName) {
97         ret = content->setProcessName(content, client, longProcName, longProcNameLen);
98         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
99             return ret, "Failed to set setProcessName");
100     }
101 
102     if (content->setSeccompFilter) {
103         content->setSeccompFilter(content, client);
104     }
105 
106     if (content->setUidGid) {
107         ret = content->setUidGid(content, client);
108         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
109             return ret, "Failed to setUidGid");
110     }
111 
112     if (content->setFileDescriptors) {
113         ret = content->setFileDescriptors(content, client);
114         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
115             return ret, "Failed to setFileDescriptors");
116     }
117 
118     if (content->setCapabilities) {
119         ret = content->setCapabilities(content, client);
120         APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
121             return ret, "Failed to setCapabilities");
122     }
123 
124     // notify success to father process and start app process
125     NotifyResToParent(content, client, 0);
126     return 0;
127 }
128 
AppSpawnChild(void * arg)129 int AppSpawnChild(void *arg)
130 {
131     APPSPAWN_CHECK(arg != NULL, return -1, "Invalid arg for appspawn child");
132     AppSandboxArg *sandbox = (AppSandboxArg *)arg;
133     struct AppSpawnContent_ *content = sandbox->content;
134     AppSpawnClient *client = sandbox->client;
135 
136 #ifdef OHOS_DEBUG
137     struct timespec tmStart = {0};
138     GetCurTime(&tmStart);
139 #endif // OHOS_DEBUG
140 
141     // close socket id and signal for child
142     if (content->clearEnvironment != NULL) {
143         content->clearEnvironment(content, client);
144     }
145 
146     if (content->setAppAccessToken != NULL) {
147         content->setAppAccessToken(content, client);
148     }
149 
150     int ret = -1;
151 #ifdef ASAN_DETECTOR
152     if ((content->getWrapBundleNameValue != NULL && content->getWrapBundleNameValue(content, client) == 0)
153         || ((client->flags & APP_COLD_START) != 0)) {
154 #else
155     if ((client->flags & APP_COLD_START) != 0) {
156 #endif
157         if (content->coldStartApp != NULL && content->coldStartApp(content, client) == 0) {
158 #ifndef APPSPAWN_TEST
159             _exit(0x7f); // 0x7f user exit
160 #endif
161             return -1;
162         } else {
163             ret = DoStartApp(content, client, content->longProcName, content->longProcNameLen);
164         }
165     } else {
166         ret = DoStartApp(content, client, content->longProcName, content->longProcNameLen);
167     }
168     if (content->initDebugParams != NULL) {
169         content->initDebugParams(content, client);
170     }
171 #ifdef OHOS_DEBUG
172     struct timespec tmEnd = {0};
173     GetCurTime(&tmEnd);
174     // 1s = 1000000000ns
175     long timeUsed = (tmEnd.tv_sec - tmStart.tv_sec) * 1000000000L + (tmEnd.tv_nsec - tmStart.tv_nsec);
176     APPSPAWN_LOGI("App timeused %d %ld ns.", getpid(), timeUsed);
177 #endif  // OHOS_DEBUG
178 
179     if (ret == 0 && content->runChildProcessor != NULL) {
180         content->runChildProcessor(content, client);
181     }
182     ProcessExit();
183     return 0;
184 }
185 
186 int AppSpawnProcessMsg(AppSandboxArg *sandbox, pid_t *childPid)
187 {
188     pid_t pid;
189     APPSPAWN_CHECK(sandbox != NULL && sandbox->content != NULL, return -1, "Invalid content for appspawn");
190     APPSPAWN_CHECK(sandbox->client != NULL && childPid != NULL, return -1, "Invalid client for appspawn");
191     APPSPAWN_LOGI("AppSpawnProcessMsg id %d 0x%x", sandbox->client->id, sandbox->client->flags);
192 
193 #ifndef APPSPAWN_TEST
194     AppSpawnClient *client = sandbox->client;
195     if (client->cloneFlags & CLONE_NEWPID) {
196         APPSPAWN_CHECK(client->cloneFlags & CLONE_NEWNS, return -1, "clone flags error");
197         char *childStack = (char *)malloc(SANDBOX_STACK_SIZE);
198         APPSPAWN_CHECK(childStack != NULL, return -1, "malloc failed");
199 
200         pid = clone(AppSpawnChild, childStack + SANDBOX_STACK_SIZE, client->cloneFlags | SIGCHLD, (void *)sandbox);
201         if (pid > 0) {
202             free(childStack);
203             *childPid = pid;
204             return 0;
205         }
206 
207         client->cloneFlags &= ~CLONE_NEWPID;
208         free(childStack);
209     }
210 
211     pid = fork();
212     APPSPAWN_CHECK(pid >= 0, return -errno, "fork child process error: %d", -errno);
213     *childPid = pid;
214 #else
215     pid = 0;
216     *childPid = pid;
217 #endif
218     if (pid == 0) {
219         AppSpawnChild((void *)sandbox);
220     }
221     return 0;
222 }
223 
224 #ifdef OHOS_DEBUG
225 void GetCurTime(struct timespec *tmCur)
226 {
227     if (tmCur == NULL) {
228         return;
229     }
230 
231     if (clock_gettime(CLOCK_REALTIME, tmCur) != 0) {
232         APPSPAWN_LOGE("[appspawn] invoke, get time failed! err %d", errno);
233     }
234 }
235 #endif  // OHOS_DEBUG
236