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