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