1 /* 2 * Copyright 2014 Google, Inc 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "libprocessgroup" 19 20 #include <assert.h> 21 #include <dirent.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <inttypes.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <unistd.h> 31 32 #include <chrono> 33 #include <memory> 34 #include <mutex> 35 #include <set> 36 #include <thread> 37 38 #include <android-base/file.h> 39 #include <android-base/logging.h> 40 #include <android-base/unique_fd.h> 41 #include <private/android_filesystem_config.h> 42 43 #include <processgroup/processgroup.h> 44 45 using android::base::WriteStringToFile; 46 47 using namespace std::chrono_literals; 48 49 #define MEM_CGROUP_PATH "/dev/memcg/apps" 50 #define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks" 51 #define ACCT_CGROUP_PATH "/acct" 52 53 #define PROCESSGROUP_UID_PREFIX "uid_" 54 #define PROCESSGROUP_PID_PREFIX "pid_" 55 #define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs" 56 #define PROCESSGROUP_MAX_UID_LEN 11 57 #define PROCESSGROUP_MAX_PID_LEN 11 58 #define PROCESSGROUP_MAX_PATH_LEN \ 59 ((sizeof(MEM_CGROUP_PATH) > sizeof(ACCT_CGROUP_PATH) ? \ 60 sizeof(MEM_CGROUP_PATH) : sizeof(ACCT_CGROUP_PATH)) + \ 61 sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \ 62 PROCESSGROUP_MAX_UID_LEN + \ 63 sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \ 64 PROCESSGROUP_MAX_PID_LEN + \ 65 sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \ 66 1) 67 68 std::once_flag init_path_flag; 69 70 class ProcessGroup { 71 public: 72 ProcessGroup() : buf_ptr_(buf_), buf_len_(0) {} 73 74 bool Open(uid_t uid, int pid); 75 76 // Return positive number and sets *pid = next pid in process cgroup on success 77 // Returns 0 if there are no pids left in the process cgroup 78 // Returns -errno if an error was encountered 79 int GetOneAppProcess(pid_t* pid); 80 81 private: 82 // Returns positive number of bytes filled on success 83 // Returns 0 if there was nothing to read 84 // Returns -errno if an error was encountered 85 int RefillBuffer(); 86 87 android::base::unique_fd fd_; 88 char buf_[128]; 89 char* buf_ptr_; 90 size_t buf_len_; 91 }; 92 93 static const char* getCgroupRootPath() { 94 static const char* cgroup_root_path = NULL; 95 std::call_once(init_path_flag, [&]() { 96 // Check if mem cgroup is mounted, only then check for write-access to avoid 97 // SELinux denials 98 cgroup_root_path = access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ? 99 ACCT_CGROUP_PATH : MEM_CGROUP_PATH; 100 }); 101 return cgroup_root_path; 102 } 103 104 static int convertUidToPath(char *path, size_t size, uid_t uid) 105 { 106 return snprintf(path, size, "%s/%s%d", 107 getCgroupRootPath(), 108 PROCESSGROUP_UID_PREFIX, 109 uid); 110 } 111 112 static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid) 113 { 114 return snprintf(path, size, "%s/%s%d/%s%d", 115 getCgroupRootPath(), 116 PROCESSGROUP_UID_PREFIX, 117 uid, 118 PROCESSGROUP_PID_PREFIX, 119 pid); 120 } 121 122 bool ProcessGroup::Open(uid_t uid, int pid) { 123 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 124 convertUidPidToPath(path, sizeof(path), uid, pid); 125 strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); 126 127 int fd = open(path, O_RDONLY); 128 if (fd < 0) return false; 129 130 fd_.reset(fd); 131 132 LOG(VERBOSE) << "Initialized context for " << path; 133 134 return true; 135 } 136 137 int ProcessGroup::RefillBuffer() { 138 memmove(buf_, buf_ptr_, buf_len_); 139 buf_ptr_ = buf_; 140 141 ssize_t ret = read(fd_, buf_ptr_ + buf_len_, sizeof(buf_) - buf_len_ - 1); 142 if (ret < 0) { 143 return -errno; 144 } else if (ret == 0) { 145 return 0; 146 } 147 148 buf_len_ += ret; 149 buf_[buf_len_] = 0; 150 LOG(VERBOSE) << "Read " << ret << " to buffer: " << buf_; 151 152 assert(buf_len_ <= sizeof(buf_)); 153 154 return ret; 155 } 156 157 int ProcessGroup::GetOneAppProcess(pid_t* out_pid) { 158 *out_pid = 0; 159 160 char* eptr; 161 while ((eptr = static_cast<char*>(memchr(buf_ptr_, '\n', buf_len_))) == nullptr) { 162 int ret = RefillBuffer(); 163 if (ret <= 0) return ret; 164 } 165 166 *eptr = '\0'; 167 char* pid_eptr = nullptr; 168 errno = 0; 169 long pid = strtol(buf_ptr_, &pid_eptr, 10); 170 if (errno != 0) { 171 return -errno; 172 } 173 if (pid_eptr != eptr) { 174 errno = EINVAL; 175 return -errno; 176 } 177 178 buf_len_ -= (eptr - buf_ptr_) + 1; 179 buf_ptr_ = eptr + 1; 180 181 *out_pid = static_cast<pid_t>(pid); 182 return 1; 183 } 184 185 static int removeProcessGroup(uid_t uid, int pid) 186 { 187 int ret; 188 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 189 190 convertUidPidToPath(path, sizeof(path), uid, pid); 191 ret = rmdir(path); 192 193 convertUidToPath(path, sizeof(path), uid); 194 rmdir(path); 195 196 return ret; 197 } 198 199 static void removeUidProcessGroups(const char *uid_path) 200 { 201 std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path), closedir); 202 if (uid != NULL) { 203 dirent* dir; 204 while ((dir = readdir(uid.get())) != nullptr) { 205 char path[PROCESSGROUP_MAX_PATH_LEN]; 206 207 if (dir->d_type != DT_DIR) { 208 continue; 209 } 210 211 if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) { 212 continue; 213 } 214 215 snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name); 216 LOG(VERBOSE) << "Removing " << path; 217 if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path; 218 } 219 } 220 } 221 222 void removeAllProcessGroups() 223 { 224 LOG(VERBOSE) << "removeAllProcessGroups()"; 225 const char* cgroup_root_path = getCgroupRootPath(); 226 std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path), closedir); 227 if (root == NULL) { 228 PLOG(ERROR) << "Failed to open " << cgroup_root_path; 229 } else { 230 dirent* dir; 231 while ((dir = readdir(root.get())) != nullptr) { 232 char path[PROCESSGROUP_MAX_PATH_LEN]; 233 234 if (dir->d_type != DT_DIR) { 235 continue; 236 } 237 if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) { 238 continue; 239 } 240 241 snprintf(path, sizeof(path), "%s/%s", cgroup_root_path, dir->d_name); 242 removeUidProcessGroups(path); 243 LOG(VERBOSE) << "Removing " << path; 244 if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path; 245 } 246 } 247 } 248 249 // Returns number of processes killed on success 250 // Returns 0 if there are no processes in the process cgroup left to kill 251 // Returns -errno on error 252 static int doKillProcessGroupOnce(uid_t uid, int initialPid, int signal) { 253 ProcessGroup process_group; 254 if (!process_group.Open(uid, initialPid)) { 255 PLOG(WARNING) << "Failed to open process cgroup uid " << uid << " pid " << initialPid; 256 return -errno; 257 } 258 259 // We separate all of the pids in the cgroup into those pids that are also the leaders of 260 // process groups (stored in the pgids set) and those that are not (stored in the pids set). 261 std::set<pid_t> pgids; 262 pgids.emplace(initialPid); 263 std::set<pid_t> pids; 264 265 int ret; 266 pid_t pid; 267 int processes = 0; 268 while ((ret = process_group.GetOneAppProcess(&pid)) > 0 && pid >= 0) { 269 processes++; 270 if (pid == 0) { 271 // Should never happen... but if it does, trying to kill this 272 // will boomerang right back and kill us! Let's not let that happen. 273 LOG(WARNING) << "Yikes, we've been told to kill pid 0! How about we don't do that?"; 274 continue; 275 } 276 pid_t pgid = getpgid(pid); 277 if (pgid == -1) PLOG(ERROR) << "getpgid(" << pid << ") failed"; 278 if (pgid == pid) { 279 pgids.emplace(pid); 280 } else { 281 pids.emplace(pid); 282 } 283 } 284 285 // Erase all pids that will be killed when we kill the process groups. 286 for (auto it = pids.begin(); it != pids.end();) { 287 pid_t pgid = getpgid(pid); 288 if (pgids.count(pgid) == 1) { 289 it = pids.erase(it); 290 } else { 291 ++it; 292 } 293 } 294 295 // Kill all process groups. 296 for (const auto pgid : pgids) { 297 LOG(VERBOSE) << "Killing process group " << -pgid << " in uid " << uid 298 << " as part of process cgroup " << initialPid; 299 300 if (kill(-pgid, signal) == -1) { 301 PLOG(WARNING) << "kill(" << -pgid << ", " << signal << ") failed"; 302 } 303 } 304 305 // Kill remaining pids. 306 for (const auto pid : pids) { 307 LOG(VERBOSE) << "Killing pid " << pid << " in uid " << uid << " as part of process cgroup " 308 << initialPid; 309 310 if (kill(pid, signal) == -1) { 311 PLOG(WARNING) << "kill(" << pid << ", " << signal << ") failed"; 312 } 313 } 314 315 return ret >= 0 ? processes : ret; 316 } 317 318 static int killProcessGroup(uid_t uid, int initialPid, int signal, int retries) { 319 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); 320 321 int retry = retries; 322 int processes; 323 while ((processes = doKillProcessGroupOnce(uid, initialPid, signal)) > 0) { 324 LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid; 325 if (retry > 0) { 326 std::this_thread::sleep_for(5ms); 327 --retry; 328 } else { 329 break; 330 } 331 } 332 333 if (processes < 0) { 334 PLOG(ERROR) << "Error encountered killing process cgroup uid " << uid << " pid " 335 << initialPid; 336 return -1; 337 } 338 339 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 340 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); 341 342 // We only calculate the number of 'processes' when killing the processes. 343 // In the retries == 0 case, we only kill the processes once and therefore 344 // will not have waited then recalculated how many processes are remaining 345 // after the first signals have been sent. 346 // Logging anything regarding the number of 'processes' here does not make sense. 347 348 if (processes == 0) { 349 if (retries > 0) { 350 LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid 351 << " in " << static_cast<int>(ms) << "ms"; 352 } 353 return removeProcessGroup(uid, initialPid); 354 } else { 355 if (retries > 0) { 356 LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid 357 << " in " << static_cast<int>(ms) << "ms, " << processes 358 << " processes remain"; 359 } 360 return -1; 361 } 362 } 363 364 int killProcessGroup(uid_t uid, int initialPid, int signal) { 365 return killProcessGroup(uid, initialPid, signal, 40 /*retries*/); 366 } 367 368 int killProcessGroupOnce(uid_t uid, int initialPid, int signal) { 369 return killProcessGroup(uid, initialPid, signal, 0 /*retries*/); 370 } 371 372 static bool mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid) 373 { 374 if (mkdir(path, mode) == -1 && errno != EEXIST) { 375 return false; 376 } 377 378 if (chown(path, uid, gid) == -1) { 379 int saved_errno = errno; 380 rmdir(path); 381 errno = saved_errno; 382 return false; 383 } 384 385 return true; 386 } 387 388 int createProcessGroup(uid_t uid, int initialPid) 389 { 390 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 391 392 convertUidToPath(path, sizeof(path), uid); 393 394 if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) { 395 PLOG(ERROR) << "Failed to make and chown " << path; 396 return -errno; 397 } 398 399 convertUidPidToPath(path, sizeof(path), uid, initialPid); 400 401 if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) { 402 PLOG(ERROR) << "Failed to make and chown " << path; 403 return -errno; 404 } 405 406 strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); 407 408 int ret = 0; 409 if (!WriteStringToFile(std::to_string(initialPid), path)) { 410 ret = -errno; 411 PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path; 412 } 413 414 return ret; 415 } 416 417 static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) { 418 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 419 if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) { 420 PLOG(ERROR) << "Memcg is not mounted." << path; 421 return false; 422 } 423 424 convertUidPidToPath(path, sizeof(path), uid, pid); 425 strlcat(path, fileName, sizeof(path)); 426 427 if (!WriteStringToFile(std::to_string(value), path)) { 428 PLOG(ERROR) << "Failed to write '" << value << "' to " << path; 429 return false; 430 } 431 return true; 432 } 433 434 bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) { 435 return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness); 436 } 437 438 bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) { 439 return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes); 440 } 441 442 bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) { 443 return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes); 444 } 445