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