• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <dlfcn.h>
2 #include <gtest/gtest.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 
6 #include "libs/ldso_gtest_util.h"
7 
8 #define LIB_PATH "/data/tmp/libcgtest/libs/libldso_cfi_lib.so"
9 #define TYPE_ID_1 1
10 #define TYPE_ID_2 2
11 #define TYPE_ID_3 3
12 #define TYPE_ID_4 4
13 #define TYPE_ID_5 5
14 
15 using namespace std;
16 using namespace testing::ext;
17 class LdsoCfiTest : public testing::Test {
SetUp()18     void SetUp() override {}
TearDown()19     void TearDown() override {}
20 };
21 
22 struct dso {
23     char* mock;
24     unsigned char* map;
25     size_t len;
26 };
27 
28 extern "C" int init_cfi_shadow(struct dso* dso_list, struct dso* ldso);
29 extern "C" int map_dso_to_cfi_shadow(struct dso* dso);
30 extern "C" void unmap_dso_from_cfi_shadow(struct dso* dso);
31 extern "C" void __cfi_slowpath(uint64_t CallSiteTypeId, void* Ptr);
32 extern "C" void __cfi_slowpath_diag(uint64_t CallSiteTypeId, void* Ptr, void* DiagData);
33 
34 typedef void (*FuncTypeRetVoid)();
35 typedef void* (*FuncTypeRetVoidPtr)();
36 typedef char* (*FuncTypeRetCharPtr)();
37 typedef size_t (*FuncTypeRetSize)();
38 typedef uint64_t (*FuncTypeRetUint64)();
39 
TestFunc()40 static void TestFunc() {}
41 
ExitBySig(int status)42 static bool ExitBySig(int status)
43 {
44     return WIFSIGNALED(status) &&
45            (WTERMSIG(status) == SIGTRAP || WTERMSIG(status) == SIGILL || WTERMSIG(status) == SIGSEGV);
46 }
47 
48 /**
49  * @tc.name: __cfi_slowpath_001
50  * @tc.desc: Load a so twice and verify it can be mapped to cfi shadow successfully.
51  * @tc.type: FUNC
52  */
53 HWTEST_F(LdsoCfiTest, __cfi_slowpath_001, TestSize.Level1)
54 {
55     uint64_t callSiteTypeId1 = TYPE_ID_1;
56     uint64_t callSiteTypeId2 = TYPE_ID_2;
57     void* handle = dlopen(LIB_PATH, RTLD_NOW);
58     ASSERT_NE(handle, nullptr);
59 
60     FuncTypeRetVoidPtr globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetGlobalAddress"));
61     ASSERT_NE(globalAddress, nullptr);
62     __cfi_slowpath(callSiteTypeId1, (*globalAddress)());
63 
64     void* handle2 = dlopen(LIB_PATH, RTLD_NOW);
65     ASSERT_EQ(handle, handle2);
66     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle2, "GetCount"));
67     ASSERT_NE(getCount, nullptr);
68     FuncTypeRetUint64 getTypeId = reinterpret_cast<FuncTypeRetUint64>(dlsym(handle2, "GetTypeId"));
69     ASSERT_NE(getTypeId, nullptr);
70     FuncTypeRetVoidPtr getAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle2, "GetAddress"));
71     ASSERT_NE(getAddress, nullptr);
72     globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle2, "GetGlobalAddress"));
73     ASSERT_NE(globalAddress, nullptr);
74 
75     size_t count = (*getCount)();
76     __cfi_slowpath(callSiteTypeId2, (*globalAddress)());
77     EXPECT_EQ(callSiteTypeId2, (*getTypeId)());
78     EXPECT_EQ((*globalAddress)(), (*getAddress)());
79     EXPECT_EQ(++count, (*getCount)());
80 
81     dlclose(handle);
82     dlclose(handle2);
83 }
84 
85 /**
86  * @tc.name: __cfi_slowpath_002
87  * @tc.desc: Loading a so that contains __cfi_check() symbol, call the __cfi_slowpath() function with address inside
88  *           the DSO, the __cfi_check() function is called.
89  * @tc.type: FUNC
90  */
91 HWTEST_F(LdsoCfiTest, __cfi_slowpath_002, TestSize.Level1)
92 {
93     uint64_t expectedCallSiteTypeId = TYPE_ID_2;
94     void* handle = dlopen(LIB_PATH, RTLD_NOW);
95     ASSERT_NE(handle, nullptr);
96 
97     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
98     ASSERT_NE(getCount, nullptr);
99     FuncTypeRetUint64 getTypeId = reinterpret_cast<FuncTypeRetUint64>(dlsym(handle, "GetTypeId"));
100     ASSERT_NE(getTypeId, nullptr);
101     FuncTypeRetVoidPtr getAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetAddress"));
102     ASSERT_NE(getAddress, nullptr);
103     FuncTypeRetVoidPtr getDiag = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetDiag"));
104     ASSERT_NE(getDiag, nullptr);
105     FuncTypeRetVoidPtr globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetGlobalAddress"));
106     ASSERT_NE(globalAddress, nullptr);
107 
108     size_t count = (*getCount)();
109 
110     __cfi_slowpath(expectedCallSiteTypeId, (*globalAddress)());
111     EXPECT_EQ(expectedCallSiteTypeId, (*getTypeId)());
112     EXPECT_EQ((*globalAddress)(), (*getAddress)());
113     EXPECT_EQ(nullptr, (*getDiag)());
114     EXPECT_EQ(++count, (*getCount)());
115 
116     dlclose(handle);
117 }
118 
119 /**
120  * @tc.name: __cfi_slowpath_003
121  * @tc.desc: load a so that contains the __cfi_check() symbol and call the __cfi_slowpath() function whose address
122  *           belongs to another so that is not Cross so enabled and the cfi_check function will not called.
123  * @tc.type: FUNC
124  */
125 HWTEST_F(LdsoCfiTest, __cfi_slowpath_003, TestSize.Level1)
126 {
127     uint64_t expectedCallSiteTypeId = TYPE_ID_3;
128     uint64_t unexpectedCallSiteTypeId = TYPE_ID_4;
129     void* handle = dlopen(LIB_PATH, RTLD_NOW);
130     ASSERT_NE(handle, nullptr);
131 
132     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
133     ASSERT_NE(getCount, nullptr);
134     FuncTypeRetVoidPtr globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetGlobalAddress"));
135     ASSERT_NE(globalAddress, nullptr);
136 
137     __cfi_slowpath(expectedCallSiteTypeId, (*globalAddress)());
138     size_t count = (*getCount)();
139     __cfi_slowpath(unexpectedCallSiteTypeId, reinterpret_cast<void*>(&TestFunc));
140 
141     EXPECT_EQ(count, (*getCount)());
142     dlclose(handle);
143 }
144 
145 /**
146  * @tc.name: __cfi_slowpath_004
147  * @tc.desc: Call __cfi_slowpath() with nullptr addr and verify the cfi_check function will not called.
148  * @tc.type: FUNC
149  */
150 HWTEST_F(LdsoCfiTest, __cfi_slowpath_004, TestSize.Level1)
151 {
152     uint64_t callSiteTypeId = TYPE_ID_3;
153     void* handle = dlopen(LIB_PATH, RTLD_NOW);
154     ASSERT_NE(handle, nullptr);
155 
156     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
157     ASSERT_NE(getCount, nullptr);
158 
159     size_t count = (*getCount)();
160     __cfi_slowpath(callSiteTypeId, nullptr);
161     EXPECT_EQ(count, (*getCount)());
162 
163     dlclose(handle);
164 }
165 
166 /**
167  * @tc.name: __cfi_slowpath_005
168  * @tc.desc: passing a invalid address to the slowpath() function expect Call__ Cfi_ Coredump occurs.
169  * @tc.type: FUNC
170  */
171 HWTEST_F(LdsoCfiTest, __cfi_slowpath_005, TestSize.Level1)
172 {
173     uint64_t callSiteTypeId = TYPE_ID_3;
174     void* handle = dlopen(LIB_PATH, RTLD_NOW);
175     ASSERT_NE(handle, nullptr);
176 
177     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
178     ASSERT_NE(getCount, nullptr);
179 
180     size_t count = (*getCount)();
181     EXPECT_EXIT(__cfi_slowpath(callSiteTypeId, static_cast<void*>(&count)), ExitBySig, "");
182 
183     dlclose(handle);
184 }
185 
186 /**
187  * @tc.name: __cfi_slowpath_006
188  * @tc.desc: close handle then call the cfi_slowpath and the cfi_slowpath will be killed by signal.
189  * @tc.type: FUNC
190  */
191 HWTEST_F(LdsoCfiTest, __cfi_slowpath_006, TestSize.Level1)
192 {
193     uint64_t callSiteTypeId = TYPE_ID_3;
194     void* handle = dlopen(LIB_PATH, RTLD_NOW);
195     ASSERT_NE(handle, nullptr);
196     FuncTypeRetVoidPtr globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetGlobalAddress"));
197     ASSERT_NE(globalAddress, nullptr);
198     dlclose(handle);
199 
200     EXPECT_EXIT(__cfi_slowpath(callSiteTypeId, (*globalAddress)()), ExitBySig, "");
201 }
202 
203 /**
204  * @tc.name: __cfi_slowpath_007
205  * @tc.desc: Load a so greater than 1 LIBRARY_ALIGNMENT, call the __cfi_slowpath() function in a different
206  *           LIBRARY_ALIGNMENT range, and verify that __cfi_check() is called.
207  * @tc.type: FUNC
208  */
209 HWTEST_F(LdsoCfiTest, __cfi_slowpath_007, TestSize.Level1)
210 {
211     uint64_t callSiteTypeId = TYPE_ID_5;
212     void* handle = dlopen(LIB_PATH, RTLD_NOW);
213     ASSERT_NE(handle, nullptr);
214 
215     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
216     ASSERT_NE(getCount, nullptr);
217     FuncTypeRetCharPtr bufCheck = reinterpret_cast<FuncTypeRetCharPtr>(dlsym(handle, "g_buf"));
218     ASSERT_NE(bufCheck, nullptr);
219 
220     size_t count = (*getCount)();
221     const size_t size = SIZE_1024_SQUARE;
222 
223     for (size_t i = 0; i < size; ++i) {
224         __cfi_slowpath(callSiteTypeId, reinterpret_cast<char*>(bufCheck) + i);
225         EXPECT_EQ(++count, (*getCount)());
226     }
227 
228     dlclose(handle);
229 }
230 
231 /**
232  * @tc.name: __cfi_slowpath_diag_function_test_001
233  * @tc.desc: Loading with The so file of the __cfi_check() symbol calls the internal address of the so file__
234  *           cfi_slowpath_ The diag() function__cfi_the check() function is called.
235  * @tc.type: FUNC
236  */
237 HWTEST_F(LdsoCfiTest, __cfi_slowpath_diag_function_test_001, TestSize.Level1)
238 {
239     uint64_t callSiteTypeId = TYPE_ID_1;
240     uint64_t diagInfo = 0;
241     void* handle = dlopen(LIB_PATH, RTLD_NOW);
242     ASSERT_NE(handle, nullptr);
243 
244     FuncTypeRetSize getCount = reinterpret_cast<FuncTypeRetSize>(dlsym(handle, "GetCount"));
245     ASSERT_NE(getCount, nullptr);
246     FuncTypeRetUint64 getTypeId = reinterpret_cast<FuncTypeRetUint64>(dlsym(handle, "GetTypeId"));
247     ASSERT_NE(getTypeId, nullptr);
248     FuncTypeRetVoidPtr getDiag = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetDiag"));
249     ASSERT_NE(getDiag, nullptr);
250     FuncTypeRetVoidPtr globalAddress = reinterpret_cast<FuncTypeRetVoidPtr>(dlsym(handle, "GetGlobalAddress"));
251     ASSERT_NE(globalAddress, nullptr);
252 
253     size_t count = (*getCount)();
254     __cfi_slowpath_diag(callSiteTypeId, nullptr, &diagInfo);
255     EXPECT_EQ(count, (*getCount)());
256 
257     __cfi_slowpath_diag(callSiteTypeId, (*globalAddress)(), &diagInfo);
258     EXPECT_EQ(++count, (*getCount)());
259     EXPECT_EQ(callSiteTypeId, (*getTypeId)());
260     EXPECT_EQ((*getDiag)(), &diagInfo);
261 
262     dlclose(handle);
263 }
264 
265 /**
266  * @tc.name: map_dso_to_cfi_shadow_001
267  * @tc.desc: If so is nullptr while mapping to the CFI shadow, do nothing and return true.
268  * @tc.type: FUNC
269  */
270 HWTEST_F(LdsoCfiTest, map_dso_to_cfi_shadow_001, TestSize.Level1)
271 {
272     EXPECT_EQ(map_dso_to_cfi_shadow(nullptr), 0);
273 }
274 
275 /**
276  * @tc.name: cfi_init_test_001
277  * @tc.desc: check all args is null when initializing the CFI shadow. do nothing and return true.
278  * @tc.type: FUNC
279  */
280 HWTEST_F(LdsoCfiTest, cfi_init_test_001, TestSize.Level1)
281 {
282     EXPECT_EQ(init_cfi_shadow(nullptr, nullptr), 0);
283 }
284 
285 /**
286  * @tc.name: unmap_dso_to_cfi_shadow_001
287  * @tc.desc: If so is nullptr while unmapping from the CFI shadow the program can be run success.
288  * @tc.type: FUNC
289  */
290 HWTEST_F(LdsoCfiTest, unmap_dso_to_cfi_shadow_001, TestSize.Level1)
291 {
292     unmap_dso_from_cfi_shadow(nullptr);
293     SUCCEED();
294 }
295