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