• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <dlfcn.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #ifdef __MUSL__
23 #include <stropts.h>
24 #endif
25 #include <sys/capability.h>
26 #include <sys/ioctl.h>
27 #include <sys/param.h>
28 #include <sys/resource.h>
29 #include <sys/stat.h>
30 #include <time.h>
31 #include <unistd.h>
32 
33 #include "init.h"
34 #include "init_adapter.h"
35 #include "init_cmds.h"
36 #include "init_cmdexecutor.h"
37 #include "init_log.h"
38 #include "init_cmdexecutor.h"
39 #include "init_jobs_internal.h"
40 #include "init_param.h"
41 #include "init_service.h"
42 #include "init_service_manager.h"
43 #include "init_service_socket.h"
44 #include "init_utils.h"
45 #include "fd_holder_internal.h"
46 #include "loop_event.h"
47 #include "securec.h"
48 #include "service_control.h"
49 
50 #ifndef OHOS_LITE
51 #include "hookmgr.h"
52 #include "bootstage.h"
53 #endif
54 
55 #ifdef WITH_SECCOMP
56 #define APPSPAWN_NAME ("appspawn")
57 #define NWEBSPAWN_NAME ("nwebspawn")
58 #endif
59 
60 #ifndef TIOCSCTTY
61 #define TIOCSCTTY 0x540E
62 #endif
63 
64 #define DEF_CRASH_TIME 240000 // default crash time is 240000 ms
65 
SetAllAmbientCapability(void)66 static int SetAllAmbientCapability(void)
67 {
68     for (int i = 0; i <= CAP_LAST_CAP; ++i) {
69         if (SetAmbientCapability(i) != 0) {
70             return SERVICE_FAILURE;
71         }
72     }
73     return SERVICE_SUCCESS;
74 }
75 
SetSystemSeccompPolicy(const Service * service)76 static int SetSystemSeccompPolicy(const Service *service)
77 {
78 #ifdef WITH_SECCOMP
79     if (strncmp(APPSPAWN_NAME, service->name, strlen(APPSPAWN_NAME))
80         && strncmp(NWEBSPAWN_NAME, service->name, strlen(NWEBSPAWN_NAME))) {
81         char cmdContent[MAX_CMD_CONTENT_LEN + 1] = {0};
82 
83         int rc = snprintf_s(cmdContent, MAX_CMD_CONTENT_LEN + 1, strlen(service->name) + 1,
84                             "%s ", service->name);
85         if (rc == -1) {
86             return SERVICE_FAILURE;
87         }
88 
89         rc = strcat_s(cmdContent, MAX_CMD_CONTENT_LEN + 1, service->pathArgs.argv[0]);
90         if (rc != 0) {
91             return SERVICE_FAILURE;
92         }
93 
94         PluginExecCmdByName("SetSeccompPolicy", cmdContent);
95     }
96 #endif
97     return SERVICE_SUCCESS;
98 }
99 
100 #ifndef OHOS_LITE
101 /**
102  * service Hooking
103  */
ServiceHookWrapper(const HOOK_INFO * hookInfo,void * executionContext)104 static int ServiceHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
105 {
106     SERVICE_INFO_CTX *serviceContext = (SERVICE_INFO_CTX *)executionContext;
107     ServiceHook realHook = (ServiceHook)hookInfo->hookCookie;
108 
109     realHook(serviceContext);
110     return 0;
111 };
112 
InitAddServiceHook(ServiceHook hook,int hookState)113 int InitAddServiceHook(ServiceHook hook, int hookState)
114 {
115     HOOK_INFO info;
116 
117     info.stage = hookState;
118     info.prio = 0;
119     info.hook = ServiceHookWrapper;
120     info.hookCookie = (void *)hook;
121 
122     return HookMgrAddEx(GetBootStageHookMgr(), &info);
123 }
124 
ServiceRestartHookWrapper(const HOOK_INFO * hookInfo,void * executionContext)125 static int ServiceRestartHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
126 {
127     SERVICE_RESTART_CTX *serviceContext = (SERVICE_RESTART_CTX *)executionContext;
128     ServiceRestartHook realHook = (ServiceRestartHook)hookInfo->hookCookie;
129 
130     realHook(serviceContext);
131     return 0;
132 }
133 
InitServiceRestartHook(ServiceRestartHook hook,int hookState)134 int InitServiceRestartHook(ServiceRestartHook hook, int hookState)
135 {
136     HOOK_INFO info;
137 
138     info.stage = hookState;
139     info.prio = 0;
140     info.hook = ServiceRestartHookWrapper;
141     info.hookCookie = (void *)hook;
142 
143     return HookMgrAddEx(GetBootStageHookMgr(), &info);
144 }
145 
146 /**
147  * service hooking execute
148  */
ServiceHookExecute(const char * serviceName,const char * info,int stage)149 static void ServiceHookExecute(const char *serviceName, const char *info, int stage)
150 {
151     SERVICE_INFO_CTX context;
152 
153     context.serviceName = serviceName;
154     context.reserved = info;
155 
156     (void)HookMgrExecute(GetBootStageHookMgr(), stage, (void *)(&context), NULL);
157 }
158 #endif
159 
ServiceSetGid(const Service * service)160 static int ServiceSetGid(const Service *service)
161 {
162     if (service->servPerm.gIDCnt == 0) {
163         // use uid as gid
164         INIT_ERROR_CHECK(setgid(service->servPerm.uID) == 0, return SERVICE_FAILURE,
165             "Service error %d %s, failed to set gid.", errno, service->name);
166     }
167     if (service->servPerm.gIDCnt > 0) {
168         INIT_ERROR_CHECK(setgid(service->servPerm.gIDArray[0]) == 0, return SERVICE_FAILURE,
169             "Service error %d %s, failed to set gid.", errno, service->name);
170     }
171     if (service->servPerm.gIDCnt > 1) {
172         INIT_ERROR_CHECK(setgroups(service->servPerm.gIDCnt - 1, (const gid_t *)&service->servPerm.gIDArray[1]) == 0,
173             return SERVICE_FAILURE,
174             "Service error %d %s, failed to set gid.", errno, service->name);
175     }
176 
177     return SERVICE_SUCCESS;
178 }
179 
SetPerms(const Service * service)180 static int SetPerms(const Service *service)
181 {
182     INIT_ERROR_CHECK(KeepCapability() == 0,
183         return INIT_EKEEPCAP,
184         "Service error %d %s, failed to set keep capability.", errno, service->name);
185 
186     INIT_ERROR_CHECK(ServiceSetGid(service) == SERVICE_SUCCESS,
187         return INIT_EGIDSET,
188         "Service error %d %s, failed to set gid.", errno, service->name);
189 
190     // set seccomp policy before setuid
191     INIT_ERROR_CHECK(SetSystemSeccompPolicy(service) == SERVICE_SUCCESS,
192         return INIT_ESECCOMP,
193         "Service error %d %s, failed to set system seccomp policy.", errno, service->name);
194 
195     if (service->servPerm.uID != 0) {
196         INIT_ERROR_CHECK(setuid(service->servPerm.uID) == 0,
197             return INIT_EUIDSET,
198             "Service error %d %s, failed to set uid.", errno, service->name);
199     }
200 
201     struct __user_cap_header_struct capHeader;
202     capHeader.version = _LINUX_CAPABILITY_VERSION_3;
203     capHeader.pid = 0;
204     struct __user_cap_data_struct capData[CAP_NUM] = {};
205     for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) {
206         if (service->servPerm.caps[i] == FULL_CAP) {
207             for (int j = 0; j < CAP_NUM; ++j) {
208                 capData[j].effective = FULL_CAP;
209                 capData[j].permitted = FULL_CAP;
210                 capData[j].inheritable = FULL_CAP;
211             }
212             break;
213         }
214         capData[CAP_TO_INDEX(service->servPerm.caps[i])].effective |= CAP_TO_MASK(service->servPerm.caps[i]);
215         capData[CAP_TO_INDEX(service->servPerm.caps[i])].permitted |= CAP_TO_MASK(service->servPerm.caps[i]);
216         capData[CAP_TO_INDEX(service->servPerm.caps[i])].inheritable |= CAP_TO_MASK(service->servPerm.caps[i]);
217     }
218 
219     INIT_ERROR_CHECK(capset(&capHeader, capData) == 0, return SERVICE_FAILURE,
220         "capset failed for service: %s, error: %d", service->name, errno);
221     for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) {
222         if (service->servPerm.caps[i] == FULL_CAP) {
223             int ret = SetAllAmbientCapability();
224             INIT_ERROR_CHECK(ret == 0,
225                 return INIT_ECAP,
226                 "Service error %d %s, failed to set ambient capability.", errno, service->name);
227             return 0;
228         }
229         INIT_ERROR_CHECK(SetAmbientCapability(service->servPerm.caps[i]) == 0,
230             return INIT_ECAP,
231             "Service error %d %s, failed to set ambient capability.", errno, service->name);
232     }
233 #ifndef OHOS_LITE
234     /*
235      * service set Perms hooks
236      */
237     ServiceHookExecute(service->name, NULL, INIT_SERVICE_SET_PERMS);
238 #endif
239     return SERVICE_SUCCESS;
240 }
241 
WritePid(const Service * service)242 static int WritePid(const Service *service)
243 {
244     pid_t childPid = getpid();
245     for (int i = 0; i < service->writePidArgs.count; i++) {
246         if (service->writePidArgs.argv[i] == NULL) {
247             continue;
248         }
249         FILE *fd = NULL;
250         char *realPath = GetRealPath(service->writePidArgs.argv[i]);
251         if (realPath != NULL) {
252             fd = fopen(realPath, "wb");
253         } else {
254             fd = fopen(service->writePidArgs.argv[i], "wb");
255         }
256         if (fd != NULL) {
257             INIT_CHECK_ONLY_ELOG((int)fprintf(fd, "%d", childPid) > 0,
258                 "Failed to write %s pid:%d", service->writePidArgs.argv[i], childPid);
259             (void)fclose(fd);
260         } else {
261             INIT_LOGE("Failed to open realPath: %s  %s errno:%d.", realPath, service->writePidArgs.argv[i], errno);
262         }
263         if (realPath != NULL) {
264             free(realPath);
265         }
266         INIT_LOGV("ServiceStart writepid filename=%s, childPid=%d, ok", service->writePidArgs.argv[i], childPid);
267     }
268     return SERVICE_SUCCESS;
269 }
270 
CloseServiceFds(Service * service,bool needFree)271 void CloseServiceFds(Service *service, bool needFree)
272 {
273     INIT_ERROR_CHECK(service != NULL, return, "Service null");
274     INIT_LOGI("Closing service \' %s \' fds", service->name);
275     // fdCount > 0, There is no reason fds is NULL
276     if (service->fdCount != 0) {
277         size_t fdCount = service->fdCount;
278         int *fds = service->fds;
279         for (size_t i = 0; i < fdCount; i++) {
280             INIT_LOGV("Closing fd: %d", fds[i]);
281             if (fds[i] != -1) {
282                 close(fds[i]);
283                 fds[i] = -1;
284             }
285         }
286     }
287     service->fdCount = 0;
288     if (needFree && service->fds != NULL) {
289         free(service->fds);
290         service->fds = NULL;
291     }
292 }
293 
PublishHoldFds(Service * service)294 static int PublishHoldFds(Service *service)
295 {
296     INIT_ERROR_CHECK(service != NULL, return INIT_EPARAMETER, "Publish hold fds with invalid service");
297     if (service->fdCount == 0 || service->fds == NULL) {
298         return 0;
299     }
300     char fdBuffer[MAX_FD_HOLDER_BUFFER] = {};
301     char envName[MAX_BUFFER_LEN] = {};
302     int ret = snprintf_s(envName, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, ENV_FD_HOLD_PREFIX"%s", service->name);
303     INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT,
304         "Service error %d %s, failed to format string for publish", ret, service->name);
305 
306     size_t pos = 0;
307     for (size_t i = 0; i < service->fdCount; i++) {
308         int fd = dup(service->fds[i]);
309         if (fd < 0) {
310             INIT_LOGW("Service warning %d %s, failed to dup fd for publish", errno, service->name);
311             continue;
312         }
313         ret = snprintf_s((char *)fdBuffer + pos, sizeof(fdBuffer) - pos, sizeof(fdBuffer) - 1, "%d ", fd);
314         INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT,
315             "Service error %d %s, failed to format fd for publish", ret, service->name);
316         pos += ret;
317     }
318     fdBuffer[pos - 1] = '\0'; // Remove last ' '
319     INIT_LOGI("Service %s publish fd [%s]", service->name, fdBuffer);
320     return setenv(envName, fdBuffer, 1);
321 }
322 
BindCpuCore(Service * service)323 static int BindCpuCore(Service *service)
324 {
325     if (service == NULL || service->cpuSet == NULL) {
326         return SERVICE_SUCCESS;
327     }
328     if (CPU_COUNT(service->cpuSet) == 0) {
329         return SERVICE_SUCCESS;
330     }
331 #ifndef __LITEOS_A__
332     int pid = getpid();
333     INIT_ERROR_CHECK(sched_setaffinity(pid, sizeof(cpu_set_t), service->cpuSet) == 0,
334         return SERVICE_FAILURE, "%s set affinity between process(pid=%d) with CPU's core failed", service->name, pid);
335     INIT_LOGI("%s set affinity between process(pid=%d) with CPU's core successfully", service->name, pid);
336 #endif
337     return SERVICE_SUCCESS;
338 }
339 
ClearEnvironment(Service * service)340 static void ClearEnvironment(Service *service)
341 {
342     if (strcmp(service->name, "appspawn") != 0 && strcmp(service->name, "nwebspawn") != 0) {
343         sigset_t mask;
344         sigemptyset(&mask);
345         sigaddset(&mask, SIGCHLD);
346         sigaddset(&mask, SIGTERM);
347         sigprocmask(SIG_UNBLOCK, &mask, NULL);
348     }
349     return;
350 }
351 
InitServiceProperties(Service * service,const ServiceArgs * pathArgs)352 static int InitServiceProperties(Service *service, const ServiceArgs *pathArgs)
353 {
354     INIT_ERROR_CHECK(service != NULL, return -1, "Invalid parameter.");
355     int ret = SetServiceEnterSandbox(service, pathArgs->argv[0]);
356     if (ret != 0) {
357         INIT_LOGW("Service warning %d %s, failed to enter sandbox.", ret, service->name);
358         service->lastErrno = INIT_ESANDBOX;
359     }
360     ret = SetAccessToken(service);
361     if (ret != 0) {
362         INIT_LOGW("Service warning %d %s, failed to set access token.", ret, service->name);
363         service->lastErrno = INIT_EACCESSTOKEN;
364     }
365 
366     // deal start job
367     if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
368         DoJobNow(service->serviceJobs.jobsName[JOB_ON_START]);
369     }
370     ClearEnvironment(service);
371     if (!IsOnDemandService(service)) {
372         INIT_ERROR_CHECK(CreateServiceSocket(service) == 0,
373             service->lastErrno = INIT_ESOCKET;
374             return INIT_ESOCKET,
375             "Service error %d %s, failed to create service socket.", errno, service->name);
376     }
377     INIT_ERROR_CHECK(CreateServiceFile(service) == 0,
378         service->lastErrno = INIT_EFILE;
379         return INIT_EFILE,
380         "Service error %d %s, failed to create service file.", errno, service->name);
381 
382     if ((service->attribute & SERVICE_ATTR_CONSOLE)) {
383         INIT_ERROR_CHECK(OpenConsole() == 0,
384             service->lastErrno = INIT_ECONSOLE;
385             return INIT_ECONSOLE,
386             "Service error %d %s, failed to open console.", errno, service->name);
387     }
388     if ((service->attribute & SERVICE_ATTR_KMSG)) {
389         OpenKmsg();
390     }
391 
392     INIT_ERROR_CHECK(PublishHoldFds(service) == 0,
393         service->lastErrno = INIT_EHOLDER;
394         return INIT_EHOLDER,
395         "Service error %d %s, failed to publish fd", errno, service->name);
396 
397     INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS,
398         "Service warning %d %s, failed to publish fd", errno, service->name);
399 
400     // permissions
401     ret = SetPerms(service);
402     INIT_ERROR_CHECK(ret == SERVICE_SUCCESS,
403         service->lastErrno = ret;
404         return ret,
405         "Service error %d %s, failed to set permissions.", ret, service->name);
406 
407     // write pid
408     INIT_ERROR_CHECK(WritePid(service) == SERVICE_SUCCESS,
409         service->lastErrno = INIT_EWRITEPID;
410         return INIT_EWRITEPID,
411         "Service error %d %s, failed to write pid.", errno, service->name);
412 
413     PluginExecCmdByName("setServiceContent", service->name);
414     return 0;
415 }
416 
EnterServiceSandbox(Service * service)417 void EnterServiceSandbox(Service *service)
418 {
419     INIT_ERROR_CHECK(InitServiceProperties(service, &service->pathArgs) == 0, return, "Failed init service property");
420     if (service->importance != 0) {
421         if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) {
422             INIT_LOGE("setpriority failed for %s, importance = %d, err=%d",
423                 service->name, service->importance, errno);
424                 _exit(0x7f); // 0x7f: user specified
425         }
426     }
427 #ifndef STARTUP_INIT_TEST
428     char *argv[] = { (char *)"/bin/sh", NULL };
429     INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0,
430         "service %s execv sh failed! err %d.", service->name, errno);
431     _exit(PROCESS_EXIT_CODE);
432 #endif
433 }
434 
AddUpdateList(ServiceArgs * args,char * updateList)435 static void AddUpdateList(ServiceArgs *args, char *updateList)
436 {
437     char** argvOrig = args->argv;
438     const int paramCount = 2; // -u updatelist
439     args->argv = (char **)malloc((args->count + paramCount) * sizeof(char *));
440     INIT_ERROR_CHECK(args->argv != NULL, return, "Failed to malloc for argv");
441     int i = 0;
442     for (; i < args->count + 1; ++i) {
443         if (i == args->count - 1) {
444             args->argv[i] = "-u";
445             args->argv[++i] = updateList;
446             break;
447         } else {
448             args->argv[i] = argvOrig[i];
449         }
450     }
451     args->argv[++i] = NULL;
452     args->count += paramCount;
453     free(argvOrig);
454 }
455 
CheckModuleUpdate(ServiceArgs * args)456 static void CheckModuleUpdate(ServiceArgs *args)
457 {
458     INIT_LOGI("CheckModuleUpdate start");
459     void *handle = dlopen("libmodule_update.z.so", RTLD_NOW);
460     INIT_ERROR_CHECK(handle != NULL, return, "dlopen module update lib failed with error:%s", dlerror());
461     typedef char* (*ExtFunc)(int, char **);
462     ExtFunc func = (ExtFunc)dlsym(handle, "CheckModuleUpdate");
463     if (func == NULL) {
464         INIT_LOGE("dlsym get func failed with error:%s", dlerror());
465     } else {
466         char *updateList = func(args->count, args->argv);
467         INIT_LOGI("update list: %s", updateList);
468         if (updateList != NULL) {
469             AddUpdateList(args, updateList);
470         } else {
471             INIT_LOGW("no update list");
472         }
473     }
474     INIT_LOGI("CheckModuleUpdate end");
475 }
476 
477 #ifdef IS_DEBUG_VERSION
ServiceNeedDebug(char * name)478 static bool ServiceNeedDebug(char *name)
479 {
480     char nameValue[PARAM_VALUE_LEN_MAX] = {0};
481     unsigned int nameLen = PARAM_VALUE_LEN_MAX;
482     // specify process debugging: param set llvm.debug.service.name "service name"
483     if (SystemReadParam("llvm.debug.service.name", nameValue, &nameLen) == 0) {
484         if (strcmp(nameValue, name) == 0) {
485             return true;
486         }
487     }
488 
489     char debugValue[PARAM_VALUE_LEN_MAX] = {0};
490     unsigned int debugLen = PARAM_VALUE_LEN_MAX;
491     // multi process debugging: param set llvm.debug.service.all 1
492     if (SystemReadParam("llvm.debug.service.all", debugValue, &debugLen) == 0) {
493         if (strcmp(debugValue, "1") == 0) {
494             return true;
495         }
496     }
497     return false;
498 }
499 
IsDebuggableVersion(void)500 static bool IsDebuggableVersion(void)
501 {
502     char secureValue[PARAM_VALUE_LEN_MAX] = {0};
503     unsigned int secureLen = PARAM_VALUE_LEN_MAX;
504     char debugValue[PARAM_VALUE_LEN_MAX] = {0};
505     unsigned int debugLen = PARAM_VALUE_LEN_MAX;
506     // the image is debuggable only when secureValue is 0 and debugValue is 1
507     if (SystemReadParam("const.secure", secureValue, &secureLen) == 0 &&
508         SystemReadParam("const.debuggable", debugValue, &debugLen) == 0) {
509         if (strcmp(secureValue, "0") == 0 &&
510             strcmp(debugValue, "1") == 0) {
511             return true;
512         }
513     }
514     return false;
515 }
516 
CheckTraceStatus(void)517 static int32_t CheckTraceStatus(void)
518 {
519     int fd = open("/proc/self/status", O_RDONLY);
520     if (fd == -1) {
521         INIT_LOGE("lldb: open /proc/self/status error: %{public}d", errno);
522         return (-errno);
523     }
524 
525     char data[1024] = { 0 };  // 1024 data len
526     ssize_t dataNum = read(fd, data, sizeof(data));
527     if (close(fd) < 0) {
528         INIT_LOGE("lldb: close fd error: %{public}d", errno);
529         return (-errno);
530     }
531 
532     if (dataNum <= 0) {
533         INIT_LOGE("lldb: fail to read data");
534         return -1;
535     }
536 
537     const char* tracerPid = "TracerPid:\t";
538     data[1023] = '\0'; // 1023 data last position
539     char *traceStr = strstr(data, tracerPid);
540     if (traceStr == NULL) {
541         INIT_LOGE("lldb: fail to find %{public}s", tracerPid);
542         return -1;
543     }
544     char *separator = strchr(traceStr, '\n');
545     if (separator == NULL) {
546         INIT_LOGE("lldb: fail to find line break");
547         return -1;
548     }
549 
550     int len = separator - traceStr - strlen(tracerPid);
551     char pid = *(traceStr + strlen(tracerPid));
552     if (len > 1 || pid != '0') {
553         return 0;
554     }
555     return -1;
556 }
557 
WaitForDebugger(void)558 static int32_t WaitForDebugger(void)
559 {
560     uint32_t count = 0;
561     while (CheckTraceStatus() != 0) {
562         usleep(1000 * 100); // sleep 1000 * 100 microsecond
563         count++;
564         // remind users to connect to the debugger every 60 * 10 times
565         if (count % (10 * 60) == 0) {
566             INIT_LOGI("lldb: wait for debugger, please attach the process");
567             count = 0;
568         }
569     }
570     return 0;
571 }
572 #endif
573 
ServiceStart(Service * service,ServiceArgs * pathArgs)574 int ServiceStart(Service *service, ServiceArgs *pathArgs)
575 {
576     INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr.");
577     INIT_ERROR_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "Service info %s already started", service->name);
578     INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0,
579         return SERVICE_FAILURE, "start service %s pathArgs is NULL.", service->name);
580 
581     INIT_LOGI("Service info %s starting", service->name);
582     if (service->attribute & SERVICE_ATTR_INVALID) {
583         INIT_LOGE("start service %s invalid.", service->name);
584         return SERVICE_FAILURE;
585     }
586     struct stat pathStat = { 0 };
587     service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP));
588     if (stat(pathArgs->argv[0], &pathStat) != 0) {
589         service->attribute |= SERVICE_ATTR_INVALID;
590         service->lastErrno = INIT_EPATH;
591         INIT_LOGE("start service %s invalid, please check %s.", service->name, service->pathArgs.argv[0]);
592         return SERVICE_FAILURE;
593     }
594 #ifndef OHOS_LITE
595     /*
596      * before service fork hooks
597      */
598     ServiceHookExecute(service->name, NULL, INIT_SERVICE_FORK_BEFORE);
599 #endif
600     int pid = fork();
601     if (pid == 0) {
602         // set selinux label by context
603         if (service->context.type != INIT_CONTEXT_MAIN && SetSubInitContext(&service->context, service->name) != 0) {
604             service->lastErrno = INIT_ECONTENT;
605         }
606 
607         if (service->attribute & SERVICE_ATTR_MODULE_UPDATE) {
608             CheckModuleUpdate(pathArgs);
609         }
610 #ifdef IS_DEBUG_VERSION
611         // only the image is debuggable and need debug, then wait for debugger
612         if (ServiceNeedDebug(service->name) && IsDebuggableVersion()) {
613             WaitForDebugger();
614         }
615 #endif
616         // fail must exit sub process
617         int ret = InitServiceProperties(service, pathArgs);
618         INIT_ERROR_CHECK(ret == 0,
619             _exit(service->lastErrno), "Service error %d %s, failed to set properties", ret, service->name);
620 
621         (void)ServiceExec(service, pathArgs);
622         _exit(service->lastErrno);
623     } else if (pid < 0) {
624         INIT_LOGE("Service error %d %s, failed to fork.", errno, service->name);
625         service->lastErrno = INIT_EFORK;
626         return SERVICE_FAILURE;
627     }
628     INIT_LOGI("Service info %s(pid %d) started", service->name, pid);
629     service->pid = pid;
630     NotifyServiceChange(service, SERVICE_STARTED);
631 #ifndef OHOS_LITE
632     /*
633      * after service fork hooks
634      */
635     ServiceHookExecute(service->name, (const char *)&pid, INIT_SERVICE_FORK_AFTER);
636 #endif
637     return SERVICE_SUCCESS;
638 }
639 
ServiceStop(Service * service)640 int ServiceStop(Service *service)
641 {
642     INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "stop service failed! null ptr.");
643     NotifyServiceChange(service, SERVICE_STOPPING);
644     if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
645         DoJobNow(service->serviceJobs.jobsName[JOB_ON_STOP]);
646     }
647     service->attribute &= ~SERVICE_ATTR_NEED_RESTART;
648     service->attribute |= SERVICE_ATTR_NEED_STOP;
649     if (service->pid <= 0) {
650         return SERVICE_SUCCESS;
651     }
652     CloseServiceSocket(service);
653     CloseServiceFile(service->fileCfg);
654     // Service stop means service is killed by init or command(i.e stop_service) or system is rebooting
655     // There is no reason still to hold fds
656     if (service->fdCount != 0) {
657         CloseServiceFds(service, true);
658     }
659 
660     if (IsServiceWithTimerEnabled(service)) {
661         ServiceStopTimer(service);
662     }
663     INIT_ERROR_CHECK(kill(service->pid, GetKillServiceSig(service->name)) == 0, return SERVICE_FAILURE,
664         "stop service %s pid %d failed! err %d.", service->name, service->pid, errno);
665     INIT_LOGI("stop service %s, pid %d.", service->name, service->pid);
666     service->pid = -1;
667     NotifyServiceChange(service, SERVICE_STOPPED);
668     return SERVICE_SUCCESS;
669 }
670 
CalculateCrashTime(Service * service,int crashTimeLimit,int crashCountLimit)671 static bool CalculateCrashTime(Service *service, int crashTimeLimit, int crashCountLimit)
672 {
673     INIT_ERROR_CHECK(service != NULL && crashTimeLimit > 0 && crashCountLimit > 0,
674         return false, "input params error.");
675     struct timespec curTime = {0};
676     (void)clock_gettime(CLOCK_MONOTONIC, &curTime);
677     struct timespec crashTime = {service->firstCrashTime, 0};
678     if (service->crashCnt == 0) {
679         service->firstCrashTime = curTime.tv_sec;
680         ++service->crashCnt;
681         if (service->crashCnt == crashCountLimit) {
682             return false;
683         }
684     } else if (IntervalTime(&crashTime, &curTime) > crashTimeLimit) {
685         service->firstCrashTime = curTime.tv_sec;
686         service->crashCnt = 1;
687     } else {
688         ++service->crashCnt;
689         if (service->crashCnt >= crashCountLimit) {
690             return false;
691         }
692     }
693     return true;
694 }
695 
ExecRestartCmd(Service * service)696 static int ExecRestartCmd(Service *service)
697 {
698     INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr.");
699     if (service->restartArg == NULL) {
700         return SERVICE_SUCCESS;
701     }
702     for (int i = 0; i < service->restartArg->cmdNum; i++) {
703         INIT_LOGI("ExecRestartCmd cmdLine->cmdContent %s ", service->restartArg->cmds[i].cmdContent);
704         DoCmdByIndex(service->restartArg->cmds[i].cmdIndex, service->restartArg->cmds[i].cmdContent, NULL);
705     }
706     free(service->restartArg);
707     service->restartArg = NULL;
708     return SERVICE_SUCCESS;
709 }
710 
CheckServiceSocket(Service * service)711 static void CheckServiceSocket(Service *service)
712 {
713     if (service->socketCfg == NULL) {
714         return;
715     }
716     ServiceSocket *tmpSock = service->socketCfg;
717     while (tmpSock != NULL) {
718         if (tmpSock->sockFd <= 0) {
719             INIT_LOGE("Invalid socket %s for service", service->name);
720             tmpSock = tmpSock->next;
721         }
722         AddSocketWatcher(&tmpSock->watcher, service, tmpSock->sockFd);
723         tmpSock = tmpSock->next;
724     }
725     return;
726 }
727 
CheckOndemandService(Service * service)728 static void CheckOndemandService(Service *service)
729 {
730     CheckServiceSocket(service);
731     if (strcmp(service->name, "console") == 0) {
732         if (WatchConsoleDevice(service) < 0) {
733             INIT_LOGE("Failed to watch console service after it exit, mark console service invalid");
734             service->attribute |= SERVICE_ATTR_INVALID;
735         }
736     }
737 }
738 
ServiceReapHookExecute(Service * service)739 static void ServiceReapHookExecute(Service *service)
740 {
741 #ifndef OHOS_LITE
742     HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_REAP, (void*)service, NULL);
743 #endif
744 }
745 
ServiceReap(Service * service)746 void ServiceReap(Service *service)
747 {
748     INIT_CHECK(service != NULL, return);
749     INIT_LOGI("Service info %s reap pid %d.", service->name, service->pid);
750     NotifyServiceChange(service, SERVICE_STOPPED);
751     int tmp = service->pid;
752     service->pid = -1;
753 
754     if (service->attribute & SERVICE_ATTR_INVALID) {
755         INIT_LOGE("Service error %s invalid service.", service->name);
756         return;
757     }
758 
759     // If the service set timer
760     // which means the timer handler will start the service
761     // Init should not start it automatically.
762     INIT_CHECK(IsServiceWithTimerEnabled(service) == 0, return);
763 
764     if (!IsOnDemandService(service)) {
765         CloseServiceSocket(service);
766     }
767     CloseServiceFile(service->fileCfg);
768     // stopped by system-init itself, no need to restart even if it is not one-shot service
769     if (service->attribute & SERVICE_ATTR_NEED_STOP) {
770         service->attribute &= (~SERVICE_ATTR_NEED_STOP);
771         service->crashCnt = 0;
772         return;
773     }
774 
775     // for one-shot service
776     if (service->attribute & SERVICE_ATTR_ONCE) {
777         // no need to restart
778         if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) {
779             service->attribute &= (~SERVICE_ATTR_NEED_STOP);
780             return;
781         }
782         // the service could be restart even if it is one-shot service
783     }
784 
785     // service no need to restart if it is an ondemand service.
786     if (IsOnDemandService(service)) {
787         CheckOndemandService(service);
788         return;
789     }
790     if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical
791         if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) {
792             INIT_LOGE("Service error %s critical service crashed.", service->name, service->crashCount);
793             service->pid = tmp;
794             ServiceReapHookExecute(service);
795             service->pid = -1;
796             ExecReboot("panic");
797         }
798     } else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) {
799         if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) {
800             INIT_LOGI("Service %s start failed! %d second later will reStart.", service->name, service->crashTime);
801             service->crashCnt = 0;
802             ServiceStartTimer(service, DEF_CRASH_TIME);
803             return;
804         }
805     }
806 
807     int ret = ExecRestartCmd(service);
808     INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "Failed to exec restartArg for %s", service->name);
809 
810     if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
811         DoJobNow(service->serviceJobs.jobsName[JOB_ON_RESTART]);
812     }
813     ret = ServiceStart(service, &service->pathArgs);
814     INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "reap service %s start failed!", service->name);
815     service->attribute &= (~SERVICE_ATTR_NEED_RESTART);
816 }
817 
UpdaterServiceFds(Service * service,int * fds,size_t fdCount)818 int UpdaterServiceFds(Service *service, int *fds, size_t fdCount)
819 {
820     if (service == NULL || fds == NULL) {
821         INIT_LOGE("Invalid service info or fds");
822         return -1;
823     }
824 
825     if (fdCount == 0) {
826         INIT_LOGE("Update service fds with fdCount is 0, ignore.");
827         return 0;
828     }
829 
830     // if service->fds is NULL, allocate new memory to hold the fds
831     // else if service->fds is not NULL, we will try to override it.
832     // There are two cases:
833     // 1) service->fdCount != fdCount:
834     //  It is not easy to re-use the memory of service->fds, so we have to free the memory first
835     //  then re-allocate memory to store new fds
836     // 2) service->fdCount == fdCount
837     //  A situation we happy to meet, just override it.
838 
839     int ret = 0;
840     if (service->fdCount == fdCount) {
841         // case 2
842         CloseServiceFds(service, false);
843         if (memcpy_s(service->fds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) != 0) {
844             INIT_LOGE("Failed to copy fds to service");
845             // Something wrong happened, maybe service->fds is broken, clear it.
846             free(service->fds);
847             service->fds = NULL;
848             service->fdCount = 0;
849             ret = -1;
850         } else {
851             service->fdCount = fdCount;
852         }
853     } else {
854         if (service->fdCount > 0) {
855             // case 1
856             CloseServiceFds(service, true);
857         }
858         INIT_ERROR_CHECK(fdCount <= MAX_HOLD_FDS, return -1, "Invalid fdCount %d", fdCount);
859         service->fds = calloc(fdCount + 1, sizeof(int));
860         if (service->fds == NULL) {
861             INIT_LOGE("Service \' %s \' failed to allocate memory for fds", service->name);
862             ret = -1;
863         } else {
864             if (memcpy_s(service->fds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) != 0) {
865                 INIT_LOGE("Failed to copy fds to service");
866                 // Something wrong happened, maybe service->fds is broken, clear it.
867                 free(service->fds);
868                 service->fds = NULL;
869                 service->fdCount = 0;
870                 return -1;
871             } else {
872                 service->fdCount = fdCount;
873             }
874         }
875     }
876     INIT_LOGI("Hold fd for service \' %s \' done", service->name);
877     return ret;
878 }
879 
ServiceStopTimer(Service * service)880 void ServiceStopTimer(Service *service)
881 {
882     INIT_ERROR_CHECK(service != NULL, return, "Stop timer with invalid service");
883     if (IsServiceWithTimerEnabled(service)) {
884         // Stop timer first
885         if (service->timer) {
886             LE_StopTimer(LE_GetDefaultLoop(), service->timer);
887         }
888         service->timer = NULL;
889         DisableServiceTimer(service);
890     }
891 }
892 
ServiceTimerStartProcess(const TimerHandle handler,void * context)893 static void ServiceTimerStartProcess(const TimerHandle handler, void *context)
894 {
895     UNUSED(handler);
896     Service *service = (Service *)context;
897 
898     if (service == NULL) {
899         INIT_LOGE("Service timer process with invalid service");
900         return;
901     }
902 
903     // OK, service is ready to start.
904     // Before start the service, stop service timer.
905     // make sure it will not enter timer handler next time.
906     ServiceStopTimer(service);
907     int ret = ServiceStart(service, &service->pathArgs);
908     if (ret != SERVICE_SUCCESS) {
909         INIT_LOGE("Start service \' %s \' in timer failed", service->name);
910     }
911 }
912 
ServiceStartTimer(Service * service,uint64_t timeout)913 void ServiceStartTimer(Service *service, uint64_t timeout)
914 {
915     bool oldTimerClean = false;
916     INIT_ERROR_CHECK(service != NULL, return, "Start timer with invalid service");
917     // If the service already set a timer.
918     // And a new request coming. close it and create a new one.
919     if (IsServiceWithTimerEnabled(service)) {
920         ServiceStopTimer(service);
921         oldTimerClean = true;
922     }
923     LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), &service->timer, ServiceTimerStartProcess,
924         (void *)service);
925     if (status != LE_SUCCESS) {
926         INIT_LOGE("Create service timer for service \' %s \' failed, status = %d", service->name, status);
927         if (oldTimerClean) {
928             INIT_LOGE("previous timer is cleared");
929         }
930         return;
931     }
932     status = LE_StartTimer(LE_GetDefaultLoop(), service->timer, timeout, 1);
933     INIT_ERROR_CHECK(status == LE_SUCCESS, return,
934         "Start service timer for service \' %s \' failed, status = %d", service->name, status);
935     EnableServiceTimer(service);
936 }
937