xref: /linux/tools/testing/selftests/cgroup/lib/cgroup_util.c (revision 316b06ccee04ad871f6233ad7a3884b0ea457360)
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