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