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