• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 <asm/unistd.h>
17 #include <cstdint>
18 #include <cstdlib>
19 #include <gtest/gtest.h>
20 #include <fcntl.h>
21 #include <iostream>
22 #include <cstdio>
23 #include <cstring>
24 #include <string>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/utsname.h>
28 #include <sys/ioctl.h>
29 #include <linux/fs.h>
30 #include <linux/fsverity.h>
31 #include <linux/types.h>
32 #include <linux/ioctl.h>
33 
34 #include "byte_buffer.h"
35 #include "directory_ex.h"
36 #include "enable_key_utils.h"
37 #include "log.h"
38 #include "xpm_common.h"
39 #include "code_sign_attr_utils.h"
40 #include "selinux/selinux.h"
41 
42 using namespace testing::ext;
43 
44 namespace OHOS {
45 namespace Security {
46 namespace CodeSign {
47 constexpr uint32_t HASH_PAGE_SIZE = 4096;
48 constexpr uint32_t BUFFER_LENGTH = 4096;
49 
50 const std::string TEST_FILES_DIR = "/data/test/tmp/";
51 const std::string TEST_FILES_LIST[] = {
52     "file_4K/file_4K",
53     "file_4K_greater/file_4K_greater",
54     "file_4K_less/file_4K_less",
55     "file_4M/file_4M",
56     "file_4M_greater/file_4M_greater",
57     "file_4M_less/file_4M_less"
58 };
59 const int TEST_FILE_NUM = sizeof(TEST_FILES_LIST) / sizeof(TEST_FILES_LIST[0]);
60 const std::string TEST_DEFAULT_FILE = TEST_FILES_DIR + "file_4M_greater/file_4M_greater";
61 const std::string FAKE_STRING = "AAAAA";
62 
63 const std::string TEST_SUBJECT = "OpenHarmony Application Release";
64 const std::string TEST_ISSUER = "OpenHarmony Application CA";
65 
66 const std::string DROP_CACHE_PROC_PATH = "/proc/sys/vm/drop_caches";
67 const std::string DROP_ALL_CACHE_LEVEL = "3";
68 
69 static bool g_isXpmOn;
70 static bool g_isKernelLinux = false;
71 
72 class EnableVerityTest : public testing::Test {
73 public:
EnableVerityTest()74     EnableVerityTest() {};
~EnableVerityTest()75     virtual ~EnableVerityTest() {};
SetUpTestCase()76     static void SetUpTestCase()
77     {
78         EXPECT_EQ(EnableTestKey(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str()), 0);
79         EXPECT_EQ(SetXpmOwnerId(PROCESS_OWNERID_COMPAT, NULL), 0);
80         g_isXpmOn = AllocXpmRegion();
81         SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE);
82         SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE);
83         if (g_isXpmOn) {
84             std::string realPath;
85             g_isXpmOn = OHOS::PathToRealPath(XPM_DEBUG_FS_MODE_PATH, realPath);
86         }
87         struct utsname uts;
88         if (uname(&uts) == 0 && strcmp(uts.sysname, "Linux") == 0) {
89             g_isKernelLinux = true;
90         }
91     };
TearDownTestCase()92     static void TearDownTestCase()
93     {
94         SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE);
95     };
SetUp()96     void SetUp() {};
TearDown()97     void TearDown() {};
98 };
99 
100 class SELinuxContextSetter {
101 public:
SELinuxContextSetter()102     SELinuxContextSetter()
103     {
104         getcon(&curContext);
105         setcon(BLOCKED_LABEL.c_str());
106     }
107 
~SELinuxContextSetter()108     ~SELinuxContextSetter()
109     {
110         setcon(curContext);
111         freecon(curContext);
112     }
113 
114 private:
115     const std::string BLOCKED_LABEL = "u:r:key_enable:s0";
116     char *curContext;
117 };
118 
GetFileSize(const std::string & path)119 static size_t GetFileSize(const std::string &path)
120 {
121     FILE *file = fopen(path.c_str(), "rb");
122     if (file == nullptr) {
123         return false;
124     }
125     if (fseek(file, 0L, SEEK_END) != 0) {
126         (void)fclose(file);
127         return false;
128     }
129     size_t fileSize = ftell(file);
130     (void)fclose(file);
131     return fileSize;
132 }
133 
ReadDataFromFile(const std::string & path,ByteBuffer & data)134 static bool ReadDataFromFile(const std::string &path, ByteBuffer &data)
135 {
136     FILE *file = fopen(path.c_str(), "rb");
137     if (file == nullptr) {
138         return false;
139     }
140     if (fseek(file, 0L, SEEK_END) != 0) {
141         (void)fclose(file);
142         return false;
143     }
144 
145     size_t fileSize = ftell(file);
146     if (fileSize == 0) {
147         (void)fclose(file);
148         return true;
149     }
150     rewind(file);
151     if (!data.Resize(fileSize)) {
152         (void)fclose(file);
153         return false;
154     }
155     size_t ret = fread(data.GetBuffer(), 1, fileSize, file);
156     (void)fclose(file);
157     if (ret < fileSize) {
158         LOG_ERROR(LABEL, "Read size (%{public}zu) < file size", ret);
159         return false;
160     }
161     return true;
162 }
163 
CopyData(const std::string & srcPath,FILE * fout)164 static void CopyData(const std::string &srcPath, FILE *fout)
165 {
166     ByteBuffer data;
167     EXPECT_EQ(ReadDataFromFile(srcPath, data), true);
168     if (data.GetSize() > 0) {
169         int32_t ret = fwrite(data.GetBuffer(), 1, data.GetSize(), fout);
170         EXPECT_EQ(static_cast<uint32_t>(ret), data.GetSize());
171     }
172 }
173 
CopyFile(const std::string & srcPath,const std::string & dstPath)174 static bool CopyFile(const std::string &srcPath, const std::string &dstPath)
175 {
176     FILE *fout = fopen(dstPath.c_str(), "wb");
177     if (fout == nullptr) {
178         return false;
179     }
180     CopyData(srcPath, fout);
181     (void)fclose(fout);
182     return true;
183 }
184 
CleanFile(const std::string & filePath)185 static void CleanFile(const std::string &filePath)
186 {
187     EXPECT_EQ(OHOS::RemoveFile(filePath), true);
188 }
189 
ExpandFile(const std::string & srcPath,const std::string & expandDataFile,size_t gapSize,const std::string & dstPath)190 static bool ExpandFile(const std::string &srcPath, const std::string &expandDataFile,
191     size_t gapSize, const std::string &dstPath)
192 {
193     FILE *fout = fopen(dstPath.c_str(), "wb");
194     if (fout == nullptr) {
195         return false;
196     }
197     CopyData(srcPath, fout);
198     uint8_t buffer[BUFFER_LENGTH];
199     (void)memset_s(buffer, BUFFER_LENGTH, 0, BUFFER_LENGTH);
200     size_t writeSize = BUFFER_LENGTH;
201     size_t totalSize = 0;
202     size_t ret;
203     while (totalSize < gapSize) {
204         if (gapSize - totalSize < BUFFER_LENGTH) {
205             writeSize = gapSize - totalSize;
206         }
207         ret = fwrite(buffer, 1, writeSize, fout);
208         if (ret != writeSize) {
209             (void)fclose(fout);
210             return false;
211         }
212         LOG_ERROR(LABEL, "write padding = %{public}zu", writeSize);
213         totalSize += writeSize;
214     }
215     CopyData(expandDataFile, fout);
216     (void)fclose(fout);
217     return true;
218 }
219 
CheckEnableSuccess(const std::string & filePath)220 static void CheckEnableSuccess(const std::string &filePath)
221 {
222     // drop all caches
223     SaveStringToFile(DROP_CACHE_PROC_PATH, DROP_ALL_CACHE_LEVEL);
224     FILE *fout = fopen(filePath.c_str(), "wb");
225     EXPECT_EQ(fout, nullptr);
226 
227     ByteBuffer tmp;
228     EXPECT_EQ(ReadDataFromFile(filePath, tmp), true);
229 }
230 
GetRoundUp(size_t fileSize)231 static inline size_t GetRoundUp(size_t fileSize)
232 {
233     return ceil(static_cast<double>(fileSize) / HASH_PAGE_SIZE) *
234         HASH_PAGE_SIZE;
235 }
236 
TamperFileTail(const std::string & filePath)237 static bool TamperFileTail(const std::string &filePath)
238 {
239     FILE *file = fopen(filePath.c_str(), "ab");
240     if (file == nullptr) {
241         return false;
242     }
243     if (fseek(file, 0L, SEEK_END) != 0) {
244         (void)fclose(file);
245         return false;
246     }
247 
248     size_t fileSize = ftell(file);
249     if (fseek(file, fileSize - FAKE_STRING.size(), SEEK_SET)) {
250         (void)fclose(file);
251         return false;
252     }
253     int32_t ret = fwrite(FAKE_STRING.c_str(), 1, FAKE_STRING.size(), file);
254     EXPECT_EQ(ret, FAKE_STRING.size());
255     (void)fclose(file);
256     return true;
257 }
258 
TamperFileHead(const std::string & filePath)259 static bool TamperFileHead(const std::string &filePath)
260 {
261     FILE *file = fopen(filePath.c_str(), "ab");
262     if (file == nullptr) {
263         return false;
264     }
265     if (fseek(file, 0L, SEEK_SET) != 0) {
266         (void)fclose(file);
267         return false;
268     }
269 
270     int32_t ret = fwrite(FAKE_STRING.c_str(), 1, FAKE_STRING.size(), file);
271     EXPECT_EQ(ret, FAKE_STRING.size());
272     (void)fclose(file);
273     return true;
274 }
275 
EnableVerityOnOneFile(const std::string filePath,struct code_sign_enable_arg * arg)276 int32_t EnableVerityOnOneFile(const std::string filePath,
277     struct code_sign_enable_arg *arg)
278 {
279     int fd = open(filePath.c_str(), O_RDONLY);
280     int ret = 0;
281 
282     int error = ioctl(fd, FS_IOC_ENABLE_CODE_SIGN, arg);
283     if (error < 0) {
284         LOG_ERROR(LABEL, "Enable fs-verity failed, errno = <%{public}d, %{public}s>",
285             errno, strerror(errno));
286         ret = errno;
287     }
288     close(fd);
289     return ret;
290 }
291 
MakeExpandTreeFile(const std::string & filePath,struct code_sign_enable_arg * arg)292 static std::string MakeExpandTreeFile(const std::string &filePath,
293     struct code_sign_enable_arg *arg)
294 {
295     size_t treeOffset = GetRoundUp(arg->data_size);
296     std::string expandFilePath = filePath + "_expand_tree";
297     EXPECT_EQ(ExpandFile(filePath, filePath + ".tree",
298         treeOffset - arg->data_size, expandFilePath), true);
299     return expandFilePath;
300 }
301 
FillCommonArgs(const std::string & filePath,bool isInsideTree,struct code_sign_enable_arg * arg,ByteBuffer & signature)302 static void FillCommonArgs(const std::string &filePath, bool isInsideTree,
303     struct code_sign_enable_arg *arg, ByteBuffer &signature)
304 {
305     bool ret;
306 
307     if (isInsideTree) {
308         ret = ReadDataFromFile(filePath + "_inside_tree.sig", signature);
309     } else {
310         ret = ReadDataFromFile(filePath + "_no_tree.sig", signature);
311     }
312     EXPECT_EQ(ret, true);
313 
314     size_t fileSize = GetFileSize(filePath);
315     arg->version = 1;
316     arg->cs_version = 1;    // version of code signing features
317     arg->hash_algorithm = 1;
318     arg->block_size = HASH_PAGE_SIZE;
319     arg->salt_ptr = 0;
320     arg->salt_size = 0;
321     arg->data_size = fileSize;
322     arg->sig_size = signature.GetSize();
323     arg->sig_ptr = reinterpret_cast<uintptr_t>(signature.GetBuffer());
324 }
325 
FillOptional(const std::string & filePath,struct code_sign_enable_arg * arg,ByteBuffer & rootHash)326 static void FillOptional(const std::string &filePath, struct code_sign_enable_arg *arg,
327     ByteBuffer &rootHash)
328 {
329     EXPECT_EQ(ReadDataFromFile(filePath + ".hash", rootHash), true);
330     arg->flags = 1;
331     arg->tree_offset = GetRoundUp(arg->data_size);
332     arg->root_hash_ptr = reinterpret_cast<uintptr_t>(rootHash.GetBuffer());
333 }
334 
EnableExpandedTamperFile(const std::string & filePath,bool (* tamperFileFunc)(const std::string & filePath))335 static void EnableExpandedTamperFile(const std::string &filePath,
336     bool (*tamperFileFunc)(const std::string &filePath))
337 {
338     struct code_sign_enable_arg arg = {};
339     ByteBuffer signature;
340     ByteBuffer rootHash;
341     FillCommonArgs(filePath, true, &arg, signature);
342     FillOptional(filePath, &arg, rootHash);
343 
344     // tamper file
345     std::string tmpFilePath = filePath + "_tmp";
346     EXPECT_EQ(CopyFile(filePath, tmpFilePath), true);
347     EXPECT_EQ(tamperFileFunc(tmpFilePath), true);
348 
349     // expand tampered file
350     std::string treeFile = filePath + ".tree";
351     std::string expandFilePath = filePath + "_expand_tree";
352     size_t treeOffset = GetRoundUp(arg.data_size);
353     EXPECT_EQ(ExpandFile(tmpFilePath, treeFile,
354         treeOffset - arg.data_size, expandFilePath), true);
355 
356     // Enable successully but cannot read
357     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
358     SaveStringToFile(DROP_CACHE_PROC_PATH, DROP_ALL_CACHE_LEVEL);
359     ByteBuffer tmp;
360     EXPECT_EQ(ReadDataFromFile(expandFilePath, tmp), false);
361 
362     CleanFile(expandFilePath);
363     CleanFile(tmpFilePath);
364 }
365 
366 /**
367  * @tc.name: EnableVerityTest_0001
368  * @tc.desc: enable all data in file successfully
369  * @tc.type: Func
370  * @tc.require:I8DH28
371  */
372 HWTEST_F(EnableVerityTest, EnableVerityTest_0001, TestSize.Level0)
373 {
374     for (int i = 0; i < TEST_FILE_NUM; i++) {
375         std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
376         LOG_INFO(LABEL, "Test on file path = %{public}s", filePath.c_str());
377         struct code_sign_enable_arg arg = {};
378         ByteBuffer signature;
379         FillCommonArgs(filePath, false, &arg, signature);
380         std::string copiedFile = filePath + "_copy";
381         EXPECT_EQ(CopyFile(filePath, copiedFile), true);
382         EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), 0);
383         CheckEnableSuccess(copiedFile);
384         CleanFile(copiedFile);
385     }
386 }
387 
388 /**
389  * @tc.name: EnableVerityTest_0002
390  * @tc.desc: enable orignial file with wrong file size
391  * @tc.type: Func
392  * @tc.require:I8DH28
393  */
394 HWTEST_F(EnableVerityTest, EnableVerityTest_0002, TestSize.Level0)
395 {
396     if (!g_isKernelLinux) {
397         return;
398     }
399     std::string filePath = TEST_DEFAULT_FILE;
400 
401     struct code_sign_enable_arg arg = {};
402     ByteBuffer signature;
403     FillCommonArgs(filePath, false, &arg, signature);
404 
405     std::string copiedFile = filePath + "_copy";
406     EXPECT_EQ(CopyFile(filePath, copiedFile), true);
407 
408     uint32_t fileSize = arg.data_size;
409     // size is set to less than file size
410     // descriptor is unmatched, signature verification failed.
411     arg.data_size = fileSize - 1;
412     EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), EKEYREJECTED);
413 
414     // size is set to greater than file size
415     // unable to pass parameter check
416     arg.data_size = fileSize + 1;
417     EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), EINVAL);
418 
419     CleanFile(copiedFile);
420 }
421 
422 /**
423  * @tc.name: EnableVerityTest_0003
424  * @tc.desc: enable expanded file successfully
425  * @tc.type: Func
426  * @tc.require:I8DH28
427  */
428 HWTEST_F(EnableVerityTest, EnableVerityTest_0003, TestSize.Level0)
429 {
430     for (int i = 0; i < TEST_FILE_NUM; i++) {
431         std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
432         struct code_sign_enable_arg arg = {};
433         ByteBuffer signature;
434         FillCommonArgs(filePath, false, &arg, signature);
435 
436         std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
437         EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
438         CheckEnableSuccess(expandFilePath);
439         CleanFile(expandFilePath);
440     }
441 }
442 
443 /**
444  * @tc.name: EnableVerityTest_0004
445  * @tc.desc: enable expanded file with inside tree successfully
446  * @tc.type: Func
447  * @tc.require:I8DH28
448  */
449 HWTEST_F(EnableVerityTest, EnableVerityTest_0004, TestSize.Level0)
450 {
451     for (int i = 0; i < TEST_FILE_NUM; i++) {
452         std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
453         LOG_INFO(LABEL, "Test on file path = %{public}s", filePath.c_str());
454 
455         struct code_sign_enable_arg arg = {};
456         ByteBuffer signature;
457         ByteBuffer rootHash;
458         FillCommonArgs(filePath, true, &arg, signature);
459         FillOptional(filePath, &arg, rootHash);
460         std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
461         EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
462         CheckEnableSuccess(expandFilePath);
463         CleanFile(expandFilePath);
464     }
465 }
466 
467 /**
468  * @tc.name: EnableVerityTest_0005
469  * @tc.desc: enable expanded file with wrong tree offset
470  * @tc.type: Func
471  * @tc.require:I8DH28
472  */
473 HWTEST_F(EnableVerityTest, EnableVerityTest_0005, TestSize.Level0)
474 {
475     if (!g_isKernelLinux) {
476         return;
477     }
478     std::string filePath = TEST_DEFAULT_FILE;
479     struct code_sign_enable_arg arg = {};
480     ByteBuffer signature;
481     ByteBuffer rootHash;
482     FillCommonArgs(filePath, true, &arg, signature);
483     FillOptional(filePath, &arg, rootHash);
484     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
485 
486     uint32_t treeOffset = arg.tree_offset;
487     // byte alignment check failed
488     arg.tree_offset = treeOffset + 1;
489     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EINVAL);
490 
491     // unmatched fsverity descriptor
492     arg.tree_offset = treeOffset - HASH_PAGE_SIZE;
493     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EKEYREJECTED);
494 
495     CleanFile(expandFilePath);
496 }
497 
498 /**
499  * @tc.name: EnableVerityTest_0006
500  * @tc.desc: enable expanded file with wrong root hash
501  * @tc.type: Func
502  * @tc.require:I8DH28
503  */
504 HWTEST_F(EnableVerityTest, EnableVerityTest_0006, TestSize.Level0)
505 {
506     if (!g_isKernelLinux) {
507         return;
508     }
509     std::string filePath = TEST_DEFAULT_FILE;
510     struct code_sign_enable_arg arg = {};
511     ByteBuffer signature;
512     ByteBuffer rootHash;
513     FillCommonArgs(filePath, true, &arg, signature);
514     FillOptional(filePath, &arg, rootHash);
515     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
516 
517     (void)memcpy_s(reinterpret_cast<void *>(arg.root_hash_ptr),
518         FAKE_STRING.size(), FAKE_STRING.c_str(), FAKE_STRING.size());
519 
520     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EKEYREJECTED);
521 
522     CleanFile(expandFilePath);
523 }
524 
525 /**
526  * @tc.name: EnableVerityTest_0007
527  * @tc.desc: enable expanded file with wrong file
528  * @tc.type: Func
529  * @tc.require:I8DH28
530  */
531 HWTEST_F(EnableVerityTest, EnableVerityTest_0007, TestSize.Level0)
532 {
533     std::string filePath = TEST_DEFAULT_FILE;
534     EnableExpandedTamperFile(filePath, TamperFileHead);
535 
536     EnableExpandedTamperFile(filePath, TamperFileTail);
537 }
538 
539 /**
540  * @tc.name: EnableVerityTest_0008
541  * @tc.desc: mmap signed data in xpm region success
542  * @tc.type: Func
543  * @tc.require:
544  */
545 HWTEST_F(EnableVerityTest, EnableVerityTest_0008, TestSize.Level0)
546 {
547     if (!g_isXpmOn) {
548         return;
549     }
550 
551     std::string filePath = TEST_DEFAULT_FILE;
552     struct code_sign_enable_arg arg = {};
553     ByteBuffer signature;
554     ByteBuffer rootHash;
555     FillCommonArgs(filePath, true, &arg, signature);
556     FillOptional(filePath, &arg, rootHash);
557     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
558     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
559 
560     std::unique_ptr<SELinuxContextSetter> setter = std::make_unique<SELinuxContextSetter>();
561     int fd = open(expandFilePath.c_str(), O_RDONLY);
562     // mmap with MAP_XPM flag, success
563     void *addr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM,
564         fd, 0);
565     EXPECT_NE(MAP_FAILED, addr);
566 
567     // release resource
568     munmap(addr, PAGE_SIZE);
569     close(fd);
570     CleanFile(expandFilePath);
571 }
572 
573 /**
574  * @tc.name: EnableVerityTest_0009
575  * @tc.desc: mmap unsigned data in xpm region failed
576  * @tc.type: Func
577  * @tc.require:
578  */
579 HWTEST_F(EnableVerityTest, EnableVerityTest_0009, TestSize.Level0)
580 {
581     if (!g_isXpmOn || !g_isKernelLinux) {
582         return;
583     }
584     std::string filePath = TEST_DEFAULT_FILE;
585     struct code_sign_enable_arg arg = {};
586     ByteBuffer signature;
587     ByteBuffer rootHash;
588     FillCommonArgs(filePath, true, &arg, signature);
589     FillOptional(filePath, &arg, rootHash);
590     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
591     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
592 
593     std::unique_ptr<SELinuxContextSetter> setter = std::make_unique<SELinuxContextSetter>();
594     int fd = open(expandFilePath.c_str(), O_RDONLY);
595     // mmap with MAP_XPM flag, over verity range
596     void *addr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM,
597         fd, arg.tree_offset & PAGE_MASK);
598     EXPECT_EQ(MAP_FAILED, addr);
599 
600     close(fd);
601     CleanFile(expandFilePath);
602 }
603 
604 /**
605  * @tc.name: EnableVerityTest_0010
606  * @tc.desc: mmap signed data as executable success
607  * @tc.type: Func
608  * @tc.require:
609  */
610 HWTEST_F(EnableVerityTest, EnableVerityTest_0010, TestSize.Level0)
611 {
612     if (!g_isXpmOn) {
613         return;
614     }
615     std::string filePath = TEST_FILES_DIR + "elf/elf";
616     struct code_sign_enable_arg arg = {};
617     ByteBuffer signature;
618     ByteBuffer rootHash;
619     FillCommonArgs(filePath, true, &arg, signature);
620     FillOptional(filePath, &arg, rootHash);
621     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
622     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
623 
624     std::unique_ptr<SELinuxContextSetter> setter = std::make_unique<SELinuxContextSetter>();
625     int fd = open(expandFilePath.c_str(), O_RDONLY);
626     // readelf from elf
627     // [19] .text             PROGBITS        000063ec 0053ec 002168 00  AX  0   0  4
628     int codeOffset = 0x53ec;
629     // mmap success at enforce mode
630     void *addr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE,
631         fd, codeOffset & PAGE_MASK);
632     EXPECT_NE(MAP_FAILED, addr);
633 
634     // release resource
635     munmap(addr, PAGE_SIZE);
636 
637     close(fd);
638     CleanFile(expandFilePath);
639 }
640 
641 /**
642  * @tc.name: EnableVerityTest_00011
643  * @tc.desc: mmap unsigned data as executable failed
644  * @tc.type: Func
645  * @tc.require
646  */
647 HWTEST_F(EnableVerityTest, EnableVerityTest_0011, TestSize.Level0)
648 {
649     if (!g_isXpmOn || !g_isKernelLinux) {
650         return;
651     }
652     std::string filePath = TEST_FILES_DIR + "elf/elf";
653     struct code_sign_enable_arg arg = {};
654     ByteBuffer signature;
655     ByteBuffer rootHash;
656     FillCommonArgs(filePath, true, &arg, signature);
657     FillOptional(filePath, &arg, rootHash);
658     std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
659     EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
660 
661     std::unique_ptr<SELinuxContextSetter> setter = std::make_unique<SELinuxContextSetter>();
662     int fd = open(expandFilePath.c_str(), O_RDONLY);
663     void *addr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE,
664         fd, arg.tree_offset & PAGE_MASK);
665     EXPECT_EQ(MAP_FAILED, addr);
666 
667     close(fd);
668     CleanFile(expandFilePath);
669 }
670 }  // namespace CodeSign
671 }  // namespace Security
672 }  // namespace OHOS
673