• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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