1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <gtest/gtest.h>
16 #include <cinttypes>
17 #include <climits>
18 #include <cstdio>
19 #include <unistd.h>
20 #include <string>
21 #include <sys/wait.h>
22 #include <sys/time.h>
23
handler(int s)24 static void handler(int s)
25 {
26 }
27
28 #define SIZE_ALIGN (4 * sizeof(size_t))
29 #define THRESHOLD (0x1c00 * SIZE_ALIGN)
30 #define ITER_TIME 20
31
32
33 using namespace testing::ext;
34 using namespace std;
35
36 class MallocModifyPointer : public testing::Test {
37 public:
38
39 static void SetUpTestCase();
40 static void TearDownTestCase();
41 void SetUp();
42 void TearDown();
43 private:
44 };
45
SetUp()46 void MallocModifyPointer::SetUp()
47 {
48 }
TearDown()49 void MallocModifyPointer::TearDown()
50 {
51 }
SetUpTestCase()52 void MallocModifyPointer::SetUpTestCase()
53 {
54 }
TearDownTestCase()55 void MallocModifyPointer::TearDownTestCase()
56 {
57 }
58 const int MAX_NUMBER_VALUE = 512;
59 volatile uintptr_t *g_p0;
60 volatile uintptr_t *g_p1;
61 volatile void *g_tmp[MAX_NUMBER_VALUE];
62
child(void)63 static int child(void)
64 {
65 g_p0 = (uintptr_t *)malloc(10 * sizeof(uintptr_t));
66 if (!g_p0) {
67 printf("Malloc failed:%s\n", strerror(errno));
68 }
69 /* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */
70 g_tmp[0] = (uintptr_t *)malloc(10 * sizeof(uintptr_t));
71 /* Malloc another chunk to get a key */
72 g_p1 = (uintptr_t *)malloc(10 * sizeof(uintptr_t));
73 if (!g_p1) {
74 printf("Malloc failed:%s\n", strerror(errno));
75 }
76 /* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */
77 g_tmp[0] = (uintptr_t *)malloc(10 * sizeof(uintptr_t));
78
79 if (g_p0 != nullptr) {
80 free(static_cast<void *>(const_cast<uintptr_t *>(g_p0)));
81 g_p0 = nullptr;
82 }
83
84 if (g_p1 != nullptr) {
85 free(static_cast<void *>(const_cast<uintptr_t *>(g_p1)));
86 g_p1 = nullptr;
87 }
88
89 uintptr_t *fake_ptr = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(reinterpret_cast<char *>
90 (const_cast<uintptr_t *>(g_p1)) - sizeof(size_t) * 2) ^ reinterpret_cast<uintptr_t>(g_p0[0]));
91 g_p0[0] = reinterpret_cast<uintptr_t>(fake_ptr);
92 g_p1[0] = reinterpret_cast<uintptr_t>(fake_ptr);
93
94 for (int i = 0; i < MAX_NUMBER_VALUE; ++i) {
95 /*
96 * The init procedure makes the freelist unpredictable. To make sure to trigger the ivalid ptr
97 * acess, here we create as many chunks as possible to make sure there are enough chunks in
98 * bin[j] of size "10 * sizeof(uintptr_t)". Basically this is heap spray.
99 */
100 g_tmp[i] = (uintptr_t *)malloc(10 * sizeof(uintptr_t));
101 }
102 for (int i = 0; i < MAX_NUMBER_VALUE; ++i) {
103 free(const_cast<void *>(g_tmp[i]));
104 }
105 return 0;
106 }
107
start_child(void)108 static pid_t start_child(void)
109 {
110 pid_t pid;
111 int ret;
112 pid = fork();
113 if (pid == 0) {
114 ret = child();
115 printf("child process normally out with %d\n", ret);
116 return ret;
117 }
118 return pid;
119 }
120
121 /*
122 * @tc.number CAM_FREE_FUN_0100
123 * @tc.name Apply part of the memory camfree reduction
124 * @tc.desc Test the basic features of CamFree
125 */
126 HWTEST_F(MallocModifyPointer, modifyPointerTest0100, Function | MediumTest | Level1)
127 {
128 sigset_t set;
129 int status;
130 int flag = 0;
131 struct timespec g_time1 = {5, 0};
132
133 sigemptyset(&set);
134 sigaddset(&set, SIGCHLD);
135 sigprocmask(SIG_BLOCK, &set, 0);
136 signal(SIGCHLD, handler);
137
138 pid_t pid = start_child();
139 if (pid == -1) {
140 printf("fork failed: %s\n", strerror(errno));
141 }
142 if (sigtimedwait(&set, 0, &g_time1) == -1) { /* Wait for 5 seconds */
143 if (errno == EAGAIN) {
144 flag = 1;
145 } else {
146 printf("sigtimedwait failed: %s\n", strerror(errno));
147 }
148 if (kill(pid, SIGKILL) == -1) {
149 printf("kill failed: %s\n", strerror(errno));
150 }
151 }
152
153 if (waitpid(pid, &status, 0) != pid) {
154 printf("waitpid failed: %s\n", strerror(errno));
155 }
156
157 if (flag) {
158 printf("Child process time out\n");
159 }
160
161 if (WIFSIGNALED(status)) {
162 ASSERT_TRUE(WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGILL) << "child process out with %s\n" <<
163 WTERMSIG(status);
164 } else {
165 ASSERT_TRUE(false) << "child process finished normally\n";
166 }
167 }
168
169