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