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