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 16 #include "common.h" 17 #include <array> 18 #include <cinttypes> 19 #include <csignal> 20 #include <dirent.h> 21 #include <fcntl.h> 22 #include <fstream> 23 #include <iostream> 24 #ifdef HOOK_ENABLE 25 #include <malloc.h> 26 #endif 27 #include <sstream> 28 #include <sys/file.h> 29 #include <sys/stat.h> 30 #include <sys/types.h> 31 #include <sys/wait.h> 32 #include <unistd.h> 33 #include "application_info.h" 34 #include "bundle_mgr_proxy.h" 35 #include "file_ex.h" 36 #include "iservice_registry.h" 37 #include "logging.h" 38 #include "system_ability_definition.h" 39 40 using namespace OHOS; 41 using namespace OHOS::AppExecFwk; 42 namespace COMMON { 43 constexpr int EXECVP_ERRNO = 2; 44 const int SHELL_UID = 2000; 45 const std::string DEFAULT_PATH = "/data/local/tmp/"; 46 constexpr int PIPE_LEN = 2; 47 constexpr int READ = 0; 48 constexpr int WRITE = 1; 49 const int FILE_PATH_SIZE = 512; 50 const int BUFFER_SIZE = 1024; 51 const int INVALID_PID = -1; 52 IsProcessRunning()53 bool IsProcessRunning() 54 { 55 setgid(SHELL_UID); 56 char buffer[PATH_MAX + 1] = {0}; 57 readlink("/proc/self/exe", buffer, PATH_MAX); 58 std::string processName = buffer; 59 int pos = static_cast<int>(processName.find_last_of('/')); 60 if (pos != 0) { 61 processName = processName.substr(pos + 1, processName.size()); 62 } 63 64 std::string fileName = DEFAULT_PATH + processName + ".pid"; 65 umask(S_IWOTH); 66 int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r-- 67 if (fd < 0) { 68 const int bufSize = 256; 69 char buf[bufSize] = { 0 }; 70 strerror_r(errno, buf, bufSize); 71 HILOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf); 72 return false; 73 } 74 75 if (flock(fd, LOCK_EX | LOCK_NB) == -1) { 76 // 进程正在运行,加锁失败 77 close(fd); 78 printf("%s is running, please don't start it again.\n", processName.c_str()); 79 HILOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str()); 80 return true; 81 } 82 83 std::string pidStr = std::to_string(getpid()); 84 auto nbytes = write(fd, pidStr.data(), pidStr.size()); 85 CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!"); 86 return false; 87 } 88 IsProcessExist(std::string & processName,int & pid)89 bool IsProcessExist(std::string& processName, int& pid) 90 { 91 DIR* dir = opendir("/proc"); 92 if (dir == nullptr) { 93 HILOG_ERROR(LOG_CORE, "open /proc dir failed"); 94 return false; 95 } 96 struct dirent* ptr; 97 int pidValue = INVALID_PID; 98 while ((ptr = readdir(dir)) != nullptr) { 99 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) { 100 continue; 101 } 102 if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) { 103 continue; 104 } 105 char filePath[FILE_PATH_SIZE] = {0}; 106 int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name); 107 if (len < 0) { 108 HILOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off"); 109 continue; 110 } 111 FILE* fp = fopen(filePath, "r"); 112 if (fp == nullptr) { 113 HILOG_WARN(LOG_CORE, "open file failed!"); 114 break; 115 } 116 char buf[BUFFER_SIZE] = {0}; 117 if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) { 118 fclose(fp); 119 continue; 120 } 121 std::string str(buf); 122 size_t found = str.rfind("/"); 123 std::string fullProcess; 124 if (found != std::string::npos) { 125 fullProcess = str.substr(found + 1); 126 } else { 127 fullProcess = str; 128 } 129 if (fullProcess == processName) { 130 pidValue = atoi(ptr->d_name); 131 fclose(fp); 132 break; 133 } 134 fclose(fp); 135 } 136 closedir(dir); 137 if (pidValue != INVALID_PID) { 138 pid = pidValue; 139 } 140 return pidValue != INVALID_PID; 141 } 142 CloseStdio()143 static void CloseStdio() 144 { 145 close(STDIN_FILENO); 146 close(STDOUT_FILENO); 147 close(STDERR_FILENO); 148 } 149 StartProcess(const std::string & processBin,std::vector<char * > & argv)150 int StartProcess(const std::string& processBin, std::vector<char*>& argv) 151 { 152 int pid = fork(); 153 if (pid == 0) { 154 CloseStdio(); 155 argv.push_back(nullptr); // last item in argv must be NULL 156 int retval = execvp(processBin.c_str(), argv.data()); 157 if (retval == -1 && errno == EXECVP_ERRNO) { 158 printf("warning: %s does not exist!\n", processBin.c_str()); 159 HILOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str()); 160 } 161 _exit(EXIT_FAILURE); 162 } 163 164 return pid; 165 } 166 KillProcess(int pid)167 int KillProcess(int pid) 168 { 169 if (pid == -1) { 170 return -1; 171 } 172 int stat; 173 kill(pid, SIGKILL); 174 if (waitpid(pid, &stat, 0) == -1) { 175 if (errno != EINTR) { 176 stat = -1; 177 } 178 } 179 return stat; 180 } 181 PrintMallinfoLog(const std::string & mallInfoPrefix)182 void PrintMallinfoLog(const std::string& mallInfoPrefix) 183 { 184 #ifdef HOOK_ENABLE 185 struct mallinfo2 mallinfo = mallinfo2(); 186 std::string mallinfoLog = mallInfoPrefix; 187 mallinfoLog += "arena = " + std::to_string(mallinfo.arena) + ", ordblks = " + std::to_string(mallinfo.ordblks); 188 mallinfoLog += ", smblks = " + std::to_string(mallinfo.smblks) + ", hblks = " + std::to_string(mallinfo.hblks); 189 mallinfoLog += ", hblkhd = " + std::to_string(mallinfo.hblkhd) + ", usmblks = " + std::to_string(mallinfo.usmblks); 190 mallinfoLog += 191 ", fsmblks = " + std::to_string(mallinfo.fsmblks) + ", uordblks = " + std::to_string(mallinfo.uordblks); 192 mallinfoLog += 193 ", fordblks = " + std::to_string(mallinfo.fordblks) + ", keepcost = " + std::to_string(mallinfo.keepcost); 194 HILOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str()); 195 #endif // HOOK_ENABLE 196 } 197 CustomPopen(int & childPid,const std::string & filePath,std::vector<std::string> & argv,const char * type)198 FILE* CustomPopen(int& childPid, const std::string& filePath, std::vector<std::string>& argv, const char* type) 199 { 200 if (type == nullptr) { 201 HILOG_ERROR(LOG_CORE, "Common:%s param invalid", __func__); 202 return nullptr; 203 } 204 int fd[PIPE_LEN]; 205 pipe(fd); 206 pid_t pid = fork(); 207 if (pid == -1) { 208 HILOG_ERROR(LOG_CORE, "Common:%s fork failed!", __func__); 209 return nullptr; 210 } 211 // child process 212 if (pid == 0) { 213 if (!strncmp(type, "r", strlen(type))) { 214 close(fd[READ]); 215 dup2(fd[WRITE], STDOUT_FILENO); // Redirect stdout to pipe 216 dup2(fd[WRITE], STDERR_FILENO); // 2: Redirect stderr to pipe 217 } else { 218 close(fd[WRITE]); 219 dup2(fd[READ], 0); // Redirect stdin to pipe 220 } 221 setpgid(pid, pid); 222 std::vector<char*> vectArgv; 223 for (auto& item : argv) { 224 vectArgv.push_back(const_cast<char*>(item.c_str())); 225 } 226 // execv : the last argv must be nullptr. 227 vectArgv.push_back(nullptr); 228 execv(filePath.c_str(), &vectArgv[0]); 229 exit(0); 230 } else { 231 if (!strncmp(type, "r", strlen(type))) { 232 // Close the WRITE end of the pipe since parent's fd is read-only 233 close(fd[WRITE]); 234 } else { 235 // Close the READ end of the pipe since parent's fd is write-only 236 close(fd[READ]); 237 } 238 } 239 childPid = pid; 240 if (!strncmp(type, "r", strlen(type))) { 241 return fdopen(fd[READ], "r"); 242 } 243 return fdopen(fd[WRITE], "w"); 244 } 245 CustomPclose(FILE * fp,int childPid)246 int CustomPclose(FILE* fp, int childPid) 247 { 248 HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 249 CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__); 250 int stat = 0; 251 if (fclose(fp) != 0) { 252 const int bufSize = 256; 253 char buf[bufSize] = {0}; 254 strerror_r(errno, buf, bufSize); 255 HILOG_ERROR(LOG_CORE, "Common: %s fclose failed! errno(%d:%s)", __func__, errno, buf); 256 } 257 if (waitpid(childPid, &stat, 0) == -1) { 258 if (errno != EINTR) { 259 const int bufSize = 256; 260 char buf[bufSize] = {0}; 261 strerror_r(errno, buf, bufSize); 262 HILOG_ERROR(LOG_CORE, "Common: %s waitpid failed! errno(%d:%s)", __func__, errno, buf); 263 return stat; 264 } 265 } 266 HILOG_INFO(LOG_CORE, "END %s: success!", __func__); 267 return stat; 268 } 269 GetServicePort()270 int GetServicePort() 271 { 272 const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range"; 273 std::ifstream file(portRangePath.c_str()); 274 if (!file.is_open()) { 275 HILOG_ERROR(LOG_CORE, "Open file failed! filePath:%s", portRangePath.c_str()); 276 return -1; 277 } 278 std::string rangeStr; 279 copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr)); 280 281 int minPort; 282 int maxPort; 283 std::istringstream istr(rangeStr); 284 istr >> minPort >> maxPort; 285 const int offset = 3168; // To be compatible with previously used port 50051; 286 int port = (minPort + maxPort) / 2 + offset; 287 HILOG_DEBUG(LOG_CORE, "Service port is: %d", port); 288 return port; 289 } 290 SplitString(const std::string & str,const std::string & sep,std::vector<std::string> & ret)291 void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret) 292 { 293 if (str.empty()) { 294 HILOG_ERROR(LOG_CORE, "The string splited is empty!"); 295 return; 296 } 297 std::string::size_type beginPos = str.find_first_not_of(sep); 298 std::string::size_type findPos = 0; 299 while (beginPos != std::string::npos) { 300 findPos = str.find(sep, beginPos); 301 std::string tmp; 302 if (findPos != std::string::npos) { 303 tmp = str.substr(beginPos, findPos - beginPos); 304 beginPos = findPos + sep.length(); 305 } else { 306 tmp = str.substr(beginPos); 307 beginPos = findPos; 308 } 309 if (!tmp.empty()) { 310 ret.push_back(tmp); 311 tmp.clear(); 312 } 313 } 314 } 315 CheckApplicationPermission(int pid,const std::string & processName)316 bool CheckApplicationPermission(int pid, const std::string& processName) 317 { 318 std::string bundleName; 319 if (pid > 0) { 320 std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline"; 321 if (!LoadStringFromFile(filePath, bundleName)) { 322 HILOG_ERROR(LOG_CORE, "Get process name by pid failed!"); 323 return false; 324 } 325 bundleName = bundleName.substr(0, strlen(bundleName.c_str())); 326 } else { 327 bundleName = processName; 328 } 329 if (bundleName.empty()) { 330 HILOG_ERROR(LOG_CORE, "Pid or process name is illegal!"); 331 return false; 332 } 333 334 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 335 if (sam == nullptr) { 336 HILOG_ERROR(LOG_CORE, "GetSystemAbilityManager failed!"); 337 return false; 338 } 339 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 340 if (remoteObject == nullptr) { 341 HILOG_ERROR(LOG_CORE, "Get BundleMgr SA failed!"); 342 return false; 343 } 344 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject); 345 int uid = proxy->GetUidByDebugBundleName(bundleName, Constants::ANY_USERID); 346 if (uid < 0) { 347 HILOG_ERROR(LOG_CORE, "Get %s uid = %d", bundleName.c_str(), uid); 348 return false; 349 } 350 return true; 351 } 352 VerifyPath(const std::string & filePath,const std::vector<std::string> & validPaths)353 bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths) 354 { 355 if (validPaths.size() == 0) { 356 return true; 357 } 358 359 for (const std::string& path : validPaths) { 360 if (filePath.rfind(path, 0) == 0) { 361 return true; 362 } 363 } 364 return false; 365 } 366 ReadFile(const std::string & filePath,const std::vector<std::string> & validPaths,std::string & fileContent)367 bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent) 368 { 369 char* realFilePath = realpath(filePath.c_str(), nullptr); 370 if (realFilePath == nullptr) { 371 HILOG_ERROR(LOG_CORE, "Fail to realPath: %s", filePath.c_str()); 372 return false; 373 } 374 375 std::string realFilePathStr(realFilePath); 376 free(realFilePath); 377 if (!VerifyPath(realFilePathStr, validPaths)) { 378 HILOG_ERROR(LOG_CORE, "Fail to VerifyPath: %s", realFilePathStr.c_str()); 379 return false; 380 } 381 382 std::ifstream fileStream(realFilePathStr, std::ios::in); 383 if (!fileStream.is_open()) { 384 HILOG_ERROR(LOG_CORE, "Fail to open file %s", realFilePathStr.c_str()); 385 return false; 386 } 387 388 std::istreambuf_iterator<char> firstIt = { fileStream }; 389 std::string content(firstIt, {}); 390 fileContent = content; 391 return true; 392 } 393 GetErrorMsg()394 std::string GetErrorMsg() 395 { 396 const int bufSize = 256; 397 char buffer[bufSize] = { 0 }; 398 strerror_r(errno, buffer, bufSize); 399 std::string errorMsg(buffer); 400 return errorMsg; 401 } 402 } // namespace COMMON 403