Process.cpp revision 586536c60b773e3517531ad8a6cb0de6722c67fc
1586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat/* 2586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * Copyright (C) 2008 The Android Open Source Project 3586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * 4586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * you may not use this file except in compliance with the License. 6586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * You may obtain a copy of the License at 7586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * 8586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * http://www.apache.org/licenses/LICENSE-2.0 9586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * 10586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * Unless required by applicable law or agreed to in writing, software 11586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * See the License for the specific language governing permissions and 14586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * limitations under the License. 15586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat */ 16586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 17586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <stdio.h> 18586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <unistd.h> 19586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <errno.h> 20586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <string.h> 21586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <fcntl.h> 22586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <dirent.h> 23586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <ctype.h> 24586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <pwd.h> 25586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <stdlib.h> 26586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <poll.h> 27586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <sys/stat.h> 28586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <signal.h> 29586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 30586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#define LOG_TAG "ProcessKiller" 31586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include <cutils/log.h> 32586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 33586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h" 34586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 35586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::readSymLink(const char *path, char *link, size_t max) { 36586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat struct stat s; 37586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int length; 38586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 39586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (lstat(path, &s) < 0) 40586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 41586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if ((s.st_mode & S_IFMT) != S_IFLNK) 42586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 43586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 44586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // we have a symlink 45586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat length = readlink(path, link, max- 1); 46586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (length <= 0) 47586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 48586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat link[length] = 0; 49586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 50586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 51586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 52586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::pathMatchesMountPoint(const char* path, const char* mountPoint) { 53586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int length = strlen(mountPoint); 54586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (length > 1 && strncmp(path, mountPoint, length) == 0) { 55586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // we need to do extra checking if mountPoint does not end in a '/' 56586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (mountPoint[length - 1] == '/') 57586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 58586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // if mountPoint does not have a trailing slash, we need to make sure 59586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // there is one in the path to avoid partial matches. 60586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return (path[length] == 0 || path[length] == '/'); 61586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 62586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 63586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 64586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 65586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 66586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatvoid Process::getProcessName(int pid, char *buffer, size_t max) { 67586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int fd; 68586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat snprintf(buffer, max, "/proc/%d/cmdline", pid); 69586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat fd = open(buffer, O_RDONLY); 70586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (fd < 0) { 71586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strcpy(buffer, "???"); 72586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else { 73586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int length = read(fd, buffer, max - 1); 74586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat buffer[length] = 0; 75586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat close(fd); 76586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 77586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 78586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 79586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint) { 80586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return checkFileDescriptorSymLinks(pid, mountPoint, NULL, 0); 81586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 82586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 83586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max) { 84586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 85586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 86586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // compute path to process's directory of open files 87586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char path[PATH_MAX]; 88586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat sprintf(path, "/proc/%d/fd", pid); 89586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat DIR *dir = opendir(path); 90586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!dir) 91586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 92586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 93586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // remember length of the path 94586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int parent_length = strlen(path); 95586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // append a trailing '/' 96586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat path[parent_length++] = '/'; 97586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 98586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat struct dirent* de; 99586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while ((de = readdir(dir))) { 100586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 101586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 102586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 103586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // append the file name, after truncating to parent directory 104586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat path[parent_length] = 0; 105586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strcat(path, de->d_name); 106586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 107586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char link[PATH_MAX]; 108586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 109586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) { 110586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (openFilename) { 111586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat memset(openFilename, 0, max); 112586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strncpy(openFilename, link, max-1); 113586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 114586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 115586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 116586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 117586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 118586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 119586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 120586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 121586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 122586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 123586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileMaps(int pid, const char *mountPoint) { 124586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return checkFileMaps(pid, mountPoint, NULL, 0); 125586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 126586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 127586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileMaps(int pid, const char *mountPoint, char *openFilename, size_t max) { 128586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat FILE *file; 129586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char buffer[PATH_MAX + 100]; 130586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 131586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat sprintf(buffer, "/proc/%d/maps", pid); 132586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat file = fopen(buffer, "r"); 133586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!file) 134586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 135586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 136586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while (fgets(buffer, sizeof(buffer), file)) { 137586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // skip to the path 138586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat const char* path = strchr(buffer, '/'); 139586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (path && pathMatchesMountPoint(path, mountPoint)) { 140586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (openFilename) { 141586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat memset(openFilename, 0, max); 142586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strncpy(openFilename, path, max-1); 143586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 144586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat fclose(file); 145586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 146586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 147586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 148586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 149586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat fclose(file); 150586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 151586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 152586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 153586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkSymLink(int pid, const char *mountPoint, const char *name) { 154586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char path[PATH_MAX]; 155586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char link[PATH_MAX]; 156586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 157586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat sprintf(path, "/proc/%d/%s", pid, name); 158586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) 159586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 160586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 161586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 162586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 163586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::getPid(const char *s) { 164586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int result = 0; 165586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while (*s) { 166586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!isdigit(*s)) return -1; 167586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat result = 10 * result + (*s++ - '0'); 168586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 169586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return result; 170586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 171586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 172586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat/* 173586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * Hunt down processes that have files open at the given mount point. 174586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 0 to just warn, 175586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 1 to SIGHUP, 176586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 2 to SIGKILL 177586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat */ 178586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat// hunt down and kill processes that have files open on the given mount point 179586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatvoid Process::killProcessesWithOpenFiles(const char *path, int action) { 180586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat DIR* dir; 181586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat struct dirent* de; 182586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 183586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!(dir = opendir("/proc"))) { 184586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("opendir failed (%s)", strerror(errno)); 185586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return; 186586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 187586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 188586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while ((de = readdir(dir))) { 189586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int killed = 0; 190586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int pid = getPid(de->d_name); 191586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char name[PATH_MAX]; 192586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 193586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (pid == -1) 194586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 195586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat getProcessName(pid, name, sizeof(name)); 196586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 197586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char openfile[PATH_MAX]; 198586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 199586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) { 200586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Process %s (%d) has open file %s", name, pid, openfile); 201586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) { 202586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Process %s (%d) has open filemap for %s", name, pid, openfile); 203586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "cwd")) { 204586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Process %s (%d) has cwd within %s", name, pid, path); 205586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "root")) { 206586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Process %s (%d) has chroot within %s", name, pid, path); 207586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "exe")) { 208586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Process %s (%d) has executable path within %s", name, pid, path); 209586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else { 210586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 211586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 212586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (action == 1) { 213586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGW("Sending SIGHUP to process %d", pid); 214586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat kill(pid, SIGTERM); 215586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (action == 2) { 216586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat LOGE("Sending SIGKILL to process %d", pid); 217586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat kill(pid, SIGKILL); 218586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 219586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 220586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 221586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 222