]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/cgroup-util.c
bus: handle env vars safely
[thirdparty/systemd.git] / src / shared / cgroup-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <ftw.h>
31
32 #include "cgroup-util.h"
33 #include "log.h"
34 #include "set.h"
35 #include "macro.h"
36 #include "util.h"
37 #include "path-util.h"
38 #include "strv.h"
39 #include "unit-name.h"
40 #include "fileio.h"
41
42 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
43 char *fs;
44 int r;
45 FILE *f;
46
47 assert(path);
48 assert(_f);
49
50 r = cg_get_path(controller, path, "cgroup.procs", &fs);
51 if (r < 0)
52 return r;
53
54 f = fopen(fs, "re");
55 free(fs);
56
57 if (!f)
58 return -errno;
59
60 *_f = f;
61 return 0;
62 }
63
64 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
65 char *fs;
66 int r;
67 FILE *f;
68
69 assert(path);
70 assert(_f);
71
72 r = cg_get_path(controller, path, "tasks", &fs);
73 if (r < 0)
74 return r;
75
76 f = fopen(fs, "re");
77 free(fs);
78
79 if (!f)
80 return -errno;
81
82 *_f = f;
83 return 0;
84 }
85
86 int cg_read_pid(FILE *f, pid_t *_pid) {
87 unsigned long ul;
88
89 /* Note that the cgroup.procs might contain duplicates! See
90 * cgroups.txt for details. */
91
92 errno = 0;
93 if (fscanf(f, "%lu", &ul) != 1) {
94
95 if (feof(f))
96 return 0;
97
98 return errno ? -errno : -EIO;
99 }
100
101 if (ul <= 0)
102 return -EIO;
103
104 *_pid = (pid_t) ul;
105 return 1;
106 }
107
108 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
109 char *fs;
110 int r;
111 DIR *d;
112
113 assert(path);
114 assert(_d);
115
116 /* This is not recursive! */
117
118 r = cg_get_path(controller, path, NULL, &fs);
119 if (r < 0)
120 return r;
121
122 d = opendir(fs);
123 free(fs);
124
125 if (!d)
126 return -errno;
127
128 *_d = d;
129 return 0;
130 }
131
132 int cg_read_subgroup(DIR *d, char **fn) {
133 struct dirent *de;
134
135 assert(d);
136
137 errno = 0;
138 while ((de = readdir(d))) {
139 char *b;
140
141 if (de->d_type != DT_DIR)
142 continue;
143
144 if (streq(de->d_name, ".") ||
145 streq(de->d_name, ".."))
146 continue;
147
148 if (!(b = strdup(de->d_name)))
149 return -ENOMEM;
150
151 *fn = b;
152 return 1;
153 }
154
155 if (errno)
156 return -errno;
157
158 return 0;
159 }
160
161 int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
162 char *p;
163 int r;
164
165 r = cg_get_path(controller, path, NULL, &p);
166 if (r < 0)
167 return r;
168
169 if (honour_sticky) {
170 char *tasks;
171
172 /* If the sticky bit is set don't remove the directory */
173
174 tasks = strappend(p, "/tasks");
175 if (!tasks) {
176 free(p);
177 return -ENOMEM;
178 }
179
180 r = file_is_priv_sticky(tasks);
181 free(tasks);
182
183 if (r > 0) {
184 free(p);
185 return 0;
186 }
187 }
188
189 r = rmdir(p);
190 free(p);
191
192 return (r < 0 && errno != ENOENT) ? -errno : 0;
193 }
194
195 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
196 bool done = false;
197 int r, ret = 0;
198 pid_t my_pid;
199 FILE *f = NULL;
200 Set *allocated_set = NULL;
201
202 assert(controller);
203 assert(path);
204 assert(sig >= 0);
205
206 /* This goes through the tasks list and kills them all. This
207 * is repeated until no further processes are added to the
208 * tasks list, to properly handle forking processes */
209
210 if (!s)
211 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
212 return -ENOMEM;
213
214 my_pid = getpid();
215
216 do {
217 pid_t pid = 0;
218 done = true;
219
220 if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
221 if (ret >= 0 && r != -ENOENT)
222 ret = r;
223
224 goto finish;
225 }
226
227 while ((r = cg_read_pid(f, &pid)) > 0) {
228
229 if (pid == my_pid && ignore_self)
230 continue;
231
232 if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
233 continue;
234
235 /* If we haven't killed this process yet, kill
236 * it */
237 if (kill(pid, sig) < 0) {
238 if (ret >= 0 && errno != ESRCH)
239 ret = -errno;
240 } else if (ret == 0) {
241
242 if (sigcont)
243 kill(pid, SIGCONT);
244
245 ret = 1;
246 }
247
248 done = false;
249
250 if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
251 if (ret >= 0)
252 ret = r;
253
254 goto finish;
255 }
256 }
257
258 if (r < 0) {
259 if (ret >= 0)
260 ret = r;
261
262 goto finish;
263 }
264
265 fclose(f);
266 f = NULL;
267
268 /* To avoid racing against processes which fork
269 * quicker than we can kill them we repeat this until
270 * no new pids need to be killed. */
271
272 } while (!done);
273
274 finish:
275 if (allocated_set)
276 set_free(allocated_set);
277
278 if (f)
279 fclose(f);
280
281 return ret;
282 }
283
284 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
285 int r, ret = 0;
286 DIR *d = NULL;
287 char *fn;
288 Set *allocated_set = NULL;
289
290 assert(path);
291 assert(controller);
292 assert(sig >= 0);
293
294 if (!s)
295 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
296 return -ENOMEM;
297
298 ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
299
300 if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
301 if (ret >= 0 && r != -ENOENT)
302 ret = r;
303
304 goto finish;
305 }
306
307 while ((r = cg_read_subgroup(d, &fn)) > 0) {
308 char *p = NULL;
309
310 r = asprintf(&p, "%s/%s", path, fn);
311 free(fn);
312
313 if (r < 0) {
314 if (ret >= 0)
315 ret = -ENOMEM;
316
317 goto finish;
318 }
319
320 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
321 free(p);
322
323 if (r != 0 && ret >= 0)
324 ret = r;
325 }
326
327 if (r < 0 && ret >= 0)
328 ret = r;
329
330 if (rem)
331 if ((r = cg_rmdir(controller, path, true)) < 0) {
332 if (ret >= 0 &&
333 r != -ENOENT &&
334 r != -EBUSY)
335 ret = r;
336 }
337
338 finish:
339 if (d)
340 closedir(d);
341
342 if (allocated_set)
343 set_free(allocated_set);
344
345 return ret;
346 }
347
348 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
349 unsigned i;
350
351 assert(path);
352 assert(controller);
353
354 /* This safely kills all processes; first it sends a SIGTERM,
355 * then checks 8 times after 200ms whether the group is now
356 * empty, then kills everything that is left with SIGKILL and
357 * finally checks 5 times after 200ms each whether the group
358 * is finally empty. */
359
360 for (i = 0; i < 15; i++) {
361 int sig, r;
362
363 if (i <= 0)
364 sig = SIGTERM;
365 else if (i == 9)
366 sig = SIGKILL;
367 else
368 sig = 0;
369
370 if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
371 return r;
372
373 usleep(200 * USEC_PER_MSEC);
374 }
375
376 return 0;
377 }
378
379 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
380 bool done = false;
381 _cleanup_set_free_ Set *s = NULL;
382 int r, ret = 0;
383 pid_t my_pid;
384 _cleanup_fclose_ FILE *f = NULL;
385
386 assert(cfrom);
387 assert(pfrom);
388 assert(cto);
389 assert(pto);
390
391 s = set_new(trivial_hash_func, trivial_compare_func);
392 if (!s)
393 return -ENOMEM;
394
395 my_pid = getpid();
396
397 do {
398 pid_t pid = 0;
399 done = true;
400
401 r = cg_enumerate_tasks(cfrom, pfrom, &f);
402 if (r < 0) {
403 if (ret >= 0 && r != -ENOENT)
404 ret = r;
405
406 return ret;
407 }
408
409 while ((r = cg_read_pid(f, &pid)) > 0) {
410
411 /* This might do weird stuff if we aren't a
412 * single-threaded program. However, we
413 * luckily know we are not */
414 if (pid == my_pid && ignore_self)
415 continue;
416
417 if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
418 continue;
419
420 r = cg_attach(cto, pto, pid);
421 if (r < 0) {
422 if (ret >= 0 && r != -ESRCH)
423 ret = r;
424 } else if (ret == 0)
425 ret = 1;
426
427 done = false;
428
429 r = set_put(s, LONG_TO_PTR(pid));
430 if (r < 0) {
431 if (ret >= 0)
432 ret = r;
433
434 return ret;
435 }
436 }
437
438 if (r < 0) {
439 if (ret >= 0)
440 ret = r;
441
442 return ret;
443 }
444
445 fclose(f);
446 f = NULL;
447 } while (!done);
448
449 return ret;
450 }
451
452 int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) {
453 int r, ret = 0;
454 _cleanup_closedir_ DIR *d = NULL;
455 char *fn;
456
457 assert(cfrom);
458 assert(pfrom);
459 assert(cto);
460 assert(pto);
461
462 ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
463
464 r = cg_enumerate_subgroups(cfrom, pfrom, &d);
465 if (r < 0) {
466 if (ret >= 0 && r != -ENOENT)
467 ret = r;
468 return ret;
469 }
470
471 while ((r = cg_read_subgroup(d, &fn)) > 0) {
472 _cleanup_free_ char *p = NULL;
473
474 p = strjoin(pfrom, "/", fn, NULL);
475 free(fn);
476 if (!p) {
477 if (ret >= 0)
478 ret = -ENOMEM;
479
480 return ret;
481 }
482
483 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
484 if (r != 0 && ret >= 0)
485 ret = r;
486 }
487
488 if (r < 0 && ret >= 0)
489 ret = r;
490
491 if (rem) {
492 r = cg_rmdir(cfrom, pfrom, true);
493 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
494 return r;
495 }
496
497 return ret;
498 }
499
500 static const char *normalize_controller(const char *controller) {
501
502 if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
503 return "systemd";
504 else if (startswith(controller, "name="))
505 return controller + 5;
506 else
507 return controller;
508 }
509
510 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
511 char *t = NULL;
512
513 if (!(controller || path))
514 return -EINVAL;
515
516 if (controller) {
517 if (path && suffix)
518 t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
519 else if (path)
520 t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
521 else if (suffix)
522 t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
523 else
524 t = strjoin("/sys/fs/cgroup/", controller, NULL);
525 } else {
526 if (path && suffix)
527 t = strjoin(path, "/", suffix, NULL);
528 else if (path)
529 t = strdup(path);
530 }
531
532 if (!t)
533 return -ENOMEM;
534
535 path_kill_slashes(t);
536
537 *fs = t;
538 return 0;
539 }
540
541 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
542 const char *p;
543 static __thread bool good = false;
544
545 assert(fs);
546
547 if (_unlikely_(!good)) {
548 int r;
549
550 r = path_is_mount_point("/sys/fs/cgroup", false);
551 if (r <= 0)
552 return r < 0 ? r : -ENOENT;
553
554 /* Cache this to save a few stat()s */
555 good = true;
556 }
557
558 p = controller ? normalize_controller(controller) : NULL;
559 return join_path(p, path, suffix, fs);
560 }
561
562 static int check(const char *p) {
563 char *cc;
564
565 assert(p);
566
567 /* Check if this controller actually really exists */
568 cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
569 strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
570 if (access(cc, F_OK) < 0)
571 return -errno;
572
573 return 0;
574 }
575
576 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
577 const char *p;
578 int r;
579
580 assert(controller);
581 assert(fs);
582
583 if (isempty(controller))
584 return -EINVAL;
585
586 /* Normalize the controller syntax */
587 p = normalize_controller(controller);
588
589 /* Check if this controller actually really exists */
590 r = check(p);
591 if (r < 0)
592 return r;
593
594 return join_path(p, path, suffix, fs);
595 }
596
597 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
598 char *p;
599 bool is_sticky;
600
601 if (typeflag != FTW_DP)
602 return 0;
603
604 if (ftwbuf->level < 1)
605 return 0;
606
607 p = strappend(path, "/tasks");
608 if (!p) {
609 errno = ENOMEM;
610 return 1;
611 }
612
613 is_sticky = file_is_priv_sticky(p) > 0;
614 free(p);
615
616 if (is_sticky)
617 return 0;
618
619 rmdir(path);
620 return 0;
621 }
622
623 int cg_trim(const char *controller, const char *path, bool delete_root) {
624 char *fs;
625 int r = 0;
626
627 assert(controller);
628 assert(path);
629
630 r = cg_get_path(controller, path, NULL, &fs);
631 if (r < 0)
632 return r;
633
634 errno = 0;
635 if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
636 r = errno ? -errno : -EIO;
637
638 if (delete_root) {
639 bool is_sticky;
640 char *p;
641
642 p = strappend(fs, "/tasks");
643 if (!p) {
644 free(fs);
645 return -ENOMEM;
646 }
647
648 is_sticky = file_is_priv_sticky(p) > 0;
649 free(p);
650
651 if (!is_sticky)
652 if (rmdir(fs) < 0 && errno != ENOENT) {
653 if (r == 0)
654 r = -errno;
655 }
656 }
657
658 free(fs);
659
660 return r;
661 }
662
663 int cg_delete(const char *controller, const char *path) {
664 char *parent;
665 int r;
666
667 assert(controller);
668 assert(path);
669
670 if ((r = path_get_parent(path, &parent)) < 0)
671 return r;
672
673 r = cg_migrate_recursive(controller, path, controller, parent, false, true);
674 free(parent);
675
676 return r == -ENOENT ? 0 : r;
677 }
678
679 int cg_attach(const char *controller, const char *path, pid_t pid) {
680 _cleanup_free_ char *fs = NULL;
681 char c[DECIMAL_STR_MAX(pid_t) + 2];
682 int r;
683
684 assert(controller);
685 assert(path);
686 assert(pid >= 0);
687
688 r = cg_get_path_and_check(controller, path, "tasks", &fs);
689 if (r < 0)
690 return r;
691
692 if (pid == 0)
693 pid = getpid();
694
695 snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
696
697 return write_string_file(fs, c);
698 }
699
700 int cg_set_group_access(
701 const char *controller,
702 const char *path,
703 mode_t mode,
704 uid_t uid,
705 gid_t gid) {
706
707 _cleanup_free_ char *fs = NULL;
708 int r;
709
710 assert(controller);
711 assert(path);
712
713 if (mode != (mode_t) -1)
714 mode &= 0777;
715
716 r = cg_get_path(controller, path, NULL, &fs);
717 if (r < 0)
718 return r;
719
720 return chmod_and_chown(fs, mode, uid, gid);
721 }
722
723 int cg_set_task_access(
724 const char *controller,
725 const char *path,
726 mode_t mode,
727 uid_t uid,
728 gid_t gid,
729 int sticky) {
730
731 _cleanup_free_ char *fs = NULL, *procs = NULL;
732 int r;
733
734 assert(controller);
735 assert(path);
736
737 if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
738 return 0;
739
740 if (mode != (mode_t) -1)
741 mode &= 0666;
742
743 r = cg_get_path(controller, path, "tasks", &fs);
744 if (r < 0)
745 return r;
746
747 if (sticky >= 0 && mode != (mode_t) -1)
748 /* Both mode and sticky param are passed */
749 mode |= (sticky ? S_ISVTX : 0);
750 else if ((sticky >= 0 && mode == (mode_t) -1) ||
751 (mode != (mode_t) -1 && sticky < 0)) {
752 struct stat st;
753
754 /* Only one param is passed, hence read the current
755 * mode from the file itself */
756
757 r = lstat(fs, &st);
758 if (r < 0)
759 return -errno;
760
761 if (mode == (mode_t) -1)
762 /* No mode set, we just shall set the sticky bit */
763 mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
764 else
765 /* Only mode set, leave sticky bit untouched */
766 mode = (st.st_mode & ~0777) | mode;
767 }
768
769 r = chmod_and_chown(fs, mode, uid, gid);
770 if (r < 0)
771 return r;
772
773 /* Always keep values for "cgroup.procs" in sync with "tasks" */
774 r = cg_get_path(controller, path, "cgroup.procs", &procs);
775 if (r < 0)
776 return r;
777
778 return chmod_and_chown(procs, mode, uid, gid);
779 }
780
781 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
782 int r;
783 char *p = NULL;
784 FILE *f;
785 char *fs;
786 size_t cs;
787
788 assert(controller);
789 assert(path);
790 assert(pid >= 0);
791
792 if (pid == 0)
793 pid = getpid();
794
795 if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
796 return -ENOMEM;
797
798 f = fopen(fs, "re");
799 free(fs);
800
801 if (!f)
802 return errno == ENOENT ? -ESRCH : -errno;
803
804 cs = strlen(controller);
805
806 while (!feof(f)) {
807 char line[LINE_MAX];
808 char *l;
809
810 errno = 0;
811 if (!(fgets(line, sizeof(line), f))) {
812 if (feof(f))
813 break;
814
815 r = errno ? -errno : -EIO;
816 goto finish;
817 }
818
819 truncate_nl(line);
820
821 if (!(l = strchr(line, ':')))
822 continue;
823
824 l++;
825 if (!strneq(l, controller, cs))
826 continue;
827
828 if (l[cs] != ':')
829 continue;
830
831 if (!(p = strdup(l + cs + 1))) {
832 r = -ENOMEM;
833 goto finish;
834 }
835
836 *path = p;
837 r = 0;
838 goto finish;
839 }
840
841 r = -ENOENT;
842
843 finish:
844 fclose(f);
845
846 return r;
847 }
848
849 int cg_install_release_agent(const char *controller, const char *agent) {
850 char *fs = NULL, *contents = NULL, *line = NULL, *sc;
851 int r;
852
853 assert(controller);
854 assert(agent);
855
856 if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
857 return r;
858
859 if ((r = read_one_line_file(fs, &contents)) < 0)
860 goto finish;
861
862 sc = strstrip(contents);
863 if (sc[0] == 0) {
864
865 if (asprintf(&line, "%s\n", agent) < 0) {
866 r = -ENOMEM;
867 goto finish;
868 }
869
870 r = write_string_file(fs, line);
871 if (r < 0)
872 goto finish;
873
874 } else if (!streq(sc, agent)) {
875 r = -EEXIST;
876 goto finish;
877 }
878
879 free(fs);
880 fs = NULL;
881 if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
882 goto finish;
883
884 free(contents);
885 contents = NULL;
886 if ((r = read_one_line_file(fs, &contents)) < 0)
887 goto finish;
888
889 sc = strstrip(contents);
890
891 if (streq(sc, "0")) {
892 if ((r = write_string_file(fs, "1\n")) < 0)
893 goto finish;
894
895 r = 1;
896 } else if (!streq(sc, "1")) {
897 r = -EIO;
898 goto finish;
899 } else
900 r = 0;
901
902 finish:
903 free(fs);
904 free(contents);
905 free(line);
906
907 return r;
908 }
909
910 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
911 pid_t pid = 0, self_pid;
912 int r;
913 FILE *f = NULL;
914 bool found = false;
915
916 assert(path);
917
918 r = cg_enumerate_tasks(controller, path, &f);
919 if (r < 0)
920 return r == -ENOENT ? 1 : r;
921
922 self_pid = getpid();
923
924 while ((r = cg_read_pid(f, &pid)) > 0) {
925
926 if (ignore_self && pid == self_pid)
927 continue;
928
929 found = true;
930 break;
931 }
932
933 fclose(f);
934
935 if (r < 0)
936 return r;
937
938 return !found;
939 }
940
941 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
942 int r;
943 _cleanup_free_ char *controller = NULL, *path = NULL;
944
945 assert(spec);
946
947 r = cg_split_spec(spec, &controller, &path);
948 if (r < 0)
949 return r;
950
951 return cg_is_empty(controller, path, ignore_self);
952 }
953
954 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
955 int r;
956 DIR *d = NULL;
957 char *fn;
958
959 assert(path);
960
961 r = cg_is_empty(controller, path, ignore_self);
962 if (r <= 0)
963 return r;
964
965 r = cg_enumerate_subgroups(controller, path, &d);
966 if (r < 0)
967 return r == -ENOENT ? 1 : r;
968
969 while ((r = cg_read_subgroup(d, &fn)) > 0) {
970 char *p = NULL;
971
972 r = asprintf(&p, "%s/%s", path, fn);
973 free(fn);
974
975 if (r < 0) {
976 r = -ENOMEM;
977 goto finish;
978 }
979
980 r = cg_is_empty_recursive(controller, p, ignore_self);
981 free(p);
982
983 if (r <= 0)
984 goto finish;
985 }
986
987 if (r >= 0)
988 r = 1;
989
990 finish:
991
992 if (d)
993 closedir(d);
994
995 return r;
996 }
997
998 int cg_split_spec(const char *spec, char **controller, char **path) {
999 const char *e;
1000 char *t = NULL, *u = NULL;
1001
1002 assert(spec);
1003
1004 if (*spec == '/') {
1005 if (!path_is_safe(spec))
1006 return -EINVAL;
1007
1008 if (path) {
1009 t = strdup(spec);
1010 if (!t)
1011 return -ENOMEM;
1012
1013 *path = t;
1014 }
1015
1016 if (controller)
1017 *controller = NULL;
1018
1019 return 0;
1020 }
1021
1022 e = strchr(spec, ':');
1023 if (!e) {
1024 if (!filename_is_safe(spec))
1025 return -EINVAL;
1026
1027 if (controller) {
1028 t = strdup(spec);
1029 if (!t)
1030 return -ENOMEM;
1031
1032 *controller = t;
1033 }
1034
1035 if (path)
1036 *path = NULL;
1037
1038 return 0;
1039 }
1040
1041 t = strndup(spec, e-spec);
1042 if (!t)
1043 return -ENOMEM;
1044 if (!filename_is_safe(t)) {
1045 free(t);
1046 return -EINVAL;
1047 }
1048
1049 u = strdup(e+1);
1050 if (!u) {
1051 free(t);
1052 return -ENOMEM;
1053 }
1054 if (!path_is_safe(u)) {
1055 free(t);
1056 free(u);
1057 return -EINVAL;
1058 }
1059
1060 if (controller)
1061 *controller = t;
1062 else
1063 free(t);
1064
1065 if (path)
1066 *path = u;
1067 else
1068 free(u);
1069
1070 return 0;
1071 }
1072
1073 int cg_join_spec(const char *controller, const char *path, char **spec) {
1074 assert(controller);
1075 assert(path);
1076
1077 if (!path_is_absolute(path) ||
1078 controller[0] == 0 ||
1079 strchr(controller, ':') ||
1080 strchr(controller, '/'))
1081 return -EINVAL;
1082
1083 if (asprintf(spec, "%s:%s", controller, path) < 0)
1084 return -ENOMEM;
1085
1086 return 0;
1087 }
1088
1089 int cg_fix_path(const char *path, char **result) {
1090 char *t, *c, *p;
1091 int r;
1092
1093 assert(path);
1094 assert(result);
1095
1096 /* First check if it already is a filesystem path */
1097 if (path_startswith(path, "/sys/fs/cgroup") &&
1098 access(path, F_OK) >= 0) {
1099
1100 t = strdup(path);
1101 if (!t)
1102 return -ENOMEM;
1103
1104 *result = t;
1105 return 0;
1106 }
1107
1108 /* Otherwise treat it as cg spec */
1109 r = cg_split_spec(path, &c, &p);
1110 if (r < 0)
1111 return r;
1112
1113 r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1114 free(c);
1115 free(p);
1116
1117 return r;
1118 }
1119
1120 int cg_get_user_path(char **path) {
1121 char *root, *p;
1122
1123 assert(path);
1124
1125 /* Figure out the place to put user cgroups below. We use the
1126 * same as PID 1 has but with the "/system" suffix replaced by
1127 * "/user" */
1128
1129 if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
1130 p = strdup("/user");
1131 else {
1132 if (endswith(root, "/system"))
1133 root[strlen(root) - 7] = 0;
1134 else if (streq(root, "/"))
1135 root[0] = 0;
1136
1137 p = strappend(root, "/user");
1138 free(root);
1139 }
1140
1141 if (!p)
1142 return -ENOMEM;
1143
1144 *path = p;
1145 return 0;
1146 }
1147
1148 char **cg_shorten_controllers(char **controllers) {
1149 char **f, **t;
1150
1151 if (!controllers)
1152 return controllers;
1153
1154 for (f = controllers, t = controllers; *f; f++) {
1155 int r;
1156 const char *p;
1157
1158 if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
1159 free(*f);
1160 continue;
1161 }
1162
1163 p = normalize_controller(*f);
1164
1165 r = check(p);
1166 if (r < 0) {
1167 log_debug("Controller %s is not available, removing from controllers list.", *f);
1168 free(*f);
1169 continue;
1170 }
1171
1172 *(t++) = *f;
1173 }
1174
1175 *t = NULL;
1176 return strv_uniq(controllers);
1177 }
1178
1179 int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) {
1180 char *cg_process, *cg_init, *p, *q;
1181 int r;
1182
1183 assert(pid >= 0);
1184
1185 if (pid == 0)
1186 pid = getpid();
1187
1188 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1189 if (r < 0)
1190 return r;
1191
1192 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
1193 if (r < 0) {
1194 free(cg_process);
1195 return r;
1196 }
1197
1198 if (endswith(cg_init, "/system"))
1199 cg_init[strlen(cg_init)-7] = 0;
1200 else if (streq(cg_init, "/"))
1201 cg_init[0] = 0;
1202
1203 q = startswith(cg_process, cg_init);
1204 p = q ? q : cg_process;
1205 free(cg_init);
1206
1207 if (cgroup) {
1208 char* c;
1209
1210 c = strdup(p);
1211 if (!c) {
1212 free(cg_process);
1213 return -ENOMEM;
1214 }
1215
1216 *cgroup = c;
1217 }
1218
1219 if (root) {
1220 cg_process[p-cg_process] = 0;
1221 *root = cg_process;
1222 } else
1223 free(cg_process);
1224
1225 return 0;
1226 }
1227
1228 /* non-static only for testing purposes */
1229 int cg_cgroup_to_unit(const char *cgroup, char **unit){
1230 char *p, *e, *c, *s, *k;
1231
1232 assert(cgroup);
1233 assert(unit);
1234
1235 e = strchrnul(cgroup, '/');
1236 c = strndupa(cgroup, e - cgroup);
1237
1238 /* Could this be a valid unit name? */
1239 if (!unit_name_is_valid(c, true))
1240 return -EINVAL;
1241
1242 if (!unit_name_is_template(c))
1243 s = strdup(c);
1244 else {
1245 if (*e != '/')
1246 return -EINVAL;
1247
1248 e += strspn(e, "/");
1249 p = strchrnul(e, '/');
1250
1251 /* Don't allow empty instance strings */
1252 if (p == e)
1253 return -EINVAL;
1254
1255 k = strndupa(e, p - e);
1256
1257 s = unit_name_replace_instance(c, k);
1258 }
1259
1260 if (!s)
1261 return -ENOMEM;
1262
1263 *unit = s;
1264 return 0;
1265 }
1266
1267 int cg_path_get_unit(const char *path, char **unit) {
1268 const char *e;
1269
1270 assert(path);
1271 assert(unit);
1272
1273 e = path_startswith(path, "/system/");
1274 if (!e)
1275 return -ENOENT;
1276
1277 return cg_cgroup_to_unit(e, unit);
1278 }
1279
1280 int cg_pid_get_unit(pid_t pid, char **unit) {
1281 char _cleanup_free_ *cgroup = NULL;
1282 int r;
1283
1284 assert(unit);
1285
1286 r = cg_pid_get_cgroup(pid, NULL, &cgroup);
1287 if (r < 0)
1288 return r;
1289
1290 return cg_path_get_unit(cgroup, unit);
1291 }
1292
1293 static const char *skip_label(const char *e) {
1294 assert(e);
1295
1296 e += strspn(e, "/");
1297 e = strchr(e, '/');
1298 if (!e)
1299 return NULL;
1300
1301 e += strspn(e, "/");
1302 return e;
1303 }
1304
1305 int cg_path_get_user_unit(const char *path, char **unit) {
1306 const char *e;
1307
1308 assert(path);
1309 assert(unit);
1310
1311 /* We always have to parse the path from the beginning as unit
1312 * cgroups might have arbitrary child cgroups and we shouldn't get
1313 * confused by those */
1314
1315 e = path_startswith(path, "/user/");
1316 if (!e)
1317 return -ENOENT;
1318
1319 /* Skip the user name */
1320 e = skip_label(e);
1321 if (!e)
1322 return -ENOENT;
1323
1324 /* Skip the session ID */
1325 e = skip_label(e);
1326 if (!e)
1327 return -ENOENT;
1328
1329 /* Skip the systemd cgroup */
1330 e = skip_label(e);
1331 if (!e)
1332 return -ENOENT;
1333
1334 return cg_cgroup_to_unit(e, unit);
1335 }
1336
1337 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1338 char _cleanup_free_ *cgroup = NULL;
1339 int r;
1340
1341 assert(unit);
1342
1343 r = cg_pid_get_cgroup(pid, NULL, &cgroup);
1344 if (r < 0)
1345 return r;
1346
1347 return cg_path_get_user_unit(cgroup, unit);
1348 }
1349
1350 int cg_controller_from_attr(const char *attr, char **controller) {
1351 const char *dot;
1352 char *c;
1353
1354 assert(attr);
1355 assert(controller);
1356
1357 if (!filename_is_safe(attr))
1358 return -EINVAL;
1359
1360 dot = strchr(attr, '.');
1361 if (!dot) {
1362 *controller = NULL;
1363 return 0;
1364 }
1365
1366 c = strndup(attr, dot - attr);
1367 if (!c)
1368 return -ENOMEM;
1369
1370 if (!filename_is_safe(c)) {
1371 free(c);
1372 return -EINVAL;
1373 }
1374
1375 *controller = c;
1376 return 1;
1377 }