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