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