• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 <dlfcn.h>
19 #include <fcntl.h>
20 #include <memory>
21 #include <csignal>
22 #include <sys/signalfd.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <sys/wait.h>
26 #include <sys/mount.h>
27 #include <sys/prctl.h>
28 #include <sys/capability.h>
29 #include <sys/syscall.h>
30 #include <thread>
31 #include <string>
32 #include <map>
33 
34 #include "errors.h"
35 #include "hilog/log.h"
36 #include "main_thread.h"
37 #include "securec.h"
38 #include "bundle_mgr_interface.h"
39 #include "if_system_ability_manager.h"
40 #include "iservice_registry.h"
41 #include "system_ability_definition.h"
42 #include "token_setproc.h"
43 #include "parameter.h"
44 #include "parameters.h"
45 #include "beget_ext.h"
46 #ifdef WITH_SELINUX
47 #include "hap_restorecon.h"
48 #endif
49 
50 #include <dirent.h>
51 #include <dlfcn.h>
52 #include <sys/stat.h>
53 #include <sys/types.h>
54 #include <unistd.h>
55 
56 constexpr static mode_t FILE_MODE = 0711;
57 constexpr static mode_t NWEB_FILE_MODE = 0511;
58 
59 #define APPSPAWN_LOGI(fmt, ...) STARTUP_LOGI("appspawn_server.log", "APPSPAWN", fmt, ##__VA_ARGS__)
60 #define APPSPAWN_LOGE(fmt, ...) STARTUP_LOGE("appspawn_server.log", "APPSPAWN", fmt, ##__VA_ARGS__)
61 #define GRAPHIC_PERMISSION_CHECK
62 
63 namespace OHOS {
64 namespace AppSpawn {
65 namespace {
66 constexpr int32_t ERR_PIPE_FAIL = -100;
67 constexpr int32_t MAX_LEN_SHORT_NAME = 16;
68 constexpr int32_t WAIT_DELAY_US = 100 * 1000;  // 100ms
69 constexpr int32_t GID_USER_DATA_RW = 1008;
70 constexpr int32_t MAX_GIDS = 64;
71 constexpr int32_t UID_BASE = 200000;
72 constexpr int32_t WAIT_PARAM_TIME = 5;
73 
74 constexpr std::string_view BUNDLE_NAME_MEDIA_LIBRARY("com.ohos.medialibrary.MediaLibraryDataA");
75 constexpr std::string_view BUNDLE_NAME_SCANNER("com.ohos.medialibrary.MediaScannerAbilityA");
76 }  // namespace
77 
78 using namespace OHOS::HiviewDFX;
79 static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnServer"};
80 
81 #ifdef NWEB_SPAWN
82 struct RenderProcessNode {
RenderProcessNodeOHOS::AppSpawn::RenderProcessNode83     RenderProcessNode(time_t now, int exit):recordTime_(now), exitStatus_(exit) {}
84     time_t recordTime_;
85     int exitStatus_;
86 };
87 
88 namespace {
89 constexpr int32_t RENDER_PROCESS_MAX_NUM = 16;
90 std::map<int32_t, RenderProcessNode> g_renderProcessMap;
91 std::mutex g_mapMut;
92 }
93 
DumpRenderProcessExitedMap()94 static void DumpRenderProcessExitedMap()
95 {
96     APPSPAWN_LOGI("dump render process exited array:");
97     for (auto& it : g_renderProcessMap) {
98         APPSPAWN_LOGI("[pid, time, exitedStatus] = [%d, %ld, %d]",
99             it.first, it.second.recordTime_, it.second.exitStatus_);
100     }
101 }
102 
RecordRenderProcessExitedStatus(pid_t pid,int status)103 void RecordRenderProcessExitedStatus(pid_t pid, int status)
104 {
105     if (g_renderProcessMap.size() < RENDER_PROCESS_MAX_NUM) {
106         RenderProcessNode node(time(nullptr), status);
107         g_renderProcessMap.insert({pid, node});
108         return;
109     }
110 
111     APPSPAWN_LOGI("render process map size reach max, need to erase oldest data.");
112     DumpRenderProcessExitedMap();
113     auto oldestData = std::min_element(g_renderProcessMap.begin(), g_renderProcessMap.end(),
114         [](const std::pair<int32_t, RenderProcessNode>& left, const std::pair<int32_t, RenderProcessNode>& right) {
115             return left.second.recordTime_ < right.second.recordTime_;
116         });
117     g_renderProcessMap.erase(oldestData);
118     RenderProcessNode node(time(nullptr), status);
119     g_renderProcessMap.insert({pid, node});
120     DumpRenderProcessExitedMap();
121 }
122 
GetRenderProcessTerminationStatus(int32_t pid,int * status)123 int GetRenderProcessTerminationStatus(int32_t pid, int *status)
124 {
125     if (status == nullptr) {
126         return -1;
127     }
128 
129     auto it = g_renderProcessMap.find(pid);
130     if (it != g_renderProcessMap.end()) {
131         *status = it->second.exitStatus_;
132         g_renderProcessMap.erase(it);
133         return 0;
134     }
135     APPSPAWN_LOGE("not find pid[%d] in render process exited map", pid);
136     DumpRenderProcessExitedMap();
137     return -1;
138 }
139 
GetProcessStatusInner(int32_t pid,int * status)140 static int GetProcessStatusInner(int32_t pid, int *status)
141 {
142     if (status == nullptr) {
143         return -EINVAL;
144     }
145 
146     std::lock_guard<std::mutex> lock(g_mapMut);
147     if (GetRenderProcessTerminationStatus(pid, status) == 0) {
148         // this shows that the parent process has recived SIGCHLD signal.
149         return 0;
150     }
151 
152     if (kill(pid, SIGKILL) != 0) {
153         APPSPAWN_LOGE("unable to kill render process, pid: %d", pid);
154     }
155 
156     pid_t exitPid = waitpid(pid, status, 0);
157     if (exitPid != pid) {
158         APPSPAWN_LOGE("SignalHandler HandleSignal: %d, status: %d", pid, status);
159         return -EINVAL;
160     }
161 
162     return 0;
163 }
164 
HandleSigChldSignal()165 static void HandleSigChldSignal()
166 {
167     std::lock_guard<std::mutex> lock(g_mapMut);
168     pid_t pid;
169     int status;
170     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
171         APPSPAWN_LOGI("nweb HandleSigChldSignal pid: %d, status: %d", pid, status);
172         RecordRenderProcessExitedStatus(pid, status);
173     }
174 }
175 #endif
176 
177 #ifdef __cplusplus
178 extern "C" {
179 #endif
SignalHandler(int sig)180 static void SignalHandler([[maybe_unused]] int sig)
181 {
182 #ifndef NWEB_SPAWN
183     pid_t pid;
184     int status;
185 
186     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
187     }
188 #else
189     std::thread(HandleSigChldSignal).detach();
190 #endif
191 }
192 
InstallSigHandler()193 static void InstallSigHandler()
194 {
195     struct sigaction sa = {};
196     sa.sa_handler = SignalHandler;
197     int err = sigaction(SIGCHLD, &sa, nullptr);
198     if (err < 0) {
199         HiLog::Error(LABEL, "Error installing SIGCHLD handler: %{public}d", errno);
200         return;
201     }
202 
203     struct sigaction sah = {};
204     sah.sa_handler = SIG_IGN;
205     err = sigaction(SIGHUP, &sah, nullptr);
206     if (err < 0) {
207         HiLog::Error(LABEL, "Error installing SIGHUP handler: %{public}d", errno);
208     }
209 }
210 
UninstallSigHandler()211 static void UninstallSigHandler()
212 {
213     struct sigaction sa = {};
214     sa.sa_handler = nullptr;
215     int err = sigaction(SIGCHLD, &sa, nullptr);
216     if (err < 0) {
217         HiLog::Error(LABEL, "Error uninstalling SIGCHLD handler: %d", errno);
218     }
219 
220     struct sigaction sah = {};
221     sah.sa_handler = nullptr;
222     err = sigaction(SIGHUP, &sah, nullptr);
223     if (err < 0) {
224         HiLog::Error(LABEL, "Error uninstalling SIGHUP handler: %d", errno);
225     }
226 }
227 #ifdef __cplusplus
228 }
229 #endif
230 
AppSpawnServer(const std::string & socketName)231 AppSpawnServer::AppSpawnServer(const std::string &socketName)
232 {
233     socketName_ = socketName;
234     socket_ = std::make_shared<ServerSocket>(socketName_);
235     isRunning_ = true;
236 }
237 
MsgPeer(int connectFd)238 void AppSpawnServer::MsgPeer(int connectFd)
239 {
240     std::unique_ptr<AppSpawnMsgPeer> msgPeer = std::make_unique<AppSpawnMsgPeer>(socket_, connectFd);
241     if (msgPeer == nullptr || msgPeer->MsgPeer() != 0) {
242         HiLog::Error(LABEL, "Failed to listen connection %d, %d", connectFd, errno);
243         return;
244     }
245 
246     std::lock_guard<std::mutex> lock(mut_);
247     appQueue_.push(std::move(msgPeer));
248     dataCond_.notify_one();
249 }
250 
ConnectionPeer()251 void AppSpawnServer::ConnectionPeer()
252 {
253     int connectFd;
254 
255     /* AppSpawn keeps receiving msg from AppMgr and never exits */
256     while (isRunning_) {
257         connectFd = socket_->WaitForConnection();
258         if (connectFd < 0) {
259             usleep(WAIT_DELAY_US);
260             HiLog::Info(LABEL, "AppSpawnServer::ConnectionPeer connectFd is %{public}d", connectFd);
261             continue;
262         }
263 
264         mut_.lock();  // Ensure that mutex in SaveConnection is unlocked before being forked
265         socket_->SaveConnection(connectFd);
266         mut_.unlock();
267         std::thread(&AppSpawnServer::MsgPeer, this, connectFd).detach();
268     }
269 }
270 
WaitRebootEvent()271 void AppSpawnServer::WaitRebootEvent()
272 {
273     APPSPAWN_LOGI("wait 'startup.device.ctl' event");
274     while (isRunning_) {
275         int ret = WaitParameter("startup.device.ctl", "stop", WAIT_PARAM_TIME);
276         if (ret == 0) {
277             std::lock_guard<std::mutex> lock(mut_);
278             isStop_ = true;
279             dataCond_.notify_one();
280             break;
281         } else {
282             std::string value = OHOS::system::GetParameter("startup.device.ctl", "");
283             if (value == "stop") {
284                 std::lock_guard<std::mutex> lock(mut_);
285                 isStop_ = true;
286                 dataCond_.notify_one();
287                 break;
288             }
289         }
290     }
291 }
292 
HandleSignal()293 void AppSpawnServer::HandleSignal()
294 {
295     sigset_t mask;
296     sigemptyset(&mask);
297     sigaddset(&mask, SIGCHLD);
298     sigprocmask(SIG_BLOCK, &mask, nullptr);
299     int signalFd = signalfd(-1, &mask, SFD_CLOEXEC);
300     if (signalFd < 0) {
301         APPSPAWN_LOGE("Error installing SIGHUP handler: %d", errno);
302     }
303     while (isRunning_) {
304         struct signalfd_siginfo fdsi;
305         ssize_t ret = read(signalFd, &fdsi, sizeof(fdsi));
306         if (ret != sizeof(fdsi) || fdsi.ssi_signo != SIGCHLD) {
307             continue;
308         }
309 #ifndef NWEB_SPAWN
310         pid_t pid;
311         int status;
312         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
313             APPSPAWN_LOGE("HandleSignal: %d", pid);
314         }
315 #else
316         std::thread(HandleSigChldSignal).detach();
317 #endif
318         std::lock_guard<std::mutex> lock(mut_);
319         isChildDie_ = true;
320         childPid_ = fdsi.ssi_pid;
321         APPSPAWN_LOGI("exit app pid = %d", childPid_);
322         dataCond_.notify_one();
323     }
324     close(signalFd);
325     signalFd = -1;
326 }
327 
LoadAceLib()328 void AppSpawnServer::LoadAceLib()
329 {
330 #ifdef NWEB_SPAWN
331     const std::string LOAD_LIB_DIR = "/data/app/el1/bundle/public/com.ohos.nweb/libs/arm";
332 #ifdef __MUSL__
333     Dl_namespace dlns;
334     dlns_init(&dlns, "nweb_ns");
335     dlns_create(&dlns, LOAD_LIB_DIR.c_str());
336     void *handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
337 #else
338     const std::string ENGINE_LIB_DIR = LOAD_LIB_DIR + "/libweb_engine.so";
339     void *handle = dlopen(ENGINE_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL);
340 #endif
341     if (handle == nullptr) {
342         HiLog::Error(LABEL, "Fail to dlopen libweb_engine.so, [%{public}s]", dlerror());
343     } else {
344         HiLog::Info(LABEL, "Success to dlopen libweb_engine.so");
345     }
346 #ifdef __MUSL__
347     nwebHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
348 #else
349     const std::string RENDER_LIB_DIR = LOAD_LIB_DIR + "/libnweb_render.so";
350     nwebHandle = dlopen(RENDER_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL);
351 #endif
352     if (nwebHandle == nullptr) {
353         HiLog::Error(LABEL, "Fail to dlopen libnweb_render.so, [%{public}s]", dlerror());
354     } else {
355         HiLog::Info(LABEL, "Success to dlopen libnweb_render.so");
356     }
357 
358 #else
359     std::string acelibdir("/system/lib/libace.z.so");
360     void *AceAbilityLib = nullptr;
361     HiLog::Info(LABEL, "MainThread::LoadAbilityLibrary. Start calling dlopen acelibdir.");
362     AceAbilityLib = dlopen(acelibdir.c_str(), RTLD_NOW | RTLD_GLOBAL);
363     if (AceAbilityLib == nullptr) {
364         HiLog::Error(LABEL, "Fail to dlopen %{public}s, [%{public}s]", acelibdir.c_str(), dlerror());
365     } else {
366         HiLog::Info(LABEL, "Success to dlopen %{public}s", acelibdir.c_str());
367     }
368     HiLog::Info(LABEL, "MainThread::LoadAbilityLibrary. End calling dlopen.");
369 #endif
370 }
371 
InitDebugParams(const ClientSocket::AppProperty * appProperty)372 static void InitDebugParams(const ClientSocket::AppProperty *appProperty)
373 {
374     if (access("/system/lib/libhidebug.so", F_OK) != 0) {
375         HiLog::Error(LABEL, "access failed, errno = %{public}d", errno);
376         return;
377     }
378     void* handle = dlopen("/system/lib/libhidebug.so", RTLD_LAZY);
379     if (handle == nullptr) {
380         HiLog::Error(LABEL, "Failed to dlopen libhidebug.so, %{public}s", dlerror());
381         return;
382     }
383     bool (* initParam)(const char *name);
384     initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam");
385     if (initParam == nullptr) {
386         HiLog::Error(LABEL, "Failed to dlsym InitEnvironmentParam, %{public}s", dlerror());
387         dlclose(handle);
388         return;
389     }
390     bool ret = (*initParam)(appProperty->processName);
391     if (!ret) {
392         HiLog::Error(LABEL, "init parameters failed.");
393     }
394     dlclose(handle);
395 }
396 
ClearEnvironment(void)397 static void ClearEnvironment(void)
398 {
399     sigset_t mask;
400     sigemptyset(&mask);
401     sigaddset(&mask, SIGCHLD);
402     sigprocmask(SIG_UNBLOCK, &mask, nullptr);
403     return;
404 }
405 
DoColdStartApp(ClientSocket::AppProperty * appProperty,int fd)406 int AppSpawnServer::DoColdStartApp(ClientSocket::AppProperty *appProperty, int fd)
407 {
408     APPSPAWN_LOGI("DoColdStartApp::appName %s", appProperty->processName);
409     std::vector<char *> extractedCmds;
410     extractedCmds.push_back(const_cast<char *>("/system/bin/appspawntools"));
411     std::string tmp = std::to_string(fd);
412     APPSPAWN_LOGI("DoColdStartApp::fd %d %s", fd, tmp.c_str());
413     extractedCmds.push_back(const_cast<char *>(tmp.c_str()));
414     std::string uid = std::to_string(appProperty->uid);
415     APPSPAWN_LOGI("DoColdStartApp::uid %d gid %d  %s", appProperty->uid, appProperty->gid, uid.c_str());
416     extractedCmds.push_back(const_cast<char *>(uid.c_str()));
417     std::string gid = std::to_string(appProperty->gid);
418     extractedCmds.push_back(const_cast<char *>(gid.c_str()));
419     extractedCmds.push_back(const_cast<char *>(appProperty->processName));
420     extractedCmds.push_back(const_cast<char *>(appProperty->bundleName));
421     extractedCmds.push_back(const_cast<char *>(appProperty->soPath));
422     std::string accessTokenId = std::to_string(appProperty->accessTokenId);
423     APPSPAWN_LOGI("DoColdStartApp::accessTokenId %d %s", appProperty->accessTokenId, accessTokenId.c_str());
424     extractedCmds.push_back(const_cast<char *>(accessTokenId.c_str()));
425     extractedCmds.push_back(const_cast<char *>(appProperty->apl));
426     APPSPAWN_LOGI("DoColdStartApp renderCmd %s", appProperty->renderCmd);
427     extractedCmds.push_back(const_cast<char *>(appProperty->renderCmd));
428     std::string flags = std::to_string(appProperty->flags);
429     extractedCmds.push_back(const_cast<char *>(flags.c_str()));
430     std::string gidCount = std::to_string(appProperty->gidCount);
431     APPSPAWN_LOGI("DoColdStartApp gidCount %d %s", appProperty->gidCount, gidCount.c_str());
432     extractedCmds.push_back(const_cast<char *>(gidCount.c_str()));
433     for (uint32_t i = 0; i < appProperty->gidCount; i++) {
434         extractedCmds.push_back(const_cast<char *>(std::string(std::to_string(appProperty->gidTable[i])).c_str()));
435     }
436     extractedCmds.push_back(nullptr);
437     APPSPAWN_LOGI("DoColdStartApp extractedCmds %d", extractedCmds.size());
438     int ret = execv(extractedCmds[0], extractedCmds.data());
439     if (ret != 0) {
440         HiLog::Error(LABEL, "Failed to execv, errno = %{public}d", errno);
441         NotifyResToParentProc(fd, -1);
442     }
443     return 0;
444 }
445 
WaitChild(int fd,int pid,ClientSocket::AppProperty * appProperty)446 static int WaitChild(int fd, int pid, ClientSocket::AppProperty *appProperty)
447 {
448     int result = ERR_OK;
449     fd_set rd;
450     struct timeval tv;
451     FD_ZERO(&rd);
452     FD_SET(fd, &rd);
453     tv.tv_sec = 1;
454     tv.tv_usec = 0;
455     int ret = select(fd + 1, &rd, nullptr, nullptr, &tv);
456     if (ret == 0) { // timeout
457         APPSPAWN_LOGI("Time out for child %s %d", appProperty->processName, pid);
458         result = ERR_OK;
459     } else if (ret == -1) {
460         APPSPAWN_LOGI("Error for child %s %d", appProperty->processName, pid);
461         result = ERR_OK;
462     } else {
463         ret = read(fd, &result, sizeof(result));
464     }
465     APPSPAWN_LOGI("child process %s %s pid %d",
466         appProperty->processName, (result == ERR_OK) ? "success" : "fail", pid);
467     return (result == ERR_OK) ? 0 : result;
468 }
469 
StartApp(char * longProcName,int64_t longProcNameLen,ClientSocket::AppProperty * appProperty,int connectFd,pid_t & pid)470 int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen,
471     ClientSocket::AppProperty *appProperty, int connectFd, pid_t &pid)
472 {
473     if (!CheckAppProperty(appProperty)) {
474         return -EINVAL;
475     }
476     int32_t fd[FDLEN2] = {FD_INIT_VALUE, FD_INIT_VALUE};
477     if (pipe(fd) == -1) {
478         HiLog::Error(LABEL, "create pipe fail, errno = %{public}d", errno);
479         return ERR_PIPE_FAIL;
480     }
481     fcntl(fd[0], F_SETFL, O_NDELAY);
482 
483     InstallSigHandler();
484     pid = fork();
485     if (pid < 0) {
486         HiLog::Error(LABEL, "AppSpawnServer::Failed to fork new process, errno = %{public}d", errno);
487         close(fd[0]);
488         close(fd[1]);
489         return -errno;
490     } else if (pid == 0) {
491         InitDebugParams(appProperty);
492         SpecialHandle(appProperty);
493         // close socket connection and peer socket in child process
494         if (socket_ != NULL) {
495             socket_->CloseConnection(connectFd);
496             socket_->CloseServerMonitor();
497         }
498         close(fd[0]); // close read fd
499         ClearEnvironment();
500         UninstallSigHandler();
501         SetAppAccessToken(appProperty);
502         if ((appProperty->flags == ClientSocket::APPSPAWN_COLD_BOOT) &&
503             OHOS::system::GetBoolParameter("appspawn.cold.boot", false)) {
504             DoColdStartApp(appProperty, fd[1]);
505         } else {
506             SetAppProcProperty(appProperty, longProcName, longProcNameLen, fd[1]);
507         }
508         _exit(0);
509     }
510     int ret = WaitChild(fd[0], pid, appProperty);
511     close(fd[0]);
512     close(fd[1]);
513     return ret;
514 }
515 
QuickExitMain()516 void AppSpawnServer::QuickExitMain()
517 {
518 #ifndef TEST_EXIT
519     quick_exit(0);
520 #endif
521     return;
522 }
523 
ProcessAppSpawnMsg(char * longProcName,int64_t longProcNameLen,const std::unique_ptr<AppSpawnMsgPeer> & msg)524 void AppSpawnServer::ProcessAppSpawnMsg(char *longProcName, int64_t longProcNameLen,
525                                         const std::unique_ptr<AppSpawnMsgPeer> &msg)
526 {
527     int connectFd = msg->GetConnectFd();
528     ClientSocket::AppProperty *appProperty = msg->GetMsg();
529 #ifdef NWEB_SPAWN
530     if (appProperty->code == ClientSocket::GET_RENDER_TERMINATION_STATUS) {
531         int exitStatus = 0;
532         int ret = GetProcessStatusInner(appProperty->pid, &exitStatus);
533         if (ret) {
534             msg->Response(ret);
535         } else {
536             msg->Response(exitStatus);
537         }
538         APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s",
539             exitStatus, appProperty->pid, appProperty->uid, appProperty->processName, appProperty->bundleName);
540         return;
541     }
542 #endif
543     pid_t pid = 0;
544     int ret = StartApp(longProcName, longProcNameLen, appProperty, connectFd, pid);
545     if (ret) {
546         msg->Response(ret);
547     } else {
548         msg->Response(pid);
549         appMap_[pid] = appProperty->processName;
550     }
551     APPSPAWN_LOGI("AppSpawnServer::parent process create app finish, pid = %d uid %d %s %s",
552         pid, appProperty->uid, appProperty->processName, appProperty->bundleName);
553 }
554 
ServerMain(char * longProcName,int64_t longProcNameLen)555 bool AppSpawnServer::ServerMain(char *longProcName, int64_t longProcNameLen)
556 {
557     if (socket_->RegisterServerSocket() != 0) {
558         HiLog::Error(LABEL, "AppSpawnServer::Failed to register server socket");
559         return false;
560     }
561     std::thread(&AppSpawnServer::ConnectionPeer, this).detach();
562 #ifndef APPSPAWN_UT
563     LoadAceLib();
564 #endif
565 
566     std::thread(&AppSpawnServer::WaitRebootEvent, this).detach();
567     std::thread(&AppSpawnServer::HandleSignal, this).detach();
568     while (isRunning_) {
569         std::unique_lock<std::mutex> lock(mut_);
570         dataCond_.wait(lock, [this] { return !this->appQueue_.empty() || isStop_ || isChildDie_;});
571         if (isStop_) { // finish
572             break;
573         }
574         if (isChildDie_) { // process child die
575             isChildDie_ = false;
576             auto iter = appMap_.find(childPid_);
577             if (iter != appMap_.end()) {
578                 APPSPAWN_LOGI("delete pid=%d in appMap", iter->first);
579                 appMap_.erase(iter);
580             }
581         }
582         if (this->appQueue_.empty()) {
583             continue;
584         }
585         std::unique_ptr<AppSpawnMsgPeer> msg = std::move(appQueue_.front());
586         appQueue_.pop();
587         int connectFd = msg->GetConnectFd();
588         ProcessAppSpawnMsg(longProcName, longProcNameLen, msg);
589         socket_->CloseConnection(connectFd); // close socket connection
590     }
591 
592     while (appMap_.size() > 0) {
593         auto iter = appMap_.begin();
594         APPSPAWN_LOGI("kill app, pid = %d, processName = %s", iter->first, iter->second.c_str());
595         kill(iter->first, SIGKILL);
596         appMap_.erase(iter);
597     }
598     QuickExitMain();
599     return false;
600 }
601 
SetProcessName(char * longProcName,int64_t longProcNameLen,const char * processName,int32_t len)602 int32_t AppSpawnServer::SetProcessName(
603     char *longProcName, int64_t longProcNameLen, const char *processName, int32_t len)
604 {
605     if (longProcName == nullptr || processName == nullptr || len <= 0) {
606         HiLog::Error(LABEL, "process name is nullptr or length error");
607         return -EINVAL;
608     }
609 
610     char shortName[MAX_LEN_SHORT_NAME];
611     if (memset_s(shortName, sizeof(shortName), 0, sizeof(shortName)) != EOK) {
612         HiLog::Error(LABEL, "Failed to memset short name");
613         return -EINVAL;
614     }
615 
616     // process short name max length 16 bytes.
617     if (len > MAX_LEN_SHORT_NAME) {
618         if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, processName, MAX_LEN_SHORT_NAME - 1) != EOK) {
619             HiLog::Error(LABEL, "strncpy_s short name error: %{public}d", errno);
620             return -EINVAL;
621         }
622     } else {
623         if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, processName, len) != EOK) {
624             HiLog::Error(LABEL, "strncpy_s short name error: %{public}d", errno);
625             return -EINVAL;
626         }
627     }
628 
629     // set short name
630     if (prctl(PR_SET_NAME, shortName) == -1) {
631         HiLog::Error(LABEL, "prctl(PR_SET_NAME) error: %{public}d", errno);
632         return (-errno);
633     }
634 
635     // reset longProcName
636     if (memset_s(longProcName, static_cast<size_t>(longProcNameLen), 0, static_cast<size_t>(longProcNameLen)) != EOK) {
637         HiLog::Error(LABEL, "Failed to memset long process name");
638         return -EINVAL;
639     }
640 
641     // set long process name
642     if (strncpy_s(longProcName, longProcNameLen, processName, len) != EOK) {
643         HiLog::Error(LABEL, "strncpy_s long name error: %{public}d", errno);
644         return -EINVAL;
645     }
646 
647     return ERR_OK;
648 }
649 
SetUidGid(const uint32_t uid,const uint32_t gid,const uint32_t * gitTable,const uint32_t gidCount)650 int32_t AppSpawnServer::SetUidGid(
651     const uint32_t uid, const uint32_t gid, const uint32_t *gitTable, const uint32_t gidCount)
652 {
653     if (gitTable == nullptr) {
654         HiLog::Error(LABEL, "gitTable is nullptr");
655         return (-errno);
656     }
657 
658     // set gids
659     if (setgroups(gidCount, reinterpret_cast<const gid_t *>(&gitTable[0])) == -1) {
660         HiLog::Error(LABEL, "setgroups failed: %{public}d, gids.size=%{public}u", errno, gidCount);
661         return (-errno);
662     }
663 
664     // set gid
665     if (setresgid(gid, gid, gid) == -1) {
666         HiLog::Error(LABEL, "setgid(%{public}u) failed: %{public}d", gid, errno);
667         return (-errno);
668     }
669 
670     // If the effective user ID is changed from 0 to nonzero, then all capabilities are cleared from the effective set
671     if (setresuid(uid, uid, uid) == -1) {
672         HiLog::Error(LABEL, "setuid(%{public}u) failed: %{public}d", uid, errno);
673         return (-errno);
674     }
675 
676     return ERR_OK;
677 }
678 
SetFileDescriptors()679 int32_t AppSpawnServer::SetFileDescriptors()
680 {
681     // close stdin stdout stderr
682     close(STDIN_FILENO);
683     close(STDOUT_FILENO);
684     close(STDERR_FILENO);
685 
686     // redirect to /dev/null
687     int dev_null_fd = open(deviceNull_.c_str(), O_RDWR);
688     if (dev_null_fd == -1) {
689         HiLog::Error(LABEL, "open dev_null error: %{public}d", errno);
690         return (-errno);
691     }
692 
693     // stdin
694     if (dup2(dev_null_fd, STDIN_FILENO) == -1) {
695         HiLog::Error(LABEL, "dup2 STDIN error: %{public}d", errno);
696         return (-errno);
697     };
698 
699     // stdout
700     if (dup2(dev_null_fd, STDOUT_FILENO) == -1) {
701         HiLog::Error(LABEL, "dup2 STDOUT error: %{public}d", errno);
702         return (-errno);
703     };
704 
705     // stderr
706     if (dup2(dev_null_fd, STDERR_FILENO) == -1) {
707         HiLog::Error(LABEL, "dup2 STDERR error: %{public}d", errno);
708         return (-errno);
709     };
710 
711     return ERR_OK;
712 }
713 
SetCapabilities()714 int32_t AppSpawnServer::SetCapabilities()
715 {
716     // init cap
717     __user_cap_header_struct cap_header;
718 
719     if (memset_s(&cap_header, sizeof(cap_header), 0, sizeof(cap_header)) != EOK) {
720         HiLog::Error(LABEL, "Failed to memset cap header");
721         return -EINVAL;
722     }
723     cap_header.version = _LINUX_CAPABILITY_VERSION_3;
724     cap_header.pid = 0;
725 
726     __user_cap_data_struct cap_data[2];
727     if (memset_s(&cap_data, sizeof(cap_data), 0, sizeof(cap_data)) != EOK) {
728         HiLog::Error(LABEL, "Failed to memset cap data");
729         return -EINVAL;
730     }
731 
732     // init inheritable permitted effective zero
733 #ifdef GRAPHIC_PERMISSION_CHECK
734     const uint64_t inheriTable = 0;
735     const uint64_t permitted = 0;
736     const uint64_t effective = 0;
737 #else
738     const uint64_t inheriTable = 0x3fffffffff;
739     const uint64_t permitted = 0x3fffffffff;
740     const uint64_t effective = 0x3fffffffff;
741 #endif
742 
743     cap_data[0].inheritable = static_cast<__u32>(inheriTable);
744     cap_data[1].inheritable = static_cast<__u32>(inheriTable >> BITLEN32);
745     cap_data[0].permitted = static_cast<__u32>(permitted);
746     cap_data[1].permitted = static_cast<__u32>(permitted >> BITLEN32);
747     cap_data[0].effective = static_cast<__u32>(effective);
748     cap_data[1].effective = static_cast<__u32>(effective >> BITLEN32);
749 
750     // set capabilities
751     if (capset(&cap_header, &cap_data[0]) == -1) {
752         HiLog::Error(LABEL, "capset failed: %{public}d", errno);
753         return (-errno);
754     }
755 
756     return ERR_OK;
757 }
758 
SetRunning(bool isRunning)759 void AppSpawnServer::SetRunning(bool isRunning)
760 {
761     isRunning_ = isRunning;
762 }
763 
SetServerSocket(const std::shared_ptr<ServerSocket> & serverSocket)764 void AppSpawnServer::SetServerSocket(const std::shared_ptr<ServerSocket> &serverSocket)
765 {
766     socket_ = serverSocket;
767 }
768 
DoAppSandboxMountOnce(const std::string originPath,const std::string destinationPath)769 int32_t AppSpawnServer::DoAppSandboxMountOnce(const std::string originPath, const std::string destinationPath)
770 {
771     int rc = 0;
772 
773     rc = mount(originPath.c_str(), destinationPath.c_str(), NULL, MS_BIND | MS_REC, NULL);
774     if (rc) {
775         HiLog::Error(LABEL, "bind mount %{public}s to %{public}s failed %{public}d", originPath.c_str(),
776             destinationPath.c_str(), errno);
777         return rc;
778     }
779 
780     rc = mount(NULL, destinationPath.c_str(), NULL, MS_PRIVATE, NULL);
781     if (rc) {
782         HiLog::Error(LABEL, "private mount to %{public}s failed %{public}d", destinationPath.c_str(), errno);
783         return rc;
784     }
785 
786     return 0;
787 }
788 
DoAppSandboxMount(const ClientSocket::AppProperty * appProperty,std::string rootPath)789 int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appProperty,
790                                           std::string rootPath)
791 {
792     std::string currentUserId = std::to_string(appProperty->uid / UID_BASE);
793     std::string oriInstallPath = "/data/app/el1/bundle/public/";
794     std::string oriel1DataPath = "/data/app/el1/" + currentUserId + "/base/";
795     std::string oriel2DataPath = "/data/app/el2/" + currentUserId + "/base/";
796     std::string oriDatabasePath = "/data/app/el2/" + currentUserId + "/database/";
797     const std::string oriappdataPath = "/data/accounts/account_0/appdata/";
798     std::string destDatabasePath = rootPath + "/data/storage/el2/database";
799     std::string destInstallPath = rootPath + "/data/storage/el1/bundle";
800     std::string destel1DataPath = rootPath + "/data/storage/el1/base";
801     std::string destel2DataPath = rootPath + "/data/storage/el2/base";
802     std::string destappdataPath = rootPath + oriappdataPath;
803 
804     int rc = 0;
805 
806     std::string bundleName = appProperty->bundleName;
807     oriInstallPath += bundleName;
808     oriel1DataPath += bundleName;
809     oriel2DataPath += bundleName;
810     oriDatabasePath += bundleName;
811 
812     std::map<std::string, std::string> mountMap;
813     mountMap[destDatabasePath] = oriDatabasePath;
814     mountMap[destInstallPath] = oriInstallPath;
815     mountMap[destel1DataPath] = oriel1DataPath;
816     mountMap[destel2DataPath] = oriel2DataPath;
817     mountMap[destappdataPath] = oriappdataPath;
818 
819     std::map<std::string, std::string>::iterator iter;
820     for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) {
821         rc = DoAppSandboxMountOnce(iter->second.c_str(), iter->first.c_str());
822         if (rc) {
823             return rc;
824         }
825     }
826 
827     // to create some useful dir when mount point created
828     std::vector<std::string> mkdirInfo;
829     std::string dirPath;
830     mkdirInfo.push_back("/data/storage/el1/bundle/nweb");
831 
832     for (int i = 0; i < mkdirInfo.size(); i++) {
833         dirPath = rootPath + mkdirInfo[i];
834         mkdir(dirPath.c_str(), FILE_MODE);
835     }
836 
837     return 0;
838 }
839 
DoAppSandboxMountCustomized(const ClientSocket::AppProperty * appProperty,std::string rootPath)840 int32_t AppSpawnServer::DoAppSandboxMountCustomized(const ClientSocket::AppProperty *appProperty, std::string rootPath)
841 {
842     std::string bundleName = appProperty->bundleName;
843     std::string currentUserId = std::to_string(appProperty->uid / UID_BASE);
844     std::string destInstallPath = rootPath + "/data/storage/el1/bundle";
845 
846     // account_0/applications/ dir can still access other packages' data now for compatibility purpose
847     std::string oriapplicationsPath = "/data/app/el1/bundle/public/";
848     std::string destapplicationsPath = rootPath + "/data/accounts/account_0/applications/";
849     DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destapplicationsPath.c_str());
850 
851     // need permission check for system app here
852     std::string destbundlesPath = rootPath + "/data/bundles/";
853     DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destbundlesPath.c_str());
854 
855     std::string orimntHmdfsPath = "/mnt/hmdfs/";
856     std::string destmntHmdfsPath = rootPath + orimntHmdfsPath;
857     DoAppSandboxMountOnce(orimntHmdfsPath.c_str(), destmntHmdfsPath.c_str());
858 
859     // Add distributedfile module support, later reconstruct it
860     std::string oriDistributedPath = "/mnt/hmdfs/" +  currentUserId + "/account/merge_view/data/" + bundleName;
861     std::string destDistributedPath = rootPath + "/data/storage/el2/distributedfiles";
862     DoAppSandboxMountOnce(oriDistributedPath.c_str(), destDistributedPath.c_str());
863 
864     std::string oriDistributedGroupPath = "/mnt/hmdfs/" +  currentUserId + "/non_account/merge_view/data/" + bundleName;
865     std::string destDistributedGroupPath = rootPath + "/data/storage/el2/auth_groups";
866     DoAppSandboxMountOnce(oriDistributedGroupPath.c_str(), destDistributedGroupPath.c_str());
867 
868     // do nweb adaption
869     std::string orinwebPath = "/data/app/el1/bundle/public/com.ohos.nweb";
870     std::string destnwebPath = destInstallPath + "/nweb";
871     chmod(destnwebPath.c_str(), NWEB_FILE_MODE);
872     DoAppSandboxMountOnce(orinwebPath.c_str(), destnwebPath.c_str());
873 
874     if (bundleName.find("medialibrary") != std::string::npos) {
875         std::string oriMediaPath = "/storage/media/" +  currentUserId;
876         std::string destMediaPath = rootPath + "/storage/media";
877         DoAppSandboxMountOnce(oriMediaPath.c_str(), destMediaPath.c_str());
878     }
879 
880     return 0;
881 }
882 
DoAppSandboxMkdir(std::string sandboxPackagePath,const ClientSocket::AppProperty * appProperty)883 void AppSpawnServer::DoAppSandboxMkdir(std::string sandboxPackagePath, const ClientSocket::AppProperty *appProperty)
884 {
885     std::vector<std::string> mkdirInfo;
886     std::string dirPath;
887 
888     mkdirInfo.push_back("/mnt/");
889     mkdirInfo.push_back("/mnt/hmdfs/");
890     mkdirInfo.push_back("/data/");
891     mkdirInfo.push_back("/storage/");
892     mkdirInfo.push_back("/storage/media");
893     mkdirInfo.push_back("/data/storage");
894     // to create /mnt/sandbox/<packagename>/data/storage/el1 related path, later should delete this code.
895     mkdirInfo.push_back("/data/storage/el1");
896     mkdirInfo.push_back("/data/storage/el1/bundle");
897     mkdirInfo.push_back("/data/storage/el1/base");
898     mkdirInfo.push_back("/data/storage/el1/database");
899     mkdirInfo.push_back("/data/storage/el2");
900     mkdirInfo.push_back("/data/storage/el2/base");
901     mkdirInfo.push_back("/data/storage/el2/database");
902     mkdirInfo.push_back("/data/storage/el2/distributedfiles");
903     mkdirInfo.push_back("/data/storage/el2/auth_groups");
904     // create applications folder for compatibility purpose
905     mkdirInfo.push_back("/data/accounts");
906     mkdirInfo.push_back("/data/accounts/account_0");
907     mkdirInfo.push_back("/data/accounts/account_0/applications/");
908     mkdirInfo.push_back("/data/accounts/account_0/appdata/");
909     mkdirInfo.push_back("/data/bundles/");
910 
911     for (int i = 0; i < mkdirInfo.size(); i++) {
912         dirPath = sandboxPackagePath + mkdirInfo[i];
913         mkdir(dirPath.c_str(), FILE_MODE);
914     }
915 }
916 
DoSandboxRootFolderCreateAdapt(std::string sandboxPackagePath)917 int32_t AppSpawnServer::DoSandboxRootFolderCreateAdapt(std::string sandboxPackagePath)
918 {
919     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
920     if (rc) {
921         HiLog::Error(LABEL, "set propagation slave failed");
922         return rc;
923     }
924 
925     // bind mount "/" to /mnt/sandbox/<packageName> path
926     // rootfs: to do more resouces bind mount here to get more strict resources constraints
927     rc = mount("/", sandboxPackagePath.c_str(), NULL, MS_BIND | MS_REC, NULL);
928     if (rc) {
929         HiLog::Error(LABEL, "mount bind / failed");
930         return rc;
931     }
932 
933     return 0;
934 }
935 
DoSandboxRootFolderCreate(std::string sandboxPackagePath)936 int32_t AppSpawnServer::DoSandboxRootFolderCreate(std::string sandboxPackagePath)
937 {
938     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
939     if (rc) {
940         return rc;
941     }
942 
943     // bind mount sandboxPackagePath to make it a mount point for pivot_root syscall
944     DoAppSandboxMountOnce(sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
945 
946     // do /mnt/sandbox/<packageName> path mkdir
947     std::map<std::string, std::string> mountMap;
948     std::vector<std::string> vecInfo;
949     std::string tmpDir = "";
950 
951     vecInfo.push_back("/config");
952     vecInfo.push_back("/dev");
953     vecInfo.push_back("/proc");
954     vecInfo.push_back("/sys");
955     vecInfo.push_back("/sys_prod");
956     vecInfo.push_back("/system");
957 
958     for (int i = 0; i < vecInfo.size(); i++) {
959         tmpDir = sandboxPackagePath + vecInfo[i];
960         mkdir(tmpDir.c_str(), FILE_MODE);
961         mountMap[vecInfo[i]] = tmpDir;
962     }
963 
964     // bind mount root folder to /mnt/sandbox/<packageName> path
965     std::map<std::string, std::string>::iterator iter;
966     for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) {
967         rc = DoAppSandboxMountOnce(iter->first.c_str(), iter->second.c_str());
968         if (rc) {
969             HiLog::Error(LABEL, "move root folder failed, %{public}s", sandboxPackagePath.c_str());
970         }
971     }
972 
973     // to create symlink at /mnt/sandbox/<packageName> path
974     // bin -> /system/bin
975     // d -> /sys/kernel/debug
976     // etc -> /system/etc
977     // init -> /system/bin/init
978     // lib -> /system/lib
979     // sdcard -> /storage/self/primary
980     std::map<std::string, std::string> symlinkMap;
981     symlinkMap["/system/bin"] = sandboxPackagePath + "/bin";
982     symlinkMap["/sys/kernel/debug"] = sandboxPackagePath + "/d";
983     symlinkMap["/system/etc"] = sandboxPackagePath + "/etc";
984     symlinkMap["/system/bin/init"] = sandboxPackagePath + "/init";
985     symlinkMap["/system/lib"] = sandboxPackagePath + "/lib";
986 
987     for (iter = symlinkMap.begin(); iter != symlinkMap.end(); ++iter) {
988         symlink(iter->first.c_str(), iter->second.c_str());
989     }
990 
991     return 0;
992 }
993 
SetAppSandboxProperty(const ClientSocket::AppProperty * appProperty)994 int32_t AppSpawnServer::SetAppSandboxProperty(const ClientSocket::AppProperty *appProperty)
995 {
996     int rc = 0;
997 
998     // create /mnt/sandbox/<packagename> path, later put it to rootfs module
999     std::string sandboxPackagePath = "/mnt/sandbox/";
1000     mkdir(sandboxPackagePath.c_str(), FILE_MODE);
1001     sandboxPackagePath += appProperty->bundleName;
1002     mkdir(sandboxPackagePath.c_str(), FILE_MODE);
1003 
1004     // add pid to a new mnt namespace
1005     rc = unshare(CLONE_NEWNS);
1006     if (rc) {
1007         HiLog::Error(LABEL, "unshare failed, packagename is %{public}s", appProperty->processName);
1008         return rc;
1009     }
1010 
1011     // to make wargnar work
1012     if (access("/3rdmodem", F_OK) == 0) {
1013         rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
1014     } else {
1015         rc = DoSandboxRootFolderCreate(sandboxPackagePath);
1016     }
1017     if (rc) {
1018         HiLog::Error(LABEL, "DoSandboxRootFolderCreate failed, %{public}s", appProperty->processName);
1019         return rc;
1020     }
1021 
1022     // to create /mnt/sandbox/<packagename>/data/storage related path
1023     DoAppSandboxMkdir(sandboxPackagePath, appProperty);
1024 
1025     rc = DoAppSandboxMount(appProperty, sandboxPackagePath);
1026     if (rc) {
1027         HiLog::Error(LABEL, "DoAppSandboxMount failed, packagename is %{public}s", appProperty->processName);
1028         return rc;
1029     }
1030 
1031     rc = DoAppSandboxMountCustomized(appProperty, sandboxPackagePath);
1032     if (rc) {
1033         HiLog::Error(LABEL, "DoAppSandboxMountCustomized failed, packagename is %{public}s", appProperty->processName);
1034         return rc;
1035     }
1036 
1037     rc = chdir(sandboxPackagePath.c_str());
1038     if (rc) {
1039         HiLog::Error(LABEL, "chdir failed, packagename is %{public}s, path is %{public}s", \
1040             appProperty->processName, sandboxPackagePath.c_str());
1041         return rc;
1042     }
1043 
1044     rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
1045     if (rc) {
1046         HiLog::Error(LABEL, "pivot root failed, packagename is %{public}s, errno is %{public}d", \
1047             appProperty->processName, errno);
1048         return rc;
1049     }
1050 
1051     rc = umount2(".", MNT_DETACH);
1052     if (rc) {
1053         HiLog::Error(LABEL, "MNT_DETACH failed, packagename is %{public}s", appProperty->processName);
1054         return rc;
1055     }
1056 
1057     return ERR_OK;
1058 }
1059 
SetAppAccessToken(const ClientSocket::AppProperty * appProperty)1060 void AppSpawnServer::SetAppAccessToken(const ClientSocket::AppProperty *appProperty)
1061 {
1062     int32_t ret = SetSelfTokenID(appProperty->accessTokenId);
1063     HiLog::Info(LABEL, "AppSpawnServer::set access token id = %{public}d, ret = %{public}d %{public}d",
1064         appProperty->accessTokenId, ret, getuid());
1065 
1066 #ifdef WITH_SELINUX
1067     HapContext hapContext;
1068     ret = hapContext.HapDomainSetcontext(appProperty->apl, appProperty->processName);
1069     if (ret != 0) {
1070         HiLog::Error(LABEL, "AppSpawnServer::Failed to hap domain set context, errno = %{public}d %{public}s",
1071             errno, appProperty->apl);
1072     } else {
1073         HiLog::Info(LABEL, "AppSpawnServer::Success to hap domain set context, ret = %{public}d", ret);
1074     }
1075 #endif
1076 }
1077 
SetAppProcProperty(const ClientSocket::AppProperty * appProperty,char * longProcName,int64_t longProcNameLen,const int32_t fd)1078 bool AppSpawnServer::SetAppProcProperty(const ClientSocket::AppProperty *appProperty, char *longProcName,
1079     int64_t longProcNameLen, const int32_t fd)
1080 {
1081     HiLog::Debug(LABEL, "AppSpawnServer::Success to fork new process, pid = %{public}d", getpid());
1082     int32_t ret = SetAppSandboxProperty(appProperty);
1083     if (FAILED(ret)) {
1084         NotifyResToParentProc(fd, ret);
1085         return false;
1086     }
1087 
1088     ret = SetKeepCapabilities(appProperty->uid);
1089     if (FAILED(ret)) {
1090         NotifyResToParentProc(fd, ret);
1091         return false;
1092     }
1093 
1094     ret = SetProcessName(longProcName, longProcNameLen, appProperty->processName, strlen(appProperty->processName) + 1);
1095     if (FAILED(ret)) {
1096         NotifyResToParentProc(fd, ret);
1097         return false;
1098     }
1099 
1100 #ifdef GRAPHIC_PERMISSION_CHECK
1101     ret = SetUidGid(appProperty->uid, appProperty->gid, appProperty->gidTable, appProperty->gidCount);
1102     if (FAILED(ret)) {
1103         NotifyResToParentProc(fd, ret);
1104         return false;
1105     }
1106 #endif
1107 
1108     ret = SetFileDescriptors();
1109     if (FAILED(ret)) {
1110         NotifyResToParentProc(fd, ret);
1111         return false;
1112     }
1113 
1114     ret = SetCapabilities();
1115     if (FAILED(ret)) {
1116         NotifyResToParentProc(fd, ret);
1117         return false;
1118     }
1119     // notify success to father process and start app process
1120     NotifyResToParentProc(fd, ret);
1121 
1122 #ifdef NWEB_SPAWN
1123     using FuncType = void (*)(const char *cmd);
1124     FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(nwebHandle, "NWebRenderMain"));
1125     if (funcNWebRenderMain == nullptr) {
1126         HiLog::Error(LABEL, "nwebspawn dlsym ERROR=%{public}s", dlerror());
1127         return false;
1128     }
1129     funcNWebRenderMain(appProperty->renderCmd);
1130 #else
1131     AppExecFwk::MainThread::Start();
1132 #endif
1133 
1134     HiLog::Error(LABEL, "Failed to start process, pid = %{public}d", getpid());
1135     return false;
1136 }
1137 
NotifyResToParentProc(const int32_t fd,const int32_t value)1138 void AppSpawnServer::NotifyResToParentProc(const int32_t fd, const int32_t value)
1139 {
1140     write(fd, &value, sizeof(value));
1141     close(fd);
1142 }
1143 
SpecialHandle(ClientSocket::AppProperty * appProperty)1144 void AppSpawnServer::SpecialHandle(ClientSocket::AppProperty *appProperty)
1145 {
1146     if (appProperty == nullptr) {
1147         HiLog::Error(LABEL, "appProperty is nullptr");
1148         return;
1149     }
1150     // special handle bundle name medialibrary and scanner
1151     if ((strcmp(appProperty->processName, BUNDLE_NAME_MEDIA_LIBRARY.data()) == 0) ||
1152         (strcmp(appProperty->processName, BUNDLE_NAME_SCANNER.data()) == 0)) {
1153         if (appProperty->gidCount < MAX_GIDS) {
1154             appProperty->gidTable[appProperty->gidCount] = GID_USER_DATA_RW;
1155             appProperty->gidCount++;
1156         } else {
1157             HiLog::Info(LABEL, "gidCount out of bounds !");
1158         }
1159     }
1160 }
1161 
SetKeepCapabilities(uint32_t uid)1162 int32_t AppSpawnServer::SetKeepCapabilities(uint32_t uid)
1163 {
1164     // set keep capabilities when user not root.
1165     if (uid != 0) {
1166         if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
1167             HiLog::Error(LABEL, "set keepcaps failed: %{public}d", errno);
1168             return (-errno);
1169         }
1170     }
1171 
1172     return ERR_OK;
1173 }
1174 
CheckBundleName(const std::string & bundleName)1175 static int CheckBundleName(const std::string &bundleName)
1176 {
1177     if (bundleName.empty() || bundleName.size() > ClientSocket::LEN_BUNDLE_NAME) {
1178         return -1;
1179     }
1180     if (bundleName.find('\\') != std::string::npos || bundleName.find('/') != std::string::npos) {
1181         return -1;
1182     }
1183     return 0;
1184 }
1185 
CheckAppProperty(const ClientSocket::AppProperty * appProperty)1186 bool AppSpawnServer::CheckAppProperty(const ClientSocket::AppProperty *appProperty)
1187 {
1188     if (appProperty == nullptr) {
1189         HiLog::Error(LABEL, "appProperty is nullptr");
1190         return false;
1191     }
1192 
1193     if (appProperty->gidCount > ClientSocket::MAX_GIDS) {
1194         HiLog::Error(LABEL, "gidCount error: %{public}u", appProperty->gidCount);
1195         return false;
1196     }
1197 
1198     if (CheckBundleName(appProperty->processName) != 0) {
1199         HiLog::Error(LABEL, "process name error");
1200         return false;
1201     }
1202 
1203     if (CheckBundleName(appProperty->bundleName) != 0) {
1204         HiLog::Error(LABEL, "bundle name error");
1205         return false;
1206     }
1207     return true;
1208 }
1209 
AppColdStart(char * longProcName,int64_t longProcNameLen,const ClientSocket::AppProperty * appProperty,int fd)1210 int AppSpawnServer::AppColdStart(char *longProcName,
1211     int64_t longProcNameLen, const ClientSocket::AppProperty *appProperty, int fd)
1212 {
1213     APPSPAWN_LOGI("AppColdStart appName %s", appProperty->bundleName);
1214     LoadAceLib();
1215     if (!SetAppProcProperty(appProperty, longProcName, longProcNameLen, fd)) {
1216         return -1;
1217     }
1218     APPSPAWN_LOGI("AppColdStart appName %s success", appProperty->bundleName);
1219     return 0;
1220 }
1221 }  // namespace AppSpawn
1222 }  // namespace OHOS
1223