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