blob: 1c0f504564fb0cf2a9345302f0afbd27512866ff [file] [log] [blame]
San Mehat586536c2010-02-16 17:12:00 -08001/*
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 <dirent.h>
23#include <ctype.h>
24#include <pwd.h>
25#include <stdlib.h>
26#include <poll.h>
27#include <sys/stat.h>
28#include <signal.h>
29
30#define LOG_TAG "ProcessKiller"
Jeff Sharkey32ebb732017-03-27 16:18:50 -060031
32#include <android-base/file.h>
33#include <android-base/stringprintf.h>
34#include <android-base/logging.h>
San Mehat586536c2010-02-16 17:12:00 -080035#include <cutils/log.h>
36
37#include "Process.h"
38
Jeff Sharkey32ebb732017-03-27 16:18:50 -060039using android::base::ReadFileToString;
40using android::base::StringPrintf;
41
San Mehat586536c2010-02-16 17:12:00 -080042int Process::readSymLink(const char *path, char *link, size_t max) {
43 struct stat s;
44 int length;
45
46 if (lstat(path, &s) < 0)
47 return 0;
48 if ((s.st_mode & S_IFMT) != S_IFLNK)
49 return 0;
Jeff Sharkey32ebb732017-03-27 16:18:50 -060050
51 // we have a symlink
San Mehat586536c2010-02-16 17:12:00 -080052 length = readlink(path, link, max- 1);
Jeff Sharkey32ebb732017-03-27 16:18:50 -060053 if (length <= 0)
San Mehat586536c2010-02-16 17:12:00 -080054 return 0;
55 link[length] = 0;
56 return 1;
57}
58
59int Process::pathMatchesMountPoint(const char* path, const char* mountPoint) {
60 int length = strlen(mountPoint);
61 if (length > 1 && strncmp(path, mountPoint, length) == 0) {
62 // we need to do extra checking if mountPoint does not end in a '/'
63 if (mountPoint[length - 1] == '/')
64 return 1;
65 // if mountPoint does not have a trailing slash, we need to make sure
66 // there is one in the path to avoid partial matches.
67 return (path[length] == 0 || path[length] == '/');
68 }
69
70 return 0;
71}
72
Jeff Sharkey32ebb732017-03-27 16:18:50 -060073void Process::getProcessName(int pid, std::string& out_name) {
74 if (!ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &out_name)) {
75 out_name = "???";
San Mehat586536c2010-02-16 17:12:00 -080076 }
77}
78
79int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint) {
80 return checkFileDescriptorSymLinks(pid, mountPoint, NULL, 0);
81}
82
83int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max) {
84
85
86 // compute path to process's directory of open files
87 char path[PATH_MAX];
George Burgess IV605d7ae2016-02-29 13:39:17 -080088 snprintf(path, sizeof(path), "/proc/%d/fd", pid);
San Mehat586536c2010-02-16 17:12:00 -080089 DIR *dir = opendir(path);
90 if (!dir)
91 return 0;
92
93 // remember length of the path
94 int parent_length = strlen(path);
95 // append a trailing '/'
96 path[parent_length++] = '/';
97
98 struct dirent* de;
99 while ((de = readdir(dir))) {
Kenny Rootb3b43182010-02-18 09:34:07 -0800100 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")
101 || strlen(de->d_name) + parent_length + 1 >= PATH_MAX)
San Mehat586536c2010-02-16 17:12:00 -0800102 continue;
103
104 // append the file name, after truncating to parent directory
105 path[parent_length] = 0;
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600106 strlcat(path, de->d_name, PATH_MAX);
San Mehat586536c2010-02-16 17:12:00 -0800107
108 char link[PATH_MAX];
109
110 if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) {
111 if (openFilename) {
112 memset(openFilename, 0, max);
Henrik Baard21522662015-02-06 09:24:14 +0100113 strlcpy(openFilename, link, max);
San Mehat586536c2010-02-16 17:12:00 -0800114 }
115 closedir(dir);
116 return 1;
117 }
118 }
119
120 closedir(dir);
121 return 0;
122}
123
124int Process::checkFileMaps(int pid, const char *mountPoint) {
125 return checkFileMaps(pid, mountPoint, NULL, 0);
126}
127
128int Process::checkFileMaps(int pid, const char *mountPoint, char *openFilename, size_t max) {
129 FILE *file;
130 char buffer[PATH_MAX + 100];
131
George Burgess IV605d7ae2016-02-29 13:39:17 -0800132 snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
Jeff Sharkeyfd3dc3c2017-03-27 10:49:21 -0600133 file = fopen(buffer, "re");
San Mehat586536c2010-02-16 17:12:00 -0800134 if (!file)
135 return 0;
136
137 while (fgets(buffer, sizeof(buffer), file)) {
138 // skip to the path
139 const char* path = strchr(buffer, '/');
140 if (path && pathMatchesMountPoint(path, mountPoint)) {
141 if (openFilename) {
142 memset(openFilename, 0, max);
Henrik Baard21522662015-02-06 09:24:14 +0100143 strlcpy(openFilename, path, max);
San Mehat586536c2010-02-16 17:12:00 -0800144 }
145 fclose(file);
146 return 1;
147 }
148 }
149
150 fclose(file);
151 return 0;
152}
153
154int Process::checkSymLink(int pid, const char *mountPoint, const char *name) {
155 char path[PATH_MAX];
156 char link[PATH_MAX];
157
George Burgess IV605d7ae2016-02-29 13:39:17 -0800158 snprintf(path, sizeof(path), "/proc/%d/%s", pid, name);
San Mehat586536c2010-02-16 17:12:00 -0800159 if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint))
160 return 1;
161 return 0;
162}
163
164int Process::getPid(const char *s) {
165 int result = 0;
166 while (*s) {
167 if (!isdigit(*s)) return -1;
168 result = 10 * result + (*s++ - '0');
169 }
170 return result;
171}
172
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700173extern "C" void vold_killProcessesWithOpenFiles(const char *path, int signal) {
174 Process::killProcessesWithOpenFiles(path, signal);
jessica_yu3f14fe42014-09-22 15:57:40 +0800175}
176
San Mehat586536c2010-02-16 17:12:00 -0800177/*
178 * Hunt down processes that have files open at the given mount point.
San Mehat586536c2010-02-16 17:12:00 -0800179 */
Jeff Sharkey89f74fb2015-10-21 12:16:12 -0700180int Process::killProcessesWithOpenFiles(const char *path, int signal) {
181 int count = 0;
182 DIR* dir;
San Mehat586536c2010-02-16 17:12:00 -0800183 struct dirent* de;
184
185 if (!(dir = opendir("/proc"))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700186 SLOGE("opendir failed (%s)", strerror(errno));
Jeff Sharkey89f74fb2015-10-21 12:16:12 -0700187 return count;
San Mehat586536c2010-02-16 17:12:00 -0800188 }
189
190 while ((de = readdir(dir))) {
San Mehat586536c2010-02-16 17:12:00 -0800191 int pid = getPid(de->d_name);
San Mehat586536c2010-02-16 17:12:00 -0800192 if (pid == -1)
193 continue;
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600194
195 std::string name;
196 getProcessName(pid, name);
San Mehat586536c2010-02-16 17:12:00 -0800197
198 char openfile[PATH_MAX];
199
200 if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600201 SLOGE("Process %s (%d) has open file %s", name.c_str(), pid, openfile);
San Mehat586536c2010-02-16 17:12:00 -0800202 } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600203 SLOGE("Process %s (%d) has open filemap for %s", name.c_str(), pid, openfile);
San Mehat586536c2010-02-16 17:12:00 -0800204 } else if (checkSymLink(pid, path, "cwd")) {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600205 SLOGE("Process %s (%d) has cwd within %s", name.c_str(), pid, path);
San Mehat586536c2010-02-16 17:12:00 -0800206 } else if (checkSymLink(pid, path, "root")) {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600207 SLOGE("Process %s (%d) has chroot within %s", name.c_str(), pid, path);
San Mehat586536c2010-02-16 17:12:00 -0800208 } else if (checkSymLink(pid, path, "exe")) {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600209 SLOGE("Process %s (%d) has executable path within %s", name.c_str(), pid, path);
San Mehat586536c2010-02-16 17:12:00 -0800210 } else {
211 continue;
212 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700213
214 if (signal != 0) {
215 SLOGW("Sending %s to process %d", strsignal(signal), pid);
216 kill(pid, signal);
Jeff Sharkey89f74fb2015-10-21 12:16:12 -0700217 count++;
San Mehat586536c2010-02-16 17:12:00 -0800218 }
219 }
220 closedir(dir);
Jeff Sharkey89f74fb2015-10-21 12:16:12 -0700221 return count;
San Mehat586536c2010-02-16 17:12:00 -0800222}