1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <string.h> 21 #include <fcntl.h> 22 #include <fts.h> 23 #include <dirent.h> 24 #include <ctype.h> 25 #include <pwd.h> 26 #include <stdlib.h> 27 #include <poll.h> 28 #include <sys/stat.h> 29 #include <signal.h> 30 31 #include <fstream> 32 #include <unordered_set> 33 34 #include <android-base/file.h> 35 #include <android-base/parseint.h> 36 #include <android-base/strings.h> 37 #include <android-base/stringprintf.h> 38 #include <android-base/logging.h> 39 40 #include "Process.h" 41 42 using android::base::StringPrintf; 43 44 namespace android { 45 namespace vold { 46 47 static bool checkMaps(const std::string& path, const std::string& prefix) { 48 bool found = false; 49 std::ifstream infile(path); 50 std::string line; 51 while (std::getline(infile, line)) { 52 std::string::size_type pos = line.find('/'); 53 if (pos != std::string::npos) { 54 line = line.substr(pos); 55 if (android::base::StartsWith(line, prefix)) { 56 LOG(WARNING) << "Found map " << path << " referencing " << line; 57 found = true; 58 } 59 } 60 } 61 return found; 62 } 63 64 static bool checkSymlink(const std::string& path, const std::string& prefix) { 65 std::string res; 66 if (android::base::Readlink(path, &res)) { 67 if (android::base::StartsWith(res, prefix)) { 68 LOG(WARNING) << "Found symlink " << path << " referencing " << res; 69 return true; 70 } 71 } 72 return false; 73 } 74 75 int KillProcessesWithOpenFiles(const std::string& prefix, int signal) { 76 std::unordered_set<pid_t> pids; 77 78 auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir); 79 if (!proc_d) { 80 PLOG(ERROR) << "Failed to open proc"; 81 return -1; 82 } 83 84 struct dirent* proc_de; 85 while ((proc_de = readdir(proc_d.get())) != nullptr) { 86 // We only care about valid PIDs 87 pid_t pid; 88 if (proc_de->d_type != DT_DIR) continue; 89 if (!android::base::ParseInt(proc_de->d_name, &pid)) continue; 90 91 // Look for references to prefix 92 bool found = false; 93 auto path = StringPrintf("/proc/%d", pid); 94 found |= checkMaps(path + "/maps", prefix); 95 found |= checkSymlink(path + "/cwd", prefix); 96 found |= checkSymlink(path + "/root", prefix); 97 found |= checkSymlink(path + "/exe", prefix); 98 99 auto fd_path = path + "/fd"; 100 auto fd_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(fd_path.c_str()), closedir); 101 if (!fd_d) { 102 PLOG(WARNING) << "Failed to open " << fd_path; 103 } else { 104 struct dirent* fd_de; 105 while ((fd_de = readdir(fd_d.get())) != nullptr) { 106 if (fd_de->d_type != DT_LNK) continue; 107 found |= checkSymlink(fd_path + "/" + fd_de->d_name, prefix); 108 } 109 } 110 111 if (found) { 112 pids.insert(pid); 113 } 114 } 115 if (signal != 0) { 116 for (const auto& pid : pids) { 117 LOG(WARNING) << "Sending " << strsignal(signal) << " to " << pid; 118 kill(pid, signal); 119 } 120 } 121 return pids.size(); 122 } 123 124 } // namespace vold 125 } // namespace android 126