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