Process.cpp revision 97ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76
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))) { 100b3b4318ab8e2908f7b3c75fb68a5cbfc48fe6ab2Kenny Root if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") 101b3b4318ab8e2908f7b3c75fb68a5cbfc48fe6ab2Kenny Root || strlen(de->d_name) + parent_length + 1 >= PATH_MAX) 102586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 103586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 104586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // append the file name, after truncating to parent directory 105586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat path[parent_length] = 0; 106586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strcat(path, de->d_name); 107586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 108586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char link[PATH_MAX]; 109586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 110586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) { 111586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (openFilename) { 112586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat memset(openFilename, 0, max); 113586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strncpy(openFilename, link, max-1); 114586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 115586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 116586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 117586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 118586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 119586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 120586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 121586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 122586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 123586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 124586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileMaps(int pid, const char *mountPoint) { 125586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return checkFileMaps(pid, mountPoint, NULL, 0); 126586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 127586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 128586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkFileMaps(int pid, const char *mountPoint, char *openFilename, size_t max) { 129586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat FILE *file; 130586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char buffer[PATH_MAX + 100]; 131586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 132586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat sprintf(buffer, "/proc/%d/maps", pid); 133586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat file = fopen(buffer, "r"); 134586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!file) 135586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 136586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 137586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while (fgets(buffer, sizeof(buffer), file)) { 138586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat // skip to the path 139586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat const char* path = strchr(buffer, '/'); 140586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (path && pathMatchesMountPoint(path, mountPoint)) { 141586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (openFilename) { 142586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat memset(openFilename, 0, max); 143586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat strncpy(openFilename, path, max-1); 144586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 145586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat fclose(file); 146586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 147586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 148586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 149586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 150586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat fclose(file); 151586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 152586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 153586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 154586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::checkSymLink(int pid, const char *mountPoint, const char *name) { 155586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char path[PATH_MAX]; 156586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char link[PATH_MAX]; 157586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 158586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat sprintf(path, "/proc/%d/%s", pid, name); 159586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) 160586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 1; 161586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return 0; 162586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 163586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 164586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint Process::getPid(const char *s) { 165586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int result = 0; 166586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while (*s) { 167586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!isdigit(*s)) return -1; 168586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat result = 10 * result + (*s++ - '0'); 169586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 170586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return result; 171586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 172586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 173586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat/* 174586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * Hunt down processes that have files open at the given mount point. 175586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 0 to just warn, 176586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 1 to SIGHUP, 177586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat * action = 2 to SIGKILL 178586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat */ 179586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat// hunt down and kill processes that have files open on the given mount point 180586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatvoid Process::killProcessesWithOpenFiles(const char *path, int action) { 181586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat DIR* dir; 182586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat struct dirent* de; 183586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 184586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (!(dir = opendir("/proc"))) { 18597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("opendir failed (%s)", strerror(errno)); 186586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat return; 187586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 188586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 189586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat while ((de = readdir(dir))) { 190586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int killed = 0; 191586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat int pid = getPid(de->d_name); 192586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char name[PATH_MAX]; 193586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 194586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (pid == -1) 195586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 196586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat getProcessName(pid, name, sizeof(name)); 197586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 198586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat char openfile[PATH_MAX]; 199586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat 200586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) { 20197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Process %s (%d) has open file %s", name, pid, openfile); 202586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) { 20397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Process %s (%d) has open filemap for %s", name, pid, openfile); 204586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "cwd")) { 20597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Process %s (%d) has cwd within %s", name, pid, path); 206586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "root")) { 20797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Process %s (%d) has chroot within %s", name, pid, path); 208586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (checkSymLink(pid, path, "exe")) { 20997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Process %s (%d) has executable path within %s", name, pid, path); 210586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else { 211586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat continue; 212586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 213586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat if (action == 1) { 21497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Sending SIGHUP to process %d", pid); 215586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat kill(pid, SIGTERM); 216586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } else if (action == 2) { 21797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Sending SIGKILL to process %d", pid); 218586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat kill(pid, SIGKILL); 219586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 220586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat } 221586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat closedir(dir); 222586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat} 223