1cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross/*
2cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  Copyright 2014 Google, Inc
3cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *
4cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  Licensed under the Apache License, Version 2.0 (the "License");
5cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  you may not use this file except in compliance with the License.
6cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  You may obtain a copy of the License at
7cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *
8cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *
10cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  Unless required by applicable law or agreed to in writing, software
11cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  distributed under the License is distributed on an "AS IS" BASIS,
12cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  See the License for the specific language governing permissions and
14cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross *  limitations under the License.
15cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross */
16cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
17cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross//#define LOG_NDEBUG 0
18cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#define LOG_TAG "libprocessgroup"
19cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
20cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <assert.h>
21cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <dirent.h>
220badbd6565fea17be39d82eba858fa76d28920a4Elliott Hughes#include <errno.h>
23cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <fcntl.h>
24fcc8115dcf33b547facab9c6f2f4739f85ab69c1Chih-Hung Hsieh#include <inttypes.h>
25b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#include <mutex>
26cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <stdbool.h>
27cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <stdio.h>
28cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <stdlib.h>
29cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <string.h>
30cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <sys/stat.h>
31cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <sys/types.h>
32cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
33cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <log/log.h>
34cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <private/android_filesystem_config.h>
35cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
362c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn#include <utils/SystemClock.h>
372c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn
38cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross#include <processgroup/processgroup.h>
39b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen
405bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen// Uncomment line below use memory cgroups for keeping track of (forked) PIDs
415bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen// #define USE_MEMCG 1
425bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen
43b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define MEM_CGROUP_PATH "/dev/memcg/apps"
44623b56af5da59fb57abcb2d984762669c82f57e9Martijn Coenen#define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
45b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define ACCT_CGROUP_PATH "/acct"
46b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen
47b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_UID_PREFIX "uid_"
48b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_PID_PREFIX "pid_"
49b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
50b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_MAX_UID_LEN 11
51b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_MAX_PID_LEN 11
52b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen#define PROCESSGROUP_MAX_PATH_LEN \
53b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen        ((sizeof(MEM_CGROUP_PATH) > sizeof(ACCT_CGROUP_PATH) ? \
54b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen          sizeof(MEM_CGROUP_PATH) : sizeof(ACCT_CGROUP_PATH)) + \
55b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \
56b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         PROCESSGROUP_MAX_UID_LEN + \
57b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \
58b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         PROCESSGROUP_MAX_PID_LEN + \
59b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \
60b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen         1)
61b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen
62b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenenstd::once_flag init_path_flag;
63cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
64cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstruct ctx {
65cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    bool initialized;
66cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int fd;
67cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char buf[128];
68cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char *buf_ptr;
69cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    size_t buf_len;
70cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross};
71cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
72b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenenstatic const char* getCgroupRootPath() {
735bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen#ifdef USE_MEMCG
74b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen    static const char* cgroup_root_path = NULL;
75b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen    std::call_once(init_path_flag, [&]() {
76623b56af5da59fb57abcb2d984762669c82f57e9Martijn Coenen            // Check if mem cgroup is mounted, only then check for write-access to avoid
77623b56af5da59fb57abcb2d984762669c82f57e9Martijn Coenen            // SELinux denials
78623b56af5da59fb57abcb2d984762669c82f57e9Martijn Coenen            cgroup_root_path = access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ?
79623b56af5da59fb57abcb2d984762669c82f57e9Martijn Coenen                    ACCT_CGROUP_PATH : MEM_CGROUP_PATH;
80b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen            });
81b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen    return cgroup_root_path;
825bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen#else
835bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen    return ACCT_CGROUP_PATH;
845bb91ab5530dd002f6021b2177dc2bcf5467eebdMartijn Coenen#endif
85b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen}
86b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen
87cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int convertUidToPath(char *path, size_t size, uid_t uid)
88cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
89cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return snprintf(path, size, "%s/%s%d",
90b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen            getCgroupRootPath(),
91cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            PROCESSGROUP_UID_PREFIX,
92cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            uid);
93cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
94cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
95cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid)
96cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
97cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return snprintf(path, size, "%s/%s%d/%s%d",
98b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen            getCgroupRootPath(),
99cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            PROCESSGROUP_UID_PREFIX,
100cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            uid,
101cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            PROCESSGROUP_PID_PREFIX,
102cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            pid);
103cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
104cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
105cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int initCtx(uid_t uid, int pid, struct ctx *ctx)
106cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
107cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int ret;
108cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
109cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    convertUidPidToPath(path, sizeof(path), uid, pid);
110cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
111cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
112cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int fd = open(path, O_RDONLY);
113cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (fd < 0) {
114cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        ret = -errno;
1152c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn        SLOGW("failed to open %s: %s", path, strerror(errno));
116cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return ret;
117cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
118cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
119cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->fd = fd;
120cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->buf_ptr = ctx->buf;
121cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->buf_len = 0;
122cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->initialized = true;
123cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
1242c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn    SLOGV("Initialized context for %s", path);
1252c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn
126cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return 0;
127cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
128cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
129cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int refillBuffer(struct ctx *ctx)
130cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
131cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    memmove(ctx->buf, ctx->buf_ptr, ctx->buf_len);
132cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->buf_ptr = ctx->buf;
133cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
134cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ssize_t ret = read(ctx->fd, ctx->buf_ptr + ctx->buf_len,
1352c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn                sizeof(ctx->buf) - ctx->buf_len - 1);
136cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0) {
137cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return -errno;
138cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    } else if (ret == 0) {
139cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return 0;
140cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
141cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
142cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->buf_len += ret;
14367f46cb0e137edbf4a6f7014ca8a3a58484016d1Dianne Hackborn    ctx->buf[ctx->buf_len] = 0;
144fcc8115dcf33b547facab9c6f2f4739f85ab69c1Chih-Hung Hsieh    SLOGV("Read %zd to buffer: %s", ret, ctx->buf);
1452c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn
146cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    assert(ctx->buf_len <= sizeof(ctx->buf));
147cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
148cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return ret;
149cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
150cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
151cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic pid_t getOneAppProcess(uid_t uid, int appProcessPid, struct ctx *ctx)
152cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
153cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (!ctx->initialized) {
154cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        int ret = initCtx(uid, appProcessPid, ctx);
155cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        if (ret < 0) {
156cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            return ret;
157cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
158cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
159cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
160cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char *eptr;
161cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    while ((eptr = (char *)memchr(ctx->buf_ptr, '\n', ctx->buf_len)) == NULL) {
162cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        int ret = refillBuffer(ctx);
163cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        if (ret == 0) {
164cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            return -ERANGE;
165cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
166cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        if (ret < 0) {
167cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            return ret;
168cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
169cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
170cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
171cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    *eptr = '\0';
172cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char *pid_eptr = NULL;
173cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    errno = 0;
174cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    long pid = strtol(ctx->buf_ptr, &pid_eptr, 10);
175cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (errno != 0) {
176cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return -errno;
177cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
178cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (pid_eptr != eptr) {
179cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return -EINVAL;
180cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
181cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
1822c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn    ctx->buf_len -= (eptr - ctx->buf_ptr) + 1;
183cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx->buf_ptr = eptr + 1;
184cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
185cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return (pid_t)pid;
186cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
187cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
188cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int removeProcessGroup(uid_t uid, int pid)
189cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
190cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int ret;
191cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
192cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
193cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    convertUidPidToPath(path, sizeof(path), uid, pid);
194cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ret = rmdir(path);
195cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
196cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    convertUidToPath(path, sizeof(path), uid);
197cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    rmdir(path);
198cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
199cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return ret;
200cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
201cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
202cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic void removeUidProcessGroups(const char *uid_path)
203cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
204cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    DIR *uid = opendir(uid_path);
205cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (uid != NULL) {
206cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        struct dirent cur;
207cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        struct dirent *dir;
208cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        while ((readdir_r(uid, &cur, &dir) == 0) && dir) {
209cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            char path[PROCESSGROUP_MAX_PATH_LEN];
210cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
211cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            if (dir->d_type != DT_DIR) {
212cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross                continue;
213cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            }
214cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
215cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) {
216cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross                continue;
217cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            }
218cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
219cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name);
220cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            SLOGV("removing %s\n", path);
221cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            rmdir(path);
222cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
223c15dd044705aa86f63b2642c1439d5f943a80d18Colin Cross        closedir(uid);
224cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
225cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
226cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
227cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossvoid removeAllProcessGroups()
228cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
229cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    SLOGV("removeAllProcessGroups()");
230b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen    const char *cgroup_root_path = getCgroupRootPath();
231b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen    DIR *root = opendir(cgroup_root_path);
232cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (root == NULL) {
233b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen        SLOGE("failed to open %s: %s", cgroup_root_path, strerror(errno));
234c15dd044705aa86f63b2642c1439d5f943a80d18Colin Cross    } else {
235cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        struct dirent cur;
236cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        struct dirent *dir;
237cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        while ((readdir_r(root, &cur, &dir) == 0) && dir) {
238cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            char path[PROCESSGROUP_MAX_PATH_LEN];
239cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
240cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            if (dir->d_type != DT_DIR) {
241cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross                continue;
242cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            }
243cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) {
244cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross                continue;
245cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            }
246cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
247b82bab66f318896ebad80c1feee2347c58e3ce37Martijn Coenen            snprintf(path, sizeof(path), "%s/%s", cgroup_root_path, dir->d_name);
248cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            removeUidProcessGroups(path);
249cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            SLOGV("removing %s\n", path);
250cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            rmdir(path);
251cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
252c15dd044705aa86f63b2642c1439d5f943a80d18Colin Cross        closedir(root);
253cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
254cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
255cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
256cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
257cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
258cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int processes = 0;
259cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    struct ctx ctx;
260cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    pid_t pid;
261cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
262cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ctx.initialized = false;
263cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
264cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0) {
265cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        processes++;
2662c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn        if (pid == 0) {
2672c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // Should never happen...  but if it does, trying to kill this
2682c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // will boomerang right back and kill us!  Let's not let that happen.
2692c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            SLOGW("Yikes, we've been told to kill pid 0!  How about we don't do that.");
2702c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            continue;
2712c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn        }
2722c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn        if (pid != initialPid) {
2732c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // We want to be noisy about killing processes so we can understand
2742c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // what is going on in the log; however, don't be noisy about the base
2752c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // process, since that it something we always kill, and we have already
2762c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            // logged elsewhere about killing it.
2772c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            SLOGI("Killing pid %d in uid %d as part of process group %d", pid, uid, initialPid);
2782c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn        }
279cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        int ret = kill(pid, signal);
280cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        if (ret == -1) {
2812c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            SLOGW("failed to kill pid %d: %s", pid, strerror(errno));
282cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
283cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
284cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
285cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ctx.initialized) {
286cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        close(ctx.fd);
287cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
288cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
289cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return processes;
290cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
291cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
292cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossint killProcessGroup(uid_t uid, int initialPid, int signal)
293cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
294cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int processes;
295d50393057a6551c3bb498ed3a3bb7bd9eeb48225Yusuke Sato    const int sleep_us = 5 * 1000;  // 5ms
296fcc8115dcf33b547facab9c6f2f4739f85ab69c1Chih-Hung Hsieh    int64_t startTime = android::uptimeMillis();
297d50393057a6551c3bb498ed3a3bb7bd9eeb48225Yusuke Sato    int retry = 40;
298cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
299cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
300cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
301d50393057a6551c3bb498ed3a3bb7bd9eeb48225Yusuke Sato        if (retry > 0) {
302cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            usleep(sleep_us);
303d50393057a6551c3bb498ed3a3bb7bd9eeb48225Yusuke Sato            --retry;
304cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        } else {
305cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            SLOGE("failed to kill %d processes for processgroup %d\n",
306cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross                    processes, initialPid);
307cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross            break;
308cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        }
309cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
310cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
311fcc8115dcf33b547facab9c6f2f4739f85ab69c1Chih-Hung Hsieh    SLOGV("Killed process group uid %d pid %d in %" PRId64 "ms, %d procs remain", uid, initialPid,
3122c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn            android::uptimeMillis()-startTime, processes);
3132c5e7e102bc2059d22f8457db68c567b64cec963Dianne Hackborn
314cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (processes == 0) {
315cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return removeProcessGroup(uid, initialPid);
316cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    } else {
317cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return -1;
318cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
319cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
320cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
321cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossstatic int mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
322cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
323cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int ret;
324cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
325758aeb7dadfcd29b11e8648d784ea56f31be05f3Bernhard Rosenkränzer    ret = mkdir(path, mode);
326cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0 && errno != EEXIST) {
327cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return -errno;
328cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
329cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
330758aeb7dadfcd29b11e8648d784ea56f31be05f3Bernhard Rosenkränzer    ret = chown(path, uid, gid);
331cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0) {
332cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        ret = -errno;
333cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        rmdir(path);
334cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return ret;
335cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
336cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
337cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return 0;
338cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
339cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
340cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Crossint createProcessGroup(uid_t uid, int initialPid)
341cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross{
342cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
343cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int ret;
344cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
345cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    convertUidToPath(path, sizeof(path), uid);
346cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
347cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
348cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0) {
349cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
350cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return ret;
351cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
352cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
353cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    convertUidPidToPath(path, sizeof(path), uid, initialPid);
354cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
355cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
356cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0) {
357cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
358cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return ret;
359cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
360cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
361cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
362cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
363cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int fd = open(path, O_WRONLY);
364cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (fd < 0) {
365cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        ret = -errno;
366cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        SLOGE("failed to open %s: %s", path, strerror(errno));
367cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        return ret;
368cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
369cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
370cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
371cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    int len = snprintf(pid, sizeof(pid), "%d", initialPid);
372cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
373cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    ret = write(fd, pid, len);
374cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    if (ret < 0) {
375cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        ret = -errno;
376cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        SLOGE("failed to write '%s' to %s: %s", pid, path, strerror(errno));
377cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    } else {
378cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross        ret = 0;
379cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    }
380cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
381cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    close(fd);
382cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross    return ret;
383cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross}
384cf8d1c22f7e239f502a7d209e2255d2997dbeb8bColin Cross
385