1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #define _GNU_SOURCE 4 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <linux/limits.h> 8 #include <poll.h> 9 #include <signal.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/inotify.h> 14 #include <sys/stat.h> 15 #include <sys/types.h> 16 #include <sys/wait.h> 17 #include <unistd.h> 18 19 #include "cgroup_util.h" 20 #include "../../clone3/clone3_selftests.h" 21 22 bool cg_test_v1_named; 23 24 /* Returns read len on success, or -errno on failure. */ 25 ssize_t read_text(const char *path, char *buf, size_t max_len) 26 { 27 size_t total = 0; 28 ssize_t len, ret; 29 int fd; 30 31 fd = open(path, O_RDONLY); 32 if (fd < 0) 33 return -errno; 34 35 /* 36 * A single read() is not enough. procfs and sysfs are backed by 37 * seq_file, and seq_read_iter() copies out at most one internal 38 * buffer (PAGE_SIZE) per call, leaving the rest for the next read(). 39 * Reading only once therefore silently drops everything past the 40 * first page, no matter how big the caller's buffer is. 41 * 42 * Loop until the buffer is full or EOF. A full buffer still means 43 * the file may be longer than max_len, but that is now limited by 44 * the caller's buffer rather than by a page of seq_file output. 45 */ 46 while (total < max_len - 1) { 47 len = read(fd, buf + total, max_len - 1 - total); 48 if (len < 0) { 49 if (errno == EINTR) 50 continue; 51 ret = -errno; 52 goto out; 53 } 54 if (!len) 55 break; 56 total += len; 57 } 58 59 buf[total] = 0; 60 ret = total; 61 out: 62 close(fd); 63 return ret; 64 } 65 66 /* Returns written len on success, or -errno on failure. */ 67 ssize_t write_text(const char *path, char *buf, ssize_t len) 68 { 69 int fd; 70 71 fd = open(path, O_WRONLY | O_APPEND); 72 if (fd < 0) 73 return -errno; 74 75 len = write(fd, buf, len); 76 close(fd); 77 return len < 0 ? -errno : len; 78 } 79 80 char *cg_name(const char *root, const char *name) 81 { 82 size_t len = strlen(root) + strlen(name) + 2; 83 char *ret = malloc(len); 84 85 if (ret) 86 snprintf(ret, len, "%s/%s", root, name); 87 88 return ret; 89 } 90 91 char *cg_name_indexed(const char *root, const char *name, int index) 92 { 93 size_t len = strlen(root) + strlen(name) + 10; 94 char *ret = malloc(len); 95 96 if (ret) 97 snprintf(ret, len, "%s/%s_%d", root, name, index); 98 99 return ret; 100 } 101 102 char *cg_control(const char *cgroup, const char *control) 103 { 104 size_t len = strlen(cgroup) + strlen(control) + 2; 105 char *ret = malloc(len); 106 107 if (ret) 108 snprintf(ret, len, "%s/%s", cgroup, control); 109 110 return ret; 111 } 112 113 /* Returns 0 on success, or -errno on failure. */ 114 int cg_read(const char *cgroup, const char *control, char *buf, size_t len) 115 { 116 char path[PATH_MAX]; 117 ssize_t ret; 118 119 snprintf(path, sizeof(path), "%s/%s", cgroup, control); 120 121 ret = read_text(path, buf, len); 122 return ret >= 0 ? 0 : ret; 123 } 124 125 int cg_read_strcmp(const char *cgroup, const char *control, 126 const char *expected) 127 { 128 size_t size; 129 char *buf; 130 int ret; 131 132 /* Handle the case of comparing against empty string */ 133 if (!expected) 134 return -1; 135 136 /* needs size > 1, otherwise cg_read() reads 0 bytes */ 137 size = (expected[0] == '\0') ? 2 : strlen(expected) + 1; 138 139 buf = malloc(size); 140 if (!buf) 141 return -1; 142 143 if (cg_read(cgroup, control, buf, size)) { 144 free(buf); 145 return -1; 146 } 147 148 ret = strcmp(expected, buf); 149 free(buf); 150 return ret; 151 } 152 153 int cg_read_strcmp_wait(const char *cgroup, const char *control, 154 const char *expected) 155 { 156 int i, ret; 157 158 for (i = 0; i < 100; i++) { 159 ret = cg_read_strcmp(cgroup, control, expected); 160 if (!ret) 161 return ret; 162 usleep(10000); 163 } 164 165 return ret; 166 } 167 168 int cg_read_strstr(const char *cgroup, const char *control, const char *needle) 169 { 170 char buf[BUF_SIZE]; 171 172 if (cg_read(cgroup, control, buf, sizeof(buf))) 173 return -1; 174 175 return strstr(buf, needle) ? 0 : -1; 176 } 177 178 long cg_read_long(const char *cgroup, const char *control) 179 { 180 char buf[128]; 181 182 if (cg_read(cgroup, control, buf, sizeof(buf))) 183 return -1; 184 185 return atol(buf); 186 } 187 188 long cg_read_long_fd(int fd) 189 { 190 char buf[128]; 191 192 if (pread(fd, buf, sizeof(buf), 0) <= 0) 193 return -1; 194 195 return atol(buf); 196 } 197 198 long cg_read_key_long(const char *cgroup, const char *control, const char *key) 199 { 200 char buf[BUF_SIZE]; 201 char *ptr; 202 203 if (cg_read(cgroup, control, buf, sizeof(buf))) 204 return -1; 205 206 ptr = strstr(buf, key); 207 if (!ptr) 208 return -1; 209 210 return atol(ptr + strlen(key)); 211 } 212 213 long cg_read_key_long_poll(const char *cgroup, const char *control, 214 const char *key, long expected, int retries, 215 useconds_t wait_interval_us) 216 { 217 long val = -1; 218 int i; 219 220 for (i = 0; i < retries; i++) { 221 val = cg_read_key_long(cgroup, control, key); 222 if (val < 0) 223 return val; 224 225 if (val == expected) 226 break; 227 228 usleep(wait_interval_us); 229 } 230 231 return val; 232 } 233 234 long cg_read_lc(const char *cgroup, const char *control) 235 { 236 char buf[BUF_SIZE]; 237 const char delim[] = "\n"; 238 char *line; 239 long cnt = 0; 240 241 if (cg_read(cgroup, control, buf, sizeof(buf))) 242 return -1; 243 244 for (line = strtok(buf, delim); line; line = strtok(NULL, delim)) 245 cnt++; 246 247 return cnt; 248 } 249 250 /* Returns 0 on success, or -errno on failure. */ 251 int cg_write(const char *cgroup, const char *control, char *buf) 252 { 253 char path[PATH_MAX]; 254 ssize_t len = strlen(buf), ret; 255 256 snprintf(path, sizeof(path), "%s/%s", cgroup, control); 257 ret = write_text(path, buf, len); 258 return ret == len ? 0 : ret; 259 } 260 261 /* 262 * Returns fd on success, or -1 on failure. 263 * (fd should be closed with close() as usual) 264 */ 265 int cg_open(const char *cgroup, const char *control, int flags) 266 { 267 char path[PATH_MAX]; 268 269 snprintf(path, sizeof(path), "%s/%s", cgroup, control); 270 return open(path, flags); 271 } 272 273 int cg_write_numeric(const char *cgroup, const char *control, long value) 274 { 275 char buf[64]; 276 int ret; 277 278 ret = sprintf(buf, "%lu", value); 279 if (ret < 0) 280 return ret; 281 282 return cg_write(cgroup, control, buf); 283 } 284 285 static int cg_find_root(char *root, size_t len, const char *controller, 286 bool *nsdelegate) 287 { 288 char buf[10 * BUF_SIZE]; 289 char *fs, *mount, *type, *options; 290 const char delim[] = "\n\t "; 291 292 if (read_text("/proc/self/mounts", buf, sizeof(buf)) <= 0) 293 return -1; 294 295 /* 296 * Example: 297 * cgroup /sys/fs/cgroup cgroup2 rw,seclabel,noexec,relatime 0 0 298 */ 299 for (fs = strtok(buf, delim); fs; fs = strtok(NULL, delim)) { 300 mount = strtok(NULL, delim); 301 type = strtok(NULL, delim); 302 options = strtok(NULL, delim); 303 strtok(NULL, delim); 304 strtok(NULL, delim); 305 306 /* 307 * A mount entry is "device mountpoint type options freq 308 * passno". A field can only be missing if the last entry was 309 * cut short by the buffer being too small for the file, and 310 * there is no complete entry left to look at. 311 */ 312 if (!mount || !type || !options) 313 break; 314 315 if (strcmp(type, "cgroup") == 0) { 316 if (!controller || !strstr(options, controller)) 317 continue; 318 } else if (strcmp(type, "cgroup2") == 0) { 319 if (controller && 320 cg_read_strstr(mount, "cgroup.controllers", controller)) 321 continue; 322 } else { 323 continue; 324 } 325 strncpy(root, mount, len); 326 327 if (nsdelegate) 328 *nsdelegate = !!strstr(options, "nsdelegate"); 329 return 0; 330 331 } 332 333 return -1; 334 } 335 336 int cg_find_controller_root(char *root, size_t len, const char *controller) 337 { 338 return cg_find_root(root, len, controller, NULL); 339 } 340 341 int cg_find_unified_root(char *root, size_t len, bool *nsdelegate) 342 { 343 return cg_find_root(root, len, NULL, nsdelegate); 344 } 345 346 int cg_create(const char *cgroup) 347 { 348 return mkdir(cgroup, 0755); 349 } 350 351 int cg_wait_for_proc_count(const char *cgroup, int count) 352 { 353 char buf[10 * BUF_SIZE] = {0}; 354 int attempts; 355 char *ptr; 356 357 for (attempts = 10; attempts >= 0; attempts--) { 358 int nr = 0; 359 360 if (cg_read(cgroup, "cgroup.procs", buf, sizeof(buf))) 361 break; 362 363 for (ptr = buf; *ptr; ptr++) 364 if (*ptr == '\n') 365 nr++; 366 367 if (nr >= count) 368 return 0; 369 370 usleep(100000); 371 } 372 373 return -1; 374 } 375 376 int cg_killall(const char *cgroup) 377 { 378 char buf[BUF_SIZE]; 379 char *ptr = buf; 380 381 /* If cgroup.kill exists use it. */ 382 if (!cg_write(cgroup, "cgroup.kill", "1")) 383 return 0; 384 385 if (cg_read(cgroup, "cgroup.procs", buf, sizeof(buf))) 386 return -1; 387 388 while (ptr < buf + sizeof(buf)) { 389 int pid = strtol(ptr, &ptr, 10); 390 391 if (pid == 0) 392 break; 393 if (*ptr) 394 ptr++; 395 else 396 break; 397 if (kill(pid, SIGKILL)) 398 return -1; 399 } 400 401 return 0; 402 } 403 404 int cg_destroy(const char *cgroup) 405 { 406 int ret; 407 408 if (!cgroup) 409 return 0; 410 retry: 411 ret = rmdir(cgroup); 412 if (ret && errno == EBUSY) { 413 cg_killall(cgroup); 414 usleep(100); 415 goto retry; 416 } 417 418 if (ret && errno == ENOENT) 419 ret = 0; 420 421 return ret; 422 } 423 424 int cg_enter(const char *cgroup, int pid) 425 { 426 char pidbuf[64]; 427 428 snprintf(pidbuf, sizeof(pidbuf), "%d", pid); 429 return cg_write(cgroup, "cgroup.procs", pidbuf); 430 } 431 432 int cg_enter_current(const char *cgroup) 433 { 434 return cg_write(cgroup, "cgroup.procs", "0"); 435 } 436 437 int cg_enter_current_thread(const char *cgroup) 438 { 439 return cg_write(cgroup, CG_THREADS_FILE, "0"); 440 } 441 442 int cg_run(const char *cgroup, 443 int (*fn)(const char *cgroup, void *arg), 444 void *arg) 445 { 446 int pid, retcode; 447 448 pid = fork(); 449 if (pid < 0) { 450 return pid; 451 } else if (pid == 0) { 452 char buf[64]; 453 454 snprintf(buf, sizeof(buf), "%d", getpid()); 455 if (cg_write(cgroup, "cgroup.procs", buf)) 456 exit(EXIT_FAILURE); 457 exit(fn(cgroup, arg)); 458 } else { 459 waitpid(pid, &retcode, 0); 460 if (WIFEXITED(retcode)) 461 return WEXITSTATUS(retcode); 462 else 463 return -1; 464 } 465 } 466 467 pid_t clone_into_cgroup(int cgroup_fd) 468 { 469 #ifdef CLONE_ARGS_SIZE_VER2 470 pid_t pid; 471 472 struct __clone_args args = { 473 .flags = CLONE_INTO_CGROUP, 474 .exit_signal = SIGCHLD, 475 .cgroup = cgroup_fd, 476 }; 477 478 pid = sys_clone3(&args, sizeof(struct __clone_args)); 479 /* 480 * Verify that this is a genuine test failure: 481 * ENOSYS -> clone3() not available 482 * E2BIG -> CLONE_INTO_CGROUP not available 483 */ 484 if (pid < 0 && (errno == ENOSYS || errno == E2BIG)) 485 goto pretend_enosys; 486 487 return pid; 488 489 pretend_enosys: 490 #endif 491 errno = ENOSYS; 492 return -ENOSYS; 493 } 494 495 int clone_reap(pid_t pid, int options) 496 { 497 int ret; 498 siginfo_t info = { 499 .si_signo = 0, 500 }; 501 502 again: 503 ret = waitid(P_PID, pid, &info, options | __WALL | __WNOTHREAD); 504 if (ret < 0) { 505 if (errno == EINTR) 506 goto again; 507 return -1; 508 } 509 510 if (options & WEXITED) { 511 if (WIFEXITED(info.si_status)) 512 return WEXITSTATUS(info.si_status); 513 } 514 515 if (options & WSTOPPED) { 516 if (WIFSTOPPED(info.si_status)) 517 return WSTOPSIG(info.si_status); 518 } 519 520 if (options & WCONTINUED) { 521 if (WIFCONTINUED(info.si_status)) 522 return 0; 523 } 524 525 return -1; 526 } 527 528 int dirfd_open_opath(const char *dir) 529 { 530 return open(dir, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW | O_PATH); 531 } 532 533 #define close_prot_errno(fd) \ 534 if (fd >= 0) { \ 535 int _e_ = errno; \ 536 close(fd); \ 537 errno = _e_; \ 538 } 539 540 static int clone_into_cgroup_run_nowait(const char *cgroup, 541 int (*fn)(const char *cgroup, void *arg), 542 void *arg) 543 { 544 int cgroup_fd; 545 pid_t pid; 546 547 cgroup_fd = dirfd_open_opath(cgroup); 548 if (cgroup_fd < 0) 549 return -1; 550 551 pid = clone_into_cgroup(cgroup_fd); 552 close_prot_errno(cgroup_fd); 553 if (pid == 0) 554 exit(fn(cgroup, arg)); 555 556 return pid; 557 } 558 559 int cg_run_nowait(const char *cgroup, 560 int (*fn)(const char *cgroup, void *arg), 561 void *arg) 562 { 563 int pid; 564 565 pid = clone_into_cgroup_run_nowait(cgroup, fn, arg); 566 if (pid > 0) 567 return pid; 568 569 /* Genuine test failure. */ 570 if (pid < 0 && errno != ENOSYS) 571 return -1; 572 573 pid = fork(); 574 if (pid == 0) { 575 char buf[64]; 576 577 snprintf(buf, sizeof(buf), "%d", getpid()); 578 if (cg_write(cgroup, "cgroup.procs", buf)) 579 exit(EXIT_FAILURE); 580 exit(fn(cgroup, arg)); 581 } 582 583 return pid; 584 } 585 586 int proc_mount_contains(const char *option) 587 { 588 char buf[4 * BUF_SIZE]; 589 ssize_t read; 590 591 read = read_text("/proc/mounts", buf, sizeof(buf)); 592 if (read < 0) 593 return read; 594 595 return strstr(buf, option) != NULL; 596 } 597 598 int cgroup_feature(const char *feature) 599 { 600 char buf[BUF_SIZE]; 601 ssize_t read; 602 603 read = read_text("/sys/kernel/cgroup/features", buf, sizeof(buf)); 604 if (read < 0) 605 return read; 606 607 return strstr(buf, feature) != NULL; 608 } 609 610 ssize_t proc_read_text(int pid, bool thread, const char *item, char *buf, size_t size) 611 { 612 char path[PATH_MAX]; 613 ssize_t ret; 614 615 if (!pid) 616 snprintf(path, sizeof(path), "/proc/%s/%s", 617 thread ? "thread-self" : "self", item); 618 else 619 snprintf(path, sizeof(path), "/proc/%d/%s", pid, item); 620 621 ret = read_text(path, buf, size); 622 return ret < 0 ? -1 : ret; 623 } 624 625 int proc_read_strstr(int pid, bool thread, const char *item, const char *needle) 626 { 627 char buf[BUF_SIZE]; 628 629 if (proc_read_text(pid, thread, item, buf, sizeof(buf)) < 0) 630 return -1; 631 632 return strstr(buf, needle) ? 0 : -1; 633 } 634 635 int clone_into_cgroup_run_wait(const char *cgroup) 636 { 637 int cgroup_fd; 638 pid_t pid; 639 640 cgroup_fd = dirfd_open_opath(cgroup); 641 if (cgroup_fd < 0) 642 return -1; 643 644 pid = clone_into_cgroup(cgroup_fd); 645 close_prot_errno(cgroup_fd); 646 if (pid < 0) 647 return -1; 648 649 if (pid == 0) 650 exit(EXIT_SUCCESS); 651 652 /* 653 * We don't care whether this fails. We only care whether the initial 654 * clone succeeded. 655 */ 656 (void)clone_reap(pid, WEXITED); 657 return 0; 658 } 659 660 static int __prepare_for_wait(const char *cgroup, const char *filename) 661 { 662 char *path; 663 int fd, ret; 664 665 path = cg_control(cgroup, filename); 666 if (!path) 667 return -1; 668 669 fd = inotify_init1(0); 670 if (fd == -1) 671 goto out; 672 673 ret = inotify_add_watch(fd, path, IN_MODIFY); 674 if (ret == -1) { 675 close(fd); 676 fd = -1; 677 } 678 679 out: 680 free(path); 681 return fd; 682 } 683 684 int cg_prepare_for_wait(const char *cgroup) 685 { 686 return __prepare_for_wait(cgroup, "cgroup.events"); 687 } 688 689 int memcg_prepare_for_wait(const char *cgroup) 690 { 691 return __prepare_for_wait(cgroup, "memory.events"); 692 } 693 694 int cg_wait_for(int fd) 695 { 696 int ret = -1; 697 struct pollfd fds = { 698 .fd = fd, 699 .events = POLLIN, 700 }; 701 702 while (true) { 703 ret = poll(&fds, 1, 10000); 704 705 if (ret == -1) { 706 if (errno == EINTR) 707 continue; 708 709 break; 710 } 711 712 if (ret > 0 && fds.revents & POLLIN) { 713 ret = 0; 714 break; 715 } 716 } 717 718 return ret; 719 } 720