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