1 /*
2 * Copyright (c) 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
16 #include <sys/socket.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <cstdlib>
20 #include "init.h"
21 #include "init_cmds.h"
22 #include "init_service.h"
23 #include "init_service_manager.h"
24 #include "init_service_socket.h"
25 #include "param_stub.h"
26 #include "init_utils.h"
27 #include "securec.h"
28 #include "init_group_manager.h"
29 #include "trigger_manager.h"
30 #include "bootstage.h"
31 #include "init_hook.h"
32 #include "plugin_adapter.h"
33
34 const char *SERVICE_INFO_JSONSTR = "{"
35 "\"services\":{"
36 " \"name\":\"test_service\","
37 " \"path\":[\"/data/init_ut/test_service\"],"
38 " \"importance\":-20,"
39 " \"uid\":\"system\","
40 " \"writepid\":[\"/dev/test_service\"],"
41 " \"console\":1,"
42 " \"caps\":[\"TEST_ERR\"],"
43 " \"gid\":[\"system\"],"
44 " \"period\":2,"
45 " \"env\":[{ "
46 " \"name\":\"test\","
47 " \"value\":\"xxxx\""
48 " }],"
49 " \"critical\":1,"
50 " \"jobs\" : {"
51 " \"pre-start\":\"test_service:pre-start\""
52 " }"
53 "}"
54 "}";
55 const char *JOB_INFO_JSONSTR = "{"
56 "\"jobs\": ["
57 " {"
58 " \"name\" : \"test_service:pre-start\","
59 " \"cmds\" : ["
60 " \"setparam test.test.prestartKey 1\""
61 " ]"
62 " }"
63 "]"
64 "}";
65 const char *PRE_START_KEY = "test.test.prestartKey";
DoCmdByName(const char * name,const char * cmdContent)66 static void DoCmdByName(const char *name, const char *cmdContent)
67 {
68 int cmdIndex = 0;
69 (void)GetMatchCmd(name, &cmdIndex);
70 DoCmdByIndex(cmdIndex, cmdContent, nullptr);
71 }
72
LoadJobs()73 static void LoadJobs()
74 {
75 cJSON *jobJson = cJSON_Parse(JOB_INFO_JSONSTR);
76 INIT_ERROR_CHECK(jobJson != NULL, return, "Failed to loadJobs");
77 ParseTriggerConfig(jobJson, nullptr, nullptr);
78 cJSON_Delete(jobJson);
79 }
80
ServiceTestTriggerExe(const TriggerNode * trigger,const char * content,uint32_t size)81 static int ServiceTestTriggerExe(const TriggerNode *trigger, const char *content, uint32_t size)
82 {
83 INIT_ERROR_CHECK(trigger != NULL, return -1, "ParamWriteTriggerExe trigger is NULL");
84 CommandNode *cmd = GetNextCmdNode((JobNode *)trigger, NULL);
85 while (cmd != NULL) {
86 DoCmdByIndex(cmd->cmdKeyIndex, cmd->content, &cmd->cfgContext);
87 cmd = GetNextCmdNode((JobNode *)trigger, cmd);
88 }
89 return 0;
90 }
91
92 using namespace testing::ext;
93 using namespace std;
94
95 extern "C" {
96 INIT_STATIC int GetCgroupPath(Service *service, char *buffer, uint32_t buffLen);
97 }
98
99 namespace init_ut {
100 class ServiceUnitTest : public testing::Test {
101 public:
SetUpTestCase(void)102 static void SetUpTestCase(void)
103 {
104 string svcPath = "/data/init_ut/test_service";
105 auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(svcPath.c_str(), "wb"), fclose);
106 if (fp == nullptr) {
107 cout << "ServiceUnitTest open : " << svcPath << " failed." << errno << endl;
108 }
109 sync();
110 }
111
TearDownTestCase(void)112 static void TearDownTestCase(void) {};
SetUp()113 void SetUp() {};
TearDown()114 void TearDown() {};
115 };
116
117 HWTEST_F(ServiceUnitTest, case01, TestSize.Level1)
118 {
119 cJSON* jobItem = cJSON_Parse(SERVICE_INFO_JSONSTR);
120 ASSERT_NE(nullptr, jobItem);
121 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
122 ASSERT_NE(nullptr, serviceItem);
123 Service *service = AddService("test_service");
124 int ret = ParseOneService(serviceItem, service);
125 EXPECT_EQ(ret, 0);
126
127 LoadJobs();
128 RegisterTriggerExec(TRIGGER_UNKNOW, ServiceTestTriggerExe);
129
130 ret = ServiceStart(service, &service->pathArgs);
131 EXPECT_EQ(ret, 0);
132
133 char value[PARAM_VALUE_LEN_MAX] = {0};
134 u_int32_t len = sizeof(value);
135 ret = SystemGetParameter(PRE_START_KEY, value, &len);
136 EXPECT_EQ(ret, 0);
137 EXPECT_EQ(0, strcmp("1", value));
138
139 ret = ServiceStop(service);
140 EXPECT_EQ(ret, 0);
141
142 ReleaseService(service);
143 cJSON_Delete(jobItem);
144 }
145
146 HWTEST_F(ServiceUnitTest, case02, TestSize.Level1)
147 {
148 const char *jsonStr = "{\"services\":{\"name\":\"test_service8\",\"path\":[\"/data/init_ut/test_service\"],"
149 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
150 "\"gid\":[\"system\", \"shell\", \"root\"],\"caps\":[10, 4294967295, 10000],\"cpucore\":[1]}}";
151 cJSON* jobItem = cJSON_Parse(jsonStr);
152 ASSERT_NE(nullptr, jobItem);
153 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
154 ASSERT_NE(nullptr, serviceItem);
155 Service *service = AddService("test_service8");
156 ASSERT_NE(nullptr, service);
157 int ret = ParseOneService(serviceItem, service);
158 EXPECT_EQ(ret, 0);
159
160 int fds[1] = {-1}; // ServiceStop will release fds
161 UpdaterServiceFds(service, fds, 1);
162 service->attribute = SERVICE_ATTR_ONDEMAND;
163 ret = ServiceStart(service, &service->pathArgs);
164 EXPECT_EQ(ret, 0);
165 CmdLines *cmdline = (CmdLines *)malloc(sizeof(CmdLines) + sizeof(CmdLine));
166 ASSERT_NE(nullptr, cmdline);
167 cmdline->cmdNum = 1;
168 cmdline->cmds[0].cmdIndex = 0;
169 service->restartArg = cmdline;
170 ServiceSocket tmpSock = { .next = nullptr, .sockFd = 0 };
171 ServiceSocket tmpSock1 = { .next = &tmpSock, .sockFd = 0 };
172 service->socketCfg = &tmpSock1;
173 ServiceReap(service);
174 service->socketCfg = nullptr;
175 service->attribute &= SERVICE_ATTR_NEED_RESTART;
176 service->firstCrashTime = 0;
177 ServiceReap(service);
178 DoCmdByName("reset ", "test_service8");
179 // reset again
180 DoCmdByName("reset ", "test_service8");
181 service->pid = 0xfffffff; // 0xfffffff is not exist pid
182 service->attribute = SERVICE_ATTR_TIMERSTART;
183 ret = ServiceStop(service);
184 EXPECT_EQ(ret, 0);
185 ReleaseService(service);
186 cJSON_Delete(jobItem);
187 }
188
189 HWTEST_F(ServiceUnitTest, TestServiceStartAbnormal, TestSize.Level1)
190 {
191 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/data/init_ut/test_service\"],"
192 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
193 "\"gid\":[\"system\"],\"caps\":[\"\"]}}";
194 cJSON* jobItem = cJSON_Parse(jsonStr);
195 ASSERT_NE(nullptr, jobItem);
196 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
197 ASSERT_NE(nullptr, serviceItem);
198 Service *service = AddService("test_service1");
199 ASSERT_NE(nullptr, service);
200 int ret = ParseOneService(serviceItem, service);
201 EXPECT_EQ(ret, 0);
202
203 ret = ServiceStart(service, &service->pathArgs);
204 EXPECT_EQ(ret, 0);
205
206 service->attribute &= SERVICE_ATTR_INVALID;
207 ret = ServiceStart(service, &service->pathArgs);
208 EXPECT_EQ(ret, 0);
209
210 service->pid = -1;
211 ret = ServiceStop(service);
212 EXPECT_EQ(ret, 0);
213 ReleaseService(service);
214 cJSON_Delete(jobItem);
215 }
216
217 HWTEST_F(ServiceUnitTest, TestServiceReap, TestSize.Level1)
218 {
219 Service *service = AddService("test_service2");
220 ASSERT_NE(nullptr, service);
221 EXPECT_EQ(service->attribute, 0);
222 service->attribute = SERVICE_ATTR_ONDEMAND;
223 ServiceReap(service);
224 service->attribute = 0;
225
226 service->restartArg = (CmdLines *)calloc(1, sizeof(CmdLines));
227 ASSERT_NE(nullptr, service->restartArg);
228 ServiceReap(service);
229 EXPECT_EQ(service->attribute, SERVICE_ATTR_TIMERSTART);
230
231 const int crashCount = 241;
232 service->crashCnt = crashCount;
233 ServiceReap(service);
234 EXPECT_EQ(service->attribute, SERVICE_ATTR_TIMERSTART);
235
236 service->attribute |= SERVICE_ATTR_ONCE;
237 ServiceReap(service);
238 EXPECT_EQ(service->attribute, (SERVICE_ATTR_ONCE | SERVICE_ATTR_TIMERSTART));
239 service->attribute = SERVICE_ATTR_CRITICAL;
240 service->crashCount = 1;
241 ServiceReap(service);
242 ReleaseService(service);
243 }
244
245 HWTEST_F(ServiceUnitTest, TestServiceReapOther, TestSize.Level1)
246 {
247 const char *serviceStr = "{\"services\":{\"name\":\"test_service4\",\"path\":[\"/data/init_ut/test_service\"],"
248 "\"onrestart\":[\"sleep 1\"],\"console\":1,\"writepid\":[\"/dev/test_service\"]}}";
249
250 cJSON* jobItem = cJSON_Parse(serviceStr);
251 ASSERT_NE(nullptr, jobItem);
252 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
253 ASSERT_NE(nullptr, serviceItem);
254 Service *service = AddService("test_service4");
255 ASSERT_NE(nullptr, service);
256 int ret = ParseOneService(serviceItem, service);
257 EXPECT_EQ(ret, 0);
258
259 ServiceReap(service);
260 EXPECT_NE(service->attribute, 0);
261
262 service->attribute |= SERVICE_ATTR_CRITICAL;
263 ServiceReap(service);
264 EXPECT_NE(service->attribute, 0);
265
266 service->attribute |= SERVICE_ATTR_NEED_STOP;
267 ServiceReap(service);
268 EXPECT_NE(service->attribute, 0);
269
270 service->attribute |= SERVICE_ATTR_INVALID;
271 ServiceReap(service);
272 EXPECT_NE(service->attribute, 0);
273
274 ret = ServiceStop(service);
275 EXPECT_EQ(ret, 0);
276 ReleaseService(service);
277 cJSON_Delete(jobItem);
278 }
279
280 HWTEST_F(ServiceUnitTest, TestServiceManagerRelease, TestSize.Level1)
281 {
282 Service *service = nullptr;
283 ReleaseService(service);
284 EXPECT_TRUE(service == nullptr);
285 service = AddService("test_service5");
286 ASSERT_NE(nullptr, service);
287 service->pathArgs.argv = (char **)malloc(sizeof(char *));
288 ASSERT_NE(nullptr, service->pathArgs.argv);
289 service->pathArgs.count = 1;
290 const char *path = "/data/init_ut/test_service_release";
291 service->pathArgs.argv[0] = strdup(path);
292
293 service->writePidArgs.argv = (char **)malloc(sizeof(char *));
294 ASSERT_NE(nullptr, service->writePidArgs.argv);
295 service->writePidArgs.count = 1;
296 service->writePidArgs.argv[0] = strdup(path);
297
298 service->servPerm.caps = (unsigned int *)malloc(sizeof(unsigned int));
299 ASSERT_NE(nullptr, service->servPerm.caps);
300 service->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t));
301 ASSERT_NE(nullptr, service->servPerm.gIDArray);
302 service->socketCfg = (ServiceSocket *)malloc(sizeof(ServiceSocket));
303 ASSERT_NE(nullptr, service->socketCfg);
304 service->socketCfg->sockFd = 0;
305 service->socketCfg->next = nullptr;
306 service->fileCfg = (ServiceFile *)malloc(sizeof(ServiceFile));
307 ASSERT_NE(nullptr, service->fileCfg);
308 service->fileCfg->fd = 0;
309 service->fileCfg->next = nullptr;
310 service->env = (ServiceEnv*)malloc(sizeof(ServiceEnv));
311 ASSERT_NE(nullptr, service->env);
312 int ret = strcpy_s(service->env->name, MAX_ENV_NAME, "test5");
313 EXPECT_EQ(ret, EOK);
314 ret = strcpy_s(service->env->value, MAX_ENV_VALUE, "xxxxx");
315 EXPECT_EQ(ret, EOK);
316 ReleaseService(service);
317 service = nullptr;
318 }
319
320 HWTEST_F(ServiceUnitTest, TestServiceManagerGetService, TestSize.Level1)
321 {
322 Service *service = GetServiceByPid(1);
323 StopAllServices(1, nullptr, 0, nullptr);
324 EXPECT_TRUE(service == nullptr);
325 const char *jsonStr = "{\"services\":{\"name\":\"test_service2\",\"path\":[\"/data/init_ut/test_service\"],"
326 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
327 "\"gid\":[\"system\"], \"critical\":[1,2]}}";
328 cJSON* jobItem = cJSON_Parse(jsonStr);
329 ASSERT_NE(nullptr, jobItem);
330 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
331 ASSERT_NE(nullptr, serviceItem);
332 service = AddService("test_service2");
333 ASSERT_NE(nullptr, service);
334 int ret = ParseOneService(serviceItem, service);
335 EXPECT_NE(ret, 0);
336 cJSON_Delete(jobItem);
337 const char *jsonStr1 = "{\"services\":{\"name\":\"test_service3\",\"path\":[\"/data/init_ut/test_service\"],"
338 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
339 "\"gid\":[\"system\"], \"critical\":[\"on\"]}}";
340 jobItem = cJSON_Parse(jsonStr1);
341 ASSERT_NE(nullptr, jobItem);
342 serviceItem = cJSON_GetObjectItem(jobItem, "services");
343 ASSERT_NE(nullptr, serviceItem);
344 service = AddService("test_service3");
345 ASSERT_NE(nullptr, service);
346 ret = ParseOneService(serviceItem, service);
347 EXPECT_NE(ret, 0);
348 cJSON_Delete(jobItem);
349 }
350
351 /**
352 * @tc.name: TestServiceBootEventHook
353 * @tc.desc: test bootevent module exec correct
354 * @tc.type: FUNC
355 * @tc.require: issueI5NTX4
356 * @tc.author:
357 */
358 HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1)
359 {
360 const char *serviceStr = "{"
361 "\"services\": [{"
362 "\"name\" : \"test-service\","
363 "\"path\" : [\"/dev/test_service\"],"
364 "\"start-mode\" : \"condition\","
365 "\"writepid\":[\"/dev/test_service\"],"
366 "\"bootevents\" : \"bootevent2\""
367 "},{"
368 "\"name\" : \"test-service\","
369 "\"path\" : [\"/dev/test_service\"],"
370 "\"start-mode\" : \"condition\","
371 "\"writepid\":[\"/dev/test_service\"],"
372 "\"bootevents\" : \"bootevent.bootevent2\""
373 "},{"
374 "\"name\" : \"test-service2\","
375 "\"path\" : [\"/dev/test_service\"],"
376 "\"console\":1,"
377 "\"start-mode\" : \"boot\","
378 "\"writepid\":[\"/dev/test_service\"],"
379 "\"bootevents\" : [\"bootevent.bootevent1\", \"bootevent.bootevent2\"]"
380 "}]"
381 "}";
382
383 SERVICE_INFO_CTX serviceInfoContext;
384 serviceInfoContext.serviceName = "test-service2";
385 serviceInfoContext.reserved = "bootevent";
386 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
387 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&serviceInfoContext), nullptr);
388 cJSON *fileRoot = cJSON_Parse(serviceStr);
389 ASSERT_NE(nullptr, fileRoot);
390 ConfigContext context = { INIT_CONTEXT_MAIN };
391 ParseAllServices(fileRoot, &context);
392 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), nullptr);
393 serviceInfoContext.reserved = nullptr;
394 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), nullptr);
395 const char *initBootevent[] = {"init", "test"};
396 PluginExecCmd("bootevent", ARRAY_LENGTH(initBootevent), initBootevent);
397 const char *initBooteventDup[] = {"init", "test"};
398 PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventDup), initBooteventDup);
399 const char *initBooteventErr[] = {"init"};
400 PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventErr), initBooteventErr);
401 SystemWriteParam("bootevent.bootevent1", "true");
402 SystemWriteParam("bootevent.bootevent2", "true");
403 SystemWriteParam("bootevent.bootevent2", "true");
404 SystemWriteParam("persist.init.bootevent.enable", "false");
405 HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, nullptr, nullptr);
406 cJSON_Delete(fileRoot);
407 }
408
409 HWTEST_F(ServiceUnitTest, TestSetServiceContent, TestSize.Level1)
410 {
411 int ret = WatchConsoleDevice(nullptr);
412 EXPECT_EQ(ret, -1);
413 Service service;
414 (void)WatchConsoleDevice(&service);
415 int fd = open("/dev/console", O_RDWR);
416 if (fd >= 0) {
417 (void)write(fd, "0", 1);
418 (void)close(fd);
419 }
420 PluginExecCmdByName("setServiceContent", "netmanager");
421 StopServiceByName("netmanager");
422 }
423
424 HWTEST_F(ServiceUnitTest, TestServiceExec, TestSize.Level1)
425 {
426 Service *service = AddService("test_service7");
427 ASSERT_NE(nullptr, service);
428
429 service->pathArgs.argv = (char **)malloc(sizeof(char *));
430 ASSERT_NE(service->pathArgs.argv, nullptr);
431 service->pathArgs.count = 1;
432 const char *path = "/data/init_ut/test_service_release";
433 service->pathArgs.argv[0] = strdup(path);
434 service->importance = 20;
435 service->servPerm.gIDCnt = -1;
436 service->servPerm.uID = 0;
437 unsigned int *caps = (unsigned int *)calloc(1, sizeof(unsigned int) * 1);
438 ASSERT_NE(nullptr, caps);
439 caps[0] = FULL_CAP;
440 service->servPerm.caps = caps;
441 service->servPerm.capsCnt = 1;
442 IsEnableSandbox();
443 EnterServiceSandbox(service);
444 int ret = ServiceExec(service, &service->pathArgs);
445 EXPECT_EQ(ret, 0);
446
447 const int invalidImportantValue = 20;
448 ret = SetImportantValue(service, "", invalidImportantValue, 1);
449 EXPECT_EQ(ret, -1);
450 ReleaseService(service);
451 }
452
453 HWTEST_F(ServiceUnitTest, TestServiceCGroup1, TestSize.Level1)
454 {
455 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/data/init_ut/test_service\"],"
456 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
457 "\"gid\":[\"system\"],\"caps\":[\"\"]}}";
458 cJSON* jobItem = cJSON_Parse(jsonStr);
459 ASSERT_NE(nullptr, jobItem);
460 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
461 ASSERT_NE(nullptr, serviceItem);
462 const char serviceName[] = "test_service1";
463 Service *service = AddService(serviceName);
464 ASSERT_NE(nullptr, service);
465 int ret = ParseOneService(serviceItem, service);
466 EXPECT_EQ(service->isCgroupEnabled, false);
467 EXPECT_EQ(ret, 0);
468
469 char path[PATH_MAX] = {};
470 ret = GetCgroupPath(service, path, sizeof(path));
471 ASSERT_EQ(ret, 0);
472 ReleaseService(service);
473 cJSON_Delete(jobItem);
474 }
475
476 HWTEST_F(ServiceUnitTest, TestServiceCGroup2, TestSize.Level1)
477 {
478 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/data/init_ut/test_service\"],"
479 "\"importance\":-20,\"uid\":\"system\",\"cgroup\":true,\"writepid\":[\"/dev/test_service\"],\"console\":1,"
480 "\"gid\":[\"system\"],\"caps\":[\"\"]}}";
481 cJSON* jobItem = cJSON_Parse(jsonStr);
482 ASSERT_NE(nullptr, jobItem);
483 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
484 ASSERT_NE(nullptr, serviceItem);
485 const char serviceName[] = "test_service1";
486 Service *service = AddService(serviceName);
487 ASSERT_NE(nullptr, service);
488 int ret = ParseOneService(serviceItem, service);
489 EXPECT_EQ(service->isCgroupEnabled, true);
490 EXPECT_EQ(ret, 0);
491
492 ret = ServiceStart(service, &service->pathArgs);
493 EXPECT_EQ(ret, 0);
494
495 char path[PATH_MAX] = {};
496 ret = GetCgroupPath(service, path, sizeof(path));
497 ASSERT_EQ(ret, 0);
498 ret = strcat_s(path, sizeof(path), "cgroup.procs");
499 EXPECT_EQ(ret, 0);
500
501 FILE *file = nullptr;
502 file = fopen(path, "r");
503 ASSERT_NE(file, nullptr);
504 pid_t pid = 0;
505 ret = -1;
506 while (fscanf_s(file, "%d\n", &pid) == 1 && pid > 0) {
507 if (pid == service->pid) {
508 ret = 0;
509 break;
510 }
511 }
512 fclose(file);
513 ret = ServiceStop(service);
514 EXPECT_EQ(ret, 0);
515 ReleaseService(service);
516 cJSON_Delete(jobItem);
517 }
518
519 HWTEST_F(ServiceUnitTest, TestKernelPermAllRight, TestSize.Level1)
520 {
521 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/system/bin/sa_main\"],"
522 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
523 "\"gid\":[\"system\"],\"caps\":[\"\"],\"kernel_permission\":{\"ohos.filesystem.dfs\":345,"
524 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}}";
525 const char *kernelPermStr = "{\"encaps\":{\"ohos.encaps.count\":2,\"ohos.filesystem.dfs\":345,"
526 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}";
527 cJSON* jobItem = cJSON_Parse(jsonStr);
528 ASSERT_NE(nullptr, jobItem);
529 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
530 ASSERT_NE(nullptr, serviceItem);
531 const char serviceName[] = "test_service1";
532 Service *service = AddService(serviceName);
533 ASSERT_NE(nullptr, service);
534 int ret = ParseOneService(serviceItem, service);
535 EXPECT_EQ(ret, 0);
536 ret = strcmp(service->kernelPerms, kernelPermStr);
537 EXPECT_EQ(ret, 0);
538
539 SERVICE_INFO_CTX context;
540 context.serviceName = service->name;
541 context.reserved = (const char*)service->pathArgs.argv[0];
542 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
543 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_SET_PERMS_BEFORE, (void *)(&context), NULL);
544
545 ReleaseService(service);
546 cJSON_Delete(jobItem);
547 }
548
549 HWTEST_F(ServiceUnitTest, TestKernelPermValueNotSupport, TestSize.Level1)
550 {
551 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/system/bin/sa_main\"],"
552 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
553 "\"gid\":[\"system\"],\"caps\":[\"\"],\"kernel_permission\":{\"ohos.filesystem.dfs\":[345,678],"
554 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}}";
555
556 cJSON* jobItem = cJSON_Parse(jsonStr);
557 ASSERT_NE(nullptr, jobItem);
558 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
559 ASSERT_NE(nullptr, serviceItem);
560 const char serviceName[] = "test_service1";
561 Service *service = AddService(serviceName);
562 ASSERT_NE(nullptr, service);
563 int ret = ParseOneService(serviceItem, service);
564 EXPECT_EQ(ret, 0);
565 EXPECT_TRUE(service->kernelPerms == nullptr);
566
567 SERVICE_INFO_CTX context;
568 context.serviceName = service->name;
569 context.reserved = (const char*)service->pathArgs.argv[0];
570 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
571 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_SET_PERMS_BEFORE, (void *)(&context), NULL);
572
573 ReleaseService(service);
574 cJSON_Delete(jobItem);
575 }
576
577 HWTEST_F(ServiceUnitTest, TestKernelPermNotSa, TestSize.Level1)
578 {
579 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/system/bin\"],"
580 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
581 "\"gid\":[\"system\"],\"caps\":[\"\"],\"kernel_permission\":{\"ohos.filesystem.dfs\":[345,678],"
582 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}}";
583
584 cJSON* jobItem = cJSON_Parse(jsonStr);
585 ASSERT_NE(nullptr, jobItem);
586 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
587 ASSERT_NE(nullptr, serviceItem);
588 const char serviceName[] = "test_service1";
589 Service *service = AddService(serviceName);
590 ASSERT_NE(nullptr, service);
591 int ret = ParseOneService(serviceItem, service);
592 EXPECT_EQ(ret, 0);
593 EXPECT_TRUE(service->kernelPerms == nullptr);
594
595 SERVICE_INFO_CTX context;
596 context.serviceName = service->name;
597 context.reserved = (const char*)service->pathArgs.argv[0];
598 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
599 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_SET_PERMS_BEFORE, (void *)(&context), NULL);
600
601 ReleaseService(service);
602 cJSON_Delete(jobItem);
603 }
604
605 HWTEST_F(ServiceUnitTest, TestKernelPermPermissionError, TestSize.Level1)
606 {
607 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/system/bin/sa_main\"],"
608 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
609 "\"gid\":[\"system\"],\"caps\":[\"\"],\"kernel_permission\":{\"ohos.filesystem.dfsxxx\":1,"
610 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}}";
611
612 cJSON* jobItem = cJSON_Parse(jsonStr);
613 ASSERT_NE(nullptr, jobItem);
614 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
615 ASSERT_NE(nullptr, serviceItem);
616 const char serviceName[] = "test_service1";
617 Service *service = AddService(serviceName);
618 ASSERT_NE(nullptr, service);
619 int ret = ParseOneService(serviceItem, service);
620 EXPECT_EQ(ret, 0);
621
622 SERVICE_INFO_CTX context;
623 context.serviceName = service->name;
624 context.reserved = (const char*)service->pathArgs.argv[0];
625 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
626 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_SET_PERMS_BEFORE, (void *)(&context), NULL);
627
628 ReleaseService(service);
629 cJSON_Delete(jobItem);
630 }
631
632 HWTEST_F(ServiceUnitTest, TestKernelPermServiceNameError, TestSize.Level1)
633 {
634 const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/system/bin/sa_main\"],"
635 "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
636 "\"gid\":[\"system\"],\"caps\":[\"\"],\"kernel_permission\":{\"ohos.filesystem.dfs\":1,"
637 "\"ohos.permission.kernel.ALLOW_WRITABLE_CODE_MEMORY\":true}}}";
638
639 cJSON* jobItem = cJSON_Parse(jsonStr);
640 ASSERT_NE(nullptr, jobItem);
641 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
642 ASSERT_NE(nullptr, serviceItem);
643 const char serviceName[] = "test_service1";
644 Service *service = AddService(serviceName);
645 ASSERT_NE(nullptr, service);
646 int ret = ParseOneService(serviceItem, service);
647 EXPECT_EQ(ret, 0);
648
649 SERVICE_INFO_CTX context;
650 context.serviceName = "wrongServiceName";
651 context.reserved = (const char*)service->pathArgs.argv[0];
652 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
653 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_SET_PERMS_BEFORE, (void *)(&context), NULL);
654
655 ReleaseService(service);
656 cJSON_Delete(jobItem);
657 }
658 } // namespace init_ut
659