]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/cgroup-util.c
honor SELinux labels, when creating and writing config files
[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 char *fs;
681 int r;
682 char c[32];
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 char_array_0(c);
697
698 r = write_one_line_file(fs, c);
699 free(fs);
700
701 return r;
702 }
703
704 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
705 char *fs;
706 int r;
707
708 assert(controller);
709 assert(path);
710
711 if (mode != (mode_t) -1)
712 mode &= 0777;
713
714 r = cg_get_path(controller, path, NULL, &fs);
715 if (r < 0)
716 return r;
717
718 r = chmod_and_chown(fs, mode, uid, gid);
719 free(fs);
720
721 return r;
722 }
723
724 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
725 char *fs;
726 int r;
727
728 assert(controller);
729 assert(path);
730
731 if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
732 return 0;
733
734 if (mode != (mode_t) -1)
735 mode &= 0666;
736
737 r = cg_get_path(controller, path, "tasks", &fs);
738 if (r < 0)
739 return r;
740
741 if (sticky >= 0 && mode != (mode_t) -1)
742 /* Both mode and sticky param are passed */
743 mode |= (sticky ? S_ISVTX : 0);
744 else if ((sticky >= 0 && mode == (mode_t) -1) ||
745 (mode != (mode_t) -1 && sticky < 0)) {
746 struct stat st;
747
748 /* Only one param is passed, hence read the current
749 * mode from the file itself */
750
751 r = lstat(fs, &st);
752 if (r < 0) {
753 free(fs);
754 return -errno;
755 }
756
757 if (mode == (mode_t) -1)
758 /* No mode set, we just shall set the sticky bit */
759 mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
760 else
761 /* Only mode set, leave sticky bit untouched */
762 mode = (st.st_mode & ~0777) | mode;
763 }
764
765 r = chmod_and_chown(fs, mode, uid, gid);
766 free(fs);
767
768 return r;
769 }
770
771 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
772 int r;
773 char *p = NULL;
774 FILE *f;
775 char *fs;
776 size_t cs;
777
778 assert(controller);
779 assert(path);
780 assert(pid >= 0);
781
782 if (pid == 0)
783 pid = getpid();
784
785 if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
786 return -ENOMEM;
787
788 f = fopen(fs, "re");
789 free(fs);
790
791 if (!f)
792 return errno == ENOENT ? -ESRCH : -errno;
793
794 cs = strlen(controller);
795
796 while (!feof(f)) {
797 char line[LINE_MAX];
798 char *l;
799
800 errno = 0;
801 if (!(fgets(line, sizeof(line), f))) {
802 if (feof(f))
803 break;
804
805 r = errno ? -errno : -EIO;
806 goto finish;
807 }
808
809 truncate_nl(line);
810
811 if (!(l = strchr(line, ':')))
812 continue;
813
814 l++;
815 if (!strneq(l, controller, cs))
816 continue;
817
818 if (l[cs] != ':')
819 continue;
820
821 if (!(p = strdup(l + cs + 1))) {
822 r = -ENOMEM;
823 goto finish;
824 }
825
826 *path = p;
827 r = 0;
828 goto finish;
829 }
830
831 r = -ENOENT;
832
833 finish:
834 fclose(f);
835
836 return r;
837 }
838
839 int cg_install_release_agent(const char *controller, const char *agent) {
840 char *fs = NULL, *contents = NULL, *line = NULL, *sc;
841 int r;
842
843 assert(controller);
844 assert(agent);
845
846 if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
847 return r;
848
849 if ((r = read_one_line_file(fs, &contents)) < 0)
850 goto finish;
851
852 sc = strstrip(contents);
853 if (sc[0] == 0) {
854
855 if (asprintf(&line, "%s\n", agent) < 0) {
856 r = -ENOMEM;
857 goto finish;
858 }
859
860 if ((r = write_one_line_file(fs, line)) < 0)
861 goto finish;
862
863 } else if (!streq(sc, agent)) {
864 r = -EEXIST;
865 goto finish;
866 }
867
868 free(fs);
869 fs = NULL;
870 if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
871 goto finish;
872
873 free(contents);
874 contents = NULL;
875 if ((r = read_one_line_file(fs, &contents)) < 0)
876 goto finish;
877
878 sc = strstrip(contents);
879
880 if (streq(sc, "0")) {
881 if ((r = write_one_line_file(fs, "1\n")) < 0)
882 goto finish;
883
884 r = 1;
885 } else if (!streq(sc, "1")) {
886 r = -EIO;
887 goto finish;
888 } else
889 r = 0;
890
891 finish:
892 free(fs);
893 free(contents);
894 free(line);
895
896 return r;
897 }
898
899 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
900 pid_t pid = 0, self_pid;
901 int r;
902 FILE *f = NULL;
903 bool found = false;
904
905 assert(path);
906
907 r = cg_enumerate_tasks(controller, path, &f);
908 if (r < 0)
909 return r == -ENOENT ? 1 : r;
910
911 self_pid = getpid();
912
913 while ((r = cg_read_pid(f, &pid)) > 0) {
914
915 if (ignore_self && pid == self_pid)
916 continue;
917
918 found = true;
919 break;
920 }
921
922 fclose(f);
923
924 if (r < 0)
925 return r;
926
927 return !found;
928 }
929
930 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
931 int r;
932 _cleanup_free_ char *controller = NULL, *path = NULL;
933
934 assert(spec);
935
936 r = cg_split_spec(spec, &controller, &path);
937 if (r < 0)
938 return r;
939
940 return cg_is_empty(controller, path, ignore_self);
941 }
942
943 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
944 int r;
945 DIR *d = NULL;
946 char *fn;
947
948 assert(path);
949
950 r = cg_is_empty(controller, path, ignore_self);
951 if (r <= 0)
952 return r;
953
954 r = cg_enumerate_subgroups(controller, path, &d);
955 if (r < 0)
956 return r == -ENOENT ? 1 : r;
957
958 while ((r = cg_read_subgroup(d, &fn)) > 0) {
959 char *p = NULL;
960
961 r = asprintf(&p, "%s/%s", path, fn);
962 free(fn);
963
964 if (r < 0) {
965 r = -ENOMEM;
966 goto finish;
967 }
968
969 r = cg_is_empty_recursive(controller, p, ignore_self);
970 free(p);
971
972 if (r <= 0)
973 goto finish;
974 }
975
976 if (r >= 0)
977 r = 1;
978
979 finish:
980
981 if (d)
982 closedir(d);
983
984 return r;
985 }
986
987 int cg_split_spec(const char *spec, char **controller, char **path) {
988 const char *e;
989 char *t = NULL, *u = NULL;
990
991 assert(spec);
992
993 if (*spec == '/') {
994 if (!path_is_safe(spec))
995 return -EINVAL;
996
997 if (path) {
998 t = strdup(spec);
999 if (!t)
1000 return -ENOMEM;
1001
1002 *path = t;
1003 }
1004
1005 if (controller)
1006 *controller = NULL;
1007
1008 return 0;
1009 }
1010
1011 e = strchr(spec, ':');
1012 if (!e) {
1013 if (!filename_is_safe(spec))
1014 return -EINVAL;
1015
1016 if (controller) {
1017 t = strdup(spec);
1018 if (!t)
1019 return -ENOMEM;
1020
1021 *controller = t;
1022 }
1023
1024 if (path)
1025 *path = NULL;
1026
1027 return 0;
1028 }
1029
1030 t = strndup(spec, e-spec);
1031 if (!t)
1032 return -ENOMEM;
1033 if (!filename_is_safe(t)) {
1034 free(t);
1035 return -EINVAL;
1036 }
1037
1038 u = strdup(e+1);
1039 if (!u) {
1040 free(t);
1041 return -ENOMEM;
1042 }
1043 if (!path_is_safe(u)) {
1044 free(t);
1045 free(u);
1046 return -EINVAL;
1047 }
1048
1049 if (controller)
1050 *controller = t;
1051 else
1052 free(t);
1053
1054 if (path)
1055 *path = u;
1056 else
1057 free(u);
1058
1059 return 0;
1060 }
1061
1062 int cg_join_spec(const char *controller, const char *path, char **spec) {
1063 assert(controller);
1064 assert(path);
1065
1066 if (!path_is_absolute(path) ||
1067 controller[0] == 0 ||
1068 strchr(controller, ':') ||
1069 strchr(controller, '/'))
1070 return -EINVAL;
1071
1072 if (asprintf(spec, "%s:%s", controller, path) < 0)
1073 return -ENOMEM;
1074
1075 return 0;
1076 }
1077
1078 int cg_fix_path(const char *path, char **result) {
1079 char *t, *c, *p;
1080 int r;
1081
1082 assert(path);
1083 assert(result);
1084
1085 /* First check if it already is a filesystem path */
1086 if (path_startswith(path, "/sys/fs/cgroup") &&
1087 access(path, F_OK) >= 0) {
1088
1089 t = strdup(path);
1090 if (!t)
1091 return -ENOMEM;
1092
1093 *result = t;
1094 return 0;
1095 }
1096
1097 /* Otherwise treat it as cg spec */
1098 r = cg_split_spec(path, &c, &p);
1099 if (r < 0)
1100 return r;
1101
1102 r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1103 free(c);
1104 free(p);
1105
1106 return r;
1107 }
1108
1109 int cg_get_user_path(char **path) {
1110 char *root, *p;
1111
1112 assert(path);
1113
1114 /* Figure out the place to put user cgroups below. We use the
1115 * same as PID 1 has but with the "/system" suffix replaced by
1116 * "/user" */
1117
1118 if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
1119 p = strdup("/user");
1120 else {
1121 if (endswith(root, "/system"))
1122 root[strlen(root) - 7] = 0;
1123 else if (streq(root, "/"))
1124 root[0] = 0;
1125
1126 p = strappend(root, "/user");
1127 free(root);
1128 }
1129
1130 if (!p)
1131 return -ENOMEM;
1132
1133 *path = p;
1134 return 0;
1135 }
1136
1137 char **cg_shorten_controllers(char **controllers) {
1138 char **f, **t;
1139
1140 controllers = strv_uniq(controllers);
1141
1142 if (!controllers)
1143 return controllers;
1144
1145 for (f = controllers, t = controllers; *f; f++) {
1146 int r;
1147 const char *p;
1148
1149 if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
1150 free(*f);
1151 continue;
1152 }
1153
1154 p = normalize_controller(*f);
1155
1156 r = check(p);
1157 if (r < 0) {
1158 log_debug("Controller %s is not available, removing from controllers list.", *f);
1159 free(*f);
1160 continue;
1161 }
1162
1163 *(t++) = *f;
1164 }
1165
1166 *t = NULL;
1167 return controllers;
1168 }
1169
1170 int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) {
1171 char *cg_process, *cg_init, *p;
1172 int r;
1173
1174 assert(pid >= 0);
1175
1176 if (pid == 0)
1177 pid = getpid();
1178
1179 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1180 if (r < 0)
1181 return r;
1182
1183 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
1184 if (r < 0) {
1185 free(cg_process);
1186 return r;
1187 }
1188
1189 if (endswith(cg_init, "/system"))
1190 cg_init[strlen(cg_init)-7] = 0;
1191 else if (streq(cg_init, "/"))
1192 cg_init[0] = 0;
1193
1194 if (startswith(cg_process, cg_init))
1195 p = cg_process + strlen(cg_init);
1196 else
1197 p = cg_process;
1198
1199 free(cg_init);
1200
1201 if (cgroup) {
1202 char* c;
1203
1204 c = strdup(p);
1205 if (!c) {
1206 free(cg_process);
1207 return -ENOMEM;
1208 }
1209
1210 *cgroup = c;
1211 }
1212
1213 if (root) {
1214 cg_process[p-cg_process] = 0;
1215 *root = cg_process;
1216 } else
1217 free(cg_process);
1218
1219 return 0;
1220 }
1221
1222 static int instance_unit_from_cgroup(char *cgroup){
1223 char *at;
1224
1225 assert(cgroup);
1226
1227 at = strstr(cgroup, "@.");
1228 if (at) {
1229 /* This is a templated service */
1230
1231 char *i;
1232 char _cleanup_free_ *i2 = NULL, *s = NULL;
1233
1234 i = strchr(at, '/');
1235 if (!i || !i[1]) /* disallow empty instances */
1236 return -EINVAL;
1237
1238 s = strndup(at + 1, i - at - 1);
1239 i2 = strdup(i + 1);
1240 if (!s || !i2)
1241 return -ENOMEM;
1242
1243 strcpy(at + 1, i2);
1244 strcat(at + 1, s);
1245 }
1246
1247 return 0;
1248 }
1249
1250 /* non-static only for testing purposes */
1251 int cgroup_to_unit(char *cgroup, char **unit){
1252 int r;
1253 char *p;
1254
1255 assert(cgroup);
1256 assert(unit);
1257
1258 r = instance_unit_from_cgroup(cgroup);
1259 if (r < 0)
1260 return r;
1261
1262 p = strrchr(cgroup, '/');
1263 assert(p);
1264
1265 r = unit_name_is_valid(p + 1, true);
1266 if (!r)
1267 return -EINVAL;
1268
1269 *unit = strdup(p + 1);
1270 if (!*unit)
1271 return -ENOMEM;
1272
1273 return 0;
1274 }
1275
1276 static int cg_pid_get(const char *prefix, pid_t pid, char **unit) {
1277 int r;
1278 char _cleanup_free_ *cgroup = NULL;
1279
1280 assert(pid >= 0);
1281 assert(unit);
1282
1283 r = cg_pid_get_cgroup(pid, NULL, &cgroup);
1284 if (r < 0)
1285 return r;
1286
1287 if (!startswith(cgroup, prefix))
1288 return -ENOENT;
1289
1290 r = cgroup_to_unit(cgroup, unit);
1291 return r;
1292 }
1293
1294 int cg_pid_get_unit(pid_t pid, char **unit) {
1295 return cg_pid_get("/system/", pid, unit);
1296 }
1297
1298 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1299 return cg_pid_get("/user/", pid, unit);
1300 }
1301
1302 int cg_controller_from_attr(const char *attr, char **controller) {
1303 const char *dot;
1304 char *c;
1305
1306 assert(attr);
1307 assert(controller);
1308
1309 if (!filename_is_safe(attr))
1310 return -EINVAL;
1311
1312 dot = strchr(attr, '.');
1313 if (!dot) {
1314 *controller = NULL;
1315 return 0;
1316 }
1317
1318 c = strndup(attr, dot - attr);
1319 if (!c)
1320 return -ENOMEM;
1321
1322 if (!filename_is_safe(c)) {
1323 free(c);
1324 return -EINVAL;
1325 }
1326
1327 *controller = c;
1328 return 1;
1329 }