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