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