1 /*
2 * Copyright (c) 2020-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 #include "init_service_manager.h"
16
17 #include <limits.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 #include <sys/ioctl.h>
24 #include "cJSON.h"
25 #include "init.h"
26 #include "init_group_manager.h"
27 #include "init_jobs_internal.h"
28 #include "init_log.h"
29 #include "init_service_file.h"
30 #include "init_service_socket.h"
31 #include "init_utils.h"
32 #include "securec.h"
33 #include "service_control.h"
34 #ifdef ASAN_DETECTOR
35 #include "init_param.h"
36 #endif
37
38 #ifndef OHOS_LITE
39 #include "hookmgr.h"
40 #include "bootstage.h"
41 #endif
42
43 // All service processes that init will fork+exec.
44 static ServiceSpace g_serviceSpace = { 0 };
45 static const int CRITICAL_DEFAULT_CRASH_TIME = 240;
46 // maximum number of crashes within time CRITICAL_DEFAULT_CRASH_TIME for one service
47 static const int CRITICAL_DEFAULT_CRASH_COUNT = 4;
48 static const int CRITICAL_CONFIG_ARRAY_LEN = 3;
49 static const int REBOOT_WAIT_TIME = 100000;
50 static const int INTERVAL_PER_WAIT = 10;
51
FreeServiceArg(ServiceArgs * arg)52 static void FreeServiceArg(ServiceArgs *arg)
53 {
54 if (arg == NULL) {
55 return;
56 }
57 for (int i = 0; i < arg->count; ++i) {
58 if (arg->argv[i] != NULL) {
59 free(arg->argv[i]);
60 arg->argv[i] = NULL;
61 }
62 }
63 free(arg->argv);
64 arg->argv = NULL;
65 arg->count = 0;
66 }
67
FreeServiceSocket(ServiceSocket * sockopt)68 static void FreeServiceSocket(ServiceSocket *sockopt)
69 {
70 while (sockopt != NULL) {
71 ServiceSocket *tmp = sockopt;
72 if (tmp->sockFd >= 0) {
73 close(tmp->sockFd);
74 tmp->sockFd = -1;
75 }
76 sockopt = sockopt->next;
77 free(tmp);
78 }
79 return;
80 }
81
AddService(const char * name)82 Service *AddService(const char *name)
83 {
84 // check service in group
85 if (CheckNodeValid(NODE_TYPE_SERVICES, name) != 0) {
86 INIT_LOGI("Service %s not exist in group ", name);
87 return NULL;
88 }
89 InitGroupNode *node = AddGroupNode(NODE_TYPE_SERVICES, name);
90 if (node == NULL) {
91 INIT_LOGE("Failed to create service name %s", name);
92 return NULL;
93 }
94 if (node->data.service != NULL) {
95 ReleaseService(node->data.service);
96 node->data.service = NULL;
97 }
98 Service *service = (Service *)calloc(1, sizeof(Service));
99 INIT_ERROR_CHECK(service != NULL, return NULL, "Failed to malloc for service");
100 node->data.service = service;
101 service->name = node->name;
102 service->status = SERVICE_IDLE;
103 service->cpuSet = NULL;
104 service->pid = -1;
105 service->context.type = INIT_CONTEXT_MAIN;
106 service->lastErrno = INIT_OK;
107 OH_ListInit(&service->extDataNode);
108 g_serviceSpace.serviceCount++;
109 INIT_LOGV("AddService %s", node->name);
110 return service;
111 }
112
FreeServiceFile(ServiceFile * fileOpt)113 static void FreeServiceFile(ServiceFile *fileOpt)
114 {
115 while (fileOpt != NULL) {
116 ServiceFile *tmp = fileOpt;
117 if (tmp->fd >= 0) {
118 close(tmp->fd);
119 tmp->fd = -1;
120 }
121 fileOpt = fileOpt->next;
122 free(tmp);
123 }
124 return;
125 }
126
ExecuteServiceClear(Service * service)127 static void ExecuteServiceClear(Service *service)
128 {
129 #ifndef OHOS_LITE
130 // clear ext data
131 SERVICE_INFO_CTX ctx = {0};
132 ctx.serviceName = service->name;
133 HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL);
134 #endif
135 }
136
ReleaseService(Service * service)137 void ReleaseService(Service *service)
138 {
139 INIT_CHECK(service != NULL, return);
140 FreeServiceArg(&service->pathArgs);
141 FreeServiceArg(&service->writePidArgs);
142 FreeServiceArg(&service->capsArgs);
143 FreeServiceArg(&service->permArgs);
144 FreeServiceArg(&service->permAclsArgs);
145
146 if (service->servPerm.caps != NULL) {
147 free(service->servPerm.caps);
148 service->servPerm.caps = NULL;
149 }
150 service->servPerm.capsCnt = 0;
151 if (service->servPerm.gIDArray != NULL) {
152 free(service->servPerm.gIDArray);
153 service->servPerm.gIDArray = NULL;
154 }
155 service->servPerm.gIDCnt = 0;
156 FreeServiceSocket(service->socketCfg);
157 service->socketCfg = NULL;
158 FreeServiceFile(service->fileCfg);
159 service->fileCfg = NULL;
160
161 if (service->apl != NULL) {
162 free(service->apl);
163 service->apl = NULL;
164 }
165 for (size_t i = 0; i < JOB_ON_MAX; i++) {
166 if (service->serviceJobs.jobsName[i] != NULL) {
167 free(service->serviceJobs.jobsName[i]);
168 }
169 service->serviceJobs.jobsName[i] = NULL;
170 }
171 if (service->cpuSet != NULL) {
172 free(service->cpuSet);
173 service->cpuSet = NULL;
174 }
175 if (service->restartArg != NULL) {
176 free(service->restartArg);
177 service->restartArg = NULL;
178 }
179 CloseServiceFds(service, true);
180 ExecuteServiceClear(service);
181 g_serviceSpace.serviceCount--;
182 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, service->name);
183 if (groupNode != NULL) {
184 groupNode->data.service = NULL;
185 }
186 free(service);
187 }
188
GetStringValue(const cJSON * json,const char * name,size_t * strLen)189 static char *GetStringValue(const cJSON *json, const char *name, size_t *strLen)
190 {
191 char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name));
192 INIT_CHECK(fieldStr != NULL, return NULL);
193 *strLen = strlen(fieldStr);
194 return fieldStr;
195 }
196
GetArrayItem(const cJSON * fileRoot,int * arrSize,const char * arrName)197 cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName)
198 {
199 cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
200 if (!cJSON_IsArray(arrItem)) {
201 return NULL;
202 }
203 *arrSize = cJSON_GetArraySize(arrItem);
204 INIT_CHECK_RETURN_VALUE(*arrSize > 0, NULL);
205 return arrItem;
206 }
207
GetServiceArgs(const cJSON * argJson,const char * name,int maxCount,ServiceArgs * args)208 static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args)
209 {
210 INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
211 cJSON *obj = cJSON_GetObjectItem(argJson, name);
212 INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
213
214 int ret = cJSON_IsArray(obj);
215 INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
216 int count = cJSON_GetArraySize(obj);
217 INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, "Array size = %d is wrong", count);
218 if ((args->argv != NULL) && (args->count > 0)) {
219 FreeServiceArg(args);
220 }
221 args->argv = (char **)malloc((count + 1) * sizeof(char *));
222 INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv");
223 for (int i = 0; i < count + 1; ++i) {
224 args->argv[i] = NULL;
225 }
226 // ServiceArgs have a variety of uses, some requiring a NULL ending, some not
227 if (strcmp(name, D_CAPS_STR_IN_CFG) != 0 && strcmp(name, "permission_acls") != 0 &&
228 strcmp(name, "permission") != 0) {
229 args->count = count + 1;
230 } else {
231 args->count = count;
232 }
233 for (int i = 0; i < count; ++i) {
234 char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
235 INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i);
236 INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam);
237 args->argv[i] = strdup(curParam);
238 INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to duplicate argument %s", curParam);
239 }
240 return SERVICE_SUCCESS;
241 }
242
GetUid(cJSON * json,uid_t * uid)243 static int GetUid(cJSON *json, uid_t *uid)
244 {
245 INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS);
246 if (cJSON_IsString(json)) {
247 char *str = cJSON_GetStringValue(json);
248 INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str");
249 *uid = DecodeUid(str);
250 } else if (cJSON_IsNumber(json)) {
251 *uid = (uid_t)cJSON_GetNumberValue(json);
252 } else {
253 *uid = (uid_t)(-1);
254 }
255 INIT_CHECK_RETURN_VALUE(*uid != (uid_t)(-1), SERVICE_FAILURE);
256 return SERVICE_SUCCESS;
257 }
258
GetGid(cJSON * json,gid_t * gid,Service * curServ)259 static int GetGid(cJSON *json, gid_t *gid, Service *curServ)
260 {
261 INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS);
262 if (cJSON_IsString(json)) {
263 char *str = cJSON_GetStringValue(json);
264 INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Failed to get gid for %s", curServ->name);
265 *gid = DecodeGid(str);
266 } else if (cJSON_IsNumber(json)) {
267 *gid = (gid_t)cJSON_GetNumberValue(json);
268 } else {
269 INIT_LOGW("Service %s with invalid gid configuration", curServ->name);
270 *gid = -1; // Invalid gid, set as -1
271 }
272 INIT_CHECK_RETURN_VALUE(*gid != (gid_t)(-1), SERVICE_FAILURE);
273 return SERVICE_SUCCESS;
274 }
275
GetServiceGids(const cJSON * curArrItem,Service * curServ)276 static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
277 {
278 int gidCount;
279 cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG);
280 if (!arrItem) {
281 return SERVICE_SUCCESS;
282 } else if (!cJSON_IsArray(arrItem)) {
283 gidCount = 1;
284 } else {
285 gidCount = cJSON_GetArraySize(arrItem);
286 }
287 INIT_ERROR_CHECK((gidCount != 0) && (gidCount <= NGROUPS_MAX + 1), return SERVICE_FAILURE,
288 "Invalid gid count %d", gidCount);
289 if (curServ->servPerm.gIDArray != NULL) {
290 free(curServ->servPerm.gIDArray);
291 }
292 curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * (gidCount + 1));
293 INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc err=%d", errno);
294 curServ->servPerm.gIDCnt = gidCount;
295
296 gid_t gid;
297 if (!cJSON_IsArray(arrItem)) {
298 int ret = GetGid(arrItem, &gid, curServ);
299 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE,
300 "Service error %s, failed to get gid from %s.", curServ->name, cJSON_Print(arrItem));
301 curServ->servPerm.gIDArray[0] = gid;
302 return SERVICE_SUCCESS;
303 }
304 int gidArrayIndex = 0;
305 for (int i = 0; i < gidCount; ++i) {
306 cJSON *item = cJSON_GetArrayItem(arrItem, i);
307 int ret = GetGid(item, &gid, curServ);
308 if (ret != 0) {
309 INIT_LOGW("Service warning %s, failed to get gid from %s.", curServ->name, cJSON_Print(item));
310 continue;
311 }
312 curServ->servPerm.gIDArray[gidArrayIndex++] = gid;
313 }
314 if (gidArrayIndex == 0) {
315 curServ->servPerm.gIDArray[gidArrayIndex++] = curServ->servPerm.uID;
316 }
317 curServ->servPerm.gIDCnt = gidArrayIndex;
318 return SERVICE_SUCCESS;
319 }
320
GetServiceAttr(const cJSON * curArrItem,Service * curServ,const char * attrName,int flag,int (* processAttr)(Service * curServ,const char * attrName,int value,int flag))321 static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag,
322 int (*processAttr)(Service *curServ, const char *attrName, int value, int flag))
323 {
324 cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName);
325 if (filedJ == NULL) {
326 return SERVICE_SUCCESS;
327 }
328 INIT_ERROR_CHECK(cJSON_IsNumber(filedJ), return SERVICE_FAILURE,
329 "Service error %s is null or is not a number %s", curServ->name, attrName);
330 curServ->attribute &= ~flag;
331 int value = (int)cJSON_GetNumberValue(filedJ);
332 if (processAttr == NULL) {
333 if (value == 1) {
334 curServ->attribute |= flag;
335 }
336 return 0;
337 }
338 return processAttr(curServ, attrName, value, flag);
339 }
340
ParseSocketFamily(cJSON * json,ServiceSocket * sockopt)341 static int ParseSocketFamily(cJSON *json, ServiceSocket *sockopt)
342 {
343 sockopt->family = AF_UNIX;
344 size_t strLen = 0;
345 char *stringValue = GetStringValue(json, "family", &strLen);
346 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
347 "Failed to get string for family");
348 if (strcmp(stringValue, "AF_UNIX") == 0) {
349 sockopt->family = AF_UNIX;
350 } else if (strncmp(stringValue, "AF_NETLINK", strLen) == 0) {
351 sockopt->family = AF_NETLINK;
352 }
353 return 0;
354 }
355
ParseSocketType(cJSON * json,ServiceSocket * sockopt)356 static int ParseSocketType(cJSON *json, ServiceSocket *sockopt)
357 {
358 sockopt->type = SOCK_SEQPACKET;
359 size_t strLen = 0;
360 char *stringValue = GetStringValue(json, "type", &strLen);
361 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
362 "Failed to get string for type");
363 if (strncmp(stringValue, "SOCK_SEQPACKET", strLen) == 0) {
364 sockopt->type = SOCK_SEQPACKET;
365 } else if (strncmp(stringValue, "SOCK_STREAM", strLen) == 0) {
366 sockopt->type = SOCK_STREAM;
367 } else if (strncmp(stringValue, "SOCK_DGRAM", strLen) == 0) {
368 sockopt->type = SOCK_DGRAM;
369 }
370 return 0;
371 }
372
ParseSocketProtocol(cJSON * json,ServiceSocket * sockopt)373 static int ParseSocketProtocol(cJSON *json, ServiceSocket *sockopt)
374 {
375 sockopt->protocol = 0;
376 size_t strLen = 0;
377 char *stringValue = GetStringValue(json, "protocol", &strLen);
378 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
379 "Failed to get string for protocol");
380 if (strncmp(stringValue, "default", strLen) == 0) {
381 sockopt->protocol = 0;
382 } else if (strncmp(stringValue, "NETLINK_KOBJECT_UEVENT", strLen) == 0) {
383 #ifndef __LITEOS_A__
384 sockopt->protocol = NETLINK_KOBJECT_UEVENT;
385 #else
386 return -1;
387 #endif
388 }
389 return 0;
390 }
391
ParseSocketOption(cJSON * json,ServiceSocket * sockopt)392 static int ParseSocketOption(cJSON *json, ServiceSocket *sockopt)
393 {
394 sockopt->option = 0;
395 unsigned int tempType = 0;
396 int typeCnt = 0;
397 char *stringValue = NULL;
398 cJSON *typeItem = NULL;
399 cJSON *typeArray = GetArrayItem(json, &typeCnt, "option");
400 INIT_CHECK((typeArray != NULL) && (typeCnt > 0), return 0);
401 for (int i = 0; i < typeCnt; ++i) {
402 typeItem = cJSON_GetArrayItem(typeArray, i);
403 INIT_CHECK_RETURN_VALUE(cJSON_IsString(typeItem), SERVICE_FAILURE);
404 stringValue = cJSON_GetStringValue(typeItem);
405 INIT_ERROR_CHECK(stringValue != NULL, return SERVICE_FAILURE, "Failed to get string for type");
406 if (strncmp(stringValue, "SOCKET_OPTION_PASSCRED", strlen(stringValue)) == 0) {
407 sockopt->option |= SOCKET_OPTION_PASSCRED;
408 } else if (strncmp(stringValue, "SOCKET_OPTION_RCVBUFFORCE", strlen(stringValue)) == 0) {
409 sockopt->option |= SOCKET_OPTION_RCVBUFFORCE;
410 } else if (strncmp(stringValue, "SOCK_CLOEXEC", strlen(stringValue)) == 0) {
411 tempType |= SOCK_CLOEXEC;
412 } else if (strncmp(stringValue, "SOCK_NONBLOCK", strlen(stringValue)) == 0) {
413 tempType |= SOCK_NONBLOCK;
414 }
415 }
416 if (tempType != 0) {
417 sockopt->type |= tempType;
418 }
419 return 0;
420 }
421
AddServiceSocket(cJSON * json,Service * service)422 static int AddServiceSocket(cJSON *json, Service *service)
423 {
424 size_t strLen = 0;
425 char* fieldStr = GetStringValue(json, "name", &strLen);
426 INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get socket name");
427 INIT_ERROR_CHECK(strLen <= MAX_SERVICE_NAME, return SERVICE_FAILURE, "socket name exceeds length limit");
428 ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strLen + 1);
429 INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for service %s", service->name);
430
431 int ret = strcpy_s(sockopt->name, strLen + 1, fieldStr);
432 INIT_INFO_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
433 "Failed to copy socket name %s", fieldStr);
434 sockopt->sockFd = -1;
435 sockopt->watcher = NULL;
436
437 ret = ParseSocketFamily(json, sockopt);
438 INIT_ERROR_CHECK(ret == 0, free(sockopt);
439 return SERVICE_FAILURE, "Failed to parse socket family");
440 ret = ParseSocketType(json, sockopt);
441 INIT_ERROR_CHECK(ret == 0, free(sockopt);
442 return SERVICE_FAILURE, "Failed to parse socket type");
443 ret = ParseSocketProtocol(json, sockopt);
444 INIT_ERROR_CHECK(ret == 0, free(sockopt);
445 return SERVICE_FAILURE, "Failed to parse socket protocol");
446
447 char *stringValue = GetStringValue(json, "permissions", &strLen);
448 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt);
449 return SERVICE_FAILURE, "Failed to get string for permissions");
450 sockopt->perm = strtoul(stringValue, 0, OCTAL_BASE);
451 stringValue = GetStringValue(json, "uid", &strLen);
452 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt);
453 return SERVICE_FAILURE, "Failed to get string for uid");
454 sockopt->uid = DecodeUid(stringValue);
455 stringValue = GetStringValue(json, "gid", &strLen);
456 INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt);
457 return SERVICE_FAILURE, "Failed to get string for gid");
458 sockopt->gid = DecodeGid(stringValue);
459 INIT_ERROR_CHECK((sockopt->uid != (uid_t)-1) && (sockopt->gid != (uid_t)-1), free(sockopt);
460 return SERVICE_FAILURE, "Invalid uid or gid");
461 ret = ParseSocketOption(json, sockopt);
462 INIT_ERROR_CHECK(ret == 0, free(sockopt);
463 return SERVICE_FAILURE, "Failed to parse socket option");
464
465 sockopt->next = NULL;
466 if (service->socketCfg == NULL) {
467 service->socketCfg = sockopt;
468 } else {
469 sockopt->next = service->socketCfg->next;
470 service->socketCfg->next = sockopt;
471 }
472 return SERVICE_SUCCESS;
473 }
474
ParseServiceSocket(const cJSON * curArrItem,Service * curServ)475 static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
476 {
477 int sockCnt = 0;
478 cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket");
479 INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE);
480
481 CloseServiceSocket(curServ);
482 FreeServiceSocket(curServ->socketCfg);
483 int ret = 0;
484 curServ->socketCfg = NULL;
485 for (int i = 0; i < sockCnt; ++i) {
486 cJSON *sockJ = cJSON_GetArrayItem(filedJ, i);
487 ret = AddServiceSocket(sockJ, curServ);
488 if (ret != 0) {
489 return ret;
490 }
491 }
492 if (IsOnDemandService(curServ)) {
493 ret = CreateServiceSocket(curServ);
494 }
495 return ret;
496 }
497
AddServiceFile(cJSON * json,Service * service)498 static int AddServiceFile(cJSON *json, Service *service)
499 {
500 if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) {
501 return SERVICE_FAILURE;
502 }
503 char *fileStr = cJSON_GetStringValue(json);
504 char *opt[FILE_OPT_NUMS] = {
505 NULL,
506 };
507 int num = SplitString(fileStr, " ", opt, FILE_OPT_NUMS);
508 if (num != FILE_OPT_NUMS) {
509 return SERVICE_FAILURE;
510 }
511 if (opt[SERVICE_FILE_NAME] == NULL || opt[SERVICE_FILE_FLAGS] == NULL || opt[SERVICE_FILE_PERM] == NULL ||
512 opt[SERVICE_FILE_UID] == NULL || opt[SERVICE_FILE_GID] == NULL) {
513 INIT_LOGE("Invalid file opt");
514 return SERVICE_FAILURE;
515 }
516 ServiceFile *fileOpt = (ServiceFile *)calloc(1, sizeof(ServiceFile) + strlen(opt[SERVICE_FILE_NAME]) + 1);
517 INIT_INFO_CHECK(fileOpt != NULL, return SERVICE_FAILURE, "Failed to calloc for file %s", opt[SERVICE_FILE_NAME]);
518 int ret = strcpy_s(fileOpt->fileName, strlen(opt[SERVICE_FILE_NAME]) + 1, opt[SERVICE_FILE_NAME]);
519 INIT_INFO_CHECK(ret == 0, free(fileOpt);
520 return SERVICE_FAILURE, "Failed to copy file name %s", opt[SERVICE_FILE_NAME]);
521 if (strcmp(opt[SERVICE_FILE_FLAGS], "rd") == 0) {
522 fileOpt->flags = O_RDONLY;
523 } else if (strcmp(opt[SERVICE_FILE_FLAGS], "wd") == 0) {
524 fileOpt->flags = O_WRONLY;
525 } else if (strcmp(opt[SERVICE_FILE_FLAGS], "rw") == 0) {
526 fileOpt->flags = O_RDWR;
527 } else {
528 INIT_LOGE("Failed file flags %s", opt[SERVICE_FILE_FLAGS]);
529 return SERVICE_FAILURE;
530 }
531 fileOpt->perm = strtoul(opt[SERVICE_FILE_PERM], 0, OCTAL_BASE);
532 fileOpt->uid = DecodeUid(opt[SERVICE_FILE_UID]);
533 fileOpt->gid = DecodeGid(opt[SERVICE_FILE_GID]);
534 if (fileOpt->uid == (uid_t)-1 || fileOpt->gid == (gid_t)-1) {
535 free(fileOpt);
536 fileOpt = NULL;
537 INIT_LOGE("Invalid uid or gid");
538 return SERVICE_FAILURE;
539 }
540 fileOpt->fd = -1;
541 fileOpt->next = NULL;
542 if (service->fileCfg == NULL) {
543 service->fileCfg = fileOpt;
544 } else {
545 fileOpt->next = service->fileCfg->next;
546 service->fileCfg->next = fileOpt;
547 }
548 return SERVICE_SUCCESS;
549 }
550
ParseServiceFile(const cJSON * curArrItem,Service * curServ)551 static int ParseServiceFile(const cJSON *curArrItem, Service *curServ)
552 {
553 int fileCnt = 0;
554 cJSON *filedJ = GetArrayItem(curArrItem, &fileCnt, "file");
555 INIT_CHECK(filedJ != NULL && fileCnt > 0, return SERVICE_FAILURE);
556 FreeServiceFile(curServ->fileCfg);
557 int ret = 0;
558 curServ->fileCfg = NULL;
559 for (int i = 0; i < fileCnt; ++i) {
560 cJSON *fileJ = cJSON_GetArrayItem(filedJ, i);
561 ret = AddServiceFile(fileJ, curServ);
562 if (ret != 0) {
563 break;
564 }
565 }
566 return ret;
567 }
568
GetServiceOnDemand(const cJSON * curArrItem,Service * curServ)569 static int GetServiceOnDemand(const cJSON *curArrItem, Service *curServ)
570 {
571 cJSON *item = cJSON_GetObjectItem(curArrItem, "ondemand");
572 if (item == NULL) {
573 return SERVICE_SUCCESS;
574 }
575
576 INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
577 "Service : %s ondemand value only support bool.", curServ->name);
578 curServ->attribute &= ~SERVICE_ATTR_ONDEMAND;
579
580 INIT_INFO_CHECK(cJSON_IsTrue(item), return SERVICE_SUCCESS,
581 "Service : %s ondemand value is false, it should be pulled up by init", curServ->name);
582 if (curServ->attribute & SERVICE_ATTR_CRITICAL) {
583 INIT_LOGE("Service : %s is invalid which has both critical and ondemand attribute", curServ->name);
584 return SERVICE_FAILURE;
585 }
586
587 curServ->attribute |= SERVICE_ATTR_ONDEMAND;
588 return SERVICE_SUCCESS;
589 }
590
GetMapValue(const char * name,const InitArgInfo * infos,int argNum,int defValue)591 static int GetMapValue(const char *name, const InitArgInfo *infos, int argNum, int defValue)
592 {
593 if ((argNum == 0) || (infos == NULL) || (name == NULL)) {
594 return defValue;
595 }
596 for (int i = 0; i < argNum; i++) {
597 if (strcmp(infos[i].name, name) == 0) {
598 return infos[i].value;
599 }
600 }
601 return defValue;
602 }
603
GetServiceMode(Service * service,const cJSON * json)604 static int GetServiceMode(Service *service, const cJSON *json)
605 {
606 const InitArgInfo startModeMap[] = {
607 {"condition", START_MODE_CONDITION},
608 {"boot", START_MODE_BOOT},
609 {"normal", START_MODE_NORMAL}
610 };
611 const InitArgInfo endModeMap[] = {
612 {"pre-fork", END_PRE_FORK},
613 {"after-fork", END_AFTER_FORK},
614 {"after-exec", END_AFTER_EXEC},
615 {"ready", END_RECV_READY}
616 };
617 service->startMode = START_MODE_NORMAL;
618 service->endMode = END_AFTER_EXEC;
619 char *value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "start-mode"));
620 if (value != NULL) {
621 service->startMode = GetMapValue(value,
622 (InitArgInfo *)startModeMap, (int)ARRAY_LENGTH(startModeMap), START_MODE_NORMAL);
623 }
624 value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "end-mode"));
625 if (value != NULL) {
626 service->endMode = GetMapValue(value,
627 (InitArgInfo *)endModeMap, (int)ARRAY_LENGTH(endModeMap), END_AFTER_EXEC);
628 }
629 return 0;
630 }
631
GetServiceJobs(Service * service,cJSON * json)632 static int GetServiceJobs(Service *service, cJSON *json)
633 {
634 const char *jobTypes[] = {
635 "on-boot", "on-start", "on-stop", "on-restart"
636 };
637 for (int i = 0; i < (int)ARRAY_LENGTH(jobTypes); i++) {
638 char *jobName = cJSON_GetStringValue(cJSON_GetObjectItem(json, jobTypes[i]));
639 if (jobName != NULL) {
640 if (service->serviceJobs.jobsName[i] != NULL) {
641 DelGroupNode(NODE_TYPE_JOBS, service->serviceJobs.jobsName[i]);
642 free(service->serviceJobs.jobsName[i]);
643 }
644 service->serviceJobs.jobsName[i] = strdup(jobName);
645 // save job name for group job check
646 AddGroupNode(NODE_TYPE_JOBS, jobName);
647 }
648 }
649 return SERVICE_SUCCESS;
650 }
651
GetCritical(const cJSON * curArrItem,Service * curServ,const char * attrName,int flag)652 int GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag)
653 {
654 int criticalSize = 0;
655 curServ->crashCount = CRITICAL_DEFAULT_CRASH_COUNT;
656 curServ->crashTime = CRITICAL_DEFAULT_CRASH_TIME;
657 cJSON *arrItem = cJSON_GetObjectItem(curArrItem, attrName);
658 if (arrItem == NULL) {
659 return SERVICE_SUCCESS;
660 }
661
662 if (cJSON_IsNumber(arrItem)) {
663 return GetServiceAttr(curArrItem, curServ, attrName, flag, NULL);
664 } else if (cJSON_IsArray(arrItem)) {
665 criticalSize = cJSON_GetArraySize(arrItem);
666 cJSON *attrItem = cJSON_GetArrayItem(arrItem, 0); // 0 : critical attribute index
667 if (attrItem == NULL || !cJSON_IsNumber(attrItem)) {
668 INIT_LOGE("%s critical invalid", curServ->name);
669 return SERVICE_FAILURE;
670 }
671 int attrValue = (int)cJSON_GetNumberValue(attrItem);
672 curServ->attribute &= ~flag;
673 if (criticalSize == 1) {
674 if (attrValue == 1) {
675 curServ->attribute |= flag;
676 }
677 } else if (criticalSize == CRITICAL_CONFIG_ARRAY_LEN) {
678 cJSON *crashCountItem = cJSON_GetArrayItem(arrItem, 1); // 1 : critical crash count index
679 INIT_ERROR_CHECK(crashCountItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name);
680 int value = (int)cJSON_GetNumberValue(crashCountItem);
681 INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crashc ount invalid", curServ->name);
682 curServ->crashCount = value;
683
684 cJSON *crashTimeItem = cJSON_GetArrayItem(arrItem, 2); // 2 : critical crash time index
685 INIT_ERROR_CHECK(crashTimeItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name);
686 value = (int)cJSON_GetNumberValue(crashTimeItem);
687 INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crash time invalid", curServ->name);
688 curServ->crashTime = value;
689
690 if (attrValue == 1) {
691 curServ->attribute |= flag;
692 }
693 } else {
694 curServ->attribute &= ~flag;
695 INIT_LOGE("%s critical param invalid", curServ->name);
696 return SERVICE_FAILURE;
697 }
698 } else {
699 INIT_LOGE("%s critical type error", curServ->name);
700 return SERVICE_FAILURE;
701 }
702 return SERVICE_SUCCESS;
703 }
704
GetCpuArgs(const cJSON * argJson,const char * name,Service * service)705 static int GetCpuArgs(const cJSON *argJson, const char *name, Service *service)
706 {
707 INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
708 cJSON *obj = cJSON_GetObjectItem(argJson, name);
709 INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
710
711 int ret = cJSON_IsArray(obj);
712 INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
713 int count = cJSON_GetArraySize(obj);
714 int cpus = -1;
715 int cpuNumMax = sysconf(_SC_NPROCESSORS_CONF);
716 if (count > 0 && service->cpuSet == NULL) {
717 service->cpuSet = malloc(sizeof(cpu_set_t));
718 INIT_ERROR_CHECK(service->cpuSet != NULL, return SERVICE_FAILURE, "Failed to malloc for cpuset");
719 }
720 CPU_ZERO(service->cpuSet);
721 for (int i = 0; i < count; ++i) {
722 cJSON *item = cJSON_GetArrayItem(obj, i);
723 INIT_ERROR_CHECK(item != NULL, return SERVICE_FAILURE, "prase invalid");
724 cpus = (int)cJSON_GetNumberValue(item);
725 if (cpuNumMax <= cpus) {
726 INIT_LOGW("%s core number %d of CPU cores does not exist", service->name, cpus);
727 continue;
728 }
729 if (CPU_ISSET(cpus, service->cpuSet)) {
730 continue;
731 }
732 CPU_SET(cpus, service->cpuSet);
733 }
734 return SERVICE_SUCCESS;
735 }
736
GetServiceSandbox(const cJSON * curItem,Service * service)737 static int GetServiceSandbox(const cJSON *curItem, Service *service)
738 {
739 cJSON *item = cJSON_GetObjectItem(curItem, "sandbox");
740 if (item == NULL) {
741 return SERVICE_SUCCESS;
742 }
743
744 INIT_ERROR_CHECK(cJSON_IsNumber(item), return SERVICE_FAILURE,
745 "Service : %s sandbox value only support number.", service->name);
746 int isSandbox = (int)cJSON_GetNumberValue(item);
747 if (isSandbox == 0) {
748 MarkServiceWithoutSandbox(service);
749 } else {
750 MarkServiceWithSandbox(service);
751 }
752
753 return SERVICE_SUCCESS;
754 }
755
756 #ifdef ASAN_DETECTOR
WrapPath(char * dest,size_t len,char * source,int i)757 static int WrapPath(char *dest, size_t len, char *source, int i)
758 {
759 char *q = source;
760 char *p = dest;
761 if (q == NULL) {
762 return -1;
763 }
764
765 while (*p != '\0') {
766 if (--i <= 0) {
767 int ret = memmove_s(p + strlen(source), len, p, strlen(p) + 1);
768 INIT_ERROR_CHECK(ret == 0, return -1, "Dest is %s, source is %s, ret is %d.", dest, source, ret);
769 break;
770 }
771 p++;
772 }
773 while (*q != '\0') {
774 *p = *q;
775 p++;
776 q++;
777 }
778
779 return 0;
780 }
781
GetWrapServiceNameValue(const char * serviceName)782 static int GetWrapServiceNameValue(const char *serviceName)
783 {
784 char wrapServiceNameKey[PARAM_VALUE_LEN_MAX] = {0};
785 char wrapServiceNameValue[PARAM_VALUE_LEN_MAX] = {0};
786 unsigned int valueLen = PARAM_VALUE_LEN_MAX;
787
788 int len = sprintf_s(wrapServiceNameKey, PARAM_VALUE_LEN_MAX, "wrap.%s", serviceName);
789 INIT_INFO_CHECK(len > 0 && (len < PARAM_VALUE_LEN_MAX), return -1, "Invalid to format wrapServiceNameKey");
790
791 int ret = SystemReadParam(wrapServiceNameKey, wrapServiceNameValue, &valueLen);
792 INIT_INFO_CHECK(ret == 0, return -1, "Not wrap %s.", serviceName);
793 INIT_LOGI("Asan: GetParameter %s the value is %s.", serviceName, wrapServiceNameValue);
794 return 0;
795 }
796
SetServicePathWithAsan(Service * service)797 void SetServicePathWithAsan(Service *service)
798 {
799 char tmpPathName[MAX_ONE_ARG_LEN] = {0};
800 int anchorPos = -1;
801
802 if (GetWrapServiceNameValue(service->name) != 0) {
803 return;
804 }
805
806 int ret = strcpy_s(tmpPathName, MAX_ONE_ARG_LEN, service->pathArgs.argv[0]);
807 INIT_ERROR_CHECK(ret == 0, return, "Asan: failed to copy service path %s", service->pathArgs.argv[0]);
808
809 if (strstr(tmpPathName, "/system/bin") != NULL) {
810 anchorPos = strlen("/system") + 1;
811 } else if (strstr(tmpPathName, "/vendor/bin") != NULL) {
812 anchorPos = strlen("/vendor") + 1;
813 } else {
814 INIT_LOGE("Asan: %s is not a system or vendor binary", tmpPathName);
815 return;
816 }
817
818 ret = WrapPath(tmpPathName, MAX_ONE_ARG_LEN, "/asan", anchorPos);
819 INIT_ERROR_CHECK(ret == 0, return, "Asan: failed to add asan path.");
820 free(service->pathArgs.argv[0]);
821 service->pathArgs.argv[0] = strdup(tmpPathName);
822 INIT_LOGI("Asan: replace module %s with %s successfully.", service->name, service->pathArgs.argv[0]);
823
824 return;
825 }
826 #endif
827
ParseOneServiceArgs(const cJSON * curItem,Service * service)828 static void ParseOneServiceArgs(const cJSON *curItem, Service *service)
829 {
830 GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs);
831 GetServiceArgs(curItem, D_CAPS_STR_IN_CFG, MAX_WRITEPID_FILES, &service->capsArgs);
832 GetServiceArgs(curItem, "permission", MAX_WRITEPID_FILES, &service->permArgs);
833 GetServiceArgs(curItem, "permission_acls", MAX_WRITEPID_FILES, &service->permAclsArgs);
834 size_t strLen = 0;
835 char *fieldStr = GetStringValue(curItem, APL_STR_IN_CFG, &strLen);
836 if (fieldStr != NULL) {
837 if (service->apl != NULL) {
838 free(service->apl);
839 }
840 service->apl = strdup(fieldStr);
841 INIT_CHECK(service->apl != NULL, return);
842 }
843 (void)GetCpuArgs(curItem, CPU_CORE_STR_IN_CFG, service);
844 }
845
SetConsoleValue(Service * service,const char * attrName,int value,int flag)846 static int SetConsoleValue(Service *service, const char *attrName, int value, int flag)
847 {
848 UNUSED(attrName);
849 UNUSED(flag);
850 INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr.");
851 if (value == 1) {
852 service->attribute |= SERVICE_ATTR_CONSOLE;
853 } if (value == 2) {
854 service->attribute |= SERVICE_ATTR_KMSG;
855 }
856 return SERVICE_SUCCESS;
857 }
858
ParseOneService(const cJSON * curItem,Service * service)859 int ParseOneService(const cJSON *curItem, Service *service)
860 {
861 INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE);
862 int ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs);
863 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name);
864 if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) {
865 INIT_LOGE("Service %s is forbidden.", service->name);
866 return SERVICE_FAILURE;
867 }
868 #ifdef ASAN_DETECTOR
869 SetServicePathWithAsan(service);
870 #endif
871 ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID);
872 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name);
873 ret = GetServiceGids(curItem, service);
874 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name);
875
876 ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL);
877 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name);
878 ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue);
879 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name);
880 ret = GetCritical(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL);
881 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name);
882 ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL);
883 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name);
884 ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, SetConsoleValue);
885 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name);
886 ret = GetServiceAttr(curItem, service, "notify-state", SERVICE_ATTR_NOTIFY_STATE, NULL);
887 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get notify-state for service %s", service->name);
888 ret = GetServiceAttr(curItem, service, MODULE_UPDATE_STR_IN_CFG, SERVICE_ATTR_MODULE_UPDATE, NULL);
889 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get module-update for service %s", service->name);
890
891 ParseOneServiceArgs(curItem, service);
892 ret = GetServiceSandbox(curItem, service);
893 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get sandbox for service %s", service->name);
894 ret = InitServiceCaps(curItem, service);
895 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
896 ret = GetServiceOnDemand(curItem, service);
897 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get ondemand flag for service %s", service->name);
898 ret = GetServiceMode(service, curItem);
899 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get start/end mode for service %s", service->name);
900 ret = GetServiceJobs(service, cJSON_GetObjectItem(curItem, "jobs"));
901 INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get jobs for service %s", service->name);
902 return ret;
903 }
904
905 #ifndef OHOS_LITE
906 /**
907 * Service Config File Parse Hooking
908 */
ServiceParseHookWrapper(const HOOK_INFO * hookInfo,void * executionContext)909 static int ServiceParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
910 {
911 SERVICE_PARSE_CTX *serviceParseContext = (SERVICE_PARSE_CTX *)executionContext;
912 ServiceParseHook realHook = (ServiceParseHook)hookInfo->hookCookie;
913
914 realHook(serviceParseContext);
915 return 0;
916 };
917
InitAddServiceParseHook(ServiceParseHook hook)918 int InitAddServiceParseHook(ServiceParseHook hook)
919 {
920 HOOK_INFO info;
921
922 info.stage = INIT_SERVICE_PARSE;
923 info.prio = 0;
924 info.hook = ServiceParseHookWrapper;
925 info.hookCookie = (void *)hook;
926
927 return HookMgrAddEx(GetBootStageHookMgr(), &info);
928 }
929
ParseServiceHookExecute(const char * name,const cJSON * serviceNode)930 static void ParseServiceHookExecute(const char *name, const cJSON *serviceNode)
931 {
932 SERVICE_PARSE_CTX context;
933
934 context.serviceName = name;
935 context.serviceNode = serviceNode;
936
937 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_PARSE, (void *)(&context), NULL);
938 }
939 #endif
940
ProcessConsoleEvent(const WatcherHandle handler,int fd,uint32_t * events,const void * context)941 static void ProcessConsoleEvent(const WatcherHandle handler, int fd, uint32_t *events, const void *context)
942 {
943 Service *service = (Service *)context;
944 LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)handler);
945 if (fd < 0 || service == NULL) {
946 INIT_LOGE("Process console event with invalid arguments");
947 return;
948 }
949 // Since we've got event from console device
950 // the fd related to '/dev/console' does not need anymore, close it.
951 close(fd);
952 if (strcmp(service->name, "console") != 0) {
953 INIT_LOGE("Process console event with invalid service %s, only console service should do this", service->name);
954 return;
955 }
956
957 if (ServiceStart(service, &service->pathArgs) != SERVICE_SUCCESS) {
958 INIT_LOGE("Start console service failed");
959 }
960 return;
961 }
962
AddFileDescriptorToWatcher(int fd,Service * service)963 static int AddFileDescriptorToWatcher(int fd, Service *service)
964 {
965 if (fd < 0 || service == NULL) {
966 return -1;
967 }
968
969 WatcherHandle watcher = NULL;
970 LE_WatchInfo info = {};
971 info.fd = fd;
972 info.flags = 0; // WATCHER_ONCE;
973 info.events = Event_Read;
974 info.processEvent = ProcessConsoleEvent;
975 int ret = LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, service);
976 if (ret != LE_SUCCESS) {
977 INIT_LOGE("Failed to watch console device for service \' %s \'", service->name);
978 return -1;
979 }
980 return 0;
981 }
982
WatchConsoleDevice(Service * service)983 int WatchConsoleDevice(Service *service)
984 {
985 if (service == NULL) {
986 return -1;
987 }
988
989 int fd = open("/dev/console", O_RDWR);
990 if (fd < 0) {
991 if (errno == ENOENT) {
992 INIT_LOGW("/dev/console is not exist, wait for it...");
993 WaitForFile("/dev/console", WAIT_MAX_SECOND);
994 } else {
995 INIT_LOGE("Failed to open /dev/console, err = %d", errno);
996 return -1;
997 }
998 fd = open("/dev/console", O_RDWR);
999 if (fd < 0) {
1000 INIT_LOGW("Failed to open /dev/console after try 1 time, err = %d", errno);
1001 return -1;
1002 }
1003 }
1004
1005 if (AddFileDescriptorToWatcher(fd, service) < 0) {
1006 close(fd);
1007 return -1;
1008 }
1009 return 0;
1010 }
1011
ParseAllServices(const cJSON * fileRoot,const ConfigContext * context)1012 void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context)
1013 {
1014 int servArrSize = 0;
1015 cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
1016 INIT_CHECK(serviceArr != NULL, return);
1017
1018 size_t strLen = 0;
1019 for (int i = 0; i < servArrSize; ++i) {
1020 cJSON *curItem = cJSON_GetArrayItem(serviceArr, i);
1021 char *fieldStr = GetStringValue(curItem, "name", &strLen);
1022 if (fieldStr == NULL) {
1023 INIT_LOGE("Failed to get service name");
1024 continue;
1025 }
1026 Service *service = GetServiceByName(fieldStr);
1027 if (service == NULL) {
1028 service = AddService(fieldStr);
1029 if (service == NULL) {
1030 INIT_LOGE("Failed to add service name %s", fieldStr);
1031 continue;
1032 }
1033 } else {
1034 INIT_LOGI("Service %s already exists, updating.", fieldStr);
1035 #ifndef __MUSL__
1036 continue;
1037 #endif
1038 }
1039
1040 if (context != NULL) {
1041 service->context.type = context->type;
1042 }
1043 int ret = ParseOneService(curItem, service);
1044 if (ret != SERVICE_SUCCESS) {
1045 INIT_LOGE("Service error %s parse config error.", service->name, cJSON_Print(curItem));
1046 service->lastErrno = INIT_ECFG;
1047 continue;
1048 }
1049 ret = ParseServiceSocket(curItem, service);
1050 INIT_CHECK(ret == 0, FreeServiceSocket(service->socketCfg); service->socketCfg = NULL);
1051 ret = ParseServiceFile(curItem, service);
1052 INIT_CHECK(ret == 0, FreeServiceFile(service->fileCfg); service->fileCfg = NULL);
1053 // Watch "/dev/console" node for starting console service ondemand.
1054 if ((strcmp(service->name, "console") == 0) && IsOnDemandService(service)) {
1055 if (WatchConsoleDevice(service) < 0) {
1056 INIT_LOGW("Failed to watch \'/dev/console\' device");
1057 }
1058 }
1059 #ifndef OHOS_LITE
1060 /*
1061 * Execute service parsing hooks
1062 */
1063 ParseServiceHookExecute(fieldStr, curItem);
1064 #endif
1065
1066 ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg);
1067 INIT_CHECK(ret == SERVICE_SUCCESS, service->restartArg = NULL);
1068 }
1069 }
1070
GetServiceByExtServName(const char * fullServName,ServiceArgs * extraArgs)1071 static Service *GetServiceByExtServName(const char *fullServName, ServiceArgs *extraArgs)
1072 {
1073 INIT_ERROR_CHECK(fullServName != NULL, return NULL, "Failed get parameters");
1074 Service *service = GetServiceByName(fullServName);
1075 if (service != NULL) { // none parameter in fullServName
1076 return service;
1077 }
1078 char *tmpServName = strdup(fullServName);
1079 char *dstPtr[MAX_PATH_ARGS_CNT] = {NULL};
1080 int returnCount = SplitString(tmpServName, "|", dstPtr, MAX_PATH_ARGS_CNT);
1081 if (returnCount == 0) {
1082 INIT_LOGE("Service error %s start service bt ext parameter .", fullServName);
1083 free(tmpServName);
1084 return NULL;
1085 }
1086 INIT_LOGI("Service info %s start service bt ext parameter %s.", dstPtr[0], fullServName);
1087 service = GetServiceByName(dstPtr[0]);
1088 if (service == NULL) {
1089 free(tmpServName);
1090 return NULL;
1091 }
1092 extraArgs->count = service->pathArgs.count + returnCount - 1;
1093 extraArgs->argv = (char **)calloc(extraArgs->count + 1, sizeof(char *));
1094 INIT_ERROR_CHECK(extraArgs->argv != NULL, free(tmpServName);
1095 return NULL, "Failed calloc err=%d", errno);
1096 int argc;
1097 for (argc = 0; argc < (service->pathArgs.count - 1); argc++) {
1098 extraArgs->argv[argc] = strdup(service->pathArgs.argv[argc]);
1099 }
1100 int extArgc;
1101 for (extArgc = 0; extArgc < (returnCount - 1); extArgc++) {
1102 extraArgs->argv[extArgc + argc] = strdup(dstPtr[extArgc + 1]);
1103 }
1104 extraArgs->argv[extraArgs->count] = NULL;
1105 free(tmpServName);
1106 return service;
1107 }
1108
StartServiceByName(const char * servName)1109 void StartServiceByName(const char *servName)
1110 {
1111 ServiceArgs extraArgs = { 0 };
1112 Service *service = GetServiceByName(servName);
1113 if (service == NULL) {
1114 service = GetServiceByExtServName(servName, &extraArgs);
1115 }
1116 INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
1117
1118 ServiceArgs *pathArgs = &service->pathArgs;
1119 if (extraArgs.count != 0) {
1120 pathArgs = &extraArgs;
1121 }
1122 if (ServiceStart(service, pathArgs) != SERVICE_SUCCESS) {
1123 INIT_LOGE("Service %s start failed!", servName);
1124 }
1125 // After starting, clear the extra parameters.
1126 FreeStringVector(extraArgs.argv, extraArgs.count);
1127 return;
1128 }
1129
StopServiceByName(const char * servName)1130 void StopServiceByName(const char *servName)
1131 {
1132 Service *service = GetServiceByName(servName);
1133 INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
1134
1135 if (ServiceStop(service) != SERVICE_SUCCESS) {
1136 INIT_LOGE("Service %s stop failed!", servName);
1137 }
1138 return;
1139 }
1140
StopAllServices(int flags,const char ** exclude,int size,int (* filter)(const Service * service,const char ** exclude,int size))1141 void StopAllServices(int flags, const char **exclude, int size,
1142 int (*filter)(const Service *service, const char **exclude, int size))
1143 {
1144 Service *service = GetServiceByName("appspawn");
1145 if (service != NULL && service->pid > 0) { // notify appspawn stop
1146 #ifndef STARTUP_INIT_TEST
1147 kill(service->pid, SIGTERM);
1148 waitpid(service->pid, 0, 0);
1149 service->pid = -1;
1150 #endif
1151 }
1152
1153 InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
1154 while (node != NULL) {
1155 Service *service = node->data.service;
1156 if (service == NULL) {
1157 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1158 continue;
1159 }
1160 INIT_LOGI("StopAllServices stop service %s ", service->name);
1161 if (filter != NULL && filter(service, exclude, size) != 0) {
1162 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1163 continue;
1164 }
1165 service->attribute |= (flags & SERVICE_ATTR_INVALID);
1166 int ret = ServiceStop(service);
1167 if (ret != SERVICE_SUCCESS) {
1168 INIT_LOGE("Service %s stop failed!", service->name);
1169 }
1170 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1171 }
1172
1173 INIT_TIMING_STAT cmdTimer;
1174 (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime);
1175 long long count = 1;
1176 while (count > 0) {
1177 usleep(INTERVAL_PER_WAIT);
1178 count++;
1179 (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime);
1180 long long diff = InitDiffTime(&cmdTimer);
1181 if (diff > REBOOT_WAIT_TIME) {
1182 count = 0;
1183 }
1184 }
1185 INIT_LOGI("StopAllServices end");
1186 }
1187
GetServiceByPid(pid_t pid)1188 Service *GetServiceByPid(pid_t pid)
1189 {
1190 InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
1191 while (node != NULL) {
1192 Service *service = node->data.service;
1193 if (service != NULL && service->pid == pid) {
1194 return service;
1195 }
1196 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1197 }
1198 return NULL;
1199 }
1200
GetServiceByName(const char * servName)1201 Service *GetServiceByName(const char *servName)
1202 {
1203 INIT_ERROR_CHECK(servName != NULL, return NULL, "Failed get servName");
1204 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, servName);
1205 if (groupNode != NULL) {
1206 return groupNode->data.service;
1207 }
1208 return NULL;
1209 }
1210
LoadAccessTokenId(void)1211 void LoadAccessTokenId(void)
1212 {
1213 GetAccessToken();
1214 }
1215
GetKillServiceSig(const char * name)1216 int GetKillServiceSig(const char *name)
1217 {
1218 if (strcmp(name, "appspawn") == 0 || strcmp(name, "nwebspawn") == 0) {
1219 return SIGTERM;
1220 }
1221 return SIGKILL;
1222 }
1223
GetServiceGroupIdByPid(pid_t pid,gid_t * gids,uint32_t gidSize)1224 int GetServiceGroupIdByPid(pid_t pid, gid_t *gids, uint32_t gidSize)
1225 {
1226 Service *service = GetServiceByPid(pid);
1227 if (service != NULL) {
1228 int ret = memcpy_s(gids, gidSize * sizeof(gid_t),
1229 service->servPerm.gIDArray, service->servPerm.gIDCnt * sizeof(gid_t));
1230 INIT_ERROR_CHECK(ret == 0, return 0, "Failed get copy gids");
1231 return service->servPerm.gIDCnt;
1232 }
1233 return 0;
1234 }