• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include <gtest/gtest.h>
16 #include <unistd.h>
17 #include <chrono>
18 #include <securec.h>
19 #include "json/json.h"
20 #include "file_util.h"
21 #include "gwpasan_collector.h"
22 
23 using namespace testing::ext;
24 namespace OHOS {
25 namespace HiviewDFX {
26 constexpr const uint16_t EACH_LINE_LENGTH = 100;
27 constexpr const uint16_t TOTAL_LENGTH = 4096;
28 class AsanUnittest : public testing::Test {
29 public:
SetUp()30     void SetUp()
31     {
32         chmod("/data/log/faultlog/", 0777); // 0777: add other user write permission
33         chmod("/data/log/faultlog/faultlogger/", 0777); // 0777: add other user write permission
34         sleep(1);
35     };
TearDown()36     void TearDown()
37     {
38         chmod("/data/log/faultlog/", 0770); // 0770: restore permission
39         chmod("/data/log/faultlog/faultlogger/", 0770); // 0770: restore permission
40     };
41 
ClearAllLogs(const std::string & path)42     static void ClearAllLogs(const std::string& path)
43     {
44         DIR* dir = opendir(path.c_str());
45         struct dirent* entry;
46         while ((entry = readdir(dir)) != nullptr) {
47             std::string full_path = path + "/" + entry->d_name;
48             remove(full_path.c_str());
49         }
50         closedir(dir);
51     }
52 
hasSanitizerLogs(std::string path,std::string type)53     static bool hasSanitizerLogs(std::string path, std::string type)
54     {
55         std::vector<std::string> files;
56         FileUtil::GetDirFiles(path, files, false);
57         bool hasLogs = false;
58         for (const auto& file : files) {
59             if (file.find(type) != std::string::npos) {
60                 hasLogs = true;
61                 break;
62             }
63         }
64         return hasLogs;
65     }
66 
ExecuteCmd(const std::string & cmd,std::string & result)67     static bool ExecuteCmd(const std::string &cmd, std::string &result)
68     {
69         char buff[EACH_LINE_LENGTH] = { 0x00 };
70         char output[TOTAL_LENGTH] = { 0x00 };
71         FILE *ptr = popen(cmd.c_str(), "r");
72         if (ptr != nullptr) {
73             while (fgets(buff, sizeof(buff), ptr) != nullptr) {
74                 if (strcat_s(output, sizeof(output), buff) != 0) {
75                     pclose(ptr);
76                     ptr = nullptr;
77                     return false;
78                 }
79             }
80             pclose(ptr);
81             ptr = nullptr;
82         } else {
83             return false;
84         }
85         result = std::string(output);
86         return true;
87     }
88 
GetCurrentTimestampMs()89     static int64_t GetCurrentTimestampMs()
90     {
91         auto now = std::chrono::system_clock::now();
92         auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
93         return ms.count();
94     }
95 };
96 
97 /**
98  * @tc.name: AsanTest001
99  * @tc.desc: Test calling WriteSanitizerLog Func
100  * @tc.type: FUNC
101  */
102 HWTEST_F(AsanUnittest, WriteSanitizerLogTest001, testing::ext::TestSize.Level0)
103 {
104     ClearAllLogs("/data/log/faultlog/faultlogger/");
105     char path[] = "faultlogger";
106     char gwpAsanBuf[] = "Test GWP-ASAN, End GWP-ASan report";
107     WriteSanitizerLog(gwpAsanBuf, strlen(gwpAsanBuf), path);
108     char cfiBuf[] = "Test CFI, End CFI report";
109     WriteSanitizerLog(cfiBuf, strlen(cfiBuf), path);
110     char ubsanBuf[] = "Test UBSAN, End Ubsan report";
111     WriteSanitizerLog(ubsanBuf, strlen(ubsanBuf), path);
112     char tsanBuf[] = "Test TSAN, End Tsan report";
113     WriteSanitizerLog(tsanBuf, strlen(tsanBuf), path);
114     char hwasanBuf[] = "Test HWASAN, End Hwasan report";
115     WriteSanitizerLog(hwasanBuf, strlen(hwasanBuf), path);
116     char asanBuf[] = "Test ASAN, End Asan report";
117     WriteSanitizerLog(asanBuf, strlen(asanBuf), path);
118     ASSERT_TRUE(true);
119 }
120 
121 /**
122  * @tc.name: AsanTest002
123  * @tc.desc: Test calling WriteSanitizerLog Func
124  * @tc.type: FUNC
125  */
126 HWTEST_F(AsanUnittest, WriteSanitizerLogTest002, testing::ext::TestSize.Level1)
127 {
128     ClearAllLogs("/data/log/faultlog/faultlogger/");
129     char* buf = nullptr;
130     size_t sz = 10;
131     char path[] = "faultlogger";
132     WriteSanitizerLog(buf, sz, path);
133     bool result = hasSanitizerLogs("/data/log/faultlog/faultlogger/", "asan");
134     ASSERT_FALSE(result);
135 }
136 
137 /**
138  * @tc.name: AsanTest003
139  * @tc.desc: Test calling WriteSanitizerLog Func
140  * @tc.type: FUNC
141  */
142 HWTEST_F(AsanUnittest, WriteSanitizerLogTest003, testing::ext::TestSize.Level1)
143 {
144     ClearAllLogs("/data/log/faultlog/faultlogger/");
145     char path[] = "/data/sanitizer.log";
146     char hwasanBuf[] = "Test HWASAN, End Hwasan report";
147     WriteSanitizerLog(hwasanBuf, strlen(hwasanBuf), path);
148     bool result = hasSanitizerLogs("/data/log/faultlog/faultlogger/", "hwasan");
149     ASSERT_FALSE(result);
150 }
151 
152 /**
153  * @tc.name: AsanTest004
154  * @tc.desc: Test calling WriteSanitizerLog Func
155  * @tc.type: FUNC
156  */
157 HWTEST_F(AsanUnittest, WriteSanitizerLogTest004, testing::ext::TestSize.Level1)
158 {
159     ClearAllLogs("/data/log/faultlog/faultlogger/");
160     char hwasanBuf[] =
161         "\"==debugsantizer==14705==ERROR: HWAddressSanitizer:"
162         " tag-mismatch on address 0x000100020000 at pc 0x005750422ec8\n"
163         "READ of size 8 at 0x000100020000 tags: df/2f (ptr/mem) in thread 14705\n"
164         "    #0 0x5750422ec8  (/data/libclang_rt.hwasan.so+0x1ec8) (BuildId: 123456abcd)\n"
165         "    #1 0x599883b23c  (/lib/ld-musl-aarch64-asan.so.1+0xc623c) (BuildId: 123456abcd)\n"
166         "    #2 0x5750422c7c  (/data/debugsantizer+0x1c7c) (BuildId: 123456abcd)\n"
167         "[0x000100020000,0x000100020020) is a small unallocated heap chunk; size: 32 offset: 0, Allocated By 14705\n"
168         "Potential Cause: use-after-free\n"
169         "0x000100020000 (rb[0] tags:df) is located 0 bytes inside of 8-byte region [0x000100020000,0x000100020008)\n"
170         "freed by thread 14705 here:\n"
171         "    #0 0x5999c6b2fc  (/system/asan/lib64/libclang_rt.hwasan.so+0x2b2fc) (BuildId: 123456abcd)\n"
172         "    #1 0x5999c6b2fc  (/system/asan/lib64/libclang_rt.hwasan.so+0x2b2fc) (BuildId: 123456abcd)\n"
173         "Test HWASAN, End Hwasan report\n";
174     char path[] = "faultlogger";
175     auto strat = GetCurrentTimestampMs();
176     WriteSanitizerLog(hwasanBuf, strlen(hwasanBuf), path);
177     auto end = GetCurrentTimestampMs();
178     std::string cmd = "hisysevent -l -o RELIABILITY -n ADDR_SANITIZER -s " +
179         std::to_string(strat) + " -e " + std::to_string(end + 5);
180     std::string result;
181     auto ret = ExecuteCmd(cmd, result);
182     EXPECT_TRUE(ret);
183     GTEST_LOG_(INFO) << cmd;
184     GTEST_LOG_(INFO) << result;
185     Json::Reader reader;
186     Json::Value sanitizerEvent;
187     if (!reader.parse(result, sanitizerEvent)) {
188         GTEST_LOG_(ERROR) << "Failed to parse JSON: " << reader.getFormattedErrorMessages();
189     }
190     EXPECT_EQ(sanitizerEvent["MODULE"], "AsanUnittest");
191     EXPECT_EQ(sanitizerEvent["REASON"], "use-after-free");
192     EXPECT_EQ(sanitizerEvent["FIRST_FRAME"], "use-after-free");
193     EXPECT_EQ(sanitizerEvent["SECOND_FRAME"], "debugsantizer");
194 }
195 
196 /**
197  * @tc.name: AsanTest005
198  * @tc.desc: Test calling WriteSanitizerLog Func
199  * @tc.type: FUNC
200  */
201 HWTEST_F(AsanUnittest, WriteSanitizerLogTest005, testing::ext::TestSize.Level1)
202 {
203     ClearAllLogs("/data/log/faultlog/faultlogger/");
204     char hwasanBuf[] =
205         "Potential Cause: use-after-free\n"
206         "ptrBeg was re-written after free 0x000c00036f80[0],"
207         "0x000c00036f80 0000000000000000:5555555555555555, freed by:\n"
208         "    #0 0x5a94feb2fc  (/system/asan/lib64/libclang_rt.hwasan.so+0x2b2fc) (BuildId: 123456abcd)\n"
209         "    #1 0x5a9b860678  (/system/lib64/chipset-sdk-sp/libc++.so+0xcd630) (BuildId: 123456abcd)\n"
210         "    #2 0x5a9b85ed9c  (/system/lib64/platformsdk/libeventhandler.z.so+0x1ed9c) (BuildId: 123456abcd)\n"
211         "    #3 0x56934ca940  (/system/bin/appspawn+0xb940) (BuildId: 123456abcd)\n"
212         "allocated by:\n"
213         "    #0 0x5a94feb1a8  (/system/asan/lib64/libclang_rt.hwasan.so+0x2b1a8) (BuildId: 123456abcd)\n"
214         "    #1 0x5a9b87e268  (/system/lib64/platformsdk/libeventhandler.z.so+0x3e268) (BuildId: 123456abcd)\n"
215         "==appspawn==7133==End Hwasan report\n";
216     char path[] = "faultlogger";
217     auto strat = GetCurrentTimestampMs();
218     WriteSanitizerLog(hwasanBuf, strlen(hwasanBuf), path);
219     auto end = GetCurrentTimestampMs();
220     std::string cmd = "hisysevent -l -o RELIABILITY -n ADDR_SANITIZER -s " +
221         std::to_string(strat) + " -e " + std::to_string(end + 5);
222     std::string result;
223     auto ret = ExecuteCmd(cmd, result);
224     EXPECT_TRUE(ret);
225     GTEST_LOG_(INFO) << cmd;
226     GTEST_LOG_(INFO) << result;
227     Json::Reader reader;
228     Json::Value sanitizerEvent;
229     if (!reader.parse(result, sanitizerEvent)) {
230         GTEST_LOG_(ERROR) << "Failed to parse JSON: " << reader.getFormattedErrorMessages();
231     }
232     EXPECT_EQ(sanitizerEvent["MODULE"], "AsanUnittest");
233     EXPECT_EQ(sanitizerEvent["REASON"], "use-after-free");
234     EXPECT_EQ(sanitizerEvent["FIRST_FRAME"], "use-after-free");
235     EXPECT_EQ(sanitizerEvent["SECOND_FRAME"], "libeventhandler.z.so");
236 }
237 } // namespace HiviewDFX
238 } // namespace OHOS
239