1 /*
2  * Copyright (c) 2022-2024 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 "unit_test.h"
17 #include <string>
18 #include <thread>
19 #include <selinux/selinux.h>
20 #include "selinux_error.h"
21 #include "test_common.h"
22 
23 namespace OHOS {
24 namespace Security {
25 namespace SelinuxUnitTest {
26 using namespace testing::ext;
27 using namespace Selinux;
28 const static int SLEEP_SECOND = 2;
29 const static std::string BASE_PATH = "/data/app/el1/0/base/";
30 const static std::string ACCOUNT_PATH = "/data/accounts/account_0/appdata/";
31 const static std::string TEST_HAP_PATH = BASE_PATH + "com.ohos.selftest/";
32 const static std::string TEST_ACCOUNT_PATH = ACCOUNT_PATH + "com.ohos.selftest/";
33 const static std::string TEST_ACCOUNT_SUB_PATH_1_FILE_1 = TEST_ACCOUNT_PATH + "file1.txt";
34 
35 const static std::string TEST_SUB_PATH_1 = TEST_HAP_PATH + "subpath1/";
36 const static std::string TEST_SUB_PATH_2 = TEST_HAP_PATH + "subpath2/";
37 const static std::string TEST_SUB_PATH_3 = TEST_HAP_PATH + "subpath3/";
38 const static std::string TEST_SUB_PATH_4 = TEST_HAP_PATH + "subpath4/";
39 
40 const static std::string TEST_SUB_PATH_1_FILE_1 = TEST_SUB_PATH_1 + "file1.txt";
41 const static std::string TEST_SUB_PATH_1_FILE_2 = TEST_SUB_PATH_1 + "file2.txt";
42 const static std::string TEST_SUB_PATH_2_FILE_1 = TEST_SUB_PATH_2 + "file1.txt";
43 const static std::string TEST_SUB_PATH_2_FILE_2 = TEST_SUB_PATH_2 + "file2.txt";
44 const static std::string TEST_SUB_PATH_3_FILE_1 = TEST_SUB_PATH_3 + "file1.txt";
45 const static std::string TEST_SUB_PATH_3_FILE_2 = TEST_SUB_PATH_3 + "file2.txt";
46 const static std::string TEST_SUB_PATH_4_FILE_1 = TEST_SUB_PATH_4 + "file1.txt";
47 const static std::string TEST_SUB_PATH_4_FILE_2 = TEST_SUB_PATH_4 + "file2.txt";
48 
49 const static std::string TEST_UNSIMPLIFY_PATH = TEST_SUB_PATH_3 + "//../subpath4/";
50 const static std::string TEST_UNSIMPLIFY_FILE = TEST_SUB_PATH_4 + "//../subpath3/file1.txt";
51 
52 const static std::string INVALID_PATH = "/data/data/path";
53 const static std::string EMPTY_STRING = "";
54 const static std::string SYSTEM_CORE_APL = "system_core";
55 const static std::string NORMAL_APL = "normal";
56 const static std::string INVALID_APL = "invalid_apl";
57 
58 const static std::string TEST_HAP_BUNDLE_NAME = "com.hap.selftest";
59 const static std::string TEST_HAP_BUNDLE_NAME_WITH_NO_CONTEXTS = "com.ohos.test";
60 const static std::string TEST_HAP_BUNDLE_NAME_FOR_INVALID_CONTEXTS = "com.hap.selftest_invalid";
61 
62 const static std::string TEST_HAP_DATA_FILE_LABEL = "u:object_r:selftest_hap_data_file:s0";
63 
64 const static std::string TEST_HAP_DOMAIN = "u:r:selftest:s0";
65 const static std::string TEST_HAP_DATA_TYPE = "u:r:selftest_hap_data_file:s0";
66 const static std::string DLP_HAP_DOMAIN = "u:r:dlp_sandbox_hap:s0";
67 const static std::string DLP_HAP_DATA_TYPE = "u:r:dlp_sandbox_hap_data_file:s0";
68 const static std::string TEST_NORMAL_DOMAIN = "u:r:normal_hap:s0";
69 const static std::string TEST_NOMAL_TYPE = "u:r:normal_hap_data_file:s0";
70 
71 const static std::string SEHAP_CONTEXTS_FILE = "/data/test/sehap_contexts";
72 
73 static HapFileInfo g_hapFileInfoWithoutFlags = {
74     .pathNameOrig = {TEST_SUB_PATH_1},
75     .apl = SYSTEM_CORE_APL,
76     .packageName = TEST_HAP_BUNDLE_NAME,
77     .flags = 0,
78     .hapFlags = 1,
79 };
80 
81 static HapFileInfo g_hapFileInfoWithFlags = {
82     .pathNameOrig = {TEST_HAP_PATH},
83     .apl = SYSTEM_CORE_APL,
84     .packageName = TEST_HAP_BUNDLE_NAME,
85     .flags = 1,
86     .hapFlags = 1,
87 };
88 
89 static HapFileInfo g_hapFileInfoWithAplEmpty = {
90     .pathNameOrig = {TEST_HAP_PATH},
91     .apl = "",
92     .packageName = TEST_HAP_BUNDLE_NAME,
93     .flags = 0,
94     .hapFlags = 1,
95 };
96 
97 static HapFileInfo g_hapFileInfoWithPathEmpty = {
98     .pathNameOrig = {},
99     .apl = SYSTEM_CORE_APL,
100     .packageName = TEST_HAP_BUNDLE_NAME,
101     .flags = 0,
102     .hapFlags = 1,
103 };
104 
105 static HapFileInfo g_hapFileInfoWithAplInvalid = {
106     .pathNameOrig = {TEST_HAP_PATH},
107     .apl = INVALID_APL,
108     .packageName = TEST_HAP_BUNDLE_NAME,
109     .flags = 0,
110     .hapFlags = 1,
111 };
112 
113 static HapFileInfo g_hapFileInfoWithCannotFindContexts = {
114     .pathNameOrig = {TEST_HAP_PATH},
115     .apl = SYSTEM_CORE_APL,
116     .packageName = TEST_HAP_BUNDLE_NAME_WITH_NO_CONTEXTS,
117     .flags = 0,
118     .hapFlags = 1,
119 };
120 
121 static HapFileInfo g_hapFileInfoForRepeatLabel = {
122     .pathNameOrig = {TEST_SUB_PATH_1},
123     .apl = SYSTEM_CORE_APL,
124     .packageName = TEST_HAP_BUNDLE_NAME,
125     .flags = 0,
126     .hapFlags = 1,
127 };
128 
129 static HapFileInfo g_hapFileInfoWithPreinstallHap = {
130     .pathNameOrig = {TEST_SUB_PATH_1},
131     .apl = SYSTEM_CORE_APL,
132     .packageName = TEST_HAP_BUNDLE_NAME,
133     .flags = 0,
134     .hapFlags = 0,
135 };
136 
137 static HapFileInfo g_hapFileInfoWithInvalidPath = {
138     .pathNameOrig = {TEST_SUB_PATH_1, INVALID_PATH},
139     .apl = SYSTEM_CORE_APL,
140     .packageName = TEST_HAP_BUNDLE_NAME,
141     .flags = 0,
142     .hapFlags = 1,
143 };
144 
145 static HapFileInfo g_hapFileInfoForInvalidContexts = {
146     .pathNameOrig = {TEST_HAP_PATH},
147     .apl = NORMAL_APL,
148     .packageName = TEST_HAP_BUNDLE_NAME_FOR_INVALID_CONTEXTS,
149     .flags = 0,
150     .hapFlags = 1,
151 };
152 
153 static HapDomainInfo g_hapDomainInfoWithAplEmpty {
154     .apl = "",
155     .packageName = TEST_HAP_BUNDLE_NAME,
156     .hapFlags = 1,
157 };
158 
159 static HapDomainInfo g_hapDomainInfoWithInvalidApl {
160     .apl = INVALID_APL,
161     .packageName = TEST_HAP_BUNDLE_NAME,
162     .hapFlags = 1,
163 };
164 
165 static HapDomainInfo g_hapDomainInfo {
166     .apl = SYSTEM_CORE_APL,
167     .packageName = TEST_HAP_BUNDLE_NAME,
168     .hapFlags = 1,
169 };
170 
171 static HapDomainInfo g_hapDomainInfoForInvalidContexts {
172     .apl = NORMAL_APL,
173     .packageName = TEST_HAP_BUNDLE_NAME_FOR_INVALID_CONTEXTS,
174     .hapFlags = 1,
175 };
176 
GenerateTestFile()177 static void GenerateTestFile()
178 {
179     std::vector<std::string> sehapInfo = {
180         "apl=system_core domain=system_core_hap type=system_core_hap_data_file",
181         "apl=system_basic domain=system_basic_hap type=system_basic_hap_data_file",
182         "apl=normal domain=normal_hap type=normal_hap_data_file",
183         "apl=normal debuggable=true domain=debug_hap type=debug_hap_data_file",
184         "apl=system_core name=com.ohos.test domain= type=",
185         "apl=system_core domain=selftest type=selftest_hap_data_file",
186         "apl=system_core name=com.hap.selftest domain=selftest type=selftest_hap_data_file",
187         "apl=normal name=com.hap.selftest domain=selftest type=normal_hap_data_file",
188         "apl=normal name=com.hap.selftest_invalid domain=selftest_invalid type=selftest_invalid_hap_data_file",
189         "apl=normal extra=invalid_extra domain=dlp_sandbox_hap type=dlp_sandbox_hap_data_file",
190         "apl=normal extra=dlp_sandbox domain=dlp_sandbox_hap type=dlp_sandbox_hap_data_file"};
191     ASSERT_EQ(true, WriteFile(SEHAP_CONTEXTS_FILE, sehapInfo));
192 }
193 
RemoveTestFile()194 static void RemoveTestFile()
195 {
196     unlink(SEHAP_CONTEXTS_FILE.c_str());
197 }
198 
SetUpTestCase()199 void SelinuxUnitTest::SetUpTestCase()
200 {
201     // make test case clean
202     GenerateTestFile();
203 }
204 
TearDownTestCase()205 void SelinuxUnitTest::TearDownTestCase()
206 {
207     RemoveTestFile();
208 }
209 
SetUp()210 void SelinuxUnitTest::SetUp() {}
211 
TearDown()212 void SelinuxUnitTest::TearDown() {}
213 
CreateDataFile() const214 void SelinuxUnitTest::CreateDataFile() const {}
215 
216 /**
217  * @tc.name: HapFileRestorecon001
218  * @tc.desc: test HapFileRestorecon input para invalid.
219  * @tc.type: FUNC
220  * @tc.require: AR000GJSDQ
221  */
222 HWTEST_F(SelinuxUnitTest, HapFileRestorecon001, TestSize.Level1)
223 {
224     ASSERT_EQ(true, CreateDirectory(TEST_HAP_PATH));
225 
226     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(g_hapFileInfoWithAplEmpty));
227 
228     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(g_hapFileInfoWithPathEmpty));
229 
230     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(g_hapFileInfoWithAplInvalid));
231 
232     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
233 }
234 
235 /**
236  * @tc.name: HapFileRestorecon002
237  * @tc.desc: test HapFileRestorecon normal branch without restorecon.
238  * @tc.type: FUNC
239  * @tc.require:AR000GJSDQ
240  */
241 HWTEST_F(SelinuxUnitTest, HapFileRestorecon002, TestSize.Level1)
242 {
243     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1)); // this file should not be restorecon
244 
245     char *secontextOld = nullptr;
246     getfilecon(TEST_SUB_PATH_1_FILE_1.c_str(), &secontextOld);
247 
248     int ret = test.HapFileRestorecon(g_hapFileInfoWithoutFlags);
249     ASSERT_EQ(SELINUX_SUCC, ret);
250 
251     char *secontextNew = nullptr;
252     getfilecon(TEST_SUB_PATH_1.c_str(), &secontextNew);
253     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontextNew);
254     freecon(secontextNew);
255     secontextNew = nullptr;
256 
257     getfilecon(TEST_SUB_PATH_1_FILE_1.c_str(), &secontextNew);
258     EXPECT_STREQ(secontextOld, secontextNew);
259     freecon(secontextNew);
260     secontextNew = nullptr;
261 
262     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
263 }
264 
265 /**
266  * @tc.name: HapFileRestorecon003
267  * @tc.desc: test HapFileRestorecon normal branch with restorecon.
268  * @tc.type: FUNC
269  * @tc.require:AR000GJSDQ
270  */
271 HWTEST_F(SelinuxUnitTest, HapFileRestorecon003, TestSize.Level1)
272 {
273     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
274     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_2));
275     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_2_FILE_1));
276     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_2_FILE_2));
277 
278     int ret = test.HapFileRestorecon(g_hapFileInfoWithFlags);
279     ASSERT_EQ(SELINUX_SUCC, ret);
280 
281     char *secontext = nullptr;
282     getfilecon(TEST_SUB_PATH_1.c_str(), &secontext);
283     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
284     freecon(secontext);
285     secontext = nullptr;
286 
287     getfilecon(TEST_SUB_PATH_2.c_str(), &secontext);
288     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
289     freecon(secontext);
290     secontext = nullptr;
291 
292     getfilecon(TEST_SUB_PATH_1_FILE_1.c_str(), &secontext);
293     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
294     freecon(secontext);
295     secontext = nullptr;
296 
297     getfilecon(TEST_SUB_PATH_1_FILE_2.c_str(), &secontext);
298     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
299     freecon(secontext);
300     secontext = nullptr;
301 
302     getfilecon(TEST_SUB_PATH_2_FILE_1.c_str(), &secontext);
303     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
304     freecon(secontext);
305     secontext = nullptr;
306 
307     getfilecon(TEST_SUB_PATH_2_FILE_2.c_str(), &secontext);
308     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
309     freecon(secontext);
310     secontext = nullptr;
311 
312     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
313 }
314 
315 /**
316  * @tc.name: HapFileRestorecon004
317  * @tc.desc: test HapFileRestorecon with single path input para invalid.
318  * @tc.type: FUNC
319  * @tc.require: AR000GJSDQ
320  */
321 HWTEST_F(SelinuxUnitTest, HapFileRestorecon004, TestSize.Level1)
322 {
323     ASSERT_EQ(true, CreateDirectory(TEST_HAP_PATH));
324 
325     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(TEST_HAP_PATH, g_hapFileInfoWithAplEmpty));
326 
327     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(EMPTY_STRING, g_hapFileInfoWithPathEmpty));
328 
329     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapFileRestorecon(TEST_HAP_PATH, g_hapFileInfoWithAplInvalid));
330 
331     EXPECT_EQ(-SELINUX_CHECK_CONTEXT_ERROR, test.HapFileRestorecon(TEST_HAP_PATH, g_hapFileInfoForInvalidContexts));
332 
333     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
334 }
335 
336 /**
337  * @tc.name: HapFileRestorecon005
338  * @tc.desc: test HapFileRestorecon with no recurce.
339  * @tc.type: FUNC
340  * @tc.require: AR000GJSDQ
341  */
342 HWTEST_F(SelinuxUnitTest, HapFileRestorecon005, TestSize.Level1)
343 {
344     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
345 
346     EXPECT_EQ(SELINUX_SUCC, test.HapFileRestorecon(TEST_HAP_PATH, g_hapFileInfoWithoutFlags));
347 
348     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
349 }
350 
351 /**
352  * @tc.name: HapFileRestorecon006
353  * @tc.desc: test HapFileRestorecon checkPath fail.
354  * @tc.type: FUNC
355  * @tc.require: AR000GJSDQ
356  */
357 HWTEST_F(SelinuxUnitTest, HapFileRestorecon006, TestSize.Level1)
358 {
359     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
360 
361     EXPECT_EQ(-SELINUX_PATH_INVAILD, test.HapFileRestorecon(INVALID_PATH, g_hapFileInfoWithoutFlags));
362 
363     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
364 }
365 
366 /**
367  * @tc.name: HapFileRestorecon007
368  * @tc.desc: test HapFileRestorecon with accounts path.
369  * @tc.type: FUNC
370  * @tc.require: AR000GJSDQ
371  */
372 HWTEST_F(SelinuxUnitTest, HapFileRestorecon007, TestSize.Level1)
373 {
374     ASSERT_EQ(true, CreateFile(TEST_ACCOUNT_SUB_PATH_1_FILE_1));
375 
376     EXPECT_EQ(SELINUX_SUCC, test.HapFileRestorecon(TEST_ACCOUNT_SUB_PATH_1_FILE_1, g_hapFileInfoWithoutFlags));
377 
378     ASSERT_EQ(true, RemoveDirectory(ACCOUNT_PATH));
379 }
380 
381 /**
382  * @tc.name: HapFileRestorecon008
383  * @tc.desc: test HapFileRestorecon type is empty.
384  * @tc.type: FUNC
385  * @tc.require: AR000GJSDQ
386  */
387 HWTEST_F(SelinuxUnitTest, HapFileRestorecon008, TestSize.Level1)
388 {
389     ASSERT_EQ(true, CreateDirectory(TEST_HAP_PATH));
390 
391     EXPECT_EQ(-SELINUX_KEY_NOT_FOUND, test.HapFileRestorecon(TEST_HAP_PATH, g_hapFileInfoWithCannotFindContexts));
392 
393     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
394 }
395 
CompareContexts(const std::string & path,const std::string & label)396 static bool CompareContexts(const std::string &path, const std::string &label)
397 {
398     char *secontext = nullptr;
399     getfilecon(path.c_str(), &secontext);
400     bool res = (strcmp(label.c_str(), secontext) == 0);
401     freecon(secontext);
402     secontext = nullptr;
403     return res;
404 }
405 
406 /**
407  * @tc.name: HapFileRestorecon009
408  * @tc.desc: test HapFileRestorecon input multi path/file no recurse.
409  * @tc.type: FUNC
410  * @tc.require:AR000GJSDQ
411  */
412 HWTEST_F(SelinuxUnitTest, HapFileRestorecon009, TestSize.Level1)
413 {
414     ASSERT_EQ(true, CreateDirectory(TEST_SUB_PATH_4));
415     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
416     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_2));
417     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_2_FILE_1)); // should not be restorecon
418     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_3_FILE_1));
419 
420     char *secontextOld = nullptr;
421     getfilecon(TEST_SUB_PATH_2_FILE_1.c_str(), &secontextOld);
422 
423     HapFileInfo hapFileInfo = {
424         .pathNameOrig = {TEST_SUB_PATH_1, TEST_SUB_PATH_2, TEST_SUB_PATH_1_FILE_1, TEST_SUB_PATH_1_FILE_2,
425                          TEST_UNSIMPLIFY_FILE, TEST_UNSIMPLIFY_PATH},
426         .apl = SYSTEM_CORE_APL,
427         .packageName = TEST_HAP_BUNDLE_NAME,
428         .flags = 0,
429         .hapFlags = 1,
430     };
431 
432     ASSERT_EQ(SELINUX_SUCC, test.HapFileRestorecon(hapFileInfo));
433     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1, TEST_HAP_DATA_FILE_LABEL));
434     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_2, TEST_HAP_DATA_FILE_LABEL));
435     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1_FILE_1, TEST_HAP_DATA_FILE_LABEL));
436     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1_FILE_2, TEST_HAP_DATA_FILE_LABEL));
437     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_3_FILE_1, TEST_HAP_DATA_FILE_LABEL));
438     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_4, TEST_HAP_DATA_FILE_LABEL));
439 
440     char *secontext = nullptr;
441     getfilecon(TEST_SUB_PATH_2_FILE_1.c_str(), &secontext); // this file should not be restorecon
442     EXPECT_STREQ(secontextOld, secontext);
443     freecon(secontext);
444     freecon(secontextOld);
445     secontext = nullptr;
446     secontextOld = nullptr;
447 
448     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
449 }
450 
451 /**
452  * @tc.name: HapFileRestorecon010
453  * @tc.desc: test HapFileRestorecon input multi path/file recurse.
454  * @tc.type: FUNC
455  * @tc.require:AR000GJSDQ
456  */
457 HWTEST_F(SelinuxUnitTest, HapFileRestorecon010, TestSize.Level1)
458 {
459     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
460     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_2));
461     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_2_FILE_1));
462     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_2_FILE_2));
463     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_3_FILE_1));
464     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_3_FILE_2)); // this file should not be restorecon
465     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_4_FILE_1));
466     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_4_FILE_2));
467 
468     char *secontextOld = nullptr;
469     getfilecon(TEST_SUB_PATH_3_FILE_2.c_str(), &secontextOld);
470 
471     HapFileInfo hapFileInfo = {
472         .pathNameOrig = { TEST_SUB_PATH_1, TEST_SUB_PATH_2, TEST_UNSIMPLIFY_FILE, TEST_UNSIMPLIFY_PATH },
473         .apl = SYSTEM_CORE_APL,
474         .packageName = TEST_HAP_BUNDLE_NAME,
475         .flags = 1,
476         .hapFlags = 1,
477     };
478     ASSERT_EQ(SELINUX_SUCC, test.HapFileRestorecon(hapFileInfo));
479     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1, TEST_HAP_DATA_FILE_LABEL));
480     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_2, TEST_HAP_DATA_FILE_LABEL));
481     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_4, TEST_HAP_DATA_FILE_LABEL));
482     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1_FILE_1, TEST_HAP_DATA_FILE_LABEL));
483     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_1_FILE_2, TEST_HAP_DATA_FILE_LABEL));
484     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_2_FILE_1, TEST_HAP_DATA_FILE_LABEL));
485     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_2_FILE_2, TEST_HAP_DATA_FILE_LABEL));
486     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_4_FILE_1, TEST_HAP_DATA_FILE_LABEL));
487     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_4_FILE_2, TEST_HAP_DATA_FILE_LABEL));
488     EXPECT_TRUE(CompareContexts(TEST_SUB_PATH_3_FILE_1, TEST_HAP_DATA_FILE_LABEL));
489 
490     char *secontext = nullptr;
491     getfilecon(TEST_SUB_PATH_3_FILE_2.c_str(), &secontext);
492     EXPECT_STREQ(secontextOld, secontext);
493     freecon(secontext);
494     freecon(secontextOld);
495     secontext = nullptr;
496     secontextOld = nullptr;
497 
498     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
499 }
500 
501 /**
502  * @tc.name: HapFileRestorecon011
503  * @tc.desc: test HapFileRestorecon repeat label.
504  * @tc.type: FUNC
505  * @tc.require:AR000GJSDQ
506  */
507 HWTEST_F(SelinuxUnitTest, HapFileRestorecon011, TestSize.Level1)
508 {
509     ASSERT_EQ(true, CreateDirectory(TEST_SUB_PATH_1));
510     int ret = test.HapFileRestorecon(g_hapFileInfoForRepeatLabel);
511     ASSERT_EQ(SELINUX_SUCC, ret);
512 
513     char *secontext = nullptr;
514     getfilecon(TEST_SUB_PATH_1.c_str(), &secontext);
515     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontext);
516     freecon(secontext);
517     secontext = nullptr;
518 
519     char *secontextOld = nullptr;
520     getfilecon(TEST_SUB_PATH_1.c_str(), &secontextOld);
521 
522     ret = test.HapFileRestorecon(g_hapFileInfoForRepeatLabel); // double restorcon
523     ASSERT_EQ(SELINUX_SUCC, ret);
524 
525     getfilecon(TEST_SUB_PATH_1.c_str(), &secontext);
526     EXPECT_STREQ(secontextOld, secontext);
527     freecon(secontext);
528     freecon(secontextOld);
529     secontext = nullptr;
530     secontextOld = nullptr;
531 
532     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
533 }
534 
535 /**
536  * @tc.name: HapFileRestorecon012
537  * @tc.desc: test HapFileRestorecon normal branch with preinstalled app.
538  * @tc.type: FUNC
539  * @tc.require:AR000GJSDQ
540  */
541 HWTEST_F(SelinuxUnitTest, HapFileRestorecon012, TestSize.Level1)
542 {
543     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
544 
545     int ret = test.HapFileRestorecon(g_hapFileInfoWithPreinstallHap);
546     ASSERT_EQ(SELINUX_SUCC, ret);
547 
548     char *secontextNew = nullptr;
549     getfilecon(TEST_SUB_PATH_1.c_str(), &secontextNew);
550     EXPECT_STREQ(TEST_HAP_DATA_FILE_LABEL.c_str(), secontextNew);
551     freecon(secontextNew);
552     secontextNew = nullptr;
553 
554     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
555 }
556 
557 /**
558  * @tc.name: HapFileRestorecon013
559  * @tc.desc: test HapFileRestorecon with multi path failed.
560  * @tc.type: FUNC
561  * @tc.require:
562  */
563 HWTEST_F(SelinuxUnitTest, HapFileRestorecon013, TestSize.Level1)
564 {
565     ASSERT_EQ(true, CreateFile(TEST_SUB_PATH_1_FILE_1));
566     ASSERT_EQ(true, CreateFile(INVALID_PATH));
567 
568     ASSERT_EQ(-SELINUX_RESTORECON_ERROR, test.HapFileRestorecon(g_hapFileInfoWithInvalidPath));
569 
570     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
571     ASSERT_EQ(true, RemoveDirectory(INVALID_PATH));
572 }
573 
574 /**
575  * @tc.name: HapFileRecurseRestorecon001
576  * @tc.desc: test HapFileRecurseRestorecon realPath is nullptr.
577  * @tc.type: FUNC
578  * @tc.require: AR000GJSDQ
579  */
580 HWTEST_F(SelinuxUnitTest, HapFileRecurseRestorecon001, TestSize.Level1)
581 {
582     int ret = test.HapFileRecurseRestorecon(nullptr, g_hapFileInfoWithCannotFindContexts);
583     ASSERT_EQ(-SELINUX_FTS_OPEN_ERROR, ret);
584 }
585 
586 /**
587  * @tc.name: RestoreconSb001
588  * @tc.desc: test RestoreconSb with repeat label.
589  * @tc.type: FUNC
590  * @tc.require: AR000GJSDQ
591  */
592 HWTEST_F(SelinuxUnitTest, RestoreconSb001, TestSize.Level1)
593 {
594     ASSERT_EQ(true, CreateDirectory(TEST_SUB_PATH_1));
595 
596     ASSERT_EQ(SELINUX_SUCC, test.RestoreconSb(TEST_SUB_PATH_1, g_hapFileInfoForRepeatLabel));
597     char *secontextOld = nullptr;
598     getfilecon(TEST_SUB_PATH_1.c_str(), &secontextOld);
599     EXPECT_STREQ(secontextOld, TEST_HAP_DATA_FILE_LABEL.c_str());
600     freecon(secontextOld);
601 
602     ASSERT_EQ(SELINUX_SUCC, test.RestoreconSb(TEST_SUB_PATH_1, g_hapFileInfoForRepeatLabel)); // double restorcon
603     char *secontextNew = nullptr;
604     getfilecon(TEST_SUB_PATH_1.c_str(), &secontextNew);
605     EXPECT_STREQ(secontextNew, TEST_HAP_DATA_FILE_LABEL.c_str());
606     freecon(secontextNew);
607 
608     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
609 }
610 
611 /**
612  * @tc.name: HapDomainSetcontext001
613  * @tc.desc: test HapDomainSetcontext input para invalid.
614  * @tc.type: FUNC
615  * @tc.require: issueI6JV34
616  */
617 HWTEST_F(SelinuxUnitTest, HapDomainSetcontext001, TestSize.Level1)
618 {
619     ASSERT_EQ(true, CreateDirectory(TEST_HAP_PATH));
620 
621     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapDomainSetcontext(g_hapDomainInfoWithAplEmpty));
622     EXPECT_EQ(-SELINUX_ARG_INVALID, test.HapDomainSetcontext(g_hapDomainInfoWithInvalidApl));
623 
624     ASSERT_EQ(true, RemoveDirectory(TEST_HAP_PATH));
625 }
626 
627 /**
628  * @tc.name: HapDomainSetcontext002
629  * @tc.desc: test HapDomainSetcontext must succeed
630  * @tc.type: FUNC
631  * @tc.require: issueI6JV34
632  */
633 HWTEST_F(SelinuxUnitTest, HapDomainSetcontext002, TestSize.Level1)
634 {
635     pid_t pid = fork();
636     ASSERT_TRUE(pid >= 0);
637     if (pid == 0) {
638         EXPECT_EQ(SELINUX_SUCC, test.HapDomainSetcontext(g_hapDomainInfo));
639         usleep(200000); // sleep 200ms
640         exit(0);
641     } else {
642         usleep(150000); // sleep 150ms
643         char *con = nullptr;
644         ASSERT_EQ(0, getpidcon(pid, &con));
645         EXPECT_STREQ(con, TEST_HAP_DOMAIN.c_str());
646         freecon(con);
647     }
648 }
649 
650 /**
651  * @tc.name: HapDomainSetcontext003
652  * @tc.desc: test HapDomainSetcontext setcon normal_hap.
653  * @tc.type: FUNC
654  * @tc.require: issueI6JV34
655  */
656 HWTEST_F(SelinuxUnitTest, HapDomainSetcontext003, TestSize.Level1)
657 {
658     pid_t pid = fork();
659     ASSERT_TRUE(pid >= 0);
660     if (pid == 0) {
661         EXPECT_EQ(-SELINUX_CHECK_CONTEXT_ERROR, test.HapDomainSetcontext(g_hapDomainInfoForInvalidContexts));
662         exit(0);
663     }
664 }
665 
666 /**
667  * @tc.name: HapContextsLookup001
668  * @tc.desc: test HapContextsLookup must succeed
669  * @tc.type: FUNC
670  * @tc.require: issueI9MCSP
671  */
672 HWTEST_F(SelinuxUnitTest, HapContextsLookup001, TestSize.Level1)
673 {
674     char *oldTypeContext = nullptr;
675     ASSERT_EQ(SELINUX_SUCC, getcon(&oldTypeContext));
676     context_t con = context_new(oldTypeContext);
677 
678     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(true, SYSTEM_CORE_APL, EMPTY_STRING, con, 0));
679     EXPECT_STREQ(context_str(con), TEST_HAP_DOMAIN.c_str());
680 
681     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(true, NORMAL_APL, EMPTY_STRING, con, 0));
682     EXPECT_STREQ(context_str(con), TEST_NORMAL_DOMAIN.c_str());
683 
684     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(
685         true, NORMAL_APL, TEST_HAP_BUNDLE_NAME, con, SELINUX_HAP_RESTORECON_PREINSTALLED_APP));
686     EXPECT_STREQ(context_str(con), TEST_HAP_DOMAIN.c_str());
687 
688     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(true, NORMAL_APL, EMPTY_STRING, con, SELINUX_HAP_DLP));
689     EXPECT_STREQ(context_str(con), DLP_HAP_DOMAIN.c_str());
690 
691     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(
692         true, NORMAL_APL, EMPTY_STRING, con, SELINUX_HAP_DLP | SELINUX_HAP_DEBUGGABLE));
693     EXPECT_STREQ(context_str(con), DLP_HAP_DOMAIN.c_str());
694 
695     freecon(oldTypeContext);
696     context_free(con);
697 }
698 
699 /**
700  * @tc.name: HapContextsLookup002
701  * @tc.desc: test HapContextsLookup must succeed
702  * @tc.type: FUNC
703  * @tc.require: issueI9MCSP
704  */
705 HWTEST_F(SelinuxUnitTest, HapContextsLookup002, TestSize.Level1)
706 {
707     char *oldTypeContext = nullptr;
708     ASSERT_EQ(SELINUX_SUCC, getcon(&oldTypeContext));
709     context_t con = context_new(oldTypeContext);
710 
711     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(false, SYSTEM_CORE_APL, EMPTY_STRING, con, 0));
712     EXPECT_STREQ(context_str(con), TEST_HAP_DATA_TYPE.c_str());
713 
714     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(false, NORMAL_APL, EMPTY_STRING, con, 0));
715     EXPECT_STREQ(context_str(con), TEST_NOMAL_TYPE.c_str());
716 
717     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(
718         false, NORMAL_APL, TEST_HAP_BUNDLE_NAME, con, SELINUX_HAP_RESTORECON_PREINSTALLED_APP));
719     EXPECT_STREQ(context_str(con), TEST_NOMAL_TYPE.c_str());
720 
721     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(false, NORMAL_APL, EMPTY_STRING, con, SELINUX_HAP_DLP));
722     EXPECT_STREQ(context_str(con), DLP_HAP_DATA_TYPE.c_str());
723 
724     EXPECT_EQ(SELINUX_SUCC, test.HapContextsLookup(
725         false, NORMAL_APL, EMPTY_STRING, con, SELINUX_HAP_DLP | SELINUX_HAP_DEBUGGABLE));
726     EXPECT_STREQ(context_str(con), DLP_HAP_DATA_TYPE.c_str());
727 
728 
729     freecon(oldTypeContext);
730     context_free(con);
731 }
732 
733 /**
734  * @tc.name: TypeSet001
735  * @tc.desc: test TypeSet type is empty.
736  * @tc.type: FUNC
737  * @tc.require: issueI6JV34
738  */
739 HWTEST_F(SelinuxUnitTest, TypeSet001, TestSize.Level1)
740 {
741     ASSERT_EQ(-SELINUX_ARG_INVALID, test.TypeSet(EMPTY_STRING, nullptr));
742 }
743 } // namespace SelinuxUnitTest
744 } // namespace Security
745 } // namespace OHOS
746