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