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